packages feed

HsOpenSSL 0.11.4 → 0.11.4.1

raw patch · 9 files changed

+678/−634 lines, 9 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

Files

ChangeLog view
@@ -1,3 +1,9 @@+2017-02-27  Vladimir Shabanov  <vshabanoff@gmail.com>++	* HsOpenSSL.cabal (Version): Bump version to 0.11.4.1++	* Updated for OpenSSL 1.1.0 (#16)+ 2017-01-24  Vladimir Shabanov  <vshabanoff@gmail.com>  	* HsOpenSSL.cabal (Version): Bump version to 0.11.4
HsOpenSSL.cabal view
@@ -12,7 +12,7 @@     <http://hackage.haskell.org/package/tls>, which is a pure Haskell     implementation of SSL.     .-Version:       0.11.4+Version:       0.11.4.1 License:       PublicDomain License-File:  COPYING Author:        Adam Langley, Mikhail Vorozhtsov, PHO, Taru Karttunen
− OpenSSL/Stack.hs
@@ -1,61 +0,0 @@-{-# LANGUAGE EmptyDataDecls           #-}-{-# LANGUAGE ForeignFunctionInterface #-}-module OpenSSL.Stack-    ( STACK-    , mapStack-    , withStack-    , withForeignStack-    )-    where-import           Control.Exception-import           Foreign-import           Foreign.C---data STACK---foreign import ccall unsafe "sk_new_null"-        skNewNull :: IO (Ptr STACK)--foreign import ccall unsafe "sk_free"-        skFree :: Ptr STACK -> IO ()--foreign import ccall unsafe "sk_push"-        skPush :: Ptr STACK -> Ptr () -> IO ()--foreign import ccall unsafe "sk_num"-        skNum :: Ptr STACK -> IO CInt--foreign import ccall unsafe "sk_value"-        skValue :: Ptr STACK -> CInt -> IO (Ptr ())---mapStack :: (Ptr a -> IO b) -> Ptr STACK -> IO [b]-mapStack m st-    = do num <- skNum st-         mapM (\ i -> fmap castPtr (skValue st i) >>= m)-                  $ take (fromIntegral num) [0..]---newStack :: [Ptr a] -> IO (Ptr STACK)-newStack values-    = do st <- skNewNull-         mapM_ (skPush st . castPtr) values-         return st---withStack :: [Ptr a] -> (Ptr STACK -> IO b) -> IO b-withStack values-    = bracket (newStack values) skFree---withForeignStack :: (fp -> Ptr obj)-                 -> (fp -> IO ())-                 -> [fp]-                 -> (Ptr STACK -> IO ret)-                 -> IO ret-withForeignStack unsafeFpToPtr touchFp fps action-    = do ret <- withStack (map unsafeFpToPtr fps) action-         mapM_ touchFp fps-         return ret
+ OpenSSL/Stack.hsc view
@@ -0,0 +1,78 @@+{-# LANGUAGE EmptyDataDecls           #-}+{-# LANGUAGE ForeignFunctionInterface #-}+module OpenSSL.Stack+    ( STACK+    , mapStack+    , withStack+    , withForeignStack+    )+    where+#include "HsOpenSSL.h"+import           Control.Exception+import           Foreign+import           Foreign.C+++data STACK+++#if OPENSSL_VERSION_NUMBER >= 0x10100000L+foreign import ccall unsafe "OPENSSL_sk_new_null"+        skNewNull :: IO (Ptr STACK)++foreign import ccall unsafe "OPENSSL_sk_free"+        skFree :: Ptr STACK -> IO ()++foreign import ccall unsafe "OPENSSL_sk_push"+        skPush :: Ptr STACK -> Ptr () -> IO ()++foreign import ccall unsafe "OPENSSL_sk_num"+        skNum :: Ptr STACK -> IO CInt++foreign import ccall unsafe "OPENSSL_sk_value"+        skValue :: Ptr STACK -> CInt -> IO (Ptr ())+#else+foreign import ccall unsafe "sk_new_null"+        skNewNull :: IO (Ptr STACK)++foreign import ccall unsafe "sk_free"+        skFree :: Ptr STACK -> IO ()++foreign import ccall unsafe "sk_push"+        skPush :: Ptr STACK -> Ptr () -> IO ()++foreign import ccall unsafe "sk_num"+        skNum :: Ptr STACK -> IO CInt++foreign import ccall unsafe "sk_value"+        skValue :: Ptr STACK -> CInt -> IO (Ptr ())+#endif++mapStack :: (Ptr a -> IO b) -> Ptr STACK -> IO [b]+mapStack m st+    = do num <- skNum st+         mapM (\ i -> fmap castPtr (skValue st i) >>= m)+                  $ take (fromIntegral num) [0..]+++newStack :: [Ptr a] -> IO (Ptr STACK)+newStack values+    = do st <- skNewNull+         mapM_ (skPush st . castPtr) values+         return st+++withStack :: [Ptr a] -> (Ptr STACK -> IO b) -> IO b+withStack values+    = bracket (newStack values) skFree+++withForeignStack :: (fp -> Ptr obj)+                 -> (fp -> IO ())+                 -> [fp]+                 -> (Ptr STACK -> IO ret)+                 -> IO ret+withForeignStack unsafeFpToPtr touchFp fps action+    = do ret <- withStack (map unsafeFpToPtr fps) action+         mapM_ touchFp fps+         return ret
− OpenSSL/X509.hs
@@ -1,422 +0,0 @@-{-# LANGUAGE CPP                      #-}-{-# LANGUAGE EmptyDataDecls           #-}-{-# LANGUAGE ForeignFunctionInterface #-}-{-# OPTIONS_HADDOCK prune             #-}--- |An interface to X.509 certificate.-module OpenSSL.X509-    ( -- * Type-      X509-    , X509_--      -- * Functions to manipulate certificate-    , newX509-    , wrapX509 -- private-    , withX509Ptr -- private-    , withX509Stack -- private-    , unsafeX509ToPtr -- private-    , touchX509 -- private--    , writeDerX509-    , readDerX509-    , compareX509--    , signX509-    , verifyX509--    , printX509--      -- * Accessors-    , getVersion-    , setVersion--    , getSerialNumber-    , setSerialNumber--    , getIssuerName-    , setIssuerName--    , getSubjectName-    , setSubjectName--    , getNotBefore-    , setNotBefore--    , getNotAfter-    , setNotAfter--    , getPublicKey-    , setPublicKey--    , getSubjectEmail-    )-    where-import Control.Monad-import Data.Time.Clock-import Data.Maybe-import Foreign.ForeignPtr-#if MIN_VERSION_base(4,4,0)-import Foreign.ForeignPtr.Unsafe as Unsafe-#else-import Foreign.ForeignPtr as Unsafe-#endif-import Foreign.Ptr-import Foreign.C-import OpenSSL.ASN1-import OpenSSL.BIO-import OpenSSL.EVP.Digest-import OpenSSL.EVP.PKey-import OpenSSL.EVP.Verify-import OpenSSL.EVP.Internal-import OpenSSL.Utils-import OpenSSL.Stack-import OpenSSL.X509.Name-import Data.ByteString.Lazy (ByteString)---- |@'X509'@ is an opaque object that represents X.509 certificate.-newtype X509  = X509 (ForeignPtr X509_)-data    X509_---foreign import ccall unsafe "X509_new"-        _new :: IO (Ptr X509_)--foreign import ccall unsafe "&X509_free"-        _free :: FunPtr (Ptr X509_ -> IO ())--foreign import ccall unsafe "X509_print"-        _print :: Ptr BIO_ -> Ptr X509_ -> IO CInt--foreign import ccall unsafe "X509_cmp"-        _cmp :: Ptr X509_ -> Ptr X509_ -> IO CInt--foreign import ccall unsafe "HsOpenSSL_X509_get_version"-        _get_version :: Ptr X509_ -> IO CLong--foreign import ccall unsafe "X509_set_version"-        _set_version :: Ptr X509_ -> CLong -> IO CInt--foreign import ccall unsafe "X509_get_serialNumber"-        _get_serialNumber :: Ptr X509_ -> IO (Ptr ASN1_INTEGER)--foreign import ccall unsafe "X509_set_serialNumber"-        _set_serialNumber :: Ptr X509_ -> Ptr ASN1_INTEGER -> IO CInt--foreign import ccall unsafe "X509_get_issuer_name"-        _get_issuer_name :: Ptr X509_ -> IO (Ptr X509_NAME)--foreign import ccall unsafe "X509_set_issuer_name"-        _set_issuer_name :: Ptr X509_ -> Ptr X509_NAME -> IO CInt--foreign import ccall unsafe "X509_get_subject_name"-        _get_subject_name :: Ptr X509_ -> IO (Ptr X509_NAME)--foreign import ccall unsafe "X509_set_subject_name"-        _set_subject_name :: Ptr X509_ -> Ptr X509_NAME -> IO CInt--foreign import ccall unsafe "HsOpenSSL_X509_get_notBefore"-        _get_notBefore :: Ptr X509_ -> IO (Ptr ASN1_TIME)--foreign import ccall unsafe "X509_set_notBefore"-        _set_notBefore :: Ptr X509_ -> Ptr ASN1_TIME -> IO CInt--foreign import ccall unsafe "HsOpenSSL_X509_get_notAfter"-        _get_notAfter :: Ptr X509_ -> IO (Ptr ASN1_TIME)--foreign import ccall unsafe "X509_set_notAfter"-        _set_notAfter :: Ptr X509_ -> Ptr ASN1_TIME -> IO CInt--foreign import ccall unsafe "X509_get_pubkey"-        _get_pubkey :: Ptr X509_ -> IO (Ptr EVP_PKEY)--foreign import ccall unsafe "X509_set_pubkey"-        _set_pubkey :: Ptr X509_ -> Ptr EVP_PKEY -> IO CInt--foreign import ccall unsafe "X509_get1_email"-        _get1_email :: Ptr X509_ -> IO (Ptr STACK)--foreign import ccall unsafe "X509_email_free"-        _email_free :: Ptr STACK -> IO ()--foreign import ccall unsafe "X509_sign"-        _sign :: Ptr X509_ -> Ptr EVP_PKEY -> Ptr EVP_MD -> IO CInt--foreign import ccall unsafe "X509_verify"-        _verify :: Ptr X509_ -> Ptr EVP_PKEY -> IO CInt--foreign import ccall safe "i2d_X509_bio"-        _write_bio_X509 :: Ptr BIO_-                        -> Ptr X509_-                        -> IO CInt--foreign import ccall safe "d2i_X509_bio"-        _read_bio_X509 :: Ptr BIO_-                       -> Ptr (Ptr X509_)-                       -> IO (Ptr X509_)---- |@'newX509'@ creates an empty certificate. You must set the--- following properties to and sign it (see 'signX509') to actually--- use the certificate.------   [/Version/] See 'setVersion'.------   [/Serial number/] See 'setSerialNumber'.------   [/Issuer name/] See 'setIssuerName'.------   [/Subject name/] See 'setSubjectName'.------   [/Validity/] See 'setNotBefore' and 'setNotAfter'.------   [/Public Key/] See 'setPublicKey'.----newX509 :: IO X509-newX509 = _new >>= failIfNull >>= wrapX509---wrapX509 :: Ptr X509_ -> IO X509-wrapX509 = fmap X509 . newForeignPtr _free---withX509Ptr :: X509 -> (Ptr X509_ -> IO a) -> IO a-withX509Ptr (X509 x509) = withForeignPtr x509---withX509Stack :: [X509] -> (Ptr STACK -> IO a) -> IO a-withX509Stack = withForeignStack unsafeX509ToPtr touchX509---unsafeX509ToPtr :: X509 -> Ptr X509_-unsafeX509ToPtr (X509 x509) = Unsafe.unsafeForeignPtrToPtr x509---touchX509 :: X509 -> IO ()-touchX509 (X509 x509) = touchForeignPtr x509--writeX509' :: BIO -> X509 -> IO ()-writeX509' bio x509-    = withBioPtr bio   $ \ bioPtr ->-      withX509Ptr x509 $ \ x509Ptr ->-      _write_bio_X509 bioPtr x509Ptr-           >>= failIf (< 0)-           >>  return ()---- |@'writeDerX509' cert@ writes an X.509 certificate to DER string.-writeDerX509 :: X509 -> IO ByteString-writeDerX509 x509-    = do mem <- newMem-         writeX509' mem x509-         bioReadLBS mem--readX509' :: BIO -> IO X509-readX509' bio-    = withBioPtr bio $ \ bioPtr ->-      _read_bio_X509 bioPtr nullPtr -           >>= failIfNull-           >>= wrapX509 ---- |@'readDerX509' der@ reads in a certificate.-readDerX509 :: ByteString -> IO X509-readDerX509 derStr-    = newConstMemLBS derStr >>= readX509'---- |@'compareX509' cert1 cert2@ compares two certificates.-compareX509 :: X509 -> X509 -> IO Ordering-compareX509 cert1 cert2-    = withX509Ptr cert1 $ \ cert1Ptr ->-      withX509Ptr cert2 $ \ cert2Ptr ->-      fmap interpret (_cmp cert1Ptr cert2Ptr)-    where-      interpret :: CInt -> Ordering-      interpret n-          | n > 0     = GT-          | n < 0     = LT-          | otherwise = EQ---- |@'signX509'@ signs a certificate with an issuer private key.-signX509 :: KeyPair key =>-            X509         -- ^ The certificate to be signed.-         -> key          -- ^ The private key to sign with.-         -> Maybe Digest -- ^ A hashing algorithm to use. If @Nothing@-                         --   the most suitable algorithm for the key-                         --   is automatically used.-         -> IO ()-signX509 x509 key mDigest-    = withX509Ptr x509 $ \ x509Ptr ->-      withPKeyPtr' key $ \ pkeyPtr ->-      do dig <- case mDigest of-                  Just md -> return md-                  Nothing -> pkeyDefaultMD key-         withMDPtr dig $ \ digestPtr ->-             _sign x509Ptr pkeyPtr digestPtr-                  >>= failIf_ (== 0)-         return ()---- |@'verifyX509'@ verifies a signature of certificate with an issuer--- public key.-verifyX509 :: PublicKey key =>-              X509 -- ^ The certificate to be verified.-           -> key  -- ^ The public key to verify with.-           -> IO VerifyStatus-verifyX509 x509 key-    = withX509Ptr x509 $ \ x509Ptr ->-      withPKeyPtr' key $ \ pkeyPtr ->-      _verify x509Ptr pkeyPtr-           >>= interpret-    where-      interpret :: CInt -> IO VerifyStatus-      interpret 1 = return VerifySuccess-      interpret 0 = return VerifyFailure-      interpret _ = raiseOpenSSLError---- |@'printX509' cert@ translates a certificate into human-readable--- format.-printX509 :: X509 -> IO String-printX509 x509-    = do mem <- newMem-         withX509Ptr x509 $ \ x509Ptr ->-             withBioPtr mem $ \ memPtr ->-                 _print memPtr x509Ptr-                      >>= failIf_ (/= 1)-         bioRead mem---- |@'getVersion' cert@ returns the version number of certificate. It--- seems the number is 0-origin: version 2 means X.509 v3.-getVersion :: X509 -> IO Int-getVersion x509-    = withX509Ptr x509 $ \ x509Ptr ->-      liftM fromIntegral $ _get_version x509Ptr---- |@'setVersion' cert ver@ updates the version number of certificate.-setVersion :: X509 -> Int -> IO ()-setVersion x509 ver-    = withX509Ptr x509 $ \ x509Ptr ->-      _set_version x509Ptr (fromIntegral ver)-           >>= failIf (/= 1)-           >>  return ()---- |@'getSerialNumber' cert@ returns the serial number of certificate.-getSerialNumber :: X509 -> IO Integer-getSerialNumber x509-    = withX509Ptr x509 $ \ x509Ptr ->-      _get_serialNumber x509Ptr-           >>= peekASN1Integer---- |@'setSerialNumber' cert num@ updates the serial number of--- certificate.-setSerialNumber :: X509 -> Integer -> IO ()-setSerialNumber x509 serial-    = withX509Ptr x509 $ \ x509Ptr ->-      withASN1Integer serial $ \ serialPtr ->-      _set_serialNumber x509Ptr serialPtr-           >>= failIf (/= 1)-           >>  return ()---- |@'getIssuerName'@ returns the issuer name of certificate.-getIssuerName :: X509 -- ^ The certificate to examine.-              -> Bool -- ^ @True@ if you want the keys of each parts-                      --   to be of long form (e.g. \"commonName\"),-                      --   or @False@ if you don't (e.g. \"CN\").-              -> IO [(String, String)] -- ^ Pairs of key and value,-                                       -- for example \[(\"C\",-                                       -- \"JP\"), (\"ST\",-                                       -- \"Some-State\"), ...\].-getIssuerName x509 wantLongName-    = withX509Ptr x509 $ \ x509Ptr ->-      do namePtr <- _get_issuer_name x509Ptr-         peekX509Name namePtr wantLongName---- |@'setIssuerName' cert name@ updates the issuer name of--- certificate. Keys of each parts may be of either long form or short--- form. See 'getIssuerName'.-setIssuerName :: X509 -> [(String, String)] -> IO ()-setIssuerName x509 issuer-    = withX509Ptr x509 $ \ x509Ptr ->-      withX509Name issuer $ \ namePtr ->-      _set_issuer_name x509Ptr namePtr-           >>= failIf (/= 1)-           >>  return ()---- |@'getSubjectName' cert wantLongName@ returns the subject name of--- certificate. See 'getIssuerName'.-getSubjectName :: X509 -> Bool -> IO [(String, String)]-getSubjectName x509 wantLongName-    = withX509Ptr x509 $ \ x509Ptr ->-      do namePtr <- _get_subject_name x509Ptr-         peekX509Name namePtr wantLongName---- |@'setSubjectName' cert name@ updates the subject name of--- certificate. See 'setIssuerName'.-setSubjectName :: X509 -> [(String, String)] -> IO ()-setSubjectName x509 subject-    = withX509Ptr x509 $ \ x509Ptr ->-      withX509Name subject $ \ namePtr ->-      _set_subject_name x509Ptr namePtr-           >>= failIf (/= 1)-           >>  return ()---- |@'getNotBefore' cert@ returns the time when the certificate begins--- to be valid.-getNotBefore :: X509 -> IO UTCTime-getNotBefore x509-    = withX509Ptr x509 $ \ x509Ptr ->-      _get_notBefore x509Ptr-           >>= peekASN1Time---- |@'setNotBefore' cert utc@ updates the time when the certificate--- begins to be valid.-setNotBefore :: X509 -> UTCTime -> IO ()-setNotBefore x509 utc-    = withX509Ptr x509 $ \ x509Ptr ->-      withASN1Time utc $ \ time ->-      _set_notBefore x509Ptr time-           >>= failIf (/= 1)-           >>  return ()---- |@'getNotAfter' cert@ returns the time when the certificate--- expires.-getNotAfter :: X509 -> IO UTCTime-getNotAfter x509-    = withX509Ptr x509 $ \ x509Ptr ->-      _get_notAfter x509Ptr-           >>= peekASN1Time---- |@'setNotAfter' cert utc@ updates the time when the certificate--- expires.-setNotAfter :: X509 -> UTCTime -> IO ()-setNotAfter x509 utc-    = withX509Ptr x509 $ \ x509Ptr ->-      withASN1Time utc $ \ time ->-      _set_notAfter x509Ptr time-           >>= failIf (/= 1)-           >>  return ()---- |@'getPublicKey' cert@ returns the public key of the subject of--- certificate.-getPublicKey :: X509 -> IO SomePublicKey-getPublicKey x509-    = withX509Ptr x509 $ \ x509Ptr ->-      fmap fromJust ( _get_pubkey x509Ptr-                      >>= failIfNull-                      >>= wrapPKeyPtr-                      >>= fromPKey-                    )---- |@'setPublicKey' cert pubkey@ updates the public key of the subject--- of certificate.-setPublicKey :: PublicKey key => X509 -> key -> IO ()-setPublicKey x509 key-    = withX509Ptr x509 $ \ x509Ptr ->-      withPKeyPtr' key $ \ pkeyPtr ->-      _set_pubkey x509Ptr pkeyPtr-           >>= failIf (/= 1)-           >>  return ()---- |@'getSubjectEmail' cert@ returns every subject email addresses in--- the certificate.-getSubjectEmail :: X509 -> IO [String]-getSubjectEmail x509-    = withX509Ptr x509 $ \ x509Ptr ->-      do st   <- _get1_email x509Ptr-         list <- mapStack peekCString st-         _email_free st-         return list
+ OpenSSL/X509.hsc view
@@ -0,0 +1,430 @@+{-# LANGUAGE EmptyDataDecls           #-}+{-# LANGUAGE ForeignFunctionInterface #-}+{-# OPTIONS_HADDOCK prune             #-}+-- |An interface to X.509 certificate.+module OpenSSL.X509+    ( -- * Type+      X509+    , X509_++      -- * Functions to manipulate certificate+    , newX509+    , wrapX509 -- private+    , withX509Ptr -- private+    , withX509Stack -- private+    , unsafeX509ToPtr -- private+    , touchX509 -- private++    , writeDerX509+    , readDerX509+    , compareX509++    , signX509+    , verifyX509++    , printX509++      -- * Accessors+    , getVersion+    , setVersion++    , getSerialNumber+    , setSerialNumber++    , getIssuerName+    , setIssuerName++    , getSubjectName+    , setSubjectName++    , getNotBefore+    , setNotBefore++    , getNotAfter+    , setNotAfter++    , getPublicKey+    , setPublicKey++    , getSubjectEmail+    )+    where+#include "HsOpenSSL.h"+import Control.Monad+import Data.Time.Clock+import Data.Maybe+import Foreign.ForeignPtr+#if MIN_VERSION_base(4,4,0)+import Foreign.ForeignPtr.Unsafe as Unsafe+#else+import Foreign.ForeignPtr as Unsafe+#endif+import Foreign.Ptr+import Foreign.C+import OpenSSL.ASN1+import OpenSSL.BIO+import OpenSSL.EVP.Digest+import OpenSSL.EVP.PKey+import OpenSSL.EVP.Verify+import OpenSSL.EVP.Internal+import OpenSSL.Utils+import OpenSSL.Stack+import OpenSSL.X509.Name+import Data.ByteString.Lazy (ByteString)++-- |@'X509'@ is an opaque object that represents X.509 certificate.+newtype X509  = X509 (ForeignPtr X509_)+data    X509_+++foreign import ccall unsafe "X509_new"+        _new :: IO (Ptr X509_)++foreign import ccall unsafe "&X509_free"+        _free :: FunPtr (Ptr X509_ -> IO ())++foreign import ccall unsafe "X509_print"+        _print :: Ptr BIO_ -> Ptr X509_ -> IO CInt++foreign import ccall unsafe "X509_cmp"+        _cmp :: Ptr X509_ -> Ptr X509_ -> IO CInt++foreign import ccall unsafe "HsOpenSSL_X509_get_version"+        _get_version :: Ptr X509_ -> IO CLong++foreign import ccall unsafe "X509_set_version"+        _set_version :: Ptr X509_ -> CLong -> IO CInt++foreign import ccall unsafe "X509_get_serialNumber"+        _get_serialNumber :: Ptr X509_ -> IO (Ptr ASN1_INTEGER)++foreign import ccall unsafe "X509_set_serialNumber"+        _set_serialNumber :: Ptr X509_ -> Ptr ASN1_INTEGER -> IO CInt++foreign import ccall unsafe "X509_get_issuer_name"+        _get_issuer_name :: Ptr X509_ -> IO (Ptr X509_NAME)++foreign import ccall unsafe "X509_set_issuer_name"+        _set_issuer_name :: Ptr X509_ -> Ptr X509_NAME -> IO CInt++foreign import ccall unsafe "X509_get_subject_name"+        _get_subject_name :: Ptr X509_ -> IO (Ptr X509_NAME)++foreign import ccall unsafe "X509_set_subject_name"+        _set_subject_name :: Ptr X509_ -> Ptr X509_NAME -> IO CInt++foreign import ccall unsafe "HsOpenSSL_X509_get_notBefore"+        _get_notBefore :: Ptr X509_ -> IO (Ptr ASN1_TIME)++foreign import ccall unsafe "HsOpenSSL_X509_get_notAfter"+        _get_notAfter :: Ptr X509_ -> IO (Ptr ASN1_TIME)++#if OPENSSL_VERSION_NUMBER >= 0x10100000L+foreign import ccall unsafe "X509_set1_notBefore"+        _set_notBefore :: Ptr X509_ -> Ptr ASN1_TIME -> IO CInt++foreign import ccall unsafe "X509_set1_notAfter"+        _set_notAfter :: Ptr X509_ -> Ptr ASN1_TIME -> IO CInt+#else+foreign import ccall unsafe "X509_set_notBefore"+        _set_notBefore :: Ptr X509_ -> Ptr ASN1_TIME -> IO CInt++foreign import ccall unsafe "X509_set_notAfter"+        _set_notAfter :: Ptr X509_ -> Ptr ASN1_TIME -> IO CInt+#endif++foreign import ccall unsafe "X509_get_pubkey"+        _get_pubkey :: Ptr X509_ -> IO (Ptr EVP_PKEY)++foreign import ccall unsafe "X509_set_pubkey"+        _set_pubkey :: Ptr X509_ -> Ptr EVP_PKEY -> IO CInt++foreign import ccall unsafe "X509_get1_email"+        _get1_email :: Ptr X509_ -> IO (Ptr STACK)++foreign import ccall unsafe "X509_email_free"+        _email_free :: Ptr STACK -> IO ()++foreign import ccall unsafe "X509_sign"+        _sign :: Ptr X509_ -> Ptr EVP_PKEY -> Ptr EVP_MD -> IO CInt++foreign import ccall unsafe "X509_verify"+        _verify :: Ptr X509_ -> Ptr EVP_PKEY -> IO CInt++foreign import ccall safe "i2d_X509_bio"+        _write_bio_X509 :: Ptr BIO_+                        -> Ptr X509_+                        -> IO CInt++foreign import ccall safe "d2i_X509_bio"+        _read_bio_X509 :: Ptr BIO_+                       -> Ptr (Ptr X509_)+                       -> IO (Ptr X509_)++-- |@'newX509'@ creates an empty certificate. You must set the+-- following properties to and sign it (see 'signX509') to actually+-- use the certificate.+--+--   [/Version/] See 'setVersion'.+--+--   [/Serial number/] See 'setSerialNumber'.+--+--   [/Issuer name/] See 'setIssuerName'.+--+--   [/Subject name/] See 'setSubjectName'.+--+--   [/Validity/] See 'setNotBefore' and 'setNotAfter'.+--+--   [/Public Key/] See 'setPublicKey'.+--+newX509 :: IO X509+newX509 = _new >>= failIfNull >>= wrapX509+++wrapX509 :: Ptr X509_ -> IO X509+wrapX509 = fmap X509 . newForeignPtr _free+++withX509Ptr :: X509 -> (Ptr X509_ -> IO a) -> IO a+withX509Ptr (X509 x509) = withForeignPtr x509+++withX509Stack :: [X509] -> (Ptr STACK -> IO a) -> IO a+withX509Stack = withForeignStack unsafeX509ToPtr touchX509+++unsafeX509ToPtr :: X509 -> Ptr X509_+unsafeX509ToPtr (X509 x509) = Unsafe.unsafeForeignPtrToPtr x509+++touchX509 :: X509 -> IO ()+touchX509 (X509 x509) = touchForeignPtr x509++writeX509' :: BIO -> X509 -> IO ()+writeX509' bio x509+    = withBioPtr bio   $ \ bioPtr ->+      withX509Ptr x509 $ \ x509Ptr ->+      _write_bio_X509 bioPtr x509Ptr+           >>= failIf (< 0)+           >>  return ()++-- |@'writeDerX509' cert@ writes an X.509 certificate to DER string.+writeDerX509 :: X509 -> IO ByteString+writeDerX509 x509+    = do mem <- newMem+         writeX509' mem x509+         bioReadLBS mem++readX509' :: BIO -> IO X509+readX509' bio+    = withBioPtr bio $ \ bioPtr ->+      _read_bio_X509 bioPtr nullPtr +           >>= failIfNull+           >>= wrapX509 ++-- |@'readDerX509' der@ reads in a certificate.+readDerX509 :: ByteString -> IO X509+readDerX509 derStr+    = newConstMemLBS derStr >>= readX509'++-- |@'compareX509' cert1 cert2@ compares two certificates.+compareX509 :: X509 -> X509 -> IO Ordering+compareX509 cert1 cert2+    = withX509Ptr cert1 $ \ cert1Ptr ->+      withX509Ptr cert2 $ \ cert2Ptr ->+      fmap interpret (_cmp cert1Ptr cert2Ptr)+    where+      interpret :: CInt -> Ordering+      interpret n+          | n > 0     = GT+          | n < 0     = LT+          | otherwise = EQ++-- |@'signX509'@ signs a certificate with an issuer private key.+signX509 :: KeyPair key =>+            X509         -- ^ The certificate to be signed.+         -> key          -- ^ The private key to sign with.+         -> Maybe Digest -- ^ A hashing algorithm to use. If @Nothing@+                         --   the most suitable algorithm for the key+                         --   is automatically used.+         -> IO ()+signX509 x509 key mDigest+    = withX509Ptr x509 $ \ x509Ptr ->+      withPKeyPtr' key $ \ pkeyPtr ->+      do dig <- case mDigest of+                  Just md -> return md+                  Nothing -> pkeyDefaultMD key+         withMDPtr dig $ \ digestPtr ->+             _sign x509Ptr pkeyPtr digestPtr+                  >>= failIf_ (== 0)+         return ()++-- |@'verifyX509'@ verifies a signature of certificate with an issuer+-- public key.+verifyX509 :: PublicKey key =>+              X509 -- ^ The certificate to be verified.+           -> key  -- ^ The public key to verify with.+           -> IO VerifyStatus+verifyX509 x509 key+    = withX509Ptr x509 $ \ x509Ptr ->+      withPKeyPtr' key $ \ pkeyPtr ->+      _verify x509Ptr pkeyPtr+           >>= interpret+    where+      interpret :: CInt -> IO VerifyStatus+      interpret 1 = return VerifySuccess+      interpret 0 = return VerifyFailure+      interpret _ = raiseOpenSSLError++-- |@'printX509' cert@ translates a certificate into human-readable+-- format.+printX509 :: X509 -> IO String+printX509 x509+    = do mem <- newMem+         withX509Ptr x509 $ \ x509Ptr ->+             withBioPtr mem $ \ memPtr ->+                 _print memPtr x509Ptr+                      >>= failIf_ (/= 1)+         bioRead mem++-- |@'getVersion' cert@ returns the version number of certificate. It+-- seems the number is 0-origin: version 2 means X.509 v3.+getVersion :: X509 -> IO Int+getVersion x509+    = withX509Ptr x509 $ \ x509Ptr ->+      liftM fromIntegral $ _get_version x509Ptr++-- |@'setVersion' cert ver@ updates the version number of certificate.+setVersion :: X509 -> Int -> IO ()+setVersion x509 ver+    = withX509Ptr x509 $ \ x509Ptr ->+      _set_version x509Ptr (fromIntegral ver)+           >>= failIf (/= 1)+           >>  return ()++-- |@'getSerialNumber' cert@ returns the serial number of certificate.+getSerialNumber :: X509 -> IO Integer+getSerialNumber x509+    = withX509Ptr x509 $ \ x509Ptr ->+      _get_serialNumber x509Ptr+           >>= peekASN1Integer++-- |@'setSerialNumber' cert num@ updates the serial number of+-- certificate.+setSerialNumber :: X509 -> Integer -> IO ()+setSerialNumber x509 serial+    = withX509Ptr x509 $ \ x509Ptr ->+      withASN1Integer serial $ \ serialPtr ->+      _set_serialNumber x509Ptr serialPtr+           >>= failIf (/= 1)+           >>  return ()++-- |@'getIssuerName'@ returns the issuer name of certificate.+getIssuerName :: X509 -- ^ The certificate to examine.+              -> Bool -- ^ @True@ if you want the keys of each parts+                      --   to be of long form (e.g. \"commonName\"),+                      --   or @False@ if you don't (e.g. \"CN\").+              -> IO [(String, String)] -- ^ Pairs of key and value,+                                       -- for example \[(\"C\",+                                       -- \"JP\"), (\"ST\",+                                       -- \"Some-State\"), ...\].+getIssuerName x509 wantLongName+    = withX509Ptr x509 $ \ x509Ptr ->+      do namePtr <- _get_issuer_name x509Ptr+         peekX509Name namePtr wantLongName++-- |@'setIssuerName' cert name@ updates the issuer name of+-- certificate. Keys of each parts may be of either long form or short+-- form. See 'getIssuerName'.+setIssuerName :: X509 -> [(String, String)] -> IO ()+setIssuerName x509 issuer+    = withX509Ptr x509 $ \ x509Ptr ->+      withX509Name issuer $ \ namePtr ->+      _set_issuer_name x509Ptr namePtr+           >>= failIf (/= 1)+           >>  return ()++-- |@'getSubjectName' cert wantLongName@ returns the subject name of+-- certificate. See 'getIssuerName'.+getSubjectName :: X509 -> Bool -> IO [(String, String)]+getSubjectName x509 wantLongName+    = withX509Ptr x509 $ \ x509Ptr ->+      do namePtr <- _get_subject_name x509Ptr+         peekX509Name namePtr wantLongName++-- |@'setSubjectName' cert name@ updates the subject name of+-- certificate. See 'setIssuerName'.+setSubjectName :: X509 -> [(String, String)] -> IO ()+setSubjectName x509 subject+    = withX509Ptr x509 $ \ x509Ptr ->+      withX509Name subject $ \ namePtr ->+      _set_subject_name x509Ptr namePtr+           >>= failIf (/= 1)+           >>  return ()++-- |@'getNotBefore' cert@ returns the time when the certificate begins+-- to be valid.+getNotBefore :: X509 -> IO UTCTime+getNotBefore x509+    = withX509Ptr x509 $ \ x509Ptr ->+      _get_notBefore x509Ptr+           >>= peekASN1Time++-- |@'setNotBefore' cert utc@ updates the time when the certificate+-- begins to be valid.+setNotBefore :: X509 -> UTCTime -> IO ()+setNotBefore x509 utc+    = withX509Ptr x509 $ \ x509Ptr ->+      withASN1Time utc $ \ time ->+      _set_notBefore x509Ptr time+           >>= failIf (/= 1)+           >>  return ()++-- |@'getNotAfter' cert@ returns the time when the certificate+-- expires.+getNotAfter :: X509 -> IO UTCTime+getNotAfter x509+    = withX509Ptr x509 $ \ x509Ptr ->+      _get_notAfter x509Ptr+           >>= peekASN1Time++-- |@'setNotAfter' cert utc@ updates the time when the certificate+-- expires.+setNotAfter :: X509 -> UTCTime -> IO ()+setNotAfter x509 utc+    = withX509Ptr x509 $ \ x509Ptr ->+      withASN1Time utc $ \ time ->+      _set_notAfter x509Ptr time+           >>= failIf (/= 1)+           >>  return ()++-- |@'getPublicKey' cert@ returns the public key of the subject of+-- certificate.+getPublicKey :: X509 -> IO SomePublicKey+getPublicKey x509+    = withX509Ptr x509 $ \ x509Ptr ->+      fmap fromJust ( _get_pubkey x509Ptr+                      >>= failIfNull+                      >>= wrapPKeyPtr+                      >>= fromPKey+                    )++-- |@'setPublicKey' cert pubkey@ updates the public key of the subject+-- of certificate.+setPublicKey :: PublicKey key => X509 -> key -> IO ()+setPublicKey x509 key+    = withX509Ptr x509 $ \ x509Ptr ->+      withPKeyPtr' key $ \ pkeyPtr ->+      _set_pubkey x509Ptr pkeyPtr+           >>= failIf (/= 1)+           >>  return ()++-- |@'getSubjectEmail' cert@ returns every subject email addresses in+-- the certificate.+getSubjectEmail :: X509 -> IO [String]+getSubjectEmail x509+    = withX509Ptr x509 $ \ x509Ptr ->+      do st   <- _get1_email x509Ptr+         list <- mapStack peekCString st+         _email_free st+         return list
OpenSSL/X509/Revocation.hsc view
@@ -100,14 +100,22 @@ foreign import ccall unsafe "HsOpenSSL_X509_CRL_get_lastUpdate"         _get_lastUpdate :: Ptr X509_CRL -> IO (Ptr ASN1_TIME) -foreign import ccall unsafe "X509_CRL_set_lastUpdate"-        _set_lastUpdate :: Ptr X509_CRL -> Ptr ASN1_TIME -> IO CInt- foreign import ccall unsafe "HsOpenSSL_X509_CRL_get_nextUpdate"         _get_nextUpdate :: Ptr X509_CRL -> IO (Ptr ASN1_TIME) +#if OPENSSL_VERSION_NUMBER >= 0x10100000L+foreign import ccall unsafe "X509_CRL_set1_lastUpdate"+        _set_lastUpdate :: Ptr X509_CRL -> Ptr ASN1_TIME -> IO CInt++foreign import ccall unsafe "X509_CRL_set1_nextUpdate"+        _set_nextUpdate :: Ptr X509_CRL -> Ptr ASN1_TIME -> IO CInt+#else+foreign import ccall unsafe "X509_CRL_set_lastUpdate"+        _set_lastUpdate :: Ptr X509_CRL -> Ptr ASN1_TIME -> IO CInt+ foreign import ccall unsafe "X509_CRL_set_nextUpdate"         _set_nextUpdate :: Ptr X509_CRL -> Ptr ASN1_TIME -> IO CInt+#endif  foreign import ccall unsafe "HsOpenSSL_X509_CRL_get_issuer"         _get_issuer_name :: Ptr X509_CRL -> IO (Ptr X509_NAME)
− OpenSSL/X509/Store.hs
@@ -1,147 +0,0 @@-{-# LANGUAGE CPP                      #-}-{-# LANGUAGE EmptyDataDecls           #-}-{-# LANGUAGE ForeignFunctionInterface #-}-{-# OPTIONS_HADDOCK prune             #-}--- |An interface to X.509 certificate store.-module OpenSSL.X509.Store-    ( X509Store-    , X509_STORE -- private--    , newX509Store--    , wrapX509Store -- private-    , withX509StorePtr -- private--    , addCertToStore-    , addCRLToStore--    , X509StoreCtx-    , X509_STORE_CTX -- private--    , withX509StoreCtxPtr -- private-    , wrapX509StoreCtx -- private--    , getStoreCtxCert-    , getStoreCtxIssuer-    , getStoreCtxCRL-    , getStoreCtxChain-    )-    where-#if !MIN_VERSION_base(4,8,0)-import Control.Applicative ((<$>))-#endif-import Control.Exception (throwIO, mask_)-import Foreign-import Foreign.C-import Foreign.Concurrent as FC-import OpenSSL.X509-import OpenSSL.X509.Revocation-import OpenSSL.Stack-import OpenSSL.Utils---- |@'X509Store'@ is an opaque object that represents X.509--- certificate store. The certificate store is usually used for chain--- verification.-newtype X509Store  = X509Store (ForeignPtr X509_STORE)-data    X509_STORE---foreign import ccall unsafe "X509_STORE_new"-        _new :: IO (Ptr X509_STORE)--foreign import ccall unsafe "X509_STORE_free"-        _free :: Ptr X509_STORE -> IO ()--foreign import ccall unsafe "X509_STORE_add_cert"-        _add_cert :: Ptr X509_STORE -> Ptr X509_ -> IO CInt--foreign import ccall unsafe "X509_STORE_add_crl"-        _add_crl :: Ptr X509_STORE -> Ptr X509_CRL -> IO CInt---- |@'newX509Store'@ creates an empty X.509 certificate store.-newX509Store :: IO X509Store-newX509Store = _new-               >>= failIfNull-               >>= \ ptr -> wrapX509Store (_free ptr) ptr--wrapX509Store :: IO () -> Ptr X509_STORE -> IO X509Store-wrapX509Store finaliser ptr-    = do fp <- newForeignPtr_ ptr-         FC.addForeignPtrFinalizer fp finaliser-         return $ X509Store fp--withX509StorePtr :: X509Store -> (Ptr X509_STORE -> IO a) -> IO a-withX509StorePtr (X509Store store)-    = withForeignPtr store---- |@'addCertToStore' store cert@ adds a certificate to store.-addCertToStore :: X509Store -> X509 -> IO ()-addCertToStore store cert-    = withX509StorePtr store $ \ storePtr ->-      withX509Ptr cert       $ \ certPtr  ->-      _add_cert storePtr certPtr-           >>= failIf (/= 1)-           >>  return ()---- |@'addCRLToStore' store crl@ adds a revocation list to store.-addCRLToStore :: X509Store -> CRL -> IO ()-addCRLToStore store crl-    = withX509StorePtr store $ \ storePtr ->-      withCRLPtr crl         $ \ crlPtr   ->-      _add_crl storePtr crlPtr-           >>= failIf (/= 1)-           >>  return ()--data    X509_STORE_CTX-newtype X509StoreCtx = X509StoreCtx (ForeignPtr X509_STORE_CTX)--foreign import ccall unsafe "X509_STORE_CTX_get_current_cert"-  _store_ctx_get_current_cert :: Ptr X509_STORE_CTX -> IO (Ptr X509_)--foreign import ccall unsafe "HsOpenSSL_X509_STORE_CTX_get0_current_issuer"-  _store_ctx_get0_current_issuer :: Ptr X509_STORE_CTX -> IO (Ptr X509_)--foreign import ccall unsafe "HsOpenSSL_X509_STORE_CTX_get0_current_crl"-  _store_ctx_get0_current_crl :: Ptr X509_STORE_CTX -> IO (Ptr X509_CRL)--foreign import ccall unsafe "X509_STORE_CTX_get_chain"-  _store_ctx_get_chain :: Ptr X509_STORE_CTX -> IO (Ptr STACK)--foreign import ccall unsafe "HsOpenSSL_X509_ref"-  _x509_ref :: Ptr X509_ -> IO ()--foreign import ccall unsafe "HsOpenSSL_X509_CRL_ref"-  _crl_ref :: Ptr X509_CRL -> IO ()--withX509StoreCtxPtr :: X509StoreCtx -> (Ptr X509_STORE_CTX -> IO a) -> IO a-withX509StoreCtxPtr (X509StoreCtx fp) = withForeignPtr fp--wrapX509StoreCtx :: IO () -> Ptr X509_STORE_CTX -> IO X509StoreCtx-wrapX509StoreCtx finaliser ptr =-  X509StoreCtx <$> FC.newForeignPtr ptr finaliser--getStoreCtxCert :: X509StoreCtx -> IO X509-getStoreCtxCert ctx = withX509StoreCtxPtr ctx $ \pCtx -> do-  pCert <- _store_ctx_get_current_cert pCtx-  if pCert == nullPtr-    then throwIO $ userError "BUG: NULL certificate in X509_STORE_CTX"-    else mask_ $ _x509_ref pCert >> wrapX509 pCert--getStoreCtxIssuer :: X509StoreCtx -> IO (Maybe X509)-getStoreCtxIssuer ctx = withX509StoreCtxPtr ctx $ \pCtx -> do-  pCert <- _store_ctx_get0_current_issuer pCtx-  if pCert == nullPtr-    then return Nothing-    else fmap Just $ mask_ $ _x509_ref pCert >> wrapX509 pCert--getStoreCtxCRL :: X509StoreCtx -> IO (Maybe CRL)-getStoreCtxCRL ctx = withX509StoreCtxPtr ctx $ \pCtx -> do-  pCrl <- _store_ctx_get0_current_crl pCtx-  if pCrl == nullPtr-    then return Nothing-    else fmap Just $ mask_ $ _crl_ref pCrl >> wrapCRL pCrl--getStoreCtxChain :: X509StoreCtx -> IO [X509]-getStoreCtxChain ctx = withX509StoreCtxPtr ctx $ \pCtx -> do-  stack <- _store_ctx_get_chain pCtx-  (`mapStack` stack) $ \pCert -> mask_ $ _x509_ref pCert >> wrapX509 pCert
+ OpenSSL/X509/Store.hsc view
@@ -0,0 +1,152 @@+{-# LANGUAGE EmptyDataDecls           #-}+{-# LANGUAGE ForeignFunctionInterface #-}+{-# OPTIONS_HADDOCK prune             #-}+-- |An interface to X.509 certificate store.+module OpenSSL.X509.Store+    ( X509Store+    , X509_STORE -- private++    , newX509Store++    , wrapX509Store -- private+    , withX509StorePtr -- private++    , addCertToStore+    , addCRLToStore++    , X509StoreCtx+    , X509_STORE_CTX -- private++    , withX509StoreCtxPtr -- private+    , wrapX509StoreCtx -- private++    , getStoreCtxCert+    , getStoreCtxIssuer+    , getStoreCtxCRL+    , getStoreCtxChain+    )+    where+#include "HsOpenSSL.h"+#if !MIN_VERSION_base(4,8,0)+import Control.Applicative ((<$>))+#endif+import Control.Exception (throwIO, mask_)+import Foreign+import Foreign.C+import Foreign.Concurrent as FC+import OpenSSL.X509+import OpenSSL.X509.Revocation+import OpenSSL.Stack+import OpenSSL.Utils++-- |@'X509Store'@ is an opaque object that represents X.509+-- certificate store. The certificate store is usually used for chain+-- verification.+newtype X509Store  = X509Store (ForeignPtr X509_STORE)+data    X509_STORE+++foreign import ccall unsafe "X509_STORE_new"+        _new :: IO (Ptr X509_STORE)++foreign import ccall unsafe "X509_STORE_free"+        _free :: Ptr X509_STORE -> IO ()++foreign import ccall unsafe "X509_STORE_add_cert"+        _add_cert :: Ptr X509_STORE -> Ptr X509_ -> IO CInt++foreign import ccall unsafe "X509_STORE_add_crl"+        _add_crl :: Ptr X509_STORE -> Ptr X509_CRL -> IO CInt++-- |@'newX509Store'@ creates an empty X.509 certificate store.+newX509Store :: IO X509Store+newX509Store = _new+               >>= failIfNull+               >>= \ ptr -> wrapX509Store (_free ptr) ptr++wrapX509Store :: IO () -> Ptr X509_STORE -> IO X509Store+wrapX509Store finaliser ptr+    = do fp <- newForeignPtr_ ptr+         FC.addForeignPtrFinalizer fp finaliser+         return $ X509Store fp++withX509StorePtr :: X509Store -> (Ptr X509_STORE -> IO a) -> IO a+withX509StorePtr (X509Store store)+    = withForeignPtr store++-- |@'addCertToStore' store cert@ adds a certificate to store.+addCertToStore :: X509Store -> X509 -> IO ()+addCertToStore store cert+    = withX509StorePtr store $ \ storePtr ->+      withX509Ptr cert       $ \ certPtr  ->+      _add_cert storePtr certPtr+           >>= failIf (/= 1)+           >>  return ()++-- |@'addCRLToStore' store crl@ adds a revocation list to store.+addCRLToStore :: X509Store -> CRL -> IO ()+addCRLToStore store crl+    = withX509StorePtr store $ \ storePtr ->+      withCRLPtr crl         $ \ crlPtr   ->+      _add_crl storePtr crlPtr+           >>= failIf (/= 1)+           >>  return ()++data    X509_STORE_CTX+newtype X509StoreCtx = X509StoreCtx (ForeignPtr X509_STORE_CTX)++foreign import ccall unsafe "X509_STORE_CTX_get_current_cert"+  _store_ctx_get_current_cert :: Ptr X509_STORE_CTX -> IO (Ptr X509_)++foreign import ccall unsafe "HsOpenSSL_X509_STORE_CTX_get0_current_issuer"+  _store_ctx_get0_current_issuer :: Ptr X509_STORE_CTX -> IO (Ptr X509_)++foreign import ccall unsafe "HsOpenSSL_X509_STORE_CTX_get0_current_crl"+  _store_ctx_get0_current_crl :: Ptr X509_STORE_CTX -> IO (Ptr X509_CRL)++#if OPENSSL_VERSION_NUMBER >= 0x10100000L+foreign import ccall unsafe "X509_STORE_CTX_get1_chain"+  _store_ctx_get_chain :: Ptr X509_STORE_CTX -> IO (Ptr STACK)+#else+foreign import ccall unsafe "X509_STORE_CTX_get_chain"+  _store_ctx_get_chain :: Ptr X509_STORE_CTX -> IO (Ptr STACK)+#endif++foreign import ccall unsafe "HsOpenSSL_X509_ref"+  _x509_ref :: Ptr X509_ -> IO ()++foreign import ccall unsafe "HsOpenSSL_X509_CRL_ref"+  _crl_ref :: Ptr X509_CRL -> IO ()++withX509StoreCtxPtr :: X509StoreCtx -> (Ptr X509_STORE_CTX -> IO a) -> IO a+withX509StoreCtxPtr (X509StoreCtx fp) = withForeignPtr fp++wrapX509StoreCtx :: IO () -> Ptr X509_STORE_CTX -> IO X509StoreCtx+wrapX509StoreCtx finaliser ptr =+  X509StoreCtx <$> FC.newForeignPtr ptr finaliser++getStoreCtxCert :: X509StoreCtx -> IO X509+getStoreCtxCert ctx = withX509StoreCtxPtr ctx $ \pCtx -> do+  pCert <- _store_ctx_get_current_cert pCtx+  if pCert == nullPtr+    then throwIO $ userError "BUG: NULL certificate in X509_STORE_CTX"+    else mask_ $ _x509_ref pCert >> wrapX509 pCert++getStoreCtxIssuer :: X509StoreCtx -> IO (Maybe X509)+getStoreCtxIssuer ctx = withX509StoreCtxPtr ctx $ \pCtx -> do+  pCert <- _store_ctx_get0_current_issuer pCtx+  if pCert == nullPtr+    then return Nothing+    else fmap Just $ mask_ $ _x509_ref pCert >> wrapX509 pCert++getStoreCtxCRL :: X509StoreCtx -> IO (Maybe CRL)+getStoreCtxCRL ctx = withX509StoreCtxPtr ctx $ \pCtx -> do+  pCrl <- _store_ctx_get0_current_crl pCtx+  if pCrl == nullPtr+    then return Nothing+    else fmap Just $ mask_ $ _crl_ref pCrl >> wrapCRL pCrl++getStoreCtxChain :: X509StoreCtx -> IO [X509]+getStoreCtxChain ctx = withX509StoreCtxPtr ctx $ \pCtx -> do+  stack <- _store_ctx_get_chain pCtx+  (`mapStack` stack) $ \pCert -> mask_ $ _x509_ref pCert >> wrapX509 pCert