public void Add(Key signer)
            {
                if (ctx.IsValid)
                {
                    if (signer == null)
                    {
                        throw new ArgumentNullException("A signer key must be supplied.");
                    }
                    if (signer.KeyPtr.Equals(IntPtr.Zero))
                    {
                        throw new InvalidKeyException("An invalid signer key has been supplied.");
                    }

                    lock (ctx.CtxLock)
                    {
                        int            err     = libgpgme.gpgme_signers_add(ctx.CtxPtr, signer.KeyPtr);
                        gpg_err_code_t errcode = libgpgerror.gpg_err_code(err);
                        if (errcode != gpg_err_code_t.GPG_ERR_NO_ERROR)
                        {
                            throw new GeneralErrorException("An unexpected error occurred. Error: " + errcode.ToString());
                        }
                    }
                }
                else
                {
                    throw new InvalidContextException();
                }
            }
 internal static int gpg_err_make(gpg_err_source_t source, gpg_err_code_t code)
 {
     return code == gpg_err_code_t.GPG_ERR_NO_ERROR
         ? (int)gpg_err_code_t.GPG_ERR_NO_ERROR
         : ((((int)source & (int)Masks.GPG_ERR_SOURCE_MASK) << (int)Masks.GPG_ERR_SOURCE_SHIFT)
         | ((int)code & (int)Masks.GPG_ERR_CODE_MASK));
 }
        public Context()
        {
            IntPtr ptr;
            int    err;

            err = libgpgme.gpgme_new(out ptr);
            gpg_err_code_t errcode = libgpgme.gpgme_err_code(err);

            switch (errcode)
            {
            case gpg_err_code_t.GPG_ERR_NO_ERROR:
                this.ctxPtr   = ptr;
                this.signers  = new ContextSigners(this);
                this.signots  = new ContextSignatureNotations(this);
                this.keystore = new KeyStore(this);
                break;

            case gpg_err_code_t.GPG_ERR_INV_VALUE:
                throw new InvalidPtrException("CTX is not a valid pointer.\nBad programmer *spank* *spank*");

            case gpg_err_code_t.GPG_ERR_ENOMEM:
                throw new OutOfMemoryException();

            default:
                throw new GeneralErrorException("An unexpected error occurred during context creation. " + errcode.ToString());
            }
        }
Example #4
0
        /// <summary>
        /// Initializes the Context
        /// </summary>
        private void Initialize(ref ContextSigners signers, ref ContextSignatureNotations signots, ref KeyStore keystore)
        {
            IntPtr ptr;

            var            err     = libgpgme.NativeMethods.gpgme_new(out ptr);
            gpg_err_code_t errcode = libgpgme.gpgme_err_code(err);

            switch (errcode)
            {
            case gpg_err_code_t.GPG_ERR_NO_ERROR:
                CtxPtr   = ptr;
                signers  = new ContextSigners(this);
                signots  = new ContextSignatureNotations(this);
                keystore = new KeyStore(this);
                break;

            case gpg_err_code_t.GPG_ERR_INV_VALUE:
                throw new InvalidPtrException("CTX is not a valid pointer.\nBad programmer *spank* *spank*");

            case gpg_err_code_t.GPG_ERR_ENOMEM:
                throw new OutOfMemoryException();

            default:
                throw new GeneralErrorException("An unexpected error occurred during context creation. " +
                                                errcode.ToString());
            }
        }
        private gpg_err_code_t GetKey(string fpr, int secret, out IntPtr rkeyPtr)
        {
            // the fingerprint could be a UTF8 encoded name
            IntPtr fprPtr = Gpgme.StringToCoTaskMemUTF8(fpr);

            int err = libgpgme.gpgme_get_key(ctx.CtxPtr, fprPtr, out rkeyPtr, secret);

            // free memory
            if (fprPtr != IntPtr.Zero)
            {
                Marshal.FreeCoTaskMem(fprPtr);
                fprPtr = IntPtr.Zero;
            }

            gpg_err_code_t errcode = libgpgme.gpgme_err_code(err);

            switch (errcode)
            {
            case gpg_err_code_t.GPG_ERR_INV_VALUE:
                throw new ArgumentException("Invalid key fingerprint has been given. Error: " + err.ToString());

            case gpg_err_code_t.GPG_ERR_AMBIGUOUS_NAME:
                throw new AmbiguousKeyException("The key id was not unique. Error: " + err.ToString());

            case gpg_err_code_t.GPG_ERR_ENOMEM:
                throw new OutOfMemoryException("Not enough memory available for this operation.");

            case gpg_err_code_t.GPG_ERR_EOF:
                throw new KeyNotFoundException("The key " + fpr + " (secret=" + secret + ") could not be found in the keyring.");
            }
            return(errcode);
        }
        public ImportResult Import(GpgmeData keydata)
        {
            if (ctx == null ||
                !(ctx.IsValid))
            {
                throw new InvalidContextException();
            }

            if (keydata == null)
            {
                throw new ArgumentNullException("An invalid data buffer has been specified.",
                                                new InvalidDataBufferException());
            }

            if (!(keydata.IsValid))
            {
                throw new InvalidDataBufferException();
            }

            lock (ctx.CtxLock)
            {
                int            err     = libgpgme.gpgme_op_import(ctx.CtxPtr, keydata.dataPtr);
                gpg_err_code_t errcode = libgpgerror.gpg_err_code(err);

                if (errcode != gpg_err_code_t.GPG_ERR_NO_ERROR)
                {
                    throw new KeyImportException("Error " + errcode, err);
                }

                IntPtr result = libgpgme.gpgme_op_import_result(ctx.CtxPtr);
                return(new ImportResult(result));
            }
        }
