Example #1
0
        public void SetEngineInfo(Protocol proto, string filename, string homedir)
        {
            EnsureValid();
            lock (CtxLock) {
                IntPtr filename_ptr = IntPtr.Zero, homedir_ptr = IntPtr.Zero;

                if (filename != null)
                {
                    filename_ptr = Marshal.StringToCoTaskMemAnsi(filename);
                }
                if (homedir != null)
                {
                    homedir_ptr = Marshal.StringToCoTaskMemAnsi(homedir);
                }

                int err = libgpgme.NativeMethods.gpgme_ctx_set_engine_info(
                    CtxPtr,
                    (gpgme_protocol_t)proto,
                    filename_ptr,
                    homedir_ptr);

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

                GpgmeError.Check(err);
            }
        }
Example #2
0
        public ImportResult Import(GpgmeData keydata)
        {
            if (Context == null ||
                !(Context.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 (Context.CtxLock) {
                GpgmeError.Check(libgpgme.NativeMethods.gpgme_op_import(Context.CtxPtr, keydata.dataPtr));
                IntPtr result = libgpgme.NativeMethods.gpgme_op_import_result(Context.CtxPtr);
                return(new ImportResult(result));
            }
        }
Example #3
0
        public void Export(string[] pattern, GpgmeData keydata, ExportMode?mode = null)
        {
            if (Context == null ||
                !(Context.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;
            var apiMode = mode == null ? 0 : (uint)mode;

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

            GC.KeepAlive(keydata);

            // Free memory
            Gpgme.FreeStringArray(parray);

            GpgmeError.Check(err);
        }
Example #4
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 #5
0
        public TrustItem[] GetTrustList(string pattern, int maxlevel)
        {
            if (Context == null ||
                !(Context.IsValid))
            {
                throw new InvalidContextException();
            }

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

            IntPtr pattern_ptr = Gpgme.StringToCoTaskMemUTF8(pattern);

            var lst = new List <TrustItem>();

            lock (Context.CtxLock) {
                int            err     = libgpgme.NativeMethods.gpgme_op_trustlist_start(Context.CtxPtr, pattern_ptr, maxlevel);
                gpg_err_code_t errcode = libgpgerror.gpg_err_code(err);

                if (errcode != gpg_err_code_t.GPG_ERR_NO_ERROR)
                {
                    if (pattern_ptr != IntPtr.Zero)
                    {
                        Marshal.FreeCoTaskMem(pattern_ptr);
                    }
                    throw GpgmeError.CreateException(errcode);
                }

                while (errcode == gpg_err_code_t.GPG_ERR_NO_ERROR)
                {
                    IntPtr item_ptr;
                    err     = libgpgme.NativeMethods.gpgme_op_trustlist_next(Context.CtxPtr, out item_ptr);
                    errcode = libgpgerror.gpg_err_code(err);

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

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

                if (errcode != gpg_err_code_t.GPG_ERR_EOF)
                {
                    throw GpgmeError.CreateException(errcode);
                }
            }

            if (lst.Count == 0)
            {
                return(new TrustItem[0]);
            }
            return(lst.ToArray());
        }
Example #6
0
        public VerificationResult Verify(GpgmeData signature, GpgmeData signedtext, GpgmeData plain)
        {
            EnsureValid();
            if (signature == null)
            {
                throw new ArgumentNullException("signature", "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 sigtxt_ptr = IntPtr.Zero, plain_ptr = IntPtr.Zero;

                IntPtr sig_ptr = signature.dataPtr;
                if (signedtext != null && signedtext.IsValid)
                {
                    sigtxt_ptr = signedtext.dataPtr;
                }
                if (plain != null && plain.IsValid)
                {
                    plain_ptr = plain.dataPtr;
                }

                int err = libgpgme.NativeMethods.gpgme_op_verify(
                    CtxPtr,
                    sig_ptr,
                    sigtxt_ptr,
                    plain_ptr);

                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 GpgmeError.CreateException(errcode);
                }

                IntPtr rst_ptr = libgpgme.NativeMethods.gpgme_op_verify_result(CtxPtr);
                if (rst_ptr != IntPtr.Zero)
                {
                    VerificationResult ver_rst = new VerificationResult(rst_ptr);
                    if (errcode == gpg_err_code_t.GPG_ERR_NO_DATA)
                    {
                        throw new NoDataException("The signature does not contain any data to verify.");
                    }
                    return(ver_rst);
                }
                throw new GeneralErrorException("Could not retrieve verification result.");
            }
        }
Example #7
0
        public CombinedResult DecryptAndVerify(GpgmeData cipher, GpgmeData plain)
        {
            EnsureValid();
            if (cipher == null)
            {
                throw new ArgumentNullException(nameof(cipher), "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(nameof(plain), "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.NativeMethods.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.");

                default:
                    throw GpgmeError.CreateException(errcode);
                }

                DecryptionResult dec_rst = null;

                IntPtr rst_ptr = libgpgme.NativeMethods.gpgme_op_decrypt_result(CtxPtr);
                if (rst_ptr != IntPtr.Zero)
                {
                    dec_rst = new DecryptionResult(rst_ptr);
                }

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

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

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

                default:
                    throw GpgmeError.CreateException(errcode);
                }

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

                rst_ptr = libgpgme.NativeMethods.gpgme_op_verify_result(CtxPtr);
                if (rst_ptr != IntPtr.Zero)
                {
                    ver_rst = new VerificationResult(rst_ptr);
                }

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

                return(new CombinedResult(dec_rst, ver_rst));
            }
        }
Example #8
0
        public DecryptionResult Decrypt(GpgmeData cipher, GpgmeData plain)
        {
            EnsureValid();
            if (cipher == null)
            {
                throw new ArgumentNullException(nameof(cipher), "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(nameof(plain), "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.NativeMethods.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.");

                default:
                    throw GpgmeError.CreateException(errcode);
                }

                DecryptionResult dec_rst = null;

                IntPtr rst_ptr = libgpgme.NativeMethods.gpgme_op_decrypt_result(CtxPtr);
                if (rst_ptr != IntPtr.Zero)
                {
                    dec_rst = new DecryptionResult(rst_ptr);
                }

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

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

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

                default:
                    throw GpgmeError.CreateException(errcode);
                }

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

                return(dec_rst);
            }
        }
Example #9
0
        public EncryptionResult EncryptAndSign(Key[] recipients, EncryptFlags flags, GpgmeData plain, GpgmeData cipher)
        {
            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 (cipher == null)
            {
                throw new ArgumentNullException(nameof(cipher), "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.NativeMethods.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.");

                default:
                    throw GpgmeError.CreateException(errcode);
                }
                IntPtr rst_ptr = libgpgme.NativeMethods.gpgme_op_encrypt_result(CtxPtr);

                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());
            }
        }