Blob Blame History Raw
From 31b404f4a08322a5cf06b1d0637a4ada4323cbb1 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Miloslav=20Trma=C4=8D?= <mitr@redhat.com>
Date: Thu, 20 Feb 2020 16:30:08 +0100
Subject: [PATCH 1/2] Remove vendor/src/github.com/mtrmac/gpgme/
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

This seems to be a mistaken commit of an intermediate build state
in the old times when vendoring was used via a GOPATH at vendor/src/...

Signed-off-by: Miloslav Trmač <mitr@redhat.com>
---
 vendor/src/github.com/mtrmac/gpgme/LICENSE    |  12 -
 .../src/github.com/mtrmac/gpgme/callbacks.go  |  42 -
 vendor/src/github.com/mtrmac/gpgme/data.go    | 191 -----
 vendor/src/github.com/mtrmac/gpgme/go_gpgme.c |  89 ---
 vendor/src/github.com/mtrmac/gpgme/go_gpgme.h |  37 -
 vendor/src/github.com/mtrmac/gpgme/gpgme.go   | 740 ------------------
 6 files changed, 1111 deletions(-)
 delete mode 100644 vendor/src/github.com/mtrmac/gpgme/LICENSE
 delete mode 100644 vendor/src/github.com/mtrmac/gpgme/callbacks.go
 delete mode 100644 vendor/src/github.com/mtrmac/gpgme/data.go
 delete mode 100644 vendor/src/github.com/mtrmac/gpgme/go_gpgme.c
 delete mode 100644 vendor/src/github.com/mtrmac/gpgme/go_gpgme.h
 delete mode 100644 vendor/src/github.com/mtrmac/gpgme/gpgme.go