Example #7
0
 internal static int gpg_err_make(gpg_err_source_t source, gpg_err_code_t code)
 {
     return(code == gpg_err_code_t.GPG_ERR_NO_ERROR
         ? (int)gpg_err_code_t.GPG_ERR_NO_ERROR
         : ((((int)source & (int)Masks.GPG_ERR_SOURCE_MASK) << (int)Masks.GPG_ERR_SOURCE_SHIFT)
            | ((int)code & (int)Masks.GPG_ERR_CODE_MASK)));
 }
        public void Export(string[] pattern, GpgmeData keydata)
        {
            if (ctx == null ||
                !(ctx.IsValid))
            {
                throw new InvalidContextException();
            }

            if (keydata == null)
            {
                throw new ArgumentNullException("Invalid data buffer",
                                                new InvalidDataBufferException());
            }

            if (!(keydata.IsValid))
            {
                throw new InvalidDataBufferException();
            }

            IntPtr[] parray = null;
            if (pattern != null)
            {
                parray = Gpgme.StringToCoTaskMemUTF8(pattern);
            }

            int  err;
            uint reserved = 0;

            lock (ctx.CtxLock)
            {
                if (parray != null)
                {
                    err = libgpgme.gpgme_op_export_ext(
                        ctx.CtxPtr,
                        parray,
                        reserved,
                        keydata.dataPtr);
                }
                else
                {
                    err = libgpgme.gpgme_op_export(
                        ctx.CtxPtr,
                        IntPtr.Zero,
                        reserved,
                        keydata.dataPtr);
                }
            }

            GC.KeepAlive(keydata);

            // Free memory
            Gpgme.FreeStringArray(parray);

            gpg_err_code_t errcode = libgpgerror.gpg_err_code(err);

            if (errcode != gpg_err_code_t.GPG_ERR_NO_ERROR)
            {
                throw new KeyExportException("Error " + errcode, err);
            }
        }
        public void SetEngineInfo(Protocol proto, string filename, string homedir)
        {
            if (IsValid)
            {
                lock (CtxLock)
                {
                    IntPtr filenamePtr = IntPtr.Zero, homedirPtr = IntPtr.Zero;

                    if (filename != null)
                    {
                        filenamePtr = Marshal.StringToCoTaskMemAnsi(filename);
                    }
                    if (homedir != null)
                    {
                        homedirPtr = Marshal.StringToCoTaskMemAnsi(homedir);
                    }

                    int err = libgpgme.gpgme_ctx_set_engine_info(
                        CtxPtr,
                        (gpgme_protocol_t)proto,
                        filenamePtr,
                        homedirPtr);

                    if (filenamePtr != IntPtr.Zero)
                    {
                        Marshal.FreeCoTaskMem(filenamePtr);
                        filenamePtr = IntPtr.Zero;
                    }
                    if (homedirPtr != IntPtr.Zero)
                    {
                        Marshal.FreeCoTaskMem(homedirPtr);
                        homedirPtr = IntPtr.Zero;
                    }

                    gpg_err_code_t errcode = libgpgme.gpgme_err_code(err);
                    if (errcode != gpg_err_code_t.GPG_ERR_NO_ERROR)
                    {
                        string errmsg = null;
                        try
                        {
                            Gpgme.GetStrError(err, out errmsg);
                        }
                        catch
                        {
                            errmsg = "No error message available.";
                        }
                        throw new ArgumentException(errmsg + " Error: " + err.ToString());
                    }
                }
            }
            else
            {
                throw new InvalidContextException();
            }
        }
Example #10
0
        public SignatureResult Sign(GpgmeData plain, GpgmeData sig, SignatureMode mode)
        {
            EnsureValid();
            if (plain == null)
            {
                throw new ArgumentNullException(nameof(plain), "Source data buffer must be supplied.");
            }
            if (!(plain.IsValid))
            {
                throw new InvalidDataBufferException("The specified source data buffer is invalid.");
            }

            if (sig == null)
            {
                throw new ArgumentNullException(nameof(sig), "Destination data buffer must be supplied.");
            }
            if (!(sig.IsValid))
            {
                throw new InvalidDataBufferException("The specified destination data buffer is invalid.");
            }

            lock (CtxLock) {
                int err = libgpgme.NativeMethods.gpgme_op_sign(
                    CtxPtr,
                    plain.dataPtr,
                    sig.dataPtr,
                    (gpgme_sig_mode_t)mode);

                gpg_err_code_t errcode = libgpgerror.gpg_err_code(err);
                switch (errcode)
                {
                case gpg_err_code_t.GPG_ERR_NO_ERROR:
                    break;

                case gpg_err_code_t.GPG_ERR_UNUSABLE_SECKEY:
                    throw new InvalidKeyException(
                              "There is one or more invalid signing key(s) in the current context.");

                case gpg_err_code_t.GPG_ERR_INV_VALUE:
                    throw new InvalidPtrException(
                              "Either the context, plain text or cipher text pointer is invalid.");

                default:
                    throw GpgmeError.CreateException(errcode);
                }
                IntPtr rst_ptr = libgpgme.NativeMethods.gpgme_op_sign_result(CtxPtr);
                if (rst_ptr != IntPtr.Zero)
                {
                    var sig_rst = new SignatureResult(rst_ptr);
                    return(sig_rst);
                }
                throw new GeneralErrorException("An unexpected error occurred. " + errcode.ToString());
            }
        }
