예제 #1
0
        /// <summary>
        /// Initializes the Context
        /// </summary>
        private void Initialize(ref ContextSigners signers, ref ContextSignatureNotations signots, ref KeyStore keystore)
        {
            IntPtr ptr;

            var            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:
                _ctx_ptr = 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());
            }
        }
예제 #2
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());
            }
        }
            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();
                }
            }
        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());
            }
        }
        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();
            }
        }
            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();
                }
            }
        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();
            }
        }
예제 #10
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());
            }
        }