diff --git a/vendor/src/github.com/mtrmac/gpgme/LICENSE b/vendor/src/github.com/mtrmac/gpgme/LICENSE
deleted file mode 100644
index 06d4ab77316f..000000000000
--- a/vendor/src/github.com/mtrmac/gpgme/LICENSE
+++ /dev/null
@@ -1,12 +0,0 @@
-Copyright (c) 2015, James Fargher <proglottis@gmail.com>
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
-
-1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
-
-2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
-
-3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/vendor/src/github.com/mtrmac/gpgme/callbacks.go b/vendor/src/github.com/mtrmac/gpgme/callbacks.go
deleted file mode 100644
index d1dc610d42a8..000000000000
--- a/vendor/src/github.com/mtrmac/gpgme/callbacks.go
+++ /dev/null
@@ -1,42 +0,0 @@
-package gpgme
-
-import (
-	"sync"
-)
-
-var callbacks struct {
-	sync.Mutex
-	m map[uintptr]interface{}
-	c uintptr
-}
-
-func callbackAdd(v interface{}) uintptr {
-	callbacks.Lock()
-	defer callbacks.Unlock()
-	if callbacks.m == nil {
-		callbacks.m = make(map[uintptr]interface{})
-	}
-	callbacks.c++
-	ret := callbacks.c
-	callbacks.m[ret] = v
-	return ret
-}
-
-func callbackLookup(c uintptr) interface{} {
-	callbacks.Lock()
-	defer callbacks.Unlock()
-	ret := callbacks.m[c]
-	if ret == nil {
-		panic("callback pointer not found")
-	}
-	return ret
-}
-
-func callbackDelete(c uintptr) {
-	callbacks.Lock()
-	defer callbacks.Unlock()
-	if callbacks.m[c] == nil {
-		panic("callback pointer not found")
-	}
-	delete(callbacks.m, c)
-}
diff --git a/vendor/src/github.com/mtrmac/gpgme/data.go b/vendor/src/github.com/mtrmac/gpgme/data.go
deleted file mode 100644
index eebc9726347d..000000000000
--- a/vendor/src/github.com/mtrmac/gpgme/data.go
+++ /dev/null
@@ -1,191 +0,0 @@
-package gpgme
-
-// #include <string.h>
-// #include <gpgme.h>
-// #include <errno.h>
-// #include "go_gpgme.h"
-import "C"
-
-import (
-	"io"
-	"os"
-	"runtime"
-	"unsafe"
-)
-
-const (
-	SeekSet = C.SEEK_SET
-	SeekCur = C.SEEK_CUR
-	SeekEnd = C.SEEK_END
-)
-
-//export gogpgme_readfunc
-func gogpgme_readfunc(handle, buffer unsafe.Pointer, size C.size_t) C.ssize_t {
-	d := callbackLookup(uintptr(handle)).(*Data)
-	if len(d.buf) < int(size) {
-		d.buf = make([]byte, size)
-	}
-	n, err := d.r.Read(d.buf[:size])
-	if err != nil && err != io.EOF {
-		C.gpgme_err_set_errno(C.EIO)
-		return -1
-	}
-	C.memcpy(buffer, unsafe.Pointer(&d.buf[0]), C.size_t(n))
-	return C.ssize_t(n)
-}
-
-//export gogpgme_writefunc
-func gogpgme_writefunc(handle, buffer unsafe.Pointer, size C.size_t) C.ssize_t {
-	d := callbackLookup(uintptr(handle)).(*Data)
-	if len(d.buf) < int(size) {
-		d.buf = make([]byte, size)
-	}
-	C.memcpy(unsafe.Pointer(&d.buf[0]), buffer, C.size_t(size))
-	n, err := d.w.Write(d.buf[:size])
-	if err != nil && err != io.EOF {
-		C.gpgme_err_set_errno(C.EIO)
-		return -1
-	}
-	return C.ssize_t(n)
-}
-
-//export gogpgme_seekfunc
-func gogpgme_seekfunc(handle unsafe.Pointer, offset C.off_t, whence C.int) C.off_t {
-	d := callbackLookup(uintptr(handle)).(*Data)
-	n, err := d.s.Seek(int64(offset), int(whence))
-	if err != nil {
-		C.gpgme_err_set_errno(C.EIO)
-		return -1
-	}
-	return C.off_t(n)
-}
-
-// The Data buffer used to communicate with GPGME
-type Data struct {
-	dh  C.gpgme_data_t
-	buf []byte
-	cbs C.struct_gpgme_data_cbs
-	r   io.Reader
-	w   io.Writer
-	s   io.Seeker
-	cbc uintptr
-}
-
-func newData() *Data {
-	d := &Data{}
-	runtime.SetFinalizer(d, (*Data).Close)
-	return d
-}
-
-// NewData returns a new memory based data buffer
-func NewData() (*Data, error) {
-	d := newData()
-	return d, handleError(C.gpgme_data_new(&d.dh))
-}
-
-// NewDataFile returns a new file based data buffer
-func NewDataFile(f *os.File) (*Data, error) {
-	d := newData()
-	return d, handleError(C.gpgme_data_new_from_fd(&d.dh, C.int(f.Fd())))
-}
-
-// NewDataBytes returns a new memory based data buffer that contains `b` bytes
-func NewDataBytes(b []byte) (*Data, error) {
-	d := newData()
-	var cb *C.char
-	if len(b) != 0 {
-		cb = (*C.char)(unsafe.Pointer(&b[0]))
-	}
-	return d, handleError(C.gpgme_data_new_from_mem(&d.dh, cb, C.size_t(len(b)), 1))
-}
-
-// NewDataReader returns a new callback based data buffer
-func NewDataReader(r io.Reader) (*Data, error) {
-	d := newData()
-	d.r = r
-	d.cbs.read = C.gpgme_data_read_cb_t(C.gogpgme_readfunc)
-	cbc := callbackAdd(d)
-	d.cbc = cbc
-	return d, handleError(C.gogpgme_data_new_from_cbs(&d.dh, &d.cbs, C.uintptr_t(cbc)))
-}
-
-// NewDataWriter returns a new callback based data buffer
-func NewDataWriter(w io.Writer) (*Data, error) {
-	d := newData()
-	d.w = w
-	d.cbs.write = C.gpgme_data_write_cb_t(C.gogpgme_writefunc)
-	cbc := callbackAdd(d)
-	d.cbc = cbc
-	return d, handleError(C.gogpgme_data_new_from_cbs(&d.dh, &d.cbs, C.uintptr_t(cbc)))
-}
-
-// NewDataReadWriter returns a new callback based data buffer
-func NewDataReadWriter(rw io.ReadWriter) (*Data, error) {
-	d := newData()
-	d.r = rw
-	d.w = rw
-	d.cbs.read = C.gpgme_data_read_cb_t(C.gogpgme_readfunc)
-	d.cbs.write = C.gpgme_data_write_cb_t(C.gogpgme_writefunc)
-	cbc := callbackAdd(d)
-	d.cbc = cbc
-	return d, handleError(C.gogpgme_data_new_from_cbs(&d.dh, &d.cbs, C.uintptr_t(cbc)))
-}
-
-// NewDataReadWriteSeeker returns a new callback based data buffer
-func NewDataReadWriteSeeker(rw io.ReadWriteSeeker) (*Data, error) {
-	d := newData()
-	d.r = rw
-	d.w = rw
-	d.s = rw
-	d.cbs.read = C.gpgme_data_read_cb_t(C.gogpgme_readfunc)
-	d.cbs.write = C.gpgme_data_write_cb_t(C.gogpgme_writefunc)
-	d.cbs.seek = C.gpgme_data_seek_cb_t(C.gogpgme_seekfunc)
-	cbc := callbackAdd(d)
-	d.cbc = cbc
-	return d, handleError(C.gogpgme_data_new_from_cbs(&d.dh, &d.cbs, C.uintptr_t(cbc)))
-}
-
-// Close releases any resources associated with the data buffer
-func (d *Data) Close() error {
-	if d.dh == nil {
-		return nil
-	}
-	if d.cbc > 0 {
-		callbackDelete(d.cbc)
-	}
-	_, err := C.gpgme_data_release(d.dh)
-	d.dh = nil
-	return err
-}
-
-func (d *Data) Write(p []byte) (int, error) {
-	n, err := C.gpgme_data_write(d.dh, unsafe.Pointer(&p[0]), C.size_t(len(p)))
-	if err != nil {
-		return 0, err
-	}
-	if n == 0 {
-		return 0, io.EOF
-	}
-	return int(n), nil
-}
-
-func (d *Data) Read(p []byte) (int, error) {
-	n, err := C.gpgme_data_read(d.dh, unsafe.Pointer(&p[0]), C.size_t(len(p)))
-	if err != nil {
-		return 0, err
-	}
-	if n == 0 {
-		return 0, io.EOF
-	}
-	return int(n), nil
-}
-
-func (d *Data) Seek(offset int64, whence int) (int64, error) {
-	n, err := C.gpgme_data_seek(d.dh, C.off_t(offset), C.int(whence))
-	return int64(n), err
-}
-
-// Name returns the associated filename if any
-func (d *Data) Name() string {
-	return C.GoString(C.gpgme_data_get_file_name(d.dh))
-}
diff --git a/vendor/src/github.com/mtrmac/gpgme/go_gpgme.c b/vendor/src/github.com/mtrmac/gpgme/go_gpgme.c
deleted file mode 100644
index b887574e0cb9..000000000000
--- a/vendor/src/github.com/mtrmac/gpgme/go_gpgme.c
+++ /dev/null
@@ -1,89 +0,0 @@
-#include "go_gpgme.h"
-
-gpgme_error_t gogpgme_data_new_from_cbs(gpgme_data_t *dh, gpgme_data_cbs_t cbs, uintptr_t handle) {
-	return gpgme_data_new_from_cbs(dh, cbs, (void *)handle);
-}
-
-void gogpgme_set_passphrase_cb(gpgme_ctx_t ctx, gpgme_passphrase_cb_t cb, uintptr_t handle) {
-	gpgme_set_passphrase_cb(ctx, cb, (void *)handle);
-}
-
-unsigned int key_revoked(gpgme_key_t k) {
-	return k->revoked;
-}
-
-unsigned int key_expired(gpgme_key_t k) {
-	return k->expired;
-}
-
-unsigned int key_disabled(gpgme_key_t k) {
-	return k->disabled;
-}
-
-unsigned int key_invalid(gpgme_key_t k) {
-	return k->invalid;
-}
-
-unsigned int key_can_encrypt(gpgme_key_t k) {
-	return k->can_encrypt;
-}
-
-unsigned int key_can_sign(gpgme_key_t k) {
-	return k->can_sign;
-}
-
-unsigned int key_can_certify(gpgme_key_t k) {
-	return k->can_certify;
-}
-
-unsigned int key_secret(gpgme_key_t k) {
-	return k->secret;
-}
-
-unsigned int key_can_authenticate(gpgme_key_t k) {
-	return k->can_authenticate;
-}
-
-unsigned int key_is_qualified(gpgme_key_t k) {
-	return k->is_qualified;
-}
-
-unsigned int signature_wrong_key_usage(gpgme_signature_t s) {
-    return s->wrong_key_usage;
-}
-
-unsigned int signature_pka_trust(gpgme_signature_t s) {
-    return s->pka_trust;
-}
-
-unsigned int signature_chain_model(gpgme_signature_t s) {
-    return s->chain_model;
-}
-
-unsigned int subkey_revoked(gpgme_subkey_t k) {
-	return k->revoked;
-}
-
-unsigned int subkey_expired(gpgme_subkey_t k) {
-	return k->expired;
-}
-
-unsigned int subkey_disabled(gpgme_subkey_t k) {
-	return k->disabled;
-}
-
-unsigned int subkey_invalid(gpgme_subkey_t k) {
-	return k->invalid;
-}
-
-unsigned int subkey_secret(gpgme_subkey_t k) {
-	return k->secret;
-}
-
-unsigned int uid_revoked(gpgme_user_id_t u) {
-	return u->revoked;
-}
-
-unsigned int uid_invalid(gpgme_user_id_t u) {
-	return u->invalid;
-}
diff --git a/vendor/src/github.com/mtrmac/gpgme/go_gpgme.h b/vendor/src/github.com/mtrmac/gpgme/go_gpgme.h
deleted file mode 100644
index a3678b127ac7..000000000000
--- a/vendor/src/github.com/mtrmac/gpgme/go_gpgme.h
+++ /dev/null
@@ -1,37 +0,0 @@
-#ifndef GO_GPGME_H
-#define GO_GPGME_H
-
-#define _FILE_OFFSET_BITS 64
-#include <stdint.h>
-
-#include <gpgme.h>
-
-extern ssize_t gogpgme_readfunc(void *handle, void *buffer, size_t size);
-extern ssize_t gogpgme_writefunc(void *handle, void *buffer, size_t size);
-extern off_t gogpgme_seekfunc(void *handle, off_t offset, int whence);
-extern gpgme_error_t gogpgme_passfunc(void *hook, char *uid_hint, char *passphrase_info, int prev_was_bad, int fd);
-extern gpgme_error_t gogpgme_data_new_from_cbs(gpgme_data_t *dh, gpgme_data_cbs_t cbs, uintptr_t handle);
-extern void gogpgme_set_passphrase_cb(gpgme_ctx_t ctx, gpgme_passphrase_cb_t cb, uintptr_t handle);
-
-extern unsigned int key_revoked(gpgme_key_t k);
-extern unsigned int key_expired(gpgme_key_t k);
-extern unsigned int key_disabled(gpgme_key_t k);
-extern unsigned int key_invalid(gpgme_key_t k);
-extern unsigned int key_can_encrypt(gpgme_key_t k);
-extern unsigned int key_can_sign(gpgme_key_t k);
-extern unsigned int key_can_certify(gpgme_key_t k);
-extern unsigned int key_secret(gpgme_key_t k);
-extern unsigned int key_can_authenticate(gpgme_key_t k);
-extern unsigned int key_is_qualified(gpgme_key_t k);
-extern unsigned int signature_wrong_key_usage(gpgme_signature_t s);
-extern unsigned int signature_pka_trust(gpgme_signature_t s);
-extern unsigned int signature_chain_model(gpgme_signature_t s);
-extern unsigned int subkey_revoked(gpgme_subkey_t k);
-extern unsigned int subkey_expired(gpgme_subkey_t k);
-extern unsigned int subkey_disabled(gpgme_subkey_t k);
-extern unsigned int subkey_invalid(gpgme_subkey_t k);
-extern unsigned int subkey_secret(gpgme_subkey_t k);
-extern unsigned int uid_revoked(gpgme_user_id_t u);
-extern unsigned int uid_invalid(gpgme_user_id_t u);
-
-#endif
diff --git a/vendor/src/github.com/mtrmac/gpgme/gpgme.go b/vendor/src/github.com/mtrmac/gpgme/gpgme.go
deleted file mode 100644
index 5f1793eab32d..000000000000
--- a/vendor/src/github.com/mtrmac/gpgme/gpgme.go
+++ /dev/null
@@ -1,740 +0,0 @@
-// Package gpgme provides a Go wrapper for the GPGME library
-package gpgme
-
-// #cgo LDFLAGS: -lgpgme -lassuan -lgpg-error
-// #cgo CPPFLAGS: -D_FILE_OFFSET_BITS=64
-// #include <stdlib.h>
-// #include <gpgme.h>
-// #include "go_gpgme.h"
-import "C"
-
-import (
-	"io"
-	"os"
-	"runtime"
-	"time"
-	"unsafe"
-)
-
-var Version string
-
-func init() {
-	Version = C.GoString(C.gpgme_check_version(nil))
-}
-
-// Callback is the function that is called when a passphrase is required
-type Callback func(uidHint string, prevWasBad bool, f *os.File) error
-
-//export gogpgme_passfunc
-func gogpgme_passfunc(hook unsafe.Pointer, uid_hint, passphrase_info *C.char, prev_was_bad, fd C.int) C.gpgme_error_t {
-	c := callbackLookup(uintptr(hook)).(*Context)
-	go_uid_hint := C.GoString(uid_hint)
-	f := os.NewFile(uintptr(fd), go_uid_hint)
-	defer f.Close()
-	err := c.callback(go_uid_hint, prev_was_bad != 0, f)
-	if err != nil {
-		return C.GPG_ERR_CANCELED
-	}
-	return 0
-}
-
-type Protocol int
-
-const (
-	ProtocolOpenPGP  Protocol = C.GPGME_PROTOCOL_OpenPGP
-	ProtocolCMS      Protocol = C.GPGME_PROTOCOL_CMS
-	ProtocolGPGConf  Protocol = C.GPGME_PROTOCOL_GPGCONF
-	ProtocolAssuan   Protocol = C.GPGME_PROTOCOL_ASSUAN
-	ProtocolG13      Protocol = C.GPGME_PROTOCOL_G13
-	ProtocolUIServer Protocol = C.GPGME_PROTOCOL_UISERVER
-	// ProtocolSpawn    Protocol = C.GPGME_PROTOCOL_SPAWN // Unavailable in 1.4.3
-	ProtocolDefault Protocol = C.GPGME_PROTOCOL_DEFAULT
-	ProtocolUnknown Protocol = C.GPGME_PROTOCOL_UNKNOWN
-)
-
-type PinEntryMode int
-
-// const ( // Unavailable in 1.3.2
-// 	PinEntryDefault  PinEntryMode = C.GPGME_PINENTRY_MODE_DEFAULT
-// 	PinEntryAsk      PinEntryMode = C.GPGME_PINENTRY_MODE_ASK
-// 	PinEntryCancel   PinEntryMode = C.GPGME_PINENTRY_MODE_CANCEL
-// 	PinEntryError    PinEntryMode = C.GPGME_PINENTRY_MODE_ERROR
-// 	PinEntryLoopback PinEntryMode = C.GPGME_PINENTRY_MODE_LOOPBACK
-// )
-
-type EncryptFlag uint
-
-const (
-	EncryptAlwaysTrust EncryptFlag = C.GPGME_ENCRYPT_ALWAYS_TRUST
-	EncryptNoEncryptTo EncryptFlag = C.GPGME_ENCRYPT_NO_ENCRYPT_TO
-	EncryptPrepare     EncryptFlag = C.GPGME_ENCRYPT_PREPARE
-	EncryptExceptSign  EncryptFlag = C.GPGME_ENCRYPT_EXPECT_SIGN
-	// EncryptNoCompress  EncryptFlag = C.GPGME_ENCRYPT_NO_COMPRESS // Unavailable in 1.4.3
-)
-
-type HashAlgo int
-
-// const values for HashAlgo values should be added when necessary.
-
-type KeyListMode uint
-
-const (
-	KeyListModeLocal        KeyListMode = C.GPGME_KEYLIST_MODE_LOCAL
-	KeyListModeExtern       KeyListMode = C.GPGME_KEYLIST_MODE_EXTERN
-	KeyListModeSigs         KeyListMode = C.GPGME_KEYLIST_MODE_SIGS
-	KeyListModeSigNotations KeyListMode = C.GPGME_KEYLIST_MODE_SIG_NOTATIONS
-	// KeyListModeWithSecret   KeyListMode = C.GPGME_KEYLIST_MODE_WITH_SECRET // Unavailable in 1.4.3
-	KeyListModeEphemeral    KeyListMode = C.GPGME_KEYLIST_MODE_EPHEMERAL
-	KeyListModeModeValidate KeyListMode = C.GPGME_KEYLIST_MODE_VALIDATE
-)
-
-type PubkeyAlgo int
-
-// const values for PubkeyAlgo values should be added when necessary.
-
-type SigMode int
-
-const (
-	SigModeNormal SigMode = C.GPGME_SIG_MODE_NORMAL
-	SigModeDetach SigMode = C.GPGME_SIG_MODE_DETACH
-	SigModeClear  SigMode = C.GPGME_SIG_MODE_CLEAR
-)
-
-type SigSum int
-
-const (
-	SigSumValid      SigSum = C.GPGME_SIGSUM_VALID
-	SigSumGreen      SigSum = C.GPGME_SIGSUM_GREEN
-	SigSumRed        SigSum = C.GPGME_SIGSUM_RED
-	SigSumKeyRevoked SigSum = C.GPGME_SIGSUM_KEY_REVOKED
-	SigSumKeyExpired SigSum = C.GPGME_SIGSUM_KEY_EXPIRED
-	SigSumSigExpired SigSum = C.GPGME_SIGSUM_SIG_EXPIRED
-	SigSumKeyMissing SigSum = C.GPGME_SIGSUM_KEY_MISSING
-	SigSumCRLMissing SigSum = C.GPGME_SIGSUM_CRL_MISSING
-	SigSumCRLTooOld  SigSum = C.GPGME_SIGSUM_CRL_TOO_OLD
-	SigSumBadPolicy  SigSum = C.GPGME_SIGSUM_BAD_POLICY
-	SigSumSysError   SigSum = C.GPGME_SIGSUM_SYS_ERROR
-)
-
-type Validity int
-
-const (
-	ValidityUnknown   Validity = C.GPGME_VALIDITY_UNKNOWN
-	ValidityUndefined Validity = C.GPGME_VALIDITY_UNDEFINED
-	ValidityNever     Validity = C.GPGME_VALIDITY_NEVER
-	ValidityMarginal  Validity = C.GPGME_VALIDITY_MARGINAL
-	ValidityFull      Validity = C.GPGME_VALIDITY_FULL
-	ValidityUltimate  Validity = C.GPGME_VALIDITY_ULTIMATE
-)
-
-type ErrorCode int
-
-const (
-	ErrorNoError ErrorCode = C.GPG_ERR_NO_ERROR
-	ErrorEOF     ErrorCode = C.GPG_ERR_EOF
-)
-
-// Error is a wrapper for GPGME errors
-type Error struct {
-	err C.gpgme_error_t
-}
-
-func (e Error) Code() ErrorCode {
-	return ErrorCode(C.gpgme_err_code(e.err))
-}
-
-func (e Error) Error() string {
-	return C.GoString(C.gpgme_strerror(e.err))
-}
-
-func handleError(err C.gpgme_error_t) error {
-	e := Error{err: err}
-	if e.Code() == ErrorNoError {
-		return nil
-	}
-	return e
-}
-
-func cbool(b bool) C.int {
-	if b {
-		return 1
-	}
-	return 0
-}
-
-func EngineCheckVersion(p Protocol) error {
-	return handleError(C.gpgme_engine_check_version(C.gpgme_protocol_t(p)))
-}
-
-type EngineInfo struct {
-	info C.gpgme_engine_info_t
-}
-
-func (e *EngineInfo) Next() *EngineInfo {
-	if e.info.next == nil {
-		return nil
-	}
-	return &EngineInfo{info: e.info.next}
-}
-
-func (e *EngineInfo) Protocol() Protocol {
-	return Protocol(e.info.protocol)
-}
-
-func (e *EngineInfo) FileName() string {
-	return C.GoString(e.info.file_name)
-}
-
-func (e *EngineInfo) Version() string {
-	return C.GoString(e.info.version)
-}
-
-func (e *EngineInfo) RequiredVersion() string {
-	return C.GoString(e.info.req_version)
-}
-
-func (e *EngineInfo) HomeDir() string {
-	return C.GoString(e.info.home_dir)
-}
-
-func GetEngineInfo() (*EngineInfo, error) {
-	info := &EngineInfo{}
-	return info, handleError(C.gpgme_get_engine_info(&info.info))
-}
-
-func SetEngineInfo(proto Protocol, fileName, homeDir string) error {
-	var cfn, chome *C.char
-	if fileName != "" {
-		cfn = C.CString(fileName)
-		defer C.free(unsafe.Pointer(cfn))
-	}
-	if homeDir != "" {
-		chome = C.CString(homeDir)
-		defer C.free(unsafe.Pointer(chome))
-	}
-	return handleError(C.gpgme_set_engine_info(C.gpgme_protocol_t(proto), cfn, chome))
-}
-
-func FindKeys(pattern string, secretOnly bool) ([]*Key, error) {
-	var keys []*Key
-	ctx, err := New()
-	if err != nil {
-		return keys, err
-	}
-	defer ctx.Release()
-	if err := ctx.KeyListStart(pattern, secretOnly); err != nil {
-		return keys, err
-	}
-	defer ctx.KeyListEnd()
-	for ctx.KeyListNext() {
-		keys = append(keys, ctx.Key)
-	}
-	if ctx.KeyError != nil {
-		return keys, ctx.KeyError
-	}
-	return keys, nil
-}
-
-func Decrypt(r io.Reader) (*Data, error) {
-	ctx, err := New()
-	if err != nil {
-		return nil, err
-	}
-	defer ctx.Release()
-	cipher, err := NewDataReader(r)
-	if err != nil {
-		return nil, err
-	}
-	defer cipher.Close()
-	plain, err := NewData()
-	if err != nil {
-		return nil, err
-	}
-	err = ctx.Decrypt(cipher, plain)
-	plain.Seek(0, SeekSet)
-	return plain, err
-}
-
-type Context struct {
-	Key      *Key
-	KeyError error
-
-	callback Callback
-	cbc      uintptr
-
-	ctx C.gpgme_ctx_t
-}
-
-func New() (*Context, error) {
-	c := &Context{}
-	err := C.gpgme_new(&c.ctx)
-	runtime.SetFinalizer(c, (*Context).Release)
-	return c, handleError(err)
-}
-
-func (c *Context) Release() {
-	if c.ctx == nil {
-		return
-	}
-	if c.cbc > 0 {
-		callbackDelete(c.cbc)
-	}
-	C.gpgme_release(c.ctx)
-	c.ctx = nil
-}
-
-func (c *Context) SetArmor(yes bool) {
-	C.gpgme_set_armor(c.ctx, cbool(yes))
-}
-
-func (c *Context) Armor() bool {
-	return C.gpgme_get_armor(c.ctx) != 0
-}
-
-func (c *Context) SetTextMode(yes bool) {
-	C.gpgme_set_textmode(c.ctx, cbool(yes))
-}
-
-func (c *Context) TextMode() bool {
-	return C.gpgme_get_textmode(c.ctx) != 0
-}
-
-func (c *Context) SetProtocol(p Protocol) error {
-	return handleError(C.gpgme_set_protocol(c.ctx, C.gpgme_protocol_t(p)))
-}
-
-func (c *Context) Protocol() Protocol {
-	return Protocol(C.gpgme_get_protocol(c.ctx))
-}
-
-func (c *Context) SetKeyListMode(m KeyListMode) error {
-	return handleError(C.gpgme_set_keylist_mode(c.ctx, C.gpgme_keylist_mode_t(m)))
-}
-
-func (c *Context) KeyListMode() KeyListMode {
-	return KeyListMode(C.gpgme_get_keylist_mode(c.ctx))
-}
-
-// Unavailable in 1.3.2:
-// func (c *Context) SetPinEntryMode(m PinEntryMode) error {
-// 	return handleError(C.gpgme_set_pinentry_mode(c.ctx, C.gpgme_pinentry_mode_t(m)))
-// }
-
-// Unavailable in 1.3.2:
-// func (c *Context) PinEntryMode() PinEntryMode {
-// 	return PinEntryMode(C.gpgme_get_pinentry_mode(c.ctx))
-// }
-
-func (c *Context) SetCallback(callback Callback) error {
-	var err error
-	c.callback = callback
-	if c.cbc > 0 {
-		callbackDelete(c.cbc)
-	}
-	if callback != nil {
-		cbc := callbackAdd(c)
-		c.cbc = cbc
-		_, err = C.gogpgme_set_passphrase_cb(c.ctx, C.gpgme_passphrase_cb_t(C.gogpgme_passfunc), C.uintptr_t(cbc))
-	} else {
-		c.cbc = 0
-		_, err = C.gogpgme_set_passphrase_cb(c.ctx, nil, 0)
-	}
-	return err
-}
-
-func (c *Context) EngineInfo() *EngineInfo {
-	return &EngineInfo{info: C.gpgme_ctx_get_engine_info(c.ctx)}
-}
-
-func (c *Context) SetEngineInfo(proto Protocol, fileName, homeDir string) error {
-	var cfn, chome *C.char
-	if fileName != "" {
-		cfn = C.CString(fileName)
-		defer C.free(unsafe.Pointer(cfn))
-	}
-	if homeDir != "" {
-		chome = C.CString(homeDir)
-		defer C.free(unsafe.Pointer(chome))
-	}
-	return handleError(C.gpgme_ctx_set_engine_info(c.ctx, C.gpgme_protocol_t(proto), cfn, chome))
-}
-
-func (c *Context) KeyListStart(pattern string, secretOnly bool) error {
-	cpattern := C.CString(pattern)
-	defer C.free(unsafe.Pointer(cpattern))
-	err := C.gpgme_op_keylist_start(c.ctx, cpattern, cbool(secretOnly))
-	return handleError(err)
-}
-
-func (c *Context) KeyListNext() bool {
-	c.Key = newKey()
-	err := handleError(C.gpgme_op_keylist_next(c.ctx, &c.Key.k))
-	if err != nil {
-		if e, ok := err.(Error); ok && e.Code() == ErrorEOF {
-			c.KeyError = nil
-		} else {
-			c.KeyError = err
-		}
-		return false
-	}
-	c.KeyError = nil
-	return true
-}
-
-func (c *Context) KeyListEnd() error {
-	return handleError(C.gpgme_op_keylist_end(c.ctx))
-}
-
-func (c *Context) GetKey(fingerprint string, secret bool) (*Key, error) {
-	key := newKey()
-	cfpr := C.CString(fingerprint)
-	defer C.free(unsafe.Pointer(cfpr))
-	return key, handleError(C.gpgme_get_key(c.ctx, cfpr, &key.k, cbool(secret)))
-}
-
-func (c *Context) Decrypt(ciphertext, plaintext *Data) error {
-	return handleError(C.gpgme_op_decrypt(c.ctx, ciphertext.dh, plaintext.dh))
-}
-
-func (c *Context) DecryptVerify(ciphertext, plaintext *Data) error {
-	return handleError(C.gpgme_op_decrypt_verify(c.ctx, ciphertext.dh, plaintext.dh))
-}
-
-type Signature struct {
-	Summary        SigSum
-	Fingerprint    string
-	Status         error
-	Timestamp      time.Time
-	ExpTimestamp   time.Time
-	WrongKeyUsage  bool
-	PKATrust       uint
-	ChainModel     bool
-	Validity       Validity
-	ValidityReason error
-	PubkeyAlgo     PubkeyAlgo
-	HashAlgo       HashAlgo
-}
-
-func (c *Context) Verify(sig, signedText, plain *Data) (string, []Signature, error) {
-	var signedTextPtr, plainPtr C.gpgme_data_t = nil, nil
-	if signedText != nil {
-		signedTextPtr = signedText.dh
-	}
-	if plain != nil {
-		plainPtr = plain.dh
-	}
-	err := handleError(C.gpgme_op_verify(c.ctx, sig.dh, signedTextPtr, plainPtr))
-	if err != nil {
-		return "", nil, err
-	}
-	res := C.gpgme_op_verify_result(c.ctx)
-	sigs := []Signature{}
-	for s := res.signatures; s != nil; s = s.next {
-		sig := Signature{
-			Summary:     SigSum(s.summary),
-			Fingerprint: C.GoString(s.fpr),
-			Status:      handleError(s.status),
-			// s.notations not implemented
-			Timestamp:      time.Unix(int64(s.timestamp), 0),
-			ExpTimestamp:   time.Unix(int64(s.exp_timestamp), 0),
-			WrongKeyUsage:  C.signature_wrong_key_usage(s) != 0,
-			PKATrust:       uint(C.signature_pka_trust(s)),
-			ChainModel:     C.signature_chain_model(s) != 0,
-			Validity:       Validity(s.validity),
-			ValidityReason: handleError(s.validity_reason),
-			PubkeyAlgo:     PubkeyAlgo(s.pubkey_algo),
-			HashAlgo:       HashAlgo(s.hash_algo),
-		}
-		sigs = append(sigs, sig)
-	}
-	return C.GoString(res.file_name), sigs, nil
-}
-
-func (c *Context) Encrypt(recipients []*Key, flags EncryptFlag, plaintext, ciphertext *Data) error {
-	size := unsafe.Sizeof(new(C.gpgme_key_t))
-	recp := C.calloc(C.size_t(len(recipients)+1), C.size_t(size))
-	defer C.free(recp)
-	for i := range recipients {
-		ptr := (*C.gpgme_key_t)(unsafe.Pointer(uintptr(recp) + size*uintptr(i)))
-		*ptr = recipients[i].k
-	}
-	err := C.gpgme_op_encrypt(c.ctx, (*C.gpgme_key_t)(recp), C.gpgme_encrypt_flags_t(flags), plaintext.dh, ciphertext.dh)
-	return handleError(err)
-}
-
-func (c *Context) Sign(signers []*Key, plain, sig *Data, mode SigMode) error {
-	C.gpgme_signers_clear(c.ctx)
-	for _, k := range signers {
-		if err := handleError(C.gpgme_signers_add(c.ctx, k.k)); err != nil {
-			C.gpgme_signers_clear(c.ctx)
-			return err
-		}
-	}
-	return handleError(C.gpgme_op_sign(c.ctx, plain.dh, sig.dh, C.gpgme_sig_mode_t(mode)))
-}
-
-// ImportStatusFlags describes the type of ImportStatus.Status. The C API in gpgme.h simply uses "unsigned".
-type ImportStatusFlags uint
-
-const (
-	ImportNew    ImportStatusFlags = C.GPGME_IMPORT_NEW
-	ImportUID    ImportStatusFlags = C.GPGME_IMPORT_UID
-	ImportSIG    ImportStatusFlags = C.GPGME_IMPORT_SIG
-	ImportSubKey ImportStatusFlags = C.GPGME_IMPORT_SUBKEY
-	ImportSecret ImportStatusFlags = C.GPGME_IMPORT_SECRET
-)
-
-type ImportStatus struct {
-	Fingerprint string
-	Result      error
-	Status      ImportStatusFlags
-}
-
-type ImportResult struct {
-	Considered      int
-	NoUserID        int
-	Imported        int
-	ImportedRSA     int
-	Unchanged       int
-	NewUserIDs      int
-	NewSubKeys      int
-	NewSignatures   int
-	NewRevocations  int
-	SecretRead      int
-	SecretImported  int
-	SecretUnchanged int
-	NotImported     int
-	Imports         []ImportStatus
-}
-
-func (c *Context) Import(keyData *Data) (*ImportResult, error) {
-	err := handleError(C.gpgme_op_import(c.ctx, keyData.dh))
-	if err != nil {
-		return nil, err
-	}
-	res := C.gpgme_op_import_result(c.ctx)
-	imports := []ImportStatus{}
-	for s := res.imports; s != nil; s = s.next {
-		imports = append(imports, ImportStatus{
-			Fingerprint: C.GoString(s.fpr),
-			Result:      handleError(s.result),
-			Status:      ImportStatusFlags(s.status),
-		})
-	}
-	return &ImportResult{
-		Considered:      int(res.considered),
-		NoUserID:        int(res.no_user_id),
-		Imported:        int(res.imported),
-		ImportedRSA:     int(res.imported_rsa),
-		Unchanged:       int(res.unchanged),
-		NewUserIDs:      int(res.new_user_ids),
-		NewSubKeys:      int(res.new_sub_keys),
-		NewSignatures:   int(res.new_signatures),
-		NewRevocations:  int(res.new_revocations),
-		SecretRead:      int(res.secret_read),
-		SecretImported:  int(res.secret_imported),
-		SecretUnchanged: int(res.secret_unchanged),
-		NotImported:     int(res.not_imported),
-		Imports:         imports,
-	}, nil
-}
-
-type Key struct {
-	k C.gpgme_key_t
-}
-
-func newKey() *Key {
-	k := &Key{}
-	runtime.SetFinalizer(k, (*Key).Release)
-	return k
-}
-
-func (k *Key) Release() {
-	C.gpgme_key_release(k.k)
-	k.k = nil
-}
-
-func (k *Key) Revoked() bool {
-	return C.key_revoked(k.k) != 0
-}
-
-func (k *Key) Expired() bool {
-	return C.key_expired(k.k) != 0
-}
-
-func (k *Key) Disabled() bool {
-	return C.key_disabled(k.k) != 0
-}
-
-func (k *Key) Invalid() bool {
-	return C.key_invalid(k.k) != 0
-}
-
-func (k *Key) CanEncrypt() bool {
-	return C.key_can_encrypt(k.k) != 0
-}
-
-func (k *Key) CanSign() bool {
-	return C.key_can_sign(k.k) != 0
-}
-
-func (k *Key) CanCertify() bool {
-	return C.key_can_certify(k.k) != 0
-}
-
-func (k *Key) Secret() bool {
-	return C.key_secret(k.k) != 0
-}
-
-func (k *Key) CanAuthenticate() bool {
-	return C.key_can_authenticate(k.k) != 0
-}
-
-func (k *Key) IsQualified() bool {
-	return C.key_is_qualified(k.k) != 0
-}
-
-func (k *Key) Protocol() Protocol {
-	return Protocol(k.k.protocol)
-}
-
-func (k *Key) IssuerSerial() string {
-	return C.GoString(k.k.issuer_serial)
-}
-
-func (k *Key) IssuerName() string {
-	return C.GoString(k.k.issuer_name)
-}
-
-func (k *Key) ChainID() string {
-	return C.GoString(k.k.chain_id)
-}
-
-func (k *Key) OwnerTrust() Validity {
-	return Validity(k.k.owner_trust)
-}
-
-func (k *Key) SubKeys() *SubKey {
-	if k.k.subkeys == nil {
-		return nil
-	}
-	return &SubKey{k: k.k.subkeys, parent: k}
-}
-
-func (k *Key) UserIDs() *UserID {
-	if k.k.uids == nil {
-		return nil
-	}
-	return &UserID{u: k.k.uids, parent: k}
-}
-
-func (k *Key) KeyListMode() KeyListMode {
-	return KeyListMode(k.k.keylist_mode)
-}
-
-type SubKey struct {
-	k      C.gpgme_subkey_t
-	parent *Key // make sure the key is not released when we have a reference to a subkey
-}
-
-func (k *SubKey) Next() *SubKey {
-	if k.k.next == nil {
-		return nil
-	}
-	return &SubKey{k: k.k.next, parent: k.parent}
-}
-
-func (k *SubKey) Revoked() bool {
-	return C.subkey_revoked(k.k) != 0
-}
-
-func (k *SubKey) Expired() bool {
-	return C.subkey_expired(k.k) != 0
-}
-
-func (k *SubKey) Disabled() bool {
-	return C.subkey_disabled(k.k) != 0
-}
-
-func (k *SubKey) Invalid() bool {
-	return C.subkey_invalid(k.k) != 0
-}
-
-func (k *SubKey) Secret() bool {
-	return C.subkey_secret(k.k) != 0
-}
-
-func (k *SubKey) KeyID() string {
-	return C.GoString(k.k.keyid)
-}
-
-func (k *SubKey) Fingerprint() string {
-	return C.GoString(k.k.fpr)
-}
-
-func (k *SubKey) Created() time.Time {
-	if k.k.timestamp <= 0 {
-		return time.Time{}
-	}
-	return time.Unix(int64(k.k.timestamp), 0)
-}
-
-func (k *SubKey) Expires() time.Time {
-	if k.k.expires <= 0 {
-		return time.Time{}
-	}
-	return time.Unix(int64(k.k.expires), 0)
-}
-
-func (k *SubKey) CardNumber() string {
-	return C.GoString(k.k.card_number)
-}
-
-type UserID struct {
-	u      C.gpgme_user_id_t
-	parent *Key // make sure the key is not released when we have a reference to a user ID
-}
-
-func (u *UserID) Next() *UserID {
-	if u.u.next == nil {
-		return nil
-	}
-	return &UserID{u: u.u.next, parent: u.parent}
-}
-
-func (u *UserID) Revoked() bool {
-	return C.uid_revoked(u.u) != 0
-}
-
-func (u *UserID) Invalid() bool {
-	return C.uid_invalid(u.u) != 0
-}
-
-func (u *UserID) Validity() Validity {
-	return Validity(u.u.validity)
-}
-
-func (u *UserID) UID() string {
-	return C.GoString(u.u.uid)
-}
-
-func (u *UserID) Name() string {
-	return C.GoString(u.u.name)
-}
-
-func (u *UserID) Comment() string {
-	return C.GoString(u.u.comment)
-}
-
-func (u *UserID) Email() string {
-	return C.GoString(u.u.email)
-}
-
-// This is somewhat of a horrible hack. We need to unset GPG_AGENT_INFO so that gpgme does not pass --use-agent to GPG.
-// os.Unsetenv should be enough, but that only calls the underlying C library (which gpgme uses) if cgo is involved
-// - and cgo can't be used in tests. So, provide this helper for test initialization.
-func unsetenvGPGAgentInfo() {
-	v := C.CString("GPG_AGENT_INFO")
-	defer C.free(unsafe.Pointer(v))
-	C.unsetenv(v)
-}