Example #11
0
        public static bool EngineCheckVersion(Protocol proto)
        {
            int err = libgpgme.gpgme_engine_check_version((gpgme_protocol_t)proto);

            gpg_err_code_t errcode = libgpgme.gpgme_err_code(err);

            if (errcode == gpg_err_code_t.GPG_ERR_NO_ERROR)
            {
                return(true);
            }
            return(false);
        }
        public Key GetKey(string fpr, bool secretOnly)
        {
            if (ctx == null ||
                !(ctx.IsValid))
            {
                throw new InvalidContextException();
            }

            if (fpr == null || fpr.Equals(string.Empty))
            {
                throw new InvalidKeyFprException();
            }

            int    secret  = secretOnly ? 1 : 0;
            IntPtr rkeyPtr = (IntPtr)0;

            lock (ctx.CtxLock)
            {
                // no deadlock because the query is made by the same thread
                Protocol proto = ctx.Protocol;

                gpg_err_code_t errcode = GetKey(fpr, secret, out rkeyPtr);

                if (errcode == gpg_err_code_t.GPG_ERR_NO_ERROR &&
                    !(rkeyPtr.Equals((IntPtr)0)))
                {
                    Key key = null;

                    if (proto == Protocol.OpenPGP)
                    {
                        key = new PgpKey(rkeyPtr);
                    }
                    else if (proto == Protocol.CMS)
                    {
                        key = new X509Key(rkeyPtr);
                    }
                    else
                    {
                        key = new Key(rkeyPtr);
                    }

                    //libgpgme.gpgme_key_release(rkeyPtr);
                    return(key);
                }
                else
                {
                    throw new KeyNotFoundException("The key " + fpr + " could not be found in the keyring.");
                }
            }
        }
            public void Add(string name, string value, SignatureNotationFlags flags)
            {
                if (ctx.IsValid)
                {
                    IntPtr namePtr  = IntPtr.Zero;
                    IntPtr valuePtr = IntPtr.Zero;
                    if (name != null)
                    {
                        namePtr = Gpgme.StringToCoTaskMemUTF8(name);
                    }
                    if (value != null)
                    {
                        valuePtr = Gpgme.StringToCoTaskMemUTF8(value);
                    }

                    int err = libgpgme.gpgme_sig_notation_add(
                        ctx.CtxPtr,
                        namePtr,
                        valuePtr,
                        (gpgme_sig_notation_flags_t)flags);

                    if (namePtr != IntPtr.Zero)
                    {
                        Marshal.FreeCoTaskMem(namePtr);
                        namePtr = IntPtr.Zero;
                    }
                    if (valuePtr != IntPtr.Zero)
                    {
                        Marshal.FreeCoTaskMem(valuePtr);
                        valuePtr = IntPtr.Zero;
                    }

                    gpg_err_code_t errcode = libgpgerror.gpg_err_code(err);
                    if (errcode == gpg_err_code_t.GPG_ERR_NO_ERROR)
                    {
                        return;
                    }
                    if (errcode == gpg_err_code_t.GPG_ERR_INV_VALUE)
                    {
                        throw new ArgumentException("NAME and VALUE are in an invalid combination.");
                    }

                    throw new GeneralErrorException("An unexpected error occurred. Error: "
                                                    + errcode.ToString());
                }
                else
                {
                    throw new InvalidContextException();
                }
            }
Example #14
0
        /// <summary>
        /// Converts a GPGME error code into an exception
        /// </summary>
        /// <param name="code">GPGME error code</param>
        /// <returns>Exception</returns>
        public static Exception CreateException(gpg_err_code_t code)
        {
            string message;

            Gpgme.GetStrError((int)code, out message);
            message = $"#{code}: ${message ?? "No error message available"}";

            switch (code)
            {
            case gpg_err_code_t.GPG_ERR_AMBIGUOUS_NAME:
                return(new AmbiguousKeyException(message));

            case gpg_err_code_t.GPG_ERR_BAD_PASSPHRASE:
                return(new BadPassphraseException(message));

            case gpg_err_code_t.GPG_ERR_CONFLICT:
                return(new KeyConflictException(message));

            case gpg_err_code_t.GPG_ERR_DECRYPT_FAILED:
                return(new DecryptionFailedException(message));

            case gpg_err_code_t.GPG_ERR_INV_VALUE:
                return(new InvalidPtrException(message));

            case gpg_err_code_t.GPG_ERR_EBADF:
                return(new InvalidDataBufferException(message));

            case gpg_err_code_t.GPG_ERR_ENOMEM:
                return(new OutOfMemoryException(message));

            case gpg_err_code_t.GPG_ERR_NO_DATA:
                return(new NoDataException(message));

            case gpg_err_code_t.GPG_ERR_NO_PUBKEY:
                return(new KeyNotFoundException(message));

            case gpg_err_code_t.GPG_ERR_UNUSABLE_SECKEY:
                return(new InvalidKeyException(message));

            default:
                return(new GeneralErrorException(message));
            }
        }
        public GpgmeMemoryData()
        {
            int            err     = libgpgme.gpgme_data_new(out dataPtr);
            gpg_err_code_t errcode = libgpgme.gpgme_err_code(err);


            if (errcode == gpg_err_code_t.GPG_ERR_NO_ERROR)
            {
                // everything went fine
                return;
            }

            if (errcode == gpg_err_code_t.GPG_ERR_ENOMEM)
            {
                throw new OutOfMemoryException("Not enough memory available to create GPGME data object.");
            }

            throw new GeneralErrorException("Unknown error " + errcode + " (" + err + ")");
        }
        public void DeleteKey(Key key, bool deleteSecret)
        {
            if (ctx == null ||
                !(ctx.IsValid))
            {
                throw new InvalidContextException();
            }

            if (key == null || key.KeyPtr.Equals(IntPtr.Zero))
            {
                throw new InvalidKeyException("An invalid key has been supplied.");
            }

            int secret = deleteSecret ? 1 : 0;

            lock (ctx.CtxLock)
            {
                int err = libgpgme.gpgme_op_delete(ctx.CtxPtr, key.KeyPtr, secret);

                gpg_err_code_t errcode = libgpgme.gpgme_err_code(err);

                switch (errcode)
                {
                case gpg_err_code_t.GPG_ERR_NO_ERROR:
                    break;

                case gpg_err_code_t.GPG_ERR_NO_PUBKEY:
                    throw new KeyNotFoundException("The public key could not be found.");

                case gpg_err_code_t.GPG_ERR_CONFLICT:
                    throw new KeyConflictException("Cannot delete the public key without deleting the secret key as well.");

                case gpg_err_code_t.GPG_ERR_INV_VALUE:
                    throw new InvalidPtrException("Either the context (ctx) or the key parameter was invalid.");

                case gpg_err_code_t.GPG_ERR_AMBIGUOUS_NAME:
                    throw new AmbiguousKeyException("The key id was not unique.");
                }
            }
        }