From 2c7552e51215d4bf6982b0999df2d67d0bc0de9f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Miloslav=20Trma=C4=8D?= <mitr@redhat.com>
Date: Thu, 20 Feb 2020 16:41:57 +0100
Subject: [PATCH 2/2] Update to github.com/mtrmac/gpgme v0.1.2
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

This fixes CVE-2020-8945 by incorporating
https://github.com/proglottis/gpgme/pull/23 .

Other changes included by the rebase:
- Support for gpgme_off_t (~no-op with the RHEL 7 GPGME 1.3.2)
- Wrapping a few more GPGME functions (irrelevant if we don't call them)
- Better error reporting in Context.GetKey

Given how invasive the CVE fix is (affecting basically all binding
code), it seems safer to just update the package (and be verifiably
equivalent with upstream) than to backport and try to back out the few
other changes.

Performed by updating vendor.conf, and
$ mkdir -p _build/src/github.com/docker
$ ln -s $(pwd) _build/src/github.com/docker/docker
$ GOPATH=$(pwd)/_build:$GOPATH vndr github.com/mtrmac/gpgme

Signed-off-by: Miloslav Trmač <mitr@redhat.com>
---
 vendor.conf                                   |   2 +-
 vendor/github.com/mtrmac/gpgme/README.md      |  13 +
 vendor/github.com/mtrmac/gpgme/data.go        |  18 +-
 vendor/github.com/mtrmac/gpgme/go.mod         |   3 +
 vendor/github.com/mtrmac/gpgme/go_gpgme.c     |  22 ++
 vendor/github.com/mtrmac/gpgme/go_gpgme.h     |  12 +
 vendor/github.com/mtrmac/gpgme/gpgme.go       | 354 ++++++++++++++----
 .../mtrmac/gpgme/unset_agent_info.go          |  18 +
 .../mtrmac/gpgme/unset_agent_info_windows.go  |  14 +
 9 files changed, 378 insertions(+), 78 deletions(-)
 create mode 100644 vendor/github.com/mtrmac/gpgme/README.md
 create mode 100644 vendor/github.com/mtrmac/gpgme/go.mod
 create mode 100644 vendor/github.com/mtrmac/gpgme/unset_agent_info.go
 create mode 100644 vendor/github.com/mtrmac/gpgme/unset_agent_info_windows.go

diff --git a/vendor.conf b/vendor.conf
index d71bcac3ccec..4d4927b0d6f2 100644
--- a/vendor.conf
+++ b/vendor.conf
@@ -147,7 +147,7 @@ github.com/opencontainers/image-spec v1.0.0-rc4
 k8s.io/kubernetes 4a3f9c5b19c7ff804cbc1bf37a15c044ca5d2353 https://github.com/openshift/kubernetes
 github.com/golang/glog 44145f04b68cf362d9c4df2182967c2275eaefed
 github.com/ghodss/yaml 73d445a93680fa1a78ae23a5839bad48f32ba1ee
-github.com/mtrmac/gpgme master
+github.com/mtrmac/gpgme v0.1.2
 github.com/containers/storage master
 github.com/opencontainers/go-digest master
 
diff --git a/vendor/github.com/mtrmac/gpgme/README.md b/vendor/github.com/mtrmac/gpgme/README.md
new file mode 100644
index 000000000000..4770b82a8e61
--- /dev/null
+++ b/vendor/github.com/mtrmac/gpgme/README.md
@@ -0,0 +1,13 @@
+# GPGME (golang)
+
+Go wrapper for the GPGME library.
+
+This library is intended for use with desktop applications. If you are looking to add OpenPGP support to a server application I suggest you first look at [golang.org/x/crypto/openpgp](https://godoc.org/golang.org/x/crypto/openpgp).
+
+## Installation
+
+    go get -u github.com/proglottis/gpgme
+
+## Documentation
+
+* [godoc](https://godoc.org/github.com/proglottis/gpgme)
diff --git a/vendor/github.com/mtrmac/gpgme/data.go b/vendor/github.com/mtrmac/gpgme/data.go
index eebc9726347d..eee32c0323fc 100644
--- a/vendor/github.com/mtrmac/gpgme/data.go
+++ b/vendor/github.com/mtrmac/gpgme/data.go
@@ -50,25 +50,25 @@ func gogpgme_writefunc(handle, buffer unsafe.Pointer, size C.size_t) C.ssize_t {
 }
 
 //export gogpgme_seekfunc
-func gogpgme_seekfunc(handle unsafe.Pointer, offset C.off_t, whence C.int) C.off_t {
+func gogpgme_seekfunc(handle unsafe.Pointer, offset C.gpgme_off_t, whence C.int) C.gpgme_off_t {
 	d := callbackLookup(uintptr(handle)).(*Data)
 	n, err := d.s.Seek(int64(offset), int(whence))
 	if err != nil {
 		C.gpgme_err_set_errno(C.EIO)
 		return -1
 	}
-	return C.off_t(n)
+	return C.gpgme_off_t(n)
 }
 
 // The Data buffer used to communicate with GPGME
 type Data struct {
-	dh  C.gpgme_data_t
+	dh  C.gpgme_data_t // WARNING: Call runtime.KeepAlive(d) after ANY passing of d.dh to C
 	buf []byte
 	cbs C.struct_gpgme_data_cbs
 	r   io.Reader
 	w   io.Writer
 	s   io.Seeker
-	cbc uintptr
+	cbc uintptr // WARNING: Call runtime.KeepAlive(d) after ANY use of d.cbc in C (typically via d.dh)
 }
 
 func newData() *Data {
@@ -154,12 +154,14 @@ func (d *Data) Close() error {
 		callbackDelete(d.cbc)
 	}
 	_, err := C.gpgme_data_release(d.dh)
+	runtime.KeepAlive(d)
 	d.dh = nil
 	return err
 }
 
 func (d *Data) Write(p []byte) (int, error) {
 	n, err := C.gpgme_data_write(d.dh, unsafe.Pointer(&p[0]), C.size_t(len(p)))
+	runtime.KeepAlive(d)
 	if err != nil {
 		return 0, err
 	}
@@ -171,6 +173,7 @@ func (d *Data) Write(p []byte) (int, error) {
 
 func (d *Data) Read(p []byte) (int, error) {
 	n, err := C.gpgme_data_read(d.dh, unsafe.Pointer(&p[0]), C.size_t(len(p)))
+	runtime.KeepAlive(d)
 	if err != nil {
 		return 0, err
 	}
@@ -181,11 +184,14 @@ func (d *Data) Read(p []byte) (int, error) {
 }
 
 func (d *Data) Seek(offset int64, whence int) (int64, error) {
-	n, err := C.gpgme_data_seek(d.dh, C.off_t(offset), C.int(whence))
+	n, err := C.gogpgme_data_seek(d.dh, C.gpgme_off_t(offset), C.int(whence))
+	runtime.KeepAlive(d)
 	return int64(n), err
 }
 
 // Name returns the associated filename if any
 func (d *Data) Name() string {
-	return C.GoString(C.gpgme_data_get_file_name(d.dh))
+	res := C.GoString(C.gpgme_data_get_file_name(d.dh))
+	runtime.KeepAlive(d)
+	return res
 }
diff --git a/vendor/github.com/mtrmac/gpgme/go.mod b/vendor/github.com/mtrmac/gpgme/go.mod
new file mode 100644
index 000000000000..3dd09c9fbae5
--- /dev/null
+++ b/vendor/github.com/mtrmac/gpgme/go.mod
@@ -0,0 +1,3 @@
+module github.com/mtrmac/gpgme
+
+go 1.11
diff --git a/vendor/github.com/mtrmac/gpgme/go_gpgme.c b/vendor/github.com/mtrmac/gpgme/go_gpgme.c
index b887574e0cb9..00da3ab304f1 100644
--- a/vendor/github.com/mtrmac/gpgme/go_gpgme.c
+++ b/vendor/github.com/mtrmac/gpgme/go_gpgme.c
@@ -8,6 +8,28 @@ void gogpgme_set_passphrase_cb(gpgme_ctx_t ctx, gpgme_passphrase_cb_t cb, uintpt
 	gpgme_set_passphrase_cb(ctx, cb, (void *)handle);
 }
 
+gpgme_off_t gogpgme_data_seek(gpgme_data_t dh, gpgme_off_t offset, int whence) {
+	return gpgme_data_seek(dh, offset, whence);
+}
+
+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
+	){
+	return gpgme_op_assuan_transact_ext(
+		ctx,
+		cmd,
+		(gpgme_assuan_data_cb_t)    gogpgme_assuan_data_callback,    (void *)data_h,
+		(gpgme_assuan_inquire_cb_t) gogpgme_assuan_inquiry_callback, (void *)inquiry_h,
+		(gpgme_assuan_status_cb_t)  gogpgme_assuan_status_callback,  (void *)status_h,
+		operr
+	);
+}
+
 unsigned int key_revoked(gpgme_key_t k) {
 	return k->revoked;
 }
diff --git a/vendor/github.com/mtrmac/gpgme/go_gpgme.h b/vendor/github.com/mtrmac/gpgme/go_gpgme.h
index a3678b127ac7..d4826ab368eb 100644
--- a/vendor/github.com/mtrmac/gpgme/go_gpgme.h
+++ b/vendor/github.com/mtrmac/gpgme/go_gpgme.h
@@ -6,12 +6,24 @@
 
 #include <gpgme.h>
 
+/* GPGME_VERSION_NUMBER was introduced in 1.4.0 */
+#if !defined(GPGME_VERSION_NUMBER) || GPGME_VERSION_NUMBER < 0x010402
+typedef off_t gpgme_off_t; /* Introduced in 1.4.2 */
+#endif
+
 extern ssize_t gogpgme_readfunc(void *handle, void *buffer, size_t size);
 extern ssize_t gogpgme_writefunc(void *handle, void *buffer, size_t size);
 extern off_t gogpgme_seekfunc(void *handle, off_t offset, int whence);
 extern gpgme_error_t gogpgme_passfunc(void *hook, char *uid_hint, char *passphrase_info, int prev_was_bad, int fd);
 extern gpgme_error_t gogpgme_data_new_from_cbs(gpgme_data_t *dh, gpgme_data_cbs_t cbs, uintptr_t handle);
 extern void gogpgme_set_passphrase_cb(gpgme_ctx_t ctx, gpgme_passphrase_cb_t cb, uintptr_t handle);
+extern gpgme_off_t gogpgme_data_seek(gpgme_data_t dh, gpgme_off_t offset, int whence);
+
+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);
+
+extern gpgme_error_t gogpgme_assuan_data_callback(void *opaque, void* data, size_t datalen );
+extern gpgme_error_t gogpgme_assuan_inquiry_callback(void *opaque, char* name, char* args);
+extern gpgme_error_t gogpgme_assuan_status_callback(void *opaque, char* status, char* args);
 
 extern unsigned int key_revoked(gpgme_key_t k);
 extern unsigned int key_expired(gpgme_key_t k);
diff --git a/vendor/github.com/mtrmac/gpgme/gpgme.go b/vendor/github.com/mtrmac/gpgme/gpgme.go
index 5f1793eab32d..c19b9aebc5cd 100644
--- a/vendor/github.com/mtrmac/gpgme/gpgme.go
+++ b/vendor/github.com/mtrmac/gpgme/gpgme.go
@@ -7,8 +7,8 @@ package gpgme
 // #include <gpgme.h>
 // #include "go_gpgme.h"
 import "C"
-
 import (
+	"fmt"
 	"io"
 	"os"
 	"runtime"
@@ -47,9 +47,8 @@ const (
 	ProtocolAssuan   Protocol = C.GPGME_PROTOCOL_ASSUAN
 	ProtocolG13      Protocol = C.GPGME_PROTOCOL_G13
 	ProtocolUIServer Protocol = C.GPGME_PROTOCOL_UISERVER
-	// ProtocolSpawn    Protocol = C.GPGME_PROTOCOL_SPAWN // Unavailable in 1.4.3
-	ProtocolDefault Protocol = C.GPGME_PROTOCOL_DEFAULT
-	ProtocolUnknown Protocol = C.GPGME_PROTOCOL_UNKNOWN
+	ProtocolDefault  Protocol = C.GPGME_PROTOCOL_DEFAULT
+	ProtocolUnknown  Protocol = C.GPGME_PROTOCOL_UNKNOWN
 )
 
 type PinEntryMode int
@@ -69,7 +68,6 @@ const (
 	EncryptNoEncryptTo EncryptFlag = C.GPGME_ENCRYPT_NO_ENCRYPT_TO
 	EncryptPrepare     EncryptFlag = C.GPGME_ENCRYPT_PREPARE
 	EncryptExceptSign  EncryptFlag = C.GPGME_ENCRYPT_EXPECT_SIGN
-	// EncryptNoCompress  EncryptFlag = C.GPGME_ENCRYPT_NO_COMPRESS // Unavailable in 1.4.3
 )
 
 type HashAlgo int
@@ -83,7 +81,6 @@ const (
 	KeyListModeExtern       KeyListMode = C.GPGME_KEYLIST_MODE_EXTERN
 	KeyListModeSigs         KeyListMode = C.GPGME_KEYLIST_MODE_SIGS
 	KeyListModeSigNotations KeyListMode = C.GPGME_KEYLIST_MODE_SIG_NOTATIONS
-	// KeyListModeWithSecret   KeyListMode = C.GPGME_KEYLIST_MODE_WITH_SECRET // Unavailable in 1.4.3
 	KeyListModeEphemeral    KeyListMode = C.GPGME_KEYLIST_MODE_EPHEMERAL
 	KeyListModeModeValidate KeyListMode = C.GPGME_KEYLIST_MODE_VALIDATE
 )
@@ -167,39 +164,60 @@ func EngineCheckVersion(p Protocol) error {
 }
 
 type EngineInfo struct {
-	info C.gpgme_engine_info_t
+	next            *EngineInfo
+	protocol        Protocol
+	fileName        string
+	homeDir         string
+	version         string
+	requiredVersion string
 }
 
-func (e *EngineInfo) Next() *EngineInfo {
-	if e.info.next == nil {
-		return nil
+func copyEngineInfo(info C.gpgme_engine_info_t) *EngineInfo {
+	res := &EngineInfo{
+		next:            nil,
+		protocol:        Protocol(info.protocol),
+		fileName:        C.GoString(info.file_name),
+		homeDir:         C.GoString(info.home_dir),
+		version:         C.GoString(info.version),
+		requiredVersion: C.GoString(info.req_version),
+	}
+	if info.next != nil {
+		res.next = copyEngineInfo(info.next)
 	}
-	return &EngineInfo{info: e.info.next}
+	return res
+}
+
+func (e *EngineInfo) Next() *EngineInfo {
+	return e.next
 }
 
 func (e *EngineInfo) Protocol() Protocol {
-	return Protocol(e.info.protocol)
+	return e.protocol
 }
 
 func (e *EngineInfo) FileName() string {
-	return C.GoString(e.info.file_name)
+	return e.fileName
 }
 
 func (e *EngineInfo) Version() string {
-	return C.GoString(e.info.version)
+	return e.version
 }
 
 func (e *EngineInfo) RequiredVersion() string {
-	return C.GoString(e.info.req_version)
+	return e.requiredVersion
 }
 
 func (e *EngineInfo) HomeDir() string {
-	return C.GoString(e.info.home_dir)
+	return e.homeDir
 }
 
 func GetEngineInfo() (*EngineInfo, error) {
-	info := &EngineInfo{}
-	return info, handleError(C.gpgme_get_engine_info(&info.info))
+	var cInfo C.gpgme_engine_info_t
+	err := handleError(C.gpgme_get_engine_info(&cInfo))
+	if err != nil {
+		return nil, err
+	}
+	return copyEngineInfo(cInfo), nil // It is up to the caller not to invalidate cInfo concurrently until this is done.
 }
 
 func SetEngineInfo(proto Protocol, fileName, homeDir string) error {
@@ -260,9 +278,9 @@ type Context struct {
 	KeyError error
 
 	callback Callback
-	cbc      uintptr
+	cbc      uintptr // WARNING: Call runtime.KeepAlive(c) after ANY use of c.cbc in C (typically via c.ctx)
 
-	ctx C.gpgme_ctx_t
+	ctx C.gpgme_ctx_t // WARNING: Call runtime.KeepAlive(c) after ANY passing of c.ctx to C
 }
 
 func New() (*Context, error) {
@@ -280,49 +298,68 @@ func (c *Context) Release() {
 		callbackDelete(c.cbc)
 	}
 	C.gpgme_release(c.ctx)
+	runtime.KeepAlive(c)
 	c.ctx = nil
 }
 
 func (c *Context) SetArmor(yes bool) {
 	C.gpgme_set_armor(c.ctx, cbool(yes))
+	runtime.KeepAlive(c)
 }
 
 func (c *Context) Armor() bool {
-	return C.gpgme_get_armor(c.ctx) != 0
+	res := C.gpgme_get_armor(c.ctx) != 0
+	runtime.KeepAlive(c)
+	return res
 }
 
 func (c *Context) SetTextMode(yes bool) {
 	C.gpgme_set_textmode(c.ctx, cbool(yes))
+	runtime.KeepAlive(c)
 }
 
 func (c *Context) TextMode() bool {
-	return C.gpgme_get_textmode(c.ctx) != 0
+	res := C.gpgme_get_textmode(c.ctx) != 0
+	runtime.KeepAlive(c)
+	return res
 }
 
 func (c *Context) SetProtocol(p Protocol) error {
-	return handleError(C.gpgme_set_protocol(c.ctx, C.gpgme_protocol_t(p)))
+	err := handleError(C.gpgme_set_protocol(c.ctx, C.gpgme_protocol_t(p)))
+	runtime.KeepAlive(c)
+	return err
 }
 
 func (c *Context) Protocol() Protocol {
-	return Protocol(C.gpgme_get_protocol(c.ctx))
+	res := Protocol(C.gpgme_get_protocol(c.ctx))
+	runtime.KeepAlive(c)
+	return res
 }
 
 func (c *Context) SetKeyListMode(m KeyListMode) error {
-	return handleError(C.gpgme_set_keylist_mode(c.ctx, C.gpgme_keylist_mode_t(m)))
+	err := handleError(C.gpgme_set_keylist_mode(c.ctx, C.gpgme_keylist_mode_t(m)))
+	runtime.KeepAlive(c)
+	return err
 }
 
 func (c *Context) KeyListMode() KeyListMode {
-	return KeyListMode(C.gpgme_get_keylist_mode(c.ctx))
+	res := KeyListMode(C.gpgme_get_keylist_mode(c.ctx))
+	runtime.KeepAlive(c)
+	return res
 }
 
 // Unavailable in 1.3.2:
 // func (c *Context) SetPinEntryMode(m PinEntryMode) error {
-// 	return handleError(C.gpgme_set_pinentry_mode(c.ctx, C.gpgme_pinentry_mode_t(m)))
+// 	err := handleError(C.gpgme_set_pinentry_mode(c.ctx, C.gpgme_pinentry_mode_t(m)))
+// 	runtime.KeepAlive(c)
+// 	return err
 // }
 
 // Unavailable in 1.3.2:
 // func (c *Context) PinEntryMode() PinEntryMode {
-// 	return PinEntryMode(C.gpgme_get_pinentry_mode(c.ctx))
+// 	res := PinEntryMode(C.gpgme_get_pinentry_mode(c.ctx))
+// 	runtime.KeepAlive(c)
+// 	return res
 // }
 
 func (c *Context) SetCallback(callback Callback) error {
@@ -339,11 +376,17 @@ func (c *Context) SetCallback(callback Callback) error {
 		c.cbc = 0
 		_, err = C.gogpgme_set_passphrase_cb(c.ctx, nil, 0)
 	}
+	runtime.KeepAlive(c)
 	return err
 }
 
 func (c *Context) EngineInfo() *EngineInfo {
-	return &EngineInfo{info: C.gpgme_ctx_get_engine_info(c.ctx)}
+	cInfo := C.gpgme_ctx_get_engine_info(c.ctx)
+	runtime.KeepAlive(c)
+	// NOTE: c must be live as long as we are accessing cInfo.
+	res := copyEngineInfo(cInfo)
+	runtime.KeepAlive(c) // for accesses to cInfo
+	return res
 }
 
 func (c *Context) SetEngineInfo(proto Protocol, fileName, homeDir string) error {
@@ -356,19 +399,23 @@ func (c *Context) SetEngineInfo(proto Protocol, fileName, homeDir string) error
 		chome = C.CString(homeDir)
 		defer C.free(unsafe.Pointer(chome))
 	}
-	return handleError(C.gpgme_ctx_set_engine_info(c.ctx, C.gpgme_protocol_t(proto), cfn, chome))
+	err := handleError(C.gpgme_ctx_set_engine_info(c.ctx, C.gpgme_protocol_t(proto), cfn, chome))
+	runtime.KeepAlive(c)
+	return err
 }
 
 func (c *Context) KeyListStart(pattern string, secretOnly bool) error {
 	cpattern := C.CString(pattern)
 	defer C.free(unsafe.Pointer(cpattern))
-	err := C.gpgme_op_keylist_start(c.ctx, cpattern, cbool(secretOnly))
-	return handleError(err)
+	err := handleError(C.gpgme_op_keylist_start(c.ctx, cpattern, cbool(secretOnly)))
+	runtime.KeepAlive(c)
+	return err
 }
 
 func (c *Context) KeyListNext() bool {
 	c.Key = newKey()
 	err := handleError(C.gpgme_op_keylist_next(c.ctx, &c.Key.k))
+	runtime.KeepAlive(c) // implies runtime.KeepAlive(c.Key)
 	if err != nil {
 		if e, ok := err.(Error); ok && e.Code() == ErrorEOF {
 			c.KeyError = nil
@@ -382,22 +429,43 @@ func (c *Context) KeyListNext() bool {
 }
 
 func (c *Context) KeyListEnd() error {
-	return handleError(C.gpgme_op_keylist_end(c.ctx))
+	err := handleError(C.gpgme_op_keylist_end(c.ctx))
+	runtime.KeepAlive(c)
+	return err
 }
 
 func (c *Context) GetKey(fingerprint string, secret bool) (*Key, error) {
 	key := newKey()
 	cfpr := C.CString(fingerprint)
 	defer C.free(unsafe.Pointer(cfpr))
-	return key, handleError(C.gpgme_get_key(c.ctx, cfpr, &key.k, cbool(secret)))
+	err := handleError(C.gpgme_get_key(c.ctx, cfpr, &key.k, cbool(secret)))
+	runtime.KeepAlive(c)
+	runtime.KeepAlive(key)
+	keyKIsNil := key.k == nil
+	runtime.KeepAlive(key)
+	if e, ok := err.(Error); keyKIsNil && ok && e.Code() == ErrorEOF {
+		return nil, fmt.Errorf("key %q not found", fingerprint)
+	}
+	if err != nil {
+		return nil, err
+	}
+	return key, nil
 }
 
 func (c *Context) Decrypt(ciphertext, plaintext *Data) error {
-	return handleError(C.gpgme_op_decrypt(c.ctx, ciphertext.dh, plaintext.dh))
+	err := handleError(C.gpgme_op_decrypt(c.ctx, ciphertext.dh, plaintext.dh))
+	runtime.KeepAlive(c)
+	runtime.KeepAlive(ciphertext)
+	runtime.KeepAlive(plaintext)
+	return err
 }
 
 func (c *Context) DecryptVerify(ciphertext, plaintext *Data) error {
-	return handleError(C.gpgme_op_decrypt_verify(c.ctx, ciphertext.dh, plaintext.dh))
+	err := handleError(C.gpgme_op_decrypt_verify(c.ctx, ciphertext.dh, plaintext.dh))
+	runtime.KeepAlive(c)
+	runtime.KeepAlive(ciphertext)
+	runtime.KeepAlive(plaintext)
+	return err
 }
 
 type Signature struct {
@@ -424,10 +492,20 @@ func (c *Context) Verify(sig, signedText, plain *Data) (string, []Signature, err
 		plainPtr = plain.dh
 	}
 	err := handleError(C.gpgme_op_verify(c.ctx, sig.dh, signedTextPtr, plainPtr))
+	runtime.KeepAlive(c)
+	runtime.KeepAlive(sig)
+	if signedText != nil {
+		runtime.KeepAlive(signedText)
+	}
+	if plain != nil {
+		runtime.KeepAlive(plain)
+	}
 	if err != nil {
 		return "", nil, err
 	}
 	res := C.gpgme_op_verify_result(c.ctx)
+	runtime.KeepAlive(c)
+	// NOTE: c must be live as long as we are accessing res.
 	sigs := []Signature{}
 	for s := res.signatures; s != nil; s = s.next {
 		sig := Signature{
@@ -447,7 +525,9 @@ func (c *Context) Verify(sig, signedText, plain *Data) (string, []Signature, err
 		}
 		sigs = append(sigs, sig)
 	}
-	return C.GoString(res.file_name), sigs, nil
+	fileName := C.GoString(res.file_name)
+	runtime.KeepAlive(c) // for all accesses to res above
+	return fileName, sigs, nil
 }
 
 func (c *Context) Encrypt(recipients []*Key, flags EncryptFlag, plaintext, ciphertext *Data) error {
@@ -459,18 +539,116 @@ func (c *Context) Encrypt(recipients []*Key, flags EncryptFlag, plaintext, ciphe
 		*ptr = recipients[i].k
 	}
 	err := C.gpgme_op_encrypt(c.ctx, (*C.gpgme_key_t)(recp), C.gpgme_encrypt_flags_t(flags), plaintext.dh, ciphertext.dh)
+	runtime.KeepAlive(c)
+	runtime.KeepAlive(recipients)
+	runtime.KeepAlive(plaintext)
+	runtime.KeepAlive(ciphertext)
 	return handleError(err)
 }
 
 func (c *Context) Sign(signers []*Key, plain, sig *Data, mode SigMode) error {
 	C.gpgme_signers_clear(c.ctx)
+	runtime.KeepAlive(c)
 	for _, k := range signers {
-		if err := handleError(C.gpgme_signers_add(c.ctx, k.k)); err != nil {
+		err := handleError(C.gpgme_signers_add(c.ctx, k.k))
+		runtime.KeepAlive(c)
+		runtime.KeepAlive(k)
+		if err != nil {
 			C.gpgme_signers_clear(c.ctx)
+			runtime.KeepAlive(c)
 			return err
 		}
 	}
-	return handleError(C.gpgme_op_sign(c.ctx, plain.dh, sig.dh, C.gpgme_sig_mode_t(mode)))
+	err := handleError(C.gpgme_op_sign(c.ctx, plain.dh, sig.dh, C.gpgme_sig_mode_t(mode)))
+	runtime.KeepAlive(c)
+	runtime.KeepAlive(plain)
+	runtime.KeepAlive(sig)
+	return err
+}
+
+type AssuanDataCallback func(data []byte) error
+type AssuanInquireCallback func(name, args string) error
+type AssuanStatusCallback func(status, args string) error
+
+// AssuanSend sends a raw Assuan command to gpg-agent
+func (c *Context) AssuanSend(
+	cmd string,
+	data AssuanDataCallback,
+	inquiry AssuanInquireCallback,
+	status AssuanStatusCallback,
+) error {
+	var operr C.gpgme_error_t
+
+	dataPtr := callbackAdd(&data)
+	inquiryPtr := callbackAdd(&inquiry)
+	statusPtr := callbackAdd(&status)
+	cmdCStr := C.CString(cmd)
+	defer C.free(unsafe.Pointer(cmdCStr))
+	err := C.gogpgme_op_assuan_transact_ext(
+		c.ctx,
+		cmdCStr,
+		C.uintptr_t(dataPtr),
+		C.uintptr_t(inquiryPtr),
+		C.uintptr_t(statusPtr),
+		&operr,
+	)
+	runtime.KeepAlive(c)
+
+	if handleError(operr) != nil {
+		return handleError(operr)
+	}
+	return handleError(err)
+}
+
+//export gogpgme_assuan_data_callback
+func gogpgme_assuan_data_callback(handle unsafe.Pointer, data unsafe.Pointer, datalen C.size_t) C.gpgme_error_t {
+	c := callbackLookup(uintptr(handle)).(*AssuanDataCallback)
+	if *c == nil {
+		return 0
+	}
+	(*c)(C.GoBytes(data, C.int(datalen)))
+	return 0
+}
+
+//export gogpgme_assuan_inquiry_callback
+func gogpgme_assuan_inquiry_callback(handle unsafe.Pointer, cName *C.char, cArgs *C.char) C.gpgme_error_t {
+	name := C.GoString(cName)
+	args := C.GoString(cArgs)
+	c := callbackLookup(uintptr(handle)).(*AssuanInquireCallback)
+	if *c == nil {
+		return 0
+	}
+	(*c)(name, args)
+	return 0
+}
+
+//export gogpgme_assuan_status_callback
+func gogpgme_assuan_status_callback(handle unsafe.Pointer, cStatus *C.char, cArgs *C.char) C.gpgme_error_t {
+	status := C.GoString(cStatus)
+	args := C.GoString(cArgs)
+	c := callbackLookup(uintptr(handle)).(*AssuanStatusCallback)
+	if *c == nil {
+		return 0
+	}
+	(*c)(status, args)
+	return 0
+}
+
+// ExportModeFlags defines how keys are exported from Export
+type ExportModeFlags uint
+
+const (
+	ExportModeExtern  ExportModeFlags = C.GPGME_EXPORT_MODE_EXTERN
+	ExportModeMinimal ExportModeFlags = C.GPGME_EXPORT_MODE_MINIMAL
+)
+
+func (c *Context) Export(pattern string, mode ExportModeFlags, data *Data) error {
+	pat := C.CString(pattern)
+	defer C.free(unsafe.Pointer(pat))
+	err := handleError(C.gpgme_op_export(c.ctx, pat, C.gpgme_export_mode_t(mode), data.dh))
+	runtime.KeepAlive(c)
+	runtime.KeepAlive(data)
+	return err
 }
 
 // ImportStatusFlags describes the type of ImportStatus.Status. The C API in gpgme.h simply uses "unsigned".
@@ -509,10 +687,14 @@ type ImportResult struct {
 
 func (c *Context) Import(keyData *Data) (*ImportResult, error) {
 	err := handleError(C.gpgme_op_import(c.ctx, keyData.dh))
+	runtime.KeepAlive(c)
+	runtime.KeepAlive(keyData)
 	if err != nil {
 		return nil, err
 	}
 	res := C.gpgme_op_import_result(c.ctx)
+	runtime.KeepAlive(c)
+	// NOTE: c must be live as long as we are accessing res.
 	imports := []ImportStatus{}
 	for s := res.imports; s != nil; s = s.next {
 		imports = append(imports, ImportStatus{
@@ -521,7 +703,7 @@ func (c *Context) Import(keyData *Data) (*ImportResult, error) {
 			Status:      ImportStatusFlags(s.status),
 		})
 	}
-	return &ImportResult{
+	importResult := &ImportResult{
 		Considered:      int(res.considered),
 		NoUserID:        int(res.no_user_id),
 		Imported:        int(res.imported),
@@ -536,11 +718,13 @@ func (c *Context) Import(keyData *Data) (*ImportResult, error) {
 		SecretUnchanged: int(res.secret_unchanged),
 		NotImported:     int(res.not_imported),
 		Imports:         imports,
-	}, nil
+	}
+	runtime.KeepAlive(c) // for all accesses to res above
+	return importResult, nil
 }
 
 type Key struct {
-	k C.gpgme_key_t
+	k C.gpgme_key_t // WARNING: Call Runtime.KeepAlive(k) after ANY passing of k.k to C
 }
 
 func newKey() *Key {
@@ -551,85 +735,122 @@ func newKey() *Key {
 
 func (k *Key) Release() {
 	C.gpgme_key_release(k.k)
+	runtime.KeepAlive(k)
 	k.k = nil
 }
 
 func (k *Key) Revoked() bool {
-	return C.key_revoked(k.k) != 0
+	res := C.key_revoked(k.k) != 0
+	runtime.KeepAlive(k)
+	return res
 }
 
 func (k *Key) Expired() bool {
-	return C.key_expired(k.k) != 0
+	res := C.key_expired(k.k) != 0
+	runtime.KeepAlive(k)
+	return res
 }
 
 func (k *Key) Disabled() bool {
-	return C.key_disabled(k.k) != 0
+	res := C.key_disabled(k.k) != 0
+	runtime.KeepAlive(k)
+	return res
 }
 
 func (k *Key) Invalid() bool {
-	return C.key_invalid(k.k) != 0
+	res := C.key_invalid(k.k) != 0
+	runtime.KeepAlive(k)
+	return res
 }
 
 func (k *Key) CanEncrypt() bool {
-	return C.key_can_encrypt(k.k) != 0
+	res := C.key_can_encrypt(k.k) != 0
+	runtime.KeepAlive(k)
+	return res
 }
 
 func (k *Key) CanSign() bool {
-	return C.key_can_sign(k.k) != 0
+	res := C.key_can_sign(k.k) != 0
+	runtime.KeepAlive(k)
+	return res
 }
 
 func (k *Key) CanCertify() bool {
-	return C.key_can_certify(k.k) != 0
+	res := C.key_can_certify(k.k) != 0
+	runtime.KeepAlive(k)
+	return res
 }
 
 func (k *Key) Secret() bool {
-	return C.key_secret(k.k) != 0
+	res := C.key_secret(k.k) != 0
+	runtime.KeepAlive(k)
+	return res
 }
 
 func (k *Key) CanAuthenticate() bool {
-	return C.key_can_authenticate(k.k) != 0
+	res := C.key_can_authenticate(k.k) != 0
+	runtime.KeepAlive(k)
+	return res
 }
 
 func (k *Key) IsQualified() bool {
-	return C.key_is_qualified(k.k) != 0
+	res := C.key_is_qualified(k.k) != 0
+	runtime.KeepAlive(k)
+	return res
 }
 
 func (k *Key) Protocol() Protocol {
-	return Protocol(k.k.protocol)
+	res := Protocol(k.k.protocol)
+	runtime.KeepAlive(k)
+	return res
 }
 
 func (k *Key) IssuerSerial() string {
-	return C.GoString(k.k.issuer_serial)
+	res := C.GoString(k.k.issuer_serial)
+	runtime.KeepAlive(k)
+	return res
 }
 
 func (k *Key) IssuerName() string {
-	return C.GoString(k.k.issuer_name)
+	res := C.GoString(k.k.issuer_name)
+	runtime.KeepAlive(k)
+	return res
 }
 
 func (k *Key) ChainID() string {
-	return C.GoString(k.k.chain_id)
+	res := C.GoString(k.k.chain_id)
+	runtime.KeepAlive(k)
+	return res
 }
 
 func (k *Key) OwnerTrust() Validity {
-	return Validity(k.k.owner_trust)
+	res := Validity(k.k.owner_trust)
+	runtime.KeepAlive(k)
+	return res
 }
 
 func (k *Key) SubKeys() *SubKey {
-	if k.k.subkeys == nil {
+	subKeys := k.k.subkeys
+	runtime.KeepAlive(k)
+	if subKeys == nil {
 		return nil
 	}
-	return &SubKey{k: k.k.subkeys, parent: k}
+	return &SubKey{k: subKeys, parent: k} // The parent: k reference ensures subKeys remains valid
 }
 
 func (k *Key) UserIDs() *UserID {
-	if k.k.uids == nil {
+	uids := k.k.uids
+	runtime.KeepAlive(k)
+	if uids == nil {
 		return nil
 	}
-	return &UserID{u: k.k.uids, parent: k}
+	return &UserID{u: uids, parent: k} // The parent: k reference ensures uids remains valid
 }
 
 func (k *Key) KeyListMode() KeyListMode {
-	return KeyListMode(k.k.keylist_mode)
+	res := KeyListMode(k.k.keylist_mode)
+	runtime.KeepAlive(k)
+	return res
 }
 
 type SubKey struct {
@@ -729,12 +950,3 @@ func (u *UserID) Comment() string {
 func (u *UserID) Email() string {
 	return C.GoString(u.u.email)
 }
-
-// This is somewhat of a horrible hack. We need to unset GPG_AGENT_INFO so that gpgme does not pass --use-agent to GPG.
-// os.Unsetenv should be enough, but that only calls the underlying C library (which gpgme uses) if cgo is involved
-// - and cgo can't be used in tests. So, provide this helper for test initialization.
-func unsetenvGPGAgentInfo() {
-	v := C.CString("GPG_AGENT_INFO")
-	defer C.free(unsafe.Pointer(v))
-	C.unsetenv(v)
-}
diff --git a/vendor/github.com/mtrmac/gpgme/unset_agent_info.go b/vendor/github.com/mtrmac/gpgme/unset_agent_info.go
new file mode 100644
index 000000000000..986aca59f67b
--- /dev/null
+++ b/vendor/github.com/mtrmac/gpgme/unset_agent_info.go
@@ -0,0 +1,18 @@
+// +build !windows
+
+package gpgme
+
+// #include <stdlib.h>
+import "C"
+import (
+	"unsafe"
+)
+
+// This is somewhat of a horrible hack. We need to unset GPG_AGENT_INFO so that gpgme does not pass --use-agent to GPG.
+// os.Unsetenv should be enough, but that only calls the underlying C library (which gpgme uses) if cgo is involved
+// - and cgo can't be used in tests. So, provide this helper for test initialization.
+func unsetenvGPGAgentInfo() {
+	v := C.CString("GPG_AGENT_INFO")
+	defer C.free(unsafe.Pointer(v))
+	C.unsetenv(v)
+}
diff --git a/vendor/github.com/mtrmac/gpgme/unset_agent_info_windows.go b/vendor/github.com/mtrmac/gpgme/unset_agent_info_windows.go
new file mode 100644
index 000000000000..431ec86d3c24
--- /dev/null
+++ b/vendor/github.com/mtrmac/gpgme/unset_agent_info_windows.go
@@ -0,0 +1,14 @@
+package gpgme
+
+// #include <stdlib.h>
+import "C"
+import (
+	"unsafe"
+)
+
+// unsetenv is not available in mingw
+func unsetenvGPGAgentInfo() {
+	v := C.CString("GPG_AGENT_INFO=")
+	defer C.free(unsafe.Pointer(v))
+	C.putenv(v)
+}