Example #17
0
        public static EngineInfo GetEngineInfo()
        {
            IntPtr info_ptr;

            int            err     = libgpgme.gpgme_get_engine_info(out info_ptr);
            gpg_err_code_t errcode = libgpgme.gpgme_err_code(err);

            if (errcode != gpg_err_code_t.GPG_ERR_NO_ERROR)
            {
                throw new GpgmeException("System error: "
                                         + err.ToString(CultureInfo.InvariantCulture), err);
            }

            EngineInfo info = null;

            if (info_ptr != IntPtr.Zero)
            {
                info = new EngineInfo(info_ptr);
            }

            return(info);
        }
Example #18
0
        public static EngineInfo GetEngineInfo()
        {
            int    err;
            IntPtr infoPtr;

            err = libgpgme.gpgme_get_engine_info(out infoPtr);
            gpg_err_code_t errcode = libgpgme.gpgme_err_code(err);

            if (errcode != gpg_err_code_t.GPG_ERR_NO_ERROR)
            {
                throw new GpgmeException("System error: "
                                         + err.ToString(), err);
            }

            EngineInfo info = null;

            if (infoPtr != (IntPtr)0)
            {
                info = new EngineInfo(infoPtr);
            }

            return(info);
        }
        private void InitGpgmeMemoryData(IntPtr memAddr, int size)
        {
            _mem_ptr = memAddr;
            if (_mem_ptr.Equals(IntPtr.Zero))
            {
                _mem_size = UIntPtr.Zero;
                throw new ArgumentException("The supplied memory address was 0.");
            }

            _mem_size = (UIntPtr)size;

            /* If COPY is not zero, a private copy of the data is made. If COPY
             * is zero, the data is taken from the specified buffer as needed,
             * and the user has to ensure that the buffer remains valid for the
             * whole life span of the data object. */
            const int COPY_FLAG = 0;
            int       err       = libgpgme.gpgme_data_new_from_mem(
                out dataPtr,
                _mem_ptr,
                _mem_size,
                COPY_FLAG);

            gpg_err_code_t errcode = libgpgme.gpgme_err_code(err);

            if (errcode == gpg_err_code_t.GPG_ERR_NO_ERROR)
            {
                // everything went fine
                return;
            }

            if (errcode == gpg_err_code_t.GPG_ERR_ENOMEM)
            {
                throw new OutOfMemoryException("Not enough memory available to create GPGME data object.");
            }

            throw new GeneralErrorException("Unknown error " + errcode + " (" + err + ")");
        }
Example #20
0
 internal static extern int gpgme_err_code_to_errno(
     [In] gpg_err_code_t code);
        public TrustItem[] GetTrustList(string pattern, int maxlevel)
        {
            if (ctx == null ||
                !(ctx.IsValid))
            {
                throw new InvalidContextException();
            }

            if (pattern == null || pattern.Equals(String.Empty))
            {
                throw new ArgumentException("An invalid pattern has been specified.");
            }

            IntPtr patternPtr = Gpgme.StringToCoTaskMemUTF8(pattern);

            List <TrustItem> lst = new List <TrustItem>();

            lock (ctx.CtxLock)
            {
                int            err     = libgpgme.gpgme_op_trustlist_start(ctx.CtxPtr, patternPtr, maxlevel);
                gpg_err_code_t errcode = libgpgerror.gpg_err_code(err);

                if (errcode != gpg_err_code_t.GPG_ERR_NO_ERROR)
                {
                    if (patternPtr != IntPtr.Zero)
                    {
                        Marshal.FreeCoTaskMem(patternPtr);
                        patternPtr = IntPtr.Zero;
                    }
                    throw new GeneralErrorException("An unexpected error occurred. Error: " + err.ToString());
                }

                while (errcode == gpg_err_code_t.GPG_ERR_NO_ERROR)
                {
                    IntPtr itemPtr = IntPtr.Zero;
                    err     = libgpgme.gpgme_op_trustlist_next(ctx.CtxPtr, out itemPtr);
                    errcode = libgpgerror.gpg_err_code(err);

                    if (errcode == gpg_err_code_t.GPG_ERR_NO_ERROR)
                    {
                        lst.Add(new TrustItem(itemPtr));
                    }
                }
                // Release context if there are any pending trustlist items
                err = libgpgme.gpgme_op_trustlist_end(ctx.CtxPtr);

                if (patternPtr != IntPtr.Zero)
                {
                    Marshal.FreeCoTaskMem(patternPtr);
                    patternPtr = IntPtr.Zero;
                }

                if (errcode != gpg_err_code_t.GPG_ERR_EOF)
                {
                    throw new GeneralErrorException("An unexpected error occurred. " + errcode.ToString());
                }
            }

            if (lst.Count == 0)
            {
                return(new TrustItem[0]);
            }
            else
            {
                return(lst.ToArray());
            }
        }
Example #22
0
        public EncryptionResult Encrypt(Key[] recipients, EncryptFlags flags, GpgmeData plain, GpgmeData cipher)
        {
            if (plain == null)
            {
                throw new ArgumentNullException("plain", "Source data buffer must be supplied.");
            }
            if (!(plain.IsValid))
            {
                throw new InvalidDataBufferException("The specified source data buffer is invalid.");
            }
            if (cipher == null)
            {
                throw new ArgumentNullException("cipher", "Destination data buffer must be supplied.");
            }
            if (!(cipher.IsValid))
            {
                throw new InvalidDataBufferException("The specified destination data buffer is invalid.");
            }
            if (!IsValid)
            {
                throw new InvalidContextException();
            }

            IntPtr[] recp = Gpgme.KeyArrayToIntPtrArray(recipients);

            lock (CtxLock) {
#if (VERBOSE_DEBUG)
                DebugOutput("gpgme_op_encrypt(..) START");
#endif
                int err = libgpgme.gpgme_op_encrypt(
                    CtxPtr,
                    recp,
                    (gpgme_encrypt_flags_t)flags,
                    plain.dataPtr,
                    cipher.dataPtr);

#if (VERBOSE_DEBUG)
                DebugOutput("gpgme_op_encrypt(..) DONE");
#endif

                gpg_err_code_t errcode = libgpgerror.gpg_err_code(err);
                switch (errcode)
                {
                case gpg_err_code_t.GPG_ERR_NO_ERROR:
                    break;

                case gpg_err_code_t.GPG_ERR_UNUSABLE_PUBKEY:
                    break;

                case gpg_err_code_t.GPG_ERR_GENERAL:     // Bug? should be GPG_ERR_UNUSABLE_PUBKEY
                    break;

                case gpg_err_code_t.GPG_ERR_INV_VALUE:
                    throw new InvalidPtrException(
                              "Either the context, recipient key array, plain text or cipher text pointer is invalid.");

                case gpg_err_code_t.GPG_ERR_BAD_PASSPHRASE:
                    throw new BadPassphraseException();

                case gpg_err_code_t.GPG_ERR_EBADF:
                    throw new InvalidDataBufferException(
                              "The source (plain) or destination (cipher) data buffer is invalid for encryption.");

                default:
                    throw new GeneralErrorException("An unexpected error "
                                                    + errcode.ToString()
                                                    + " (" + err.ToString(CultureInfo.InvariantCulture)
                                                    + ") occurred.");
                }
                IntPtr rst_ptr = libgpgme.gpgme_op_encrypt_result(CtxPtr);
#if (VERBOSE_DEBUG)
                DebugOutput("gpgme_op_encrypt_result(..) DONE");
#endif
                GC.KeepAlive(recp);
                GC.KeepAlive(recipients);
                GC.KeepAlive(plain);
                GC.KeepAlive(cipher);

                if (rst_ptr != IntPtr.Zero)
                {
                    var enc_rst = new EncryptionResult(rst_ptr);
                    return(enc_rst);
                }
                throw new GeneralErrorException("An unexpected error occurred. " + errcode.ToString());
            }
        }
 internal static int gpgme_err_make(gpg_err_source_t source, gpg_err_code_t code)
 {
     return libgpgerror.gpg_err_make(source, code);
 }
        public GenkeyResult GenerateKey(Protocol protocoltype, KeyParameters keyparms)
        {
            if (!ctx.IsValid)
            {
                throw new InvalidContextException();
            }

            if (keyparms == null)
            {
                throw new ArgumentNullException("No KeyParameters object supplied. Bad programmer! *spank* *spank*");
            }

            if (keyparms.Email == null ||
                keyparms.Email.Equals(String.Empty))
            {
                throw new ArgumentException("No email address has been supplied.");
            }

            // Convert the key parameter to an XML string for GPGME
            string parms = keyparms.GetXmlText(protocoltype);

            // Convert key parameter XML string to UTF8 and retrieve the memory pointer
            IntPtr parmsPtr = Gpgme.StringToCoTaskMemUTF8(parms);

            GenkeyResult   keyresult = null;
            int            err       = 0;
            gpg_err_code_t errcode   = gpg_err_code_t.GPG_ERR_NO_ERROR;

            lock (ctx.CtxLock)
            {
                // Protocol specific key generation
                switch (protocoltype)
                {
                case Protocol.OpenPGP:
                    err     = libgpgme.gpgme_op_genkey(ctx.CtxPtr, parmsPtr, (IntPtr)0, (IntPtr)0);
                    errcode = libgpgme.gpgme_err_code(err);
                    if (errcode == gpg_err_code_t.GPG_ERR_NO_ERROR)
                    {
                        IntPtr resultPtr = libgpgme.gpgme_op_genkey_result(ctx.CtxPtr);
                        if (!resultPtr.Equals((IntPtr)0))
                        {
                            keyresult = new GenkeyResult(resultPtr);
                        }
                        else
                        {
                            errcode = gpg_err_code_t.GPG_ERR_GENERAL;
                        }
                    }
                    break;

                default:
                    // free memory
                    if (parmsPtr != IntPtr.Zero)
                    {
                        Marshal.FreeCoTaskMem(parmsPtr);
                        parmsPtr = IntPtr.Zero;
                    }
                    throw new NotSupportedException("The protocol " + protocoltype + " is currently not supported for key generation.");
                }
            }

            // free memory
            if (parmsPtr != IntPtr.Zero)
            {
                Marshal.FreeCoTaskMem(parmsPtr);
                parmsPtr = IntPtr.Zero;
            }

            if (errcode == gpg_err_code_t.GPG_ERR_INV_VALUE)
            {
                throw new ArgumentException("The key parameters are invalid.");
            }
            if (errcode == gpg_err_code_t.GPG_ERR_NOT_SUPPORTED)
            {
                throw new NotSupportedException("The PUBLIC or SECRET part is invalid. Error: " + err.ToString());
            }
            if (errcode != gpg_err_code_t.GPG_ERR_NO_ERROR)
            {
                throw new GeneralErrorException("No key has been created by the backend.");
            }

            return(keyresult);
        }
        public Key[] GetKeyList(string[] pattern, bool secretOnly)
        {
            if (ctx == null ||
                !(ctx.IsValid))
            {
                throw new InvalidContextException();
            }

            List <Key> list = new List <Key>();

            int reserved    = 0;
            int secret_only = 0;

            if (secretOnly)
            {
                secret_only = 1;
            }

            IntPtr[] parray = null;
            if (pattern != null)
            {
                parray = Gpgme.StringToCoTaskMemUTF8(pattern);
            }

            lock (ctx.CtxLock)
            {
                // no deadlock because the query is made by the same thread
                Protocol proto = ctx.Protocol;

                int err = 0;

                if (parray != null)
                {
                    err = libgpgme.gpgme_op_keylist_ext_start(
                        ctx.CtxPtr,
                        parray,
                        secret_only,
                        reserved);
                }
                else
                {
                    err = libgpgme.gpgme_op_keylist_start(
                        ctx.CtxPtr,
                        IntPtr.Zero,
                        secret_only);
                }

                while (err == 0)
                {
                    IntPtr keyPtr = (IntPtr)0;
                    err = libgpgme.gpgme_op_keylist_next(ctx.CtxPtr, out keyPtr);
                    if (err != 0)
                    {
                        break;
                    }

                    Key key = null;

                    if (proto == Protocol.OpenPGP)
                    {
                        key = new PgpKey(keyPtr);
                    }
                    else if (proto == Protocol.CMS)
                    {
                        key = new X509Key(keyPtr);
                    }
                    else
                    {
                        key = new Key(keyPtr);
                    }

                    list.Add(key);

                    //libgpgme.gpgme_key_release(keyPtr);
                }

                // Free memory
                if (parray != null)
                {
                    Gpgme.FreeStringArray(parray);
                }

                gpg_err_code_t errcode = libgpgme.gpgme_err_code(err);
                if (errcode != gpg_err_code_t.GPG_ERR_EOF)
                {
                    libgpgme.gpgme_op_keylist_end(ctx.CtxPtr);
                    throw new GpgmeException(Gpgme.GetStrError(err), err);
                }
            }
            return(list.ToArray());
        }
        public VerificationResult Verify(GpgmeData signature, GpgmeData signedtext, GpgmeData plain)
        {
            if (IsValid)
            {
                if (signature == null)
                {
                    throw new ArgumentNullException("A signature data buffer must be supplied.");
                }
                if (!(signature.IsValid))
                {
                    throw new InvalidDataBufferException("The specified signature data buffer is invalid.");
                }

                if (
                    (signedtext == null || !(signedtext.IsValid)) &&
                    (plain == null || !(plain.IsValid))
                    )
                {
                    throw new InvalidDataBufferException("Either the signed text must be provided in order to prove the detached signature, or an empty data buffer to store the plain text result.");
                }
                lock (CtxLock)
                {
                    IntPtr sigPtr = IntPtr.Zero, sigtxtPtr = IntPtr.Zero, plainPtr = IntPtr.Zero;

                    sigPtr = signature.dataPtr;
                    if (signedtext != null && signedtext.IsValid)
                    {
                        sigtxtPtr = signedtext.dataPtr;
                    }
                    if (plain != null && plain.IsValid)
                    {
                        plainPtr = plain.dataPtr;
                    }

                    int err = libgpgme.gpgme_op_verify(
                        CtxPtr,
                        sigPtr,
                        sigtxtPtr,
                        plainPtr);

                    gpg_err_code_t errcode = libgpgerror.gpg_err_code(err);
                    switch (errcode)
                    {
                    case gpg_err_code_t.GPG_ERR_NO_ERROR:
                        break;

                    case gpg_err_code_t.GPG_ERR_NO_DATA:
                        break;

                    case gpg_err_code_t.GPG_ERR_INV_VALUE:
                        throw new InvalidDataBufferException("Either the signature, signed text or plain text data buffer is invalid.");

                    default:
                        throw new GeneralErrorException("Unexpected error occurred. Error: " + errcode.ToString());
                    }

                    VerificationResult verRst = null;

                    IntPtr rstPtr = IntPtr.Zero;
                    rstPtr = libgpgme.gpgme_op_verify_result(CtxPtr);
                    if (rstPtr != IntPtr.Zero)
                    {
                        verRst = new VerificationResult(rstPtr);
                        if (errcode == gpg_err_code_t.GPG_ERR_NO_DATA)
                        {
                            throw new NoDataException("The signature does not contain any data to verify.");
                        }
                        else
                        {
                            return(verRst);
                        }
                    }
                    else
                    {
                        throw new GeneralErrorException("Could not retrieve verification result.");
                    }
                }
            }
            else
            {
                throw new InvalidContextException();
            }
        }
 internal static int gpgme_error(gpg_err_code_t code)
 {
     return gpgme_err_make((gpg_err_source_t)GPGME_ERR_SOURCE_DEFAULT, code);
 }
Example #28
0
 internal static int gpgme_error(gpg_err_code_t code)
 {
     return(gpgme_err_make((gpg_err_source_t)GPGME_ERR_SOURCE_DEFAULT, code));
 }
Example #29
0
 internal static int gpgme_err_make(gpg_err_source_t source, gpg_err_code_t code)
 {
     return(libgpgerror.gpg_err_make(source, code));
 }
Example #30
0
        private void Init(bool canRead, bool canWrite, bool canSeek, bool canRelease)
        {
#if (VERBOSE_DEBUG)
            DebugOutput("GpgmeCbsData.Init(" + canRead.ToString() + ","
                        + canWrite.ToString() + ","
                        + canSeek.ToString() + ","
                        + canRelease.ToString() + ")");
#endif
            _handle = IncGlobalHandle(); // increment the global handle

            _cbs     = new _gpgme_data_cbs();
            _cbs_lfs = new _gpgme_data_cbs_lfs();

            // Read function
            if (canRead)
            {
                _cbs.read     = InternalReadCallback;
                _cbs_lfs.read = InternalReadCallback;
            }
            else
            {
                _cbs.read     = null;
                _cbs_lfs.read = null;
            }

            // Write function
            if (canWrite)
            {
                _cbs.write     = InternalWriteCallback;
                _cbs_lfs.write = InternalWriteCallback;
            }
            else
            {
                _cbs.write     = null;
                _cbs_lfs.write = null;
            }

            // Seek function
            if (canSeek)
            {
                _cbs.seek     = InternalSeekCallback;
                _cbs_lfs.seek = InternalSeekLfsCallback;
            }
            else
            {
                _cbs.seek     = null;
                _cbs_lfs.seek = null;
            }

            // Release
            if (canRelease)
            {
                _cbs.release     = InternalReleaseCallback;
                _cbs_lfs.release = InternalReleaseCallback;
            }
            else
            {
                _cbs.release     = null;
                _cbs_lfs.release = null;
            }

            _pinned_cbs     = GCHandle.Alloc(_cbs);
            _pinned_cbs_lfs = GCHandle.Alloc(_cbs_lfs);
            if (libgpgme.use_lfs)
            {
                _cbs_ptr = Marshal.AllocCoTaskMem(Marshal.SizeOf(_cbs_lfs));
                Marshal.StructureToPtr(_cbs_lfs, _cbs_ptr, false);
            }
            else
            {
                _cbs_ptr = Marshal.AllocCoTaskMem(Marshal.SizeOf(_cbs));
                Marshal.StructureToPtr(_cbs, _cbs_ptr, false);
            }

            int err = libgpgme.NativeMethods.gpgme_data_new_from_cbs(
                out dataPtr,
                _cbs_ptr,
                _handle);

#if (VERBOSE_DEBUG)
            DebugOutput("gpgme_data_new_from_cbs(..) DONE.");
#endif
            gpg_err_code_t errcode = libgpgme.gpgme_err_code(err);

            if (errcode == gpg_err_code_t.GPG_ERR_NO_ERROR)
            {
                return;
            }

            if (errcode == gpg_err_code_t.GPG_ERR_ENOMEM)
            {
                throw new OutOfMemoryException("Not enough memory available to create user defined GPGME data object.");
            }

            throw new GeneralErrorException("Unknown error " + errcode + " (" + err + ")");
        }
        public CombinedResult DecryptAndVerify(GpgmeData cipher, GpgmeData plain)
        {
            if (IsValid)
            {
                if (cipher == null)
                {
                    throw new ArgumentNullException("Source data buffer must be supplied.");
                }
                if (!(cipher.IsValid))
                {
                    throw new InvalidDataBufferException("The specified source data buffer is invalid.");
                }

                if (plain == null)
                {
                    throw new ArgumentNullException("Destination data buffer must be supplied.");
                }
                if (!(plain.IsValid))
                {
                    throw new InvalidDataBufferException("The specified destination data buffer is invalid.");
                }

                lock (CtxLock)
                {
#if (VERBOSE_DEBUG)
                    DebugOutput("gpgme_op_decrypt_verify(..) START");
#endif
                    int err = libgpgme.gpgme_op_decrypt_verify(
                        CtxPtr,
                        cipher.dataPtr,
                        plain.dataPtr);
#if (VERBOSE_DEBUG)
                    DebugOutput("gpgme_op_decrypt_verify(..) DONE");
#endif
                    gpg_err_code_t errcode = libgpgerror.gpg_err_code(err);

                    switch (errcode)
                    {
                    case gpg_err_code_t.GPG_ERR_NO_ERROR:
                        break;

                    case gpg_err_code_t.GPG_ERR_NO_DATA:
                        // no encrypted data found - maybe it is only signed.
                        break;

                    case gpg_err_code_t.GPG_ERR_INV_VALUE:
                        throw new InvalidPtrException("Either the context, cipher text or plain text pointer is invalid.");
                    }

                    DecryptionResult decRst = null;

                    IntPtr rstPtr = libgpgme.gpgme_op_decrypt_result(CtxPtr);
                    if (rstPtr != IntPtr.Zero)
                    {
                        decRst = new DecryptionResult(rstPtr);
                    }

                    switch (errcode)
                    {
                    case gpg_err_code_t.GPG_ERR_NO_ERROR:
                        break;

                    case gpg_err_code_t.GPG_ERR_DECRYPT_FAILED:
                        if (decRst == null)
                        {
                            throw new DecryptionFailedException("An invalid cipher text has been supplied.");
                        }
                        else
                        {
                            throw new DecryptionFailedException(decRst);
                        }

                    case gpg_err_code_t.GPG_ERR_BAD_PASSPHRASE:
                        throw new BadPassphraseException(decRst);

                    default:
                        throw new GeneralErrorException("An unexpected error occurred. "
                                                        + errcode.ToString());
                    }

                    /* If decryption failed, verification cannot be proceeded */
                    VerificationResult verRst = null;

                    rstPtr = IntPtr.Zero;
                    rstPtr = libgpgme.gpgme_op_verify_result(CtxPtr);
                    if (rstPtr != IntPtr.Zero)
                    {
                        verRst = new VerificationResult(rstPtr);
                    }

                    GC.KeepAlive(cipher);
                    GC.KeepAlive(plain);

                    return(new CombinedResult(decRst, verRst));
                }
            }
            else
            {
                throw new InvalidContextException();
            }
        }
        public DecryptionResult Decrypt(GpgmeData cipher, GpgmeData plain)
        {
            if (IsValid)
            {
                if (cipher == null)
                {
                    throw new ArgumentNullException("Source data buffer must be supplied.");
                }
                if (!(cipher.IsValid))
                {
                    throw new InvalidDataBufferException("The specified source data buffer is invalid.");
                }

                if (plain == null)
                {
                    throw new ArgumentNullException("Destination data buffer must be supplied.");
                }
                if (!(plain.IsValid))
                {
                    throw new InvalidDataBufferException("The specified destination data buffer is invalid.");
                }

                lock (CtxLock)
                {
#if (VERBOSE_DEBUG)
                    DebugOutput("gpgme_op_decrypt(..) START");
#endif
                    int err = libgpgme.gpgme_op_decrypt(
                        CtxPtr,
                        cipher.dataPtr,
                        plain.dataPtr);
#if (VERBOSE_DEBUG)
                    DebugOutput("gpgme_op_decrypt(..) DONE");
#endif
                    gpg_err_code_t errcode = libgpgerror.gpg_err_code(err);

                    switch (errcode)
                    {
                    case gpg_err_code_t.GPG_ERR_NO_ERROR:
                        break;

                    case gpg_err_code_t.GPG_ERR_NO_DATA:
                        throw new NoDataException("The cipher does not contain any data to decrypt or is corrupt.");

                    case gpg_err_code_t.GPG_ERR_INV_VALUE:
                        throw new InvalidPtrException("Either the context, cipher text or plain text pointer is invalid.");
                    }

                    DecryptionResult decRst = null;

                    IntPtr rstPtr = libgpgme.gpgme_op_decrypt_result(CtxPtr);
                    if (rstPtr != IntPtr.Zero)
                    {
                        decRst = new DecryptionResult(rstPtr);
                    }

                    switch (errcode)
                    {
                    case gpg_err_code_t.GPG_ERR_NO_ERROR:
                        break;

                    case gpg_err_code_t.GPG_ERR_DECRYPT_FAILED:
                        if (decRst == null)
                        {
                            throw new DecryptionFailedException("An invalid cipher text has been supplied.");
                        }
                        else
                        {
                            throw new DecryptionFailedException(decRst);
                        }

                    case gpg_err_code_t.GPG_ERR_BAD_PASSPHRASE:
                        throw new BadPassphraseException(decRst);

                    default:
                        throw new GeneralErrorException("An unexpected error occurred. " + errcode.ToString());
                    }

                    GC.KeepAlive(cipher);
                    GC.KeepAlive(plain);

                    return(decRst);;
                }
            }
            else
            {
                throw new InvalidContextException();
            }
        }
        public EncryptionResult EncryptAndSign(Key[] recipients, EncryptFlags flags, GpgmeData plain, GpgmeData cipher)
        {
            if (IsValid)
            {
                if (plain == null)
                {
                    throw new ArgumentNullException("Source data buffer must be supplied.");
                }
                if (!(plain.IsValid))
                {
                    throw new InvalidDataBufferException("The specified source data buffer is invalid.");
                }

                if (cipher == null)
                {
                    throw new ArgumentNullException("Destination data buffer must be supplied.");
                }
                if (!(cipher.IsValid))
                {
                    throw new InvalidDataBufferException("The specified destination data buffer is invalid.");
                }

                IntPtr[] recp = Gpgme.KeyArrayToIntPtrArray(recipients);

                lock (CtxLock)
                {
                    int err = libgpgme.gpgme_op_encrypt_sign(
                        CtxPtr,
                        recp,
                        (gpgme_encrypt_flags_t)flags,
                        plain.dataPtr,
                        cipher.dataPtr);

                    gpg_err_code_t errcode = libgpgerror.gpg_err_code(err);
                    switch (errcode)
                    {
                    case gpg_err_code_t.GPG_ERR_NO_ERROR:
                        break;

                    case gpg_err_code_t.GPG_ERR_UNUSABLE_PUBKEY:
                        break;

                    case gpg_err_code_t.GPG_ERR_GENERAL:        // Bug? should be GPG_ERR_UNUSABLE_PUBKEY
                        break;

                    case gpg_err_code_t.GPG_ERR_UNUSABLE_SECKEY:
                        throw new InvalidKeyException("There is one or more invalid signing key(s) in the current context.");

                    case gpg_err_code_t.GPG_ERR_INV_VALUE:
                        throw new InvalidPtrException("Either the context, recipient key array, plain text or cipher text pointer is invalid.");

                    case gpg_err_code_t.GPG_ERR_BAD_PASSPHRASE:
                        throw new BadPassphraseException();

                    default:
                        throw new GeneralErrorException("An unexpected error "
                                                        + errcode.ToString()
                                                        + " (" + err.ToString()
                                                        + ") occurred.");
                    }
                    IntPtr rstPtr = libgpgme.gpgme_op_encrypt_result(CtxPtr);

                    GC.KeepAlive(recp);
                    GC.KeepAlive(recipients);
                    GC.KeepAlive(plain);
                    GC.KeepAlive(cipher);

                    if (rstPtr != IntPtr.Zero)
                    {
                        EncryptionResult encRst = new EncryptionResult(rstPtr);
                        return(encRst);
                    }
                    else
                    {
                        throw new GeneralErrorException("An unexpected error occurred. " + errcode.ToString());
                    }
                }
            }
            else
            {
                throw new InvalidContextException();
            }
        }