packages feed

HsOpenSSL (empty) → 0.1

raw patch · 37 files changed

+7426/−0 lines, 37 filesdep +basedep +timebuild-type:Customsetup-changed

Dependencies added: base, time

Files

+ COPYING view
@@ -0,0 +1,29 @@+<!-- -*- xml -*-++HsOpenSSL はパブリックドメインに在ります。+HsOpenSSL is in the public domain.++See http://creativecommons.org/licenses/publicdomain/++-->++<rdf:RDF xmlns="http://web.resource.org/cc/"+	     xmlns:dc="http://purl.org/dc/elements/1.1/"+	     xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">+  <Work rdf:about="http://ccm.sherry.jp/HsOpenSSL/">+	<dc:title>HsOpenSSL</dc:title>+	<dc:rights>+      <Agent>+	    <dc:title>phonohawk</dc:title>+	  </Agent>+    </dc:rights>+	<license rdf:resource="http://web.resource.org/cc/PublicDomain" />+  </Work>+      +  <License rdf:about="http://web.resource.org/cc/PublicDomain">+	<permits rdf:resource="http://web.resource.org/cc/Reproduction" />+	<permits rdf:resource="http://web.resource.org/cc/Distribution" />+	<permits rdf:resource="http://web.resource.org/cc/DerivativeWorks" />+  </License>++</rdf:RDF>
+ HsOpenSSL.buildinfo.in view
@@ -0,0 +1,2 @@+cc-options: @OPENSSL_CFLAGS@+ld-options: @OPENSSL_LIBS@
+ HsOpenSSL.cabal view
@@ -0,0 +1,63 @@+Name: HsOpenSSL+Synopsis: (Part of) OpenSSL binding for Haskell+Description:+        HsOpenSSL is a (part of) OpenSSL binding for Haskell. It can+        generate RSA keys, read and write PEM files, generate message+        digests, sign and verify messages, encrypt and decrypt+        messages.+Version: 0.1+License: PublicDomain+License-File: COPYING+Author: PHO <phonohawk at ps dot sakura dot ne dot jp>+Maintainer: PHO <phonohawk at ps dot sakura dot ne dot jp>+Stability: experimental+Homepage: http://ccm.sherry.jp/HsOpenSSL/+Category: Cryptography+Tested-With: GHC == 6.6.1+Build-Depends:+        base, time+Exposed-Modules:+        OpenSSL+        OpenSSL.ASN1+        OpenSSL.BIO+        OpenSSL.BN+        OpenSSL.ERR+        OpenSSL.EVP.Base64+        OpenSSL.EVP.Cipher+        OpenSSL.EVP.Digest+        OpenSSL.EVP.Open+        OpenSSL.EVP.PKey+        OpenSSL.EVP.Seal+        OpenSSL.EVP.Sign+        OpenSSL.EVP.Verify+        OpenSSL.Objects+        OpenSSL.PEM+        OpenSSL.PKCS7+        OpenSSL.RSA+        OpenSSL.SSL+        OpenSSL.Stack+        OpenSSL.Utils+        OpenSSL.X509+        OpenSSL.X509.Revocation+        OpenSSL.X509.Name+        OpenSSL.X509.Request+        OpenSSL.X509.Store+Extensions:+        ForeignFunctionInterface+ghc-options:+        -fglasgow-exts -O2 -fwarn-unused-imports+C-Sources:+        cbits/HsOpenSSL.c+Include-Dirs:+        cbits+Install-Includes:+        HsOpenSSL.h+Extra-Source-Files:+        HsOpenSSL.buildinfo.in+        cbits/HsOpenSSL.h+        configure+        configure.ac+        examples/Makefile+        examples/GenRSAKey.hs+        examples/HelloWorld.hs+        examples/PKCS7.hs
+ OpenSSL.hsc view
@@ -0,0 +1,78 @@+{- -*- haskell -*- -}++-- |HsOpenSSL is a (part of) OpenSSL binding for Haskell. It can+-- generate RSA keys, read and write PEM files, generate message+-- digests, sign and verify messages, encrypt and decrypt messages.+-- But since OpenSSL is a very large library, it is uneasy to cover+-- everything in it.+--+-- Features that aren't (yet) supported:+--+--   [/TLS\/SSL network connection/] ssl(3) functionalities are+--   totally uncovered. They should be covered someday.+--+--   [/Low-level API to symmetric ciphers/] Only high-level APIs (EVP+--   and BIO) are available. But I believe no one will be lost without+--   functions like @DES_set_odd_parity@.+--+--   [/Low-level API to asymmetric ciphers/] Only a high-level API+--   (EVP) is available. But I believe no one will complain about the+--   absence of functions like @RSA_public_encrypt@.+--+--   [/Key generation of DSA and Diffie-Hellman algorithms/] Only RSA+--   keys can currently be generated.+--+--   [/X.509 v3 extension handling/] It should be supported in the+--   future.+--+--   [/HMAC message authentication/] +--+--   [/Low-level API to message digest functions/] Just use EVP or BIO+--   instead of something like @MD5_Update@.+--+--   [/pseudo-random number generator/] rand(3) functionalities are+--   uncovered, but OpenSSL works very well by default.+--+--   [/API to PKCS\#12 functionality/] It should be covered someday.+--+--   [/BIO/] BIO isn't needed because we are Haskell hackers. Though+--   HsOpenSSL itself uses BIO internally.+--+--   [/ENGINE cryptographic module/] The default implementations work+--   very well, don't they?+--+-- So if you find out some features you want aren't supported, you+-- must write your own patch. Happy hacking.++#include "HsOpenSSL.h"++module OpenSSL+    ( withOpenSSL+    )+    where++import OpenSSL.SSL+++foreign import ccall "HsOpenSSL_setupMutex"+        setupMutex :: IO ()+++-- |Computation of @'withOpenSSL' action@ initializes the OpenSSL+-- library and computes @action@. Every applications that use OpenSSL+-- must wrap any other operations related to OpenSSL or they might+-- crash.+--+-- > module Main where+-- > import OpenSSL+-- >+-- > main :: IO ()+-- > main = withOpenSSL $+-- >        do ...+--+withOpenSSL :: IO a -> IO a+withOpenSSL act+    = do loadErrorStrings+         addAllAlgorithms+         setupMutex+         act
+ OpenSSL/ASN1.hsc view
@@ -0,0 +1,166 @@+{- -*- haskell -*- -}++-- #hide++#include "HsOpenSSL.h"++module OpenSSL.ASN1+    ( ASN1_OBJECT+    , obj2nid+    , nid2sn+    , nid2ln++    , ASN1_STRING+    , peekASN1String++    , ASN1_INTEGER+    , peekASN1Integer+    , withASN1Integer++    , ASN1_TIME+    , peekASN1Time+    , withASN1Time+    )+    where+++import           Control.Exception+import           Control.Monad+import           Data.Time.Clock+import           Data.Time.Clock.POSIX+import           Data.Time.Format+import           Foreign+import           Foreign.C+import           OpenSSL.BIO+import           OpenSSL.BN+import           OpenSSL.Utils+import           System.Locale++{- ASN1_OBJECT --------------------------------------------------------------- -}++data ASN1_OBJECT++foreign import ccall unsafe "OBJ_obj2nid"+        obj2nid :: Ptr ASN1_OBJECT -> IO Int++foreign import ccall unsafe "OBJ_nid2sn"+        _nid2sn :: Int -> IO CString++foreign import ccall unsafe "OBJ_nid2ln"+        _nid2ln :: Int -> IO CString+++nid2sn :: Int -> IO String+nid2sn nid = _nid2sn nid >>= peekCString+++nid2ln :: Int -> IO String+nid2ln nid = _nid2ln nid >>= peekCString+++{- ASN1_STRING --------------------------------------------------------------- -}++data ASN1_STRING++peekASN1String :: Ptr ASN1_STRING -> IO String+peekASN1String strPtr+    = do buf <- (#peek ASN1_STRING, data  ) strPtr+         len <- (#peek ASN1_STRING, length) strPtr+         peekCStringLen (buf, len)+++{- ASN1_INTEGER -------------------------------------------------------------- -}++data ASN1_INTEGER++foreign import ccall unsafe "HsOpenSSL_M_ASN1_INTEGER_new"+        _ASN1_INTEGER_new :: IO (Ptr ASN1_INTEGER)++foreign import ccall unsafe "HsOpenSSL_M_ASN1_INTEGER_free"+        _ASN1_INTEGER_free :: Ptr ASN1_INTEGER -> IO ()++foreign import ccall unsafe "ASN1_INTEGER_to_BN"+        _ASN1_INTEGER_to_BN :: Ptr ASN1_INTEGER -> BigNum -> IO BigNum++foreign import ccall unsafe "BN_to_ASN1_INTEGER"+        _BN_to_ASN1_INTEGER :: BigNum -> Ptr ASN1_INTEGER -> IO (Ptr ASN1_INTEGER)+++peekASN1Integer :: Ptr ASN1_INTEGER -> IO Integer+peekASN1Integer intPtr+    = allocaBN $ \ bn ->+      do _ASN1_INTEGER_to_BN intPtr bn+              >>= failIfNull+         peekBN bn+++allocaASN1Integer :: (Ptr ASN1_INTEGER -> IO a) -> IO a+allocaASN1Integer m+    = bracket _ASN1_INTEGER_new _ASN1_INTEGER_free m+++withASN1Integer :: Integer -> (Ptr ASN1_INTEGER -> IO a) -> IO a+withASN1Integer int m+    = withBN int $ \ bn ->+      allocaASN1Integer $ \ intPtr ->+      do _BN_to_ASN1_INTEGER bn intPtr+              >>= failIfNull+         m intPtr+++{- ASN1_TIME ---------------------------------------------------------------- -}++data ASN1_TIME++foreign import ccall unsafe "HsOpenSSL_M_ASN1_TIME_new"+        _ASN1_TIME_new :: IO (Ptr ASN1_TIME)++foreign import ccall unsafe "HsOpenSSL_M_ASN1_TIME_free"+        _ASN1_TIME_free :: Ptr ASN1_TIME -> IO ()++foreign import ccall unsafe "ASN1_TIME_set"+        _ASN1_TIME_set :: Ptr ASN1_TIME -> CTime -> IO (Ptr ASN1_TIME)++foreign import ccall unsafe "ASN1_TIME_print"+        _ASN1_TIME_print :: Ptr BIO_ -> Ptr ASN1_TIME -> IO Int+++peekASN1Time :: Ptr ASN1_TIME -> IO UTCTime -- asn1/t_x509.c+peekASN1Time time+    = do bio <- newMem+         withBioPtr bio $ \ bioPtr ->+             _ASN1_TIME_print bioPtr time+                  >>= failIf (/= 1)+         timeStr <- bioRead bio+         case parseTime locale "%b %e %H:%M:%S %Y %Z" timeStr of+           Just utc -> return utc+           Nothing  -> fail ("peekASN1Time: failed to parse time string: " ++ timeStr)+    where+      locale :: TimeLocale+      locale = TimeLocale {+                 wDays       = undefined+               , months      = [ (undefined, x)+                                     | x <- [ "Jan", "Feb", "Mar", "Apr", "May", "Jun"+                                            , "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"+                                            ]+                               ]+               , intervals   = undefined+               , amPm        = undefined+               , dateTimeFmt = undefined+               , dateFmt     = undefined+               , timeFmt     = undefined+               , time12Fmt   = undefined+               }+++allocaASN1Time :: (Ptr ASN1_TIME -> IO a) -> IO a+allocaASN1Time m+    = bracket _ASN1_TIME_new _ASN1_TIME_free m+++withASN1Time :: UTCTime -> (Ptr ASN1_TIME -> IO a) -> IO a+withASN1Time utc m+    = allocaASN1Time $ \ time ->+      do _ASN1_TIME_set time (fromIntegral $ round $ utcTimeToPOSIXSeconds utc)+              >>= failIfNull+         m time
+ OpenSSL/BIO.hsc view
@@ -0,0 +1,477 @@+{- -*- haskell -*- -}++-- #hide++{- --------------------------------------------------------------------------- -}+{-                                                                             -}+{-                           FOR INTERNAL USE ONLY                             -}+{-                                                                             -}+{- When I firstly saw the manpage of bio(3), it looked like a great API. I ac- -}+{- tually wrote a wrapper and even wrote a document. What a pain!              -}+{-                                                                             -}+{- Now I realized that BIOs aren't necessary to we Haskell hackers. Their fun- -}+{- ctionalities overlaps with Haskell's own I/O system. The only thing which   -}+{- wasn't available without bio(3) -- at least I thought so -- was the         -}+{- BIO_f_base64(3), but I found an undocumented API for the Base64 codec.      -}+{-          I FOUND AN UNDOCUMENTED API FOR THE VERY BASE64 CODEC.             -}+{- So I decided to bury all the OpenSSL.BIO module. The game is over.          -}+{-                                                                             -}+{- --------------------------------------------------------------------------- -}+++-- |A BIO is an I\/O abstraction, it hides many of the underlying I\/O+-- details from an application, if you are writing a pure C+-- application...+--+-- I know, we are hacking on Haskell so BIO components like BIO_s_file+-- are hardly needed. But for filter BIOs, such as BIO_f_base64 and+-- BIO_f_cipher, they should be useful too to us.++module OpenSSL.BIO+    ( -- * Type+      BIO+    , BIO_++    , wrapBioPtr  -- private+    , withBioPtr  -- private+    , withBioPtr' -- private++      -- * BIO chaning+    , bioPush+    , (==>)+    , (<==)+    , bioJoin++      -- * BIO control operations+    , bioFlush+    , bioReset+    , bioEOF++      -- * BIO I\/O functions+    , bioRead+    , bioReadBS+    , bioReadLBS+    , bioGets+    , bioGetsBS+    , bioGetsLBS+    , bioWrite+    , bioWriteBS+    , bioWriteLBS++      -- * Base64 BIO filter+    , newBase64++      -- * Buffering BIO filter+    , newBuffer++      -- * Memory BIO sink\/source+    , newMem+    , newConstMem+    , newConstMemBS+    , newConstMemLBS++      -- * Null data BIO sink\/source+    , newNullBIO+    )+    where++import           Control.Monad+import           Data.ByteString.Base+import qualified Data.ByteString.Char8      as B8+import qualified Data.ByteString.Lazy.Char8 as L8+import           Foreign                    hiding (new)+import           Foreign.C+import qualified GHC.ForeignPtr             as GF+import           OpenSSL.Utils+import           System.IO.Unsafe++{- bio ---------------------------------------------------------------------- -}++data    BIO_METHOD++-- |@BIO@ is a @ForeignPtr@ to an opaque BIO object. They are created by newXXX actions.+newtype BIO  = BIO (ForeignPtr BIO_)+data    BIO_++foreign import ccall unsafe "BIO_new"+        _new :: Ptr BIO_METHOD -> IO (Ptr BIO_)++foreign import ccall unsafe "&BIO_free"+        _free :: FunPtr (Ptr BIO_ -> IO ())++foreign import ccall unsafe "BIO_push"+        _push :: Ptr BIO_ -> Ptr BIO_ -> IO (Ptr BIO_)++foreign import ccall unsafe "HsOpenSSL_BIO_set_flags"+        _set_flags :: Ptr BIO_ -> Int -> IO ()++foreign import ccall unsafe "HsOpenSSL_BIO_should_retry"+        _should_retry :: Ptr BIO_ -> IO Int+++new :: Ptr BIO_METHOD -> IO BIO+new method+    = _new method >>= failIfNull >>= wrapBioPtr+++wrapBioPtr :: Ptr BIO_ -> IO BIO+wrapBioPtr bioPtr = newForeignPtr _free bioPtr >>= return . BIO+++withBioPtr :: BIO -> (Ptr BIO_ -> IO a) -> IO a+withBioPtr (BIO bio) = withForeignPtr bio+++withBioPtr' :: Maybe BIO -> (Ptr BIO_ -> IO a) -> IO a+withBioPtr' Nothing    f = f nullPtr+withBioPtr' (Just bio) f = withBioPtr bio f+++-- a の後ろに b を付ける。a の參照だけ保持してそこに書き込む事も、b の+-- 參照だけ保持してそこから讀み出す事も、兩方考へられるので、双方の+-- ForeignPtr が双方を touch する。參照カウント方式ではないから循環參照+-- しても問題無い。++-- |Computation of @'bioPush' a b@ connects @b@ behind @a@.+--+-- Example:+--+-- > do b64 <- newBase64 True+-- >    mem <- newMem+-- >    bioPush b64 mem+-- >+-- >    -- Encode some text in Base64 and write the result to the+-- >    -- memory buffer.+-- >    bioWrite b64 "Hello, world!"+-- >    bioFlush b64+-- >+-- >    -- Then dump the memory buffer.+-- >    bioRead mem >>= putStrLn+--+bioPush :: BIO -> BIO -> IO ()+bioPush (BIO a) (BIO b)+    = withForeignPtr a $ \ aPtr ->+      withForeignPtr b $ \ bPtr ->+      do _push aPtr bPtr+         GF.addForeignPtrConcFinalizer a $ touchForeignPtr b+         GF.addForeignPtrConcFinalizer b $ touchForeignPtr a+         return ()++-- |@a '==>' b@ is an alias to @'bioPush' a b@.+(==>) :: BIO -> BIO -> IO ()+(==>) = bioPush++-- |@a '<==' b@ is an alias to @'bioPush' b a@.+(<==) :: BIO -> BIO -> IO ()+(<==) = flip bioPush+++-- |@'bioJoin' [bio1, bio2, ..]@ connects many BIOs at once.+bioJoin :: [BIO] -> IO ()+bioJoin []       = return ()+bioJoin (_:[])   = return ()+bioJoin (a:b:xs) = bioPush a b >> bioJoin (b:xs)+++setFlags :: BIO -> Int -> IO ()+setFlags bio flags+    = withBioPtr bio $ \ bioPtr ->+      _set_flags bioPtr flags++bioShouldRetry :: BIO -> IO Bool+bioShouldRetry bio+    = withBioPtr bio $ \ bioPtr ->+      _should_retry bioPtr >>= return . (/= 0)+++{- ctrl --------------------------------------------------------------------- -}++foreign import ccall unsafe "HsOpenSSL_BIO_flush"+        _flush :: Ptr BIO_ -> IO Int++foreign import ccall unsafe "HsOpenSSL_BIO_reset"+        _reset :: Ptr BIO_ -> IO Int++foreign import ccall unsafe "HsOpenSSL_BIO_eof"+        _eof :: Ptr BIO_ -> IO Int++-- |@'bioFlush' bio@ normally writes out any internally buffered data,+-- in some cases it is used to signal EOF and that no more data will+-- be written.+bioFlush :: BIO -> IO ()+bioFlush bio+    = withBioPtr bio $ \ bioPtr ->+      _flush bioPtr >>= failIf (/= 1) >> return ()++-- |@'bioReset' bio@ typically resets a BIO to some initial state.+bioReset :: BIO -> IO ()+bioReset bio+    = withBioPtr bio $ \ bioPtr ->+      _reset bioPtr >> return () -- BIO_reset の戻り値は全 BIO で共通で+                                 -- ないのでエラーチェックが出來ない。++-- |@'bioEOF' bio@ returns 1 if @bio@ has read EOF, the precise+-- meaning of EOF varies according to the BIO type.+bioEOF :: BIO -> IO Bool+bioEOF bio+    = withBioPtr bio $ \ bioPtr ->+      _eof bioPtr >>= return . (== 1)+++{- I/O ---------------------------------------------------------------------- -}++foreign import ccall unsafe "BIO_read"+        _read :: Ptr BIO_ -> Ptr CChar -> Int -> IO Int++foreign import ccall unsafe "BIO_gets"+        _gets :: Ptr BIO_ -> Ptr CChar -> Int -> IO Int++foreign import ccall unsafe "BIO_write"+        _write :: Ptr BIO_ -> Ptr CChar -> Int -> IO Int++-- |@'bioRead' bio@ lazily reads all data in @bio@.+bioRead :: BIO -> IO String+bioRead bio+    = liftM L8.unpack $ bioReadLBS bio++-- |@'bioReadBS' bio len@ attempts to read @len@ bytes from @bio@,+-- then return a ByteString. The actual length of result may be less+-- than @len@.+bioReadBS :: BIO -> Int -> IO ByteString+bioReadBS bio maxLen+    = withBioPtr bio       $ \ bioPtr ->+      createAndTrim maxLen $ \ bufPtr ->+      _read bioPtr (unsafeCoercePtr bufPtr) maxLen >>= interpret+    where+      interpret :: Int -> IO Int+      interpret n+          | n ==  0   = return 0+          | n == -1   = return 0+          | n <  -1   = raiseOpenSSLError+          | otherwise = return n++-- |@'bioReadLBS' bio@ lazily reads all data in @bio@, then return a+-- LazyByteString.+bioReadLBS :: BIO -> IO LazyByteString+bioReadLBS bio = lazyRead >>= return . LPS+    where+      chunkSize = 32 * 1024+      +      lazyRead = unsafeInterleaveIO loop++      loop = do bs <- bioReadBS bio chunkSize+                if B8.null bs then+                    do isEOF <- bioEOF bio+                       if isEOF then+                           return []+                         else+                           do shouldRetry <- bioShouldRetry bio+                              if shouldRetry then+                                  loop+                                else+                                  fail "bioReadLBS: got null but isEOF=False, shouldRetry=False"+                  else+                    do bss <- lazyRead+                       return (bs:bss)++-- |@'bioGets' bio len@ normally attempts to read one line of data+-- from @bio@ of maximum length @len@. There are exceptions to this+-- however, for example 'bioGets' on a digest BIO will calculate and+-- return the digest and other BIOs may not support 'bioGets' at all.+bioGets :: BIO -> Int -> IO String+bioGets bio maxLen+    = liftM B8.unpack (bioGetsBS bio maxLen)++-- |'bioGetsBS' does the same as 'bioGets' but returns ByteString.+bioGetsBS :: BIO -> Int -> IO ByteString+bioGetsBS bio maxLen+    = withBioPtr bio       $ \ bioPtr ->+      createAndTrim maxLen $ \ bufPtr ->+      _gets bioPtr (unsafeCoercePtr bufPtr) maxLen >>= interpret+    where+      interpret :: Int -> IO Int+      interpret n+          | n ==  0   = return 0+          | n == -1   = return 0+          | n <  -1   = raiseOpenSSLError+          | otherwise = return n++-- |'bioGetsLBS' does the same as 'bioGets' but returns+-- LazyByteString.+bioGetsLBS :: BIO -> Int -> IO LazyByteString+bioGetsLBS bio maxLen+    = bioGetsBS bio maxLen >>= \ bs -> (return . LPS) [bs]++-- |@'bioWrite' bio str@ lazily writes entire @str@ to @bio@. The+-- string doesn't necessarily have to be finite.+bioWrite :: BIO -> String -> IO ()+bioWrite bio str+    = (return . L8.pack) str >>= bioWriteLBS bio++-- |@'bioWriteBS' bio bs@ writes @bs@ to @bio@.+bioWriteBS :: BIO -> ByteString -> IO ()+bioWriteBS bio bs+    = withBioPtr bio           $ \ bioPtr ->+      unsafeUseAsCStringLen bs $ \ (buf, len) ->+      _write bioPtr buf len >>= interpret+    where+      interpret :: Int -> IO ()+      interpret n+          | n == B8.length bs = return ()+          | n == -1           = bioWriteBS bio bs -- full retry+          | n <  -1           = raiseOpenSSLError+          | otherwise         = bioWriteBS bio (B8.drop n bs) -- partial retry++-- |@'bioWriteLBS' bio lbs@ lazily writes entire @lbs@ to @bio@. The+-- string doesn't necessarily have to be finite.+bioWriteLBS :: BIO -> LazyByteString -> IO ()+bioWriteLBS bio (LPS chunks)+    = mapM_ (bioWriteBS bio) chunks+++{- base64 ------------------------------------------------------------------- -}++foreign import ccall unsafe "BIO_f_base64"+        f_base64 :: IO (Ptr BIO_METHOD)++foreign import ccall unsafe "HsOpenSSL_BIO_FLAGS_BASE64_NO_NL"+        _FLAGS_BASE64_NO_NL :: Int++-- |@'newBase64' noNL@ creates a Base64 BIO filter. This is a filter+-- bio that base64 encodes any data written through it and decodes any+-- data read through it.+--+-- If @noNL@ flag is True, the filter encodes the data all on one line+-- or expects the data to be all on one line.+--+-- Base64 BIOs do not support 'bioGets'.+--+-- 'bioFlush' on a Base64 BIO that is being written through is used to+-- signal that no more data is to be encoded: this is used to flush+-- the final block through the BIO.+newBase64 :: Bool -> IO BIO+newBase64 noNL+    = do bio <- new =<< f_base64+         when noNL $ setFlags bio _FLAGS_BASE64_NO_NL+         return bio+++{- buffer ------------------------------------------------------------------- -}++foreign import ccall unsafe "BIO_f_buffer"+        f_buffer :: IO (Ptr BIO_METHOD)++foreign import ccall unsafe "HsOpenSSL_BIO_set_buffer_size"+        _set_buffer_size :: Ptr BIO_ -> Int -> IO Int+++-- |@'newBuffer' mBufSize@ creates a buffering BIO filter. Data+-- written to a buffering BIO is buffered and periodically written to+-- the next BIO in the chain. Data read from a buffering BIO comes+-- from the next BIO in the chain.+--+-- Buffering BIOs support 'bioGets'.+--+-- Calling 'bioReset' on a buffering BIO clears any buffered data.+--+-- Question: When I created a BIO chain like this and attempted to+-- read from the buf, the buffering BIO weirdly behaved: BIO_read()+-- returned nothing, but both BIO_eof() and BIO_should_retry()+-- returned zero. I tried to examine the source code of+-- crypto\/bio\/bf_buff.c but it was too complicated to+-- understand. Does anyone know why this happens? The version of+-- OpenSSL was 0.9.7l.+--+-- > main = withOpenSSL $+-- >        do mem <- newConstMem "Hello, world!"+-- >           buf <- newBuffer Nothing+-- >           mem ==> buf+-- >+-- >           bioRead buf >>= putStrLn -- This fails, but why?+--+-- I am being depressed for this unaccountable failure.+--+newBuffer :: Maybe Int -- ^ Explicit buffer size (@Just n@) or the+                       -- default size (@Nothing@).+          -> IO BIO+newBuffer bufSize+    = do bio <- new =<< f_buffer+         case bufSize of+           Just n  -> withBioPtr bio $ \ bioPtr ->+                      _set_buffer_size bioPtr n+                           >>= failIf (/= 1) >> return ()+           Nothing -> return ()+         return bio+++{- mem ---------------------------------------------------------------------- -}++foreign import ccall unsafe "BIO_s_mem"+        s_mem :: IO (Ptr BIO_METHOD)++foreign import ccall unsafe "BIO_new_mem_buf"+        _new_mem_buf :: Ptr CChar -> Int -> IO (Ptr BIO_)+++-- |@'newMem'@ creates a memory BIO sink\/source. Any data written to+-- a memory BIO can be recalled by reading from it. Unless the memory+-- BIO is read only any data read from it is deleted from the BIO.+--+-- Memory BIOs support 'bioGets'.+--+-- Calling 'bioReset' on a erad write memory BIO clears any data in+-- it. On a read only BIO it restores the BIO to its original state+-- and the read only data can be read again.+--+-- 'bioEOF' is true if no data is in the BIO.+--+-- Every read from a read write memory BIO will remove the data just+-- read with an internal copy operation, if a BIO contains a lots of+-- data and it is read in small chunks the operation can be very+-- slow. The use of a read only memory BIO avoids this problem. If the+-- BIO must be read write then adding a buffering BIO ('newBuffer') to+-- the chain will speed up the process.+newMem :: IO BIO+newMem = s_mem >>= new++-- |@'newConstMem' str@ creates a read-only memory BIO source.+newConstMem :: String -> IO BIO+newConstMem str+    = (return . B8.pack) str >>= newConstMemBS++-- |@'newConstMemBS' bs@ is like 'newConstMem' but takes a ByteString.+newConstMemBS :: ByteString -> IO BIO+newConstMemBS bs+    = let (foreignBuf, off, len) = toForeignPtr bs+      in+        -- ByteString への參照を BIO の finalizer に持たせる。+        withForeignPtr foreignBuf $ \ buf ->+        do bioPtr <- _new_mem_buf (unsafeCoercePtr $ buf `plusPtr` off) len+                     >>= failIfNull++           bio <- newForeignPtr _free bioPtr+           GF.addForeignPtrConcFinalizer bio $ touchForeignPtr foreignBuf+           +           return $ BIO bio++-- |@'newConstMemLBS' lbs@ is like 'newConstMem' but takes a+-- LazyByteString.+newConstMemLBS :: LazyByteString -> IO BIO+newConstMemLBS (LPS bss)+    = (return . B8.concat) bss >>= newConstMemBS++{- null --------------------------------------------------------------------- -}++foreign import ccall unsafe "BIO_s_null"+        s_null :: IO (Ptr BIO_METHOD)++-- |@'newNullBIO'@ creates a null BIO sink\/source. Data written to+-- the null sink is discarded, reads return EOF.+--+-- A null sink is useful if, for example, an application wishes to+-- digest some data by writing through a digest bio but not send the+-- digested data anywhere. Since a BIO chain must normally include a+-- source\/sink BIO this can be achieved by adding a null sink BIO to+-- the end of the chain.+newNullBIO :: IO BIO+newNullBIO = s_null >>= new
+ OpenSSL/BN.hsc view
@@ -0,0 +1,64 @@+{- -*- haskell -*- -}++-- #hide++module OpenSSL.BN+    ( BigNum+    , BIGNUM++    , allocaBN+    , withBN+    , peekBN+    )+    where++import           Control.Exception+import           Control.Monad+import           Foreign+import           Foreign.C+import           OpenSSL.Utils+++type BigNum = Ptr BIGNUM+data BIGNUM = BIGNUM+++foreign import ccall unsafe "BN_new"+        _new :: IO BigNum++foreign import ccall unsafe "BN_free"+        _free :: BigNum -> IO ()++foreign import ccall unsafe "BN_bn2dec"+        _bn2dec :: BigNum -> IO CString++foreign import ccall unsafe "BN_dec2bn"+        _dec2bn :: Ptr BigNum -> CString -> IO Int++foreign import ccall unsafe "HsOpenSSL_OPENSSL_free"+        _openssl_free :: Ptr a -> IO ()+++allocaBN :: (BigNum -> IO a) -> IO a+allocaBN m+    = bracket _new _free m+++withBN :: Integer -> (BigNum -> IO a) -> IO a+withBN dec m+    = withCString (show dec) $ \ strPtr ->+      alloca $ \ bnPtr ->+      do _dec2bn bnPtr strPtr+              >>= failIf (== 0)+         bracket (peek bnPtr) _free m+++peekBN :: BigNum -> IO Integer+peekBN bn+    = do strPtr <- _bn2dec bn+         when (strPtr == nullPtr) $ fail "BN_bn2dec failed"+         +         str <- peekCString strPtr+         _openssl_free strPtr++         return $ read str
+ OpenSSL/ERR.hsc view
@@ -0,0 +1,37 @@+{- -*- haskell -*- -}++-- #hide++module OpenSSL.ERR+    ( getError+    , peekError++    , errorString+    )+    where++import           Foreign+import           Foreign.C+++foreign import ccall unsafe "ERR_get_error"+        _get_error :: IO CULong++foreign import ccall unsafe "ERR_peek_error"+        _peek_error :: IO CULong++foreign import ccall unsafe "ERR_error_string"+        _error_string :: CULong -> CString -> IO CString+++getError :: IO Integer+getError = _get_error >>= return . fromIntegral+++peekError :: IO Integer+peekError = _peek_error >>= return . fromIntegral+++errorString :: Integer -> IO String+errorString code+    = _error_string (fromIntegral code) nullPtr >>= peekCString
+ OpenSSL/EVP/Base64.hsc view
@@ -0,0 +1,138 @@+{- -*- haskell -*- -}++-- |An interface to Base64 codec.++module OpenSSL.EVP.Base64+    ( -- * Encoding+      encodeBase64+    , encodeBase64BS+    , encodeBase64LBS++      -- * Decoding+    , decodeBase64+    , decodeBase64BS+    , decodeBase64LBS+    )+    where++import           Control.Exception+import           Data.ByteString.Base+import qualified Data.ByteString.Char8 as B8+import qualified Data.ByteString.Lazy.Char8 as L8+import           Data.List+import           Foreign+import           Foreign.C+import           OpenSSL.Utils+++-- エンコード時: 最低 3 バイト以上になるまで次のブロックを取り出し續け+-- る。返された[ByteString] は B8.concat してから、その文字列長より小さ+-- な最大の 3 の倍數の位置で分割し、殘りは次のブロックの一部と見做す。+--+-- デコード時: 分割のアルゴリズムは同じだが最低バイト数が 4。+nextBlock :: Int -> ([ByteString], LazyByteString) -> ([ByteString], LazyByteString)+nextBlock _      (xs, LPS [] ) = (xs, LPS [])+nextBlock minLen (xs, LPS src) = if foldl' (+) 0 (map B8.length xs) >= minLen then+                                     (xs, LPS src)+                                 else+                                     case src of+                                       (y:ys) -> nextBlock minLen (xs ++ [y], LPS ys)+++{- encode -------------------------------------------------------------------- -}++foreign import ccall unsafe "EVP_EncodeBlock"+        _EncodeBlock :: Ptr CChar -> Ptr CChar -> Int -> IO Int+++encodeBlock :: ByteString -> ByteString+encodeBlock inBS+    = unsafePerformIO $+      unsafeUseAsCStringLen inBS $ \ (inBuf, inLen) ->+      createAndTrim maxOutLen $ \ outBuf ->+      _EncodeBlock (unsafeCoercePtr outBuf) inBuf inLen+    where+      maxOutLen = (inputLen `div` 3 + 1) * 4 + 1 -- +1: '\0'+      inputLen  = B8.length inBS+++-- |@'encodeBase64' str@ lazilly encodes a stream of data to+-- Base64. The string doesn't have to be finite. Note that the string+-- must not contain any letters which aren't in the range of U+0000 -+-- U+00FF.+encodeBase64 :: String -> String+encodeBase64 = L8.unpack . encodeBase64LBS . L8.pack++-- |@'encodeBase64BS' bs@ strictly encodes a chunk of data to Base64.+encodeBase64BS :: ByteString -> ByteString+encodeBase64BS = encodeBlock++-- |@'encodeBase64LBS' lbs@ lazilly encodes a stream of data to+-- Base64. The string doesn't have to be finite.+encodeBase64LBS :: LazyByteString -> LazyByteString+encodeBase64LBS inLBS+    | L8.null inLBS = L8.empty+    | otherwise+        = let (blockParts', remain' ) = nextBlock 3 ([], inLBS)+              block'                  = B8.concat blockParts'+              blockLen'               = B8.length block'+              (block      , leftover) = if blockLen' < 3 then+                                            -- 最後の半端+                                            (block', B8.empty)+                                        else+                                            B8.splitAt (blockLen' - blockLen' `mod` 3) block'+              remain                  = if B8.null leftover then+                                            remain'+                                        else+                                            case remain' of+                                              LPS xs -> LPS (leftover:xs)+              encodedBlock             = encodeBlock block+              LPS encodedRemain        = encodeBase64LBS remain+          in+            LPS ([encodedBlock] ++ encodedRemain)+++{- decode -------------------------------------------------------------------- -}++foreign import ccall unsafe "EVP_DecodeBlock"+        _DecodeBlock :: Ptr CChar -> Ptr CChar -> Int -> IO Int+++decodeBlock :: ByteString -> ByteString+decodeBlock inBS+    = assert (B8.length inBS `mod` 4 == 0) $+      unsafePerformIO $+      unsafeUseAsCStringLen inBS $ \ (inBuf, inLen) ->+      createAndTrim (B8.length inBS) $ \ outBuf ->+      _DecodeBlock (unsafeCoercePtr outBuf) inBuf inLen++-- |@'decodeBase64' str@ lazilly decodes a stream of data from+-- Base64. The string doesn't have to be finite.+decodeBase64 :: String -> String+decodeBase64 = L8.unpack . decodeBase64LBS . L8.pack++-- |@'decodeBase64BS' bs@ strictly decodes a chunk of data from+-- Base64.+decodeBase64BS :: ByteString -> ByteString+decodeBase64BS = decodeBlock++-- |@'decodeBase64LBS' lbs@ lazilly decodes a stream of data from+-- Base64. The string doesn't have to be finite.+decodeBase64LBS :: LazyByteString -> LazyByteString+decodeBase64LBS inLBS+    | L8.null inLBS = L8.empty+    | otherwise+        = let (blockParts', remain' ) = nextBlock 4 ([], inLBS)+              block'                  = B8.concat blockParts'+              blockLen'               = B8.length block'+              (block      , leftover) = assert (blockLen' >= 4) $+                                        B8.splitAt (blockLen' - blockLen' `mod` 4) block'+              remain                  = if B8.null leftover then+                                            remain'+                                        else+                                            case remain' of+                                              LPS xs -> LPS (leftover:xs)+              decodedBlock            = decodeBlock block+              LPS decodedRemain       = decodeBase64LBS remain+          in+            LPS ([decodedBlock] ++ decodedRemain)
+ OpenSSL/EVP/Cipher.hsc view
@@ -0,0 +1,221 @@+{- -*- haskell -*- -}++-- #prune++-- |An interface to symmetric cipher algorithms.++#include "HsOpenSSL.h"++module OpenSSL.EVP.Cipher+    ( Cipher+    , EVP_CIPHER -- private+    , withCipherPtr -- private++    , getCipherByName+    , getCipherNames++    , cipherIvLength -- private++    , CipherCtx -- private+    , EVP_CIPHER_CTX -- private+    , newCtx -- private+    , withCipherCtxPtr -- private++    , CryptoMode(..)++    , cipherStrictly -- private+    , cipherLazily -- private++    , cipher+    , cipherBS+    , cipherLBS+    )+    where++import           Control.Monad+import           Data.ByteString.Base+import qualified Data.ByteString.Char8 as B8+import qualified Data.ByteString.Lazy.Char8 as L8+import           Foreign+import           Foreign.C+import           OpenSSL.Objects+import           OpenSSL.Utils+import           System.IO.Unsafe+++{- EVP_CIPHER ---------------------------------------------------------------- -}++-- |@Cipher@ is an opaque object that represents an algorithm of+-- symmetric cipher.+newtype Cipher     = Cipher (Ptr EVP_CIPHER)+data    EVP_CIPHER+++foreign import ccall unsafe "EVP_get_cipherbyname"+        _get_cipherbyname :: CString -> IO (Ptr EVP_CIPHER)+++foreign import ccall unsafe "HsOpenSSL_EVP_CIPHER_iv_length"+        _iv_length :: Ptr EVP_CIPHER -> Int+++withCipherPtr :: Cipher -> (Ptr EVP_CIPHER -> IO a) -> IO a+withCipherPtr (Cipher cipher) f = f cipher++-- |@'getCipherByName' name@ returns a symmetric cipher algorithm+-- whose name is @name@. If no algorithms are found, the result is+-- @Nothing@.+getCipherByName :: String -> IO (Maybe Cipher)+getCipherByName name+    = withCString name $ \ namePtr ->+      do ptr <- _get_cipherbyname namePtr+         if ptr == nullPtr then+             return Nothing+           else+             return $ Just $ Cipher ptr++-- |@'getCipherNames'@ returns a list of name of symmetric cipher+-- algorithms.+getCipherNames :: IO [String]+getCipherNames = getObjNames CipherMethodType True+++cipherIvLength :: Cipher -> Int+cipherIvLength (Cipher cipher) = _iv_length cipher+++{- EVP_CIPHER_CTX ------------------------------------------------------------ -}++newtype CipherCtx      = CipherCtx (ForeignPtr EVP_CIPHER_CTX)+data    EVP_CIPHER_CTX+++foreign import ccall unsafe "EVP_CIPHER_CTX_init"+        _ctx_init :: Ptr EVP_CIPHER_CTX -> IO ()++foreign import ccall unsafe "&EVP_CIPHER_CTX_cleanup"+        _ctx_cleanup :: FunPtr (Ptr EVP_CIPHER_CTX -> IO ())++foreign import ccall unsafe "HsOpenSSL_EVP_CIPHER_CTX_block_size"+        _ctx_block_size :: Ptr EVP_CIPHER_CTX -> Int+++newCtx :: IO CipherCtx+newCtx = do ctx <- mallocForeignPtrBytes (#size EVP_CIPHER_CTX)+            withForeignPtr ctx $ \ ctxPtr ->+                _ctx_init ctxPtr+            addForeignPtrFinalizer _ctx_cleanup ctx+            return $ CipherCtx ctx+++withCipherCtxPtr :: CipherCtx -> (Ptr EVP_CIPHER_CTX -> IO a) -> IO a+withCipherCtxPtr (CipherCtx ctx) = withForeignPtr ctx+++{- encrypt/decrypt ----------------------------------------------------------- -}++-- |@CryptoMode@ represents instruction to 'cipher' and such like.+data CryptoMode = Encrypt | Decrypt+++foreign import ccall unsafe "EVP_CipherInit"+        _CipherInit :: Ptr EVP_CIPHER_CTX -> Ptr EVP_CIPHER -> CString -> CString -> Int -> IO Int++foreign import ccall unsafe "EVP_CipherUpdate"+        _CipherUpdate :: Ptr EVP_CIPHER_CTX -> Ptr CChar -> Ptr Int -> Ptr CChar -> Int -> IO Int++foreign import ccall unsafe "EVP_CipherFinal"+        _CipherFinal :: Ptr EVP_CIPHER_CTX -> Ptr CChar -> Ptr Int -> IO Int+++cryptoModeToInt :: CryptoMode -> Int+cryptoModeToInt Encrypt = 1+cryptoModeToInt Decrypt = 0+++cipherInit :: Cipher -> String -> String -> CryptoMode -> IO CipherCtx+cipherInit (Cipher c) key iv mode+    = do ctx <- newCtx+         withCipherCtxPtr ctx $ \ ctxPtr ->+             withCString key $ \ keyPtr ->+                 withCString iv $ \ ivPtr ->+                     _CipherInit ctxPtr c keyPtr ivPtr (cryptoModeToInt mode)+                          >>= failIf (/= 1)+         return ctx+++cipherUpdateBS :: CipherCtx -> ByteString -> IO ByteString+cipherUpdateBS ctx inBS+    = withCipherCtxPtr ctx $ \ ctxPtr ->+      unsafeUseAsCStringLen inBS $ \ (inBuf, inLen) ->+      createAndTrim (inLen + _ctx_block_size ctxPtr - 1) $ \ outBuf ->+      alloca $ \ outLenPtr ->+      _CipherUpdate ctxPtr (unsafeCoercePtr outBuf) outLenPtr inBuf inLen+           >>= failIf (/= 1)+           >>  peek outLenPtr+++cipherFinalBS :: CipherCtx -> IO ByteString+cipherFinalBS ctx+    = withCipherCtxPtr ctx $ \ ctxPtr ->+      createAndTrim (_ctx_block_size ctxPtr) $ \ outBuf ->+      alloca $ \ outLenPtr ->+      _CipherFinal ctxPtr (unsafeCoercePtr outBuf) outLenPtr+           >>= failIf (/= 1)+           >>  peek outLenPtr++-- |@'cipher'@ lazilly encrypts or decrypts a stream of data. The+-- input string doesn't necessarily have to be finite.+cipher :: Cipher     -- ^ algorithm to use+       -> String     -- ^ symmetric key+       -> String     -- ^ IV+       -> CryptoMode -- ^ operation+       -> String     -- ^ An input string to encrypt\/decrypt. Note+                     --   that the string must not contain any letters+                     --   which aren't in the range of U+0000 -+                     --   U+00FF.+       -> IO String  -- ^ the result string+cipher c key iv mode input+    = liftM L8.unpack $ cipherLBS c key iv mode $ L8.pack input++-- |@'cipherBS'@ strictly encrypts or decrypts a chunk of data.+cipherBS :: Cipher        -- ^ algorithm to use+         -> String        -- ^ symmetric key+         -> String        -- ^ IV+         -> CryptoMode    -- ^ operation+         -> ByteString    -- ^ input string to encrypt\/decrypt+         -> IO ByteString -- ^ the result string+cipherBS c key iv mode input+    = do ctx <- cipherInit c key iv mode+         cipherStrictly ctx input++-- |@'cipherLBS'@ lazilly encrypts or decrypts a stream of data. The+-- input string doesn't necessarily have to be finite.+cipherLBS :: Cipher            -- ^ algorithm to use+          -> String            -- ^ symmetric key+          -> String            -- ^ IV+          -> CryptoMode        -- ^ operation+          -> LazyByteString    -- ^ input string to encrypt\/decrypt+          -> IO LazyByteString -- ^ the result string+cipherLBS c key iv mode input+    = do ctx <- cipherInit c key iv mode+         cipherLazily ctx input+++cipherStrictly :: CipherCtx -> ByteString -> IO ByteString+cipherStrictly ctx input+    = do output'  <- cipherUpdateBS ctx input+         output'' <- cipherFinalBS ctx+         return $ B8.append output' output''+++cipherLazily :: CipherCtx -> LazyByteString -> IO LazyByteString++cipherLazily ctx (LPS [])+    = cipherFinalBS ctx >>= \ bs -> (return . LPS) [bs]++cipherLazily ctx (LPS (x:xs))+    = do y      <- cipherUpdateBS ctx x+         LPS ys <- unsafeInterleaveIO $+                   cipherLazily ctx (LPS xs)+         return $ LPS (y:ys)
+ OpenSSL/EVP/Digest.hsc view
@@ -0,0 +1,175 @@+{- -*- haskell -*- -}++-- #prune++-- |An interface to message digest algorithms.++#include "HsOpenSSL.h"++module OpenSSL.EVP.Digest+    ( Digest+    , EVP_MD -- private+    , withMDPtr -- private++    , getDigestByName+    , getDigestNames++    , DigestCtx -- private+    , EVP_MD_CTX -- private+    , withDigestCtxPtr -- private++    , digestStrictly -- private+    , digestLazily   -- private++    , digest+    , digestBS+    , digestLBS+    )+    where++import           Control.Monad+import           Data.ByteString.Base+import qualified Data.ByteString.Char8 as B8+import qualified Data.ByteString.Lazy.Char8 as L8+import           Foreign+import           Foreign.C+import           OpenSSL.Objects+import           OpenSSL.Utils+++{- EVP_MD -------------------------------------------------------------------- -}++-- |@Digest@ is an opaque object that represents an algorithm of+-- message digest.+newtype Digest  = Digest (Ptr EVP_MD)+data    EVP_MD+++foreign import ccall unsafe "EVP_get_digestbyname"+        _get_digestbyname :: CString -> IO (Ptr EVP_MD)++foreign import ccall unsafe "HsOpenSSL_EVP_MD_size"+        mdSize :: Ptr EVP_MD -> Int+++withMDPtr :: Digest -> (Ptr EVP_MD -> IO a) -> IO a+withMDPtr (Digest mdPtr) f = f mdPtr++-- |@'getDigestByName' name@ returns a message digest algorithm whose+-- name is @name@. If no algorithms are found, the result is+-- @Nothing@.+getDigestByName :: String -> IO (Maybe Digest)+getDigestByName name+    = withCString name $ \ namePtr ->+      do ptr <- _get_digestbyname namePtr+         if ptr == nullPtr then+             return Nothing+           else+             return $ Just $ Digest ptr++-- |@'getDigestNames'@ returns a list of name of message digest+-- algorithms.+getDigestNames :: IO [String]+getDigestNames = getObjNames MDMethodType True+++{- EVP_MD_CTX ---------------------------------------------------------------- -}++newtype DigestCtx  = DigestCtx (ForeignPtr EVP_MD_CTX)+data    EVP_MD_CTX+++foreign import ccall unsafe "EVP_MD_CTX_init"+        _ctx_init :: Ptr EVP_MD_CTX -> IO ()++foreign import ccall unsafe "&EVP_MD_CTX_cleanup"+        _ctx_cleanup :: FunPtr (Ptr EVP_MD_CTX -> IO ())+++newCtx :: IO DigestCtx+newCtx = do ctx <- mallocForeignPtrBytes (#size EVP_MD_CTX)+            withForeignPtr ctx $ \ ctxPtr ->+                _ctx_init ctxPtr+            addForeignPtrFinalizer _ctx_cleanup ctx+            return $ DigestCtx ctx+++withDigestCtxPtr :: DigestCtx -> (Ptr EVP_MD_CTX -> IO a) -> IO a+withDigestCtxPtr (DigestCtx ctx) = withForeignPtr ctx+++{- digest -------------------------------------------------------------------- -}++foreign import ccall unsafe "EVP_DigestInit"+        _DigestInit :: Ptr EVP_MD_CTX -> Ptr EVP_MD -> IO Int++foreign import ccall unsafe "EVP_DigestUpdate"+        _DigestUpdate :: Ptr EVP_MD_CTX -> Ptr CChar -> CSize -> IO Int++foreign import ccall unsafe "EVP_DigestFinal"+        _DigestFinal :: Ptr EVP_MD_CTX -> Ptr CChar -> Ptr CUInt -> IO Int+++digestInit :: Digest -> IO DigestCtx+digestInit (Digest md)+    = do ctx <- newCtx+         withDigestCtxPtr ctx $ \ ctxPtr ->+             _DigestInit ctxPtr md >>= failIf (/= 1)+         return ctx   +++digestUpdateBS :: DigestCtx -> ByteString -> IO ()+digestUpdateBS ctx bs+    = withDigestCtxPtr ctx $ \ ctxPtr ->+      unsafeUseAsCStringLen bs $ \ (buf, len) ->+      _DigestUpdate ctxPtr buf (fromIntegral len) >>= failIf (/= 1) >> return ()+++digestUpdateLBS :: DigestCtx -> LazyByteString -> IO ()+digestUpdateLBS ctx (LPS chunks)+    = mapM_ (digestUpdateBS ctx) chunks+++digestFinal :: DigestCtx -> IO String+digestFinal ctx+    = withDigestCtxPtr ctx $ \ ctxPtr ->+      allocaArray (#const EVP_MAX_MD_SIZE) $ \ bufPtr ->+      alloca $ \ bufLenPtr ->+      do _DigestFinal ctxPtr bufPtr bufLenPtr >>= failIf (/= 1)+         bufLen <- liftM fromIntegral $ peek bufLenPtr+         peekCStringLen (bufPtr, bufLen)+++digestStrictly :: Digest -> ByteString -> IO DigestCtx+digestStrictly md input+    = do ctx <- digestInit md+         digestUpdateBS ctx input+         return ctx+++digestLazily :: Digest -> LazyByteString -> IO DigestCtx+digestLazily md (LPS input)+    = do ctx <- digestInit md+         mapM_ (digestUpdateBS ctx) input+         return ctx++-- |@'digest'@ digests a stream of data. The string must+-- not contain any letters which aren't in the range of U+0000 -+-- U+00FF.+digest :: Digest -> String -> String+digest md input+    = digestLBS md $ L8.pack input++-- |@'digestBS'@ digests a chunk of data.+digestBS :: Digest -> ByteString -> String+digestBS md input+    = unsafePerformIO $+      do ctx <- digestStrictly md input+         digestFinal ctx++-- |@'digestLBS'@ digests a stream of data.+digestLBS :: Digest -> LazyByteString -> String+digestLBS md input+    = unsafePerformIO $+      do ctx <- digestLazily md input+         digestFinal ctx
+ OpenSSL/EVP/Open.hsc view
@@ -0,0 +1,79 @@+{- -*- haskell -*- -}++-- |Asymmetric cipher decryption using encrypted symmetric key. This+-- is an opposite of "OpenSSL.EVP.Seal".++module OpenSSL.EVP.Open+    ( open+    , openBS+    , openLBS+    )+    where++import           Control.Monad+import           Data.ByteString.Base+import qualified Data.ByteString.Char8 as B8+import qualified Data.ByteString.Lazy.Char8 as L8+import           Foreign+import           Foreign.C+import           OpenSSL.EVP.Cipher+import           OpenSSL.EVP.PKey+import           OpenSSL.Utils+++foreign import ccall unsafe "EVP_OpenInit"+        _OpenInit :: Ptr EVP_CIPHER_CTX+                  -> Cipher+                  -> Ptr CChar+                  -> Int+                  -> CString+                  -> Ptr EVP_PKEY+                  -> IO Int+++openInit :: Cipher -> String -> String -> PKey -> IO CipherCtx+openInit cipher encKey iv pkey+    = do ctx <- newCtx+         withCipherCtxPtr ctx $ \ ctxPtr ->+             withCStringLen encKey $ \ (encKeyPtr, encKeyLen) ->+                 withCString iv $ \ ivPtr ->+                     withPKeyPtr pkey $ \ pkeyPtr ->+                         _OpenInit ctxPtr cipher encKeyPtr encKeyLen ivPtr pkeyPtr+                              >>= failIf (== 0)+         return ctx++-- |@'open'@ lazilly decrypts a stream of data. The input string+-- doesn't necessarily have to be finite.+open :: Cipher -- ^ symmetric cipher algorithm to use+     -> String -- ^ encrypted symmetric key to decrypt the input string+     -> String -- ^ IV+     -> PKey   -- ^ private key to decrypt the symmetric key+     -> String -- ^ input string to decrypt+     -> String -- ^ decrypted string+open cipher encKey iv pkey input+    = L8.unpack $ openLBS cipher encKey iv pkey $ L8.pack input++-- |@'openBS'@ decrypts a chunk of data.+openBS :: Cipher     -- ^ symmetric cipher algorithm to use+       -> String     -- ^ encrypted symmetric key to decrypt the input string+       -> String     -- ^ IV+       -> PKey       -- ^ private key to decrypt the symmetric key+       -> ByteString -- ^ input string to decrypt+       -> ByteString -- ^ decrypted string+openBS cipher encKey iv pkey input+    = unsafePerformIO $+      do ctx <- openInit cipher encKey iv pkey+         cipherStrictly ctx input++-- |@'openLBS'@ lazilly decrypts a stream of data. The input string+-- doesn't necessarily have to be finite.+openLBS :: Cipher         -- ^ symmetric cipher algorithm to use+        -> String         -- ^ encrypted symmetric key to decrypt the input string+        -> String         -- ^ IV+        -> PKey           -- ^ private key to decrypt the symmetric key+        -> LazyByteString -- ^ input string to decrypt+        -> LazyByteString -- ^ decrypted string+openLBS cipher encKey iv pkey input+    = unsafePerformIO $+      do ctx <- openInit cipher encKey iv pkey+         cipherLazily ctx input
+ OpenSSL/EVP/PKey.hsc view
@@ -0,0 +1,102 @@+{- -*- haskell -*- -}++-- #prune++-- |An interface to asymmetric cipher keypair.++#include "HsOpenSSL.h"++module OpenSSL.EVP.PKey+    ( PKey+    , EVP_PKEY -- private++    , wrapPKeyPtr -- private+    , withPKeyPtr -- private+    , unsafePKeyToPtr -- private+    , touchPKey -- private+    , pkeySize -- private+    , pkeyDefaultMD -- private++      -- FIXME: newPKeyDSA, newPKeyDH and newPKeyECKey may be needed+#ifndef OPENSSL_NO_RSA+    , newPKeyRSA+#endif+    )+    where++import           Foreign+import           OpenSSL.EVP.Digest+import           OpenSSL.RSA+import           OpenSSL.Utils++-- |@PKey@ is an opaque object that represents either public key or+-- public\/private keypair. The concrete algorithm of asymmetric+-- cipher is hidden in the object.+newtype PKey     = PKey (ForeignPtr EVP_PKEY)+data    EVP_PKEY+++foreign import ccall unsafe "EVP_PKEY_new"+        _pkey_new :: IO (Ptr EVP_PKEY)++foreign import ccall unsafe "&EVP_PKEY_free"+        _pkey_free :: FunPtr (Ptr EVP_PKEY -> IO ())++foreign import ccall unsafe "EVP_PKEY_size"+        _pkey_size :: Ptr EVP_PKEY -> IO Int+++wrapPKeyPtr :: Ptr EVP_PKEY -> IO PKey+wrapPKeyPtr pkeyPtr+    = newForeignPtr _pkey_free pkeyPtr >>= return . PKey+++withPKeyPtr :: PKey -> (Ptr EVP_PKEY -> IO a) -> IO a+withPKeyPtr (PKey pkey) = withForeignPtr pkey+++unsafePKeyToPtr :: PKey -> Ptr EVP_PKEY+unsafePKeyToPtr (PKey pkey) = unsafeForeignPtrToPtr pkey+++touchPKey :: PKey -> IO ()+touchPKey (PKey pkey) = touchForeignPtr pkey+++pkeySize :: PKey -> IO Int+pkeySize pkey+    = withPKeyPtr pkey $ \ pkeyPtr ->+      _pkey_size pkeyPtr+++pkeyDefaultMD :: PKey -> IO Digest+pkeyDefaultMD pkey+    = withPKeyPtr pkey $ \ pkeyPtr ->+      do pkeyType   <- (#peek EVP_PKEY, type) pkeyPtr :: IO Int+         digestName <- case pkeyType of+#ifndef OPENSSL_NO_RSA+                         (#const EVP_PKEY_RSA) -> return "sha1"+#endif+#ifndef OPENSSLNO_DSA+                         (#const EVP_PKEY_DSA) -> return "dss1"+#endif+                         _ -> fail ("pkeyDefaultMD: unsupported pkey type: " ++ show pkeyType)+         mDigest <- getDigestByName digestName+         case mDigest of+           Just digest -> return digest+           Nothing     -> fail ("pkeyDefaultMD: digest method not found: " ++ digestName)+++#ifndef OPENSSL_NO_RSA+foreign import ccall unsafe "EVP_PKEY_set1_RSA"+        _set1_RSA :: Ptr EVP_PKEY -> Ptr RSA_ -> IO Int++-- |@'newPKeyRSA' rsa@ encapsulates an 'RSA' key into 'PKey'.+newPKeyRSA :: RSA -> PKey+newPKeyRSA rsa+    = unsafePerformIO $+      withRSAPtr rsa $ \ rsaPtr ->+      do pkeyPtr <- _pkey_new >>= failIfNull+         _set1_RSA pkeyPtr rsaPtr >>= failIf (/= 1)+         wrapPKeyPtr pkeyPtr+#endif
+ OpenSSL/EVP/Seal.hsc view
@@ -0,0 +1,134 @@+{- -*- haskell -*- -}++-- |Asymmetric cipher decryption using encrypted symmetric key. This+-- is an opposite of "OpenSSL.EVP.Open".++module OpenSSL.EVP.Seal+    ( seal+    , sealBS+    , sealLBS+    )+    where++import           Control.Monad+import           Data.ByteString.Base+import qualified Data.ByteString.Char8 as B8+import qualified Data.ByteString.Lazy.Char8 as L8+import           Foreign+import           Foreign.C+import           OpenSSL.EVP.Cipher+import           OpenSSL.EVP.PKey+import           OpenSSL.Utils+++foreign import ccall unsafe "EVP_SealInit"+        _SealInit :: Ptr EVP_CIPHER_CTX+                  -> Cipher+                  -> Ptr (Ptr CChar)+                  -> Ptr Int+                  -> CString+                  -> Ptr (Ptr EVP_PKEY)+                  -> Int+                  -> IO Int+++sealInit :: Cipher -> [PKey] -> IO (CipherCtx, [String], String)++sealInit _ []+    = fail "sealInit: at least one public key is required"++sealInit cipher pubKeys+    = do ctx <- newCtx+         +         -- 暗号化された共通鍵の配列が書き込まれる場所を作る。各共通鍵+         -- は最大で pkeySize の長さになる。+         encKeyBufs <- mapM mallocEncKeyBuf pubKeys++         -- encKeys は [Ptr a] なので、これを Ptr (Ptr CChar) にしなけ+         -- ればならない。+         encKeyBufsPtr <- newArray encKeyBufs++         -- 暗号化された共通鍵の各々の長さが書き込まれる場所を作る。+         encKeyBufsLenPtr <- mallocArray nKeys++         -- IV の書き込まれる場所を作る。+         ivPtr <- mallocArray (cipherIvLength cipher)++         -- [PKey] から Ptr (Ptr EVP_PKEY) を作る。後でそれぞれの+         -- PKey を touchForeignPtr する事を忘れてはならない。+         pubKeysPtr <- newArray $ map unsafePKeyToPtr pubKeys++         -- 確保した領域を解放する IO アクションを作って置く+         let cleanup = do mapM_ free encKeyBufs+                          free encKeyBufsPtr+                          free encKeyBufsLenPtr+                          free ivPtr+                          free pubKeysPtr+                          mapM_ touchPKey pubKeys++         -- いよいよ EVP_SealInit を呼ぶ。+         ret <- withCipherCtxPtr ctx $ \ ctxPtr ->+                _SealInit ctxPtr cipher encKeyBufsPtr encKeyBufsLenPtr ivPtr pubKeysPtr nKeys++         if ret == 0 then+             cleanup >> raiseOpenSSLError+           else+             do encKeysLen <- peekArray nKeys encKeyBufsLenPtr+                encKeys    <- mapM peekCStringLen $ zip encKeyBufs encKeysLen+                iv         <- peekCString ivPtr+                cleanup+                return (ctx, encKeys, iv)+    where+      nKeys :: Int+      nKeys = length pubKeys++      mallocEncKeyBuf :: Storable a => PKey -> IO (Ptr a)+      mallocEncKeyBuf pubKey+          = pkeySize pubKey >>= mallocArray++-- |@'seal'@ lazilly encrypts a stream of data. The input string+-- doesn't necessarily have to be finite.+seal :: Cipher        -- ^ symmetric cipher algorithm to use+     -> [PKey]        -- ^ A list of public keys to encrypt a+                      --   symmetric key. At least one public key must+                      --   be supplied. If two or more keys are given,+                      --   the symmetric key are encrypted by each+                      --   public keys so that any of the+                      --   corresponding private keys can decrypt the+                      --   message.+     -> String        -- ^ input string to encrypt+     -> IO (String, [String], String) -- ^ (encrypted string, list of+                                      --   encrypted asymmetric keys,+                                      --   IV)+seal cipher pubKeys input+    = do (output, encKeys, iv) <- sealLBS cipher pubKeys $ L8.pack input+         return (L8.unpack output, encKeys, iv)++-- |@'sealBS'@ strictly encrypts a chunk of data.+sealBS :: Cipher     -- ^ symmetric cipher algorithm to use+       -> [PKey]     -- ^ list of public keys to encrypt a symmetric+                     --   key+       -> ByteString -- ^ input string to encrypt+       -> IO (ByteString, [String], String) -- ^ (encrypted string,+                                            --   list of encrypted+                                            --   asymmetric keys, IV)+sealBS cipher pubKeys input+    = do (ctx, encKeys, iv) <- sealInit cipher pubKeys+         output             <- cipherStrictly ctx input+         return (output, encKeys, iv)++-- |@'sealLBS'@ lazilly encrypts a stream of data. The input string+-- doesn't necessarily have to be finite.+sealLBS :: Cipher         -- ^ symmetric cipher algorithm to use+        -> [PKey]         -- ^ list of public keys to encrypt a+                          --   symmetric key+        -> LazyByteString -- ^ input string to encrypt+        -> IO (LazyByteString, [String], String) -- ^ (encrypted+                                                 --   string, list of+                                                 --   encrypted+                                                 --   asymmetric keys,+                                                 --   IV)+sealLBS cipher pubKeys input+    = do (ctx, encKeys, iv) <- sealInit cipher pubKeys+         output             <- cipherLazily ctx input+         return (output, encKeys, iv)
+ OpenSSL/EVP/Sign.hsc view
@@ -0,0 +1,67 @@+{- -*- haskell -*- -}++-- |Message signing using asymmetric cipher and message digest+-- algorithm. This is an opposite of "OpenSSL.EVP.Verify".++module OpenSSL.EVP.Sign+    ( sign+    , signBS+    , signLBS+    )+    where++import           Control.Monad+import           Data.ByteString.Base+import qualified Data.ByteString.Char8 as B8+import qualified Data.ByteString.Lazy.Char8 as L8+import           Foreign+import           Foreign.C+import           OpenSSL.EVP.Digest+import           OpenSSL.EVP.PKey+import           OpenSSL.Utils+++foreign import ccall unsafe "EVP_SignFinal"+        _SignFinal :: Ptr EVP_MD_CTX -> Ptr CChar -> Ptr CUInt -> Ptr EVP_PKEY -> IO Int+++signFinal :: DigestCtx -> PKey -> IO String+signFinal ctx pkey+    = do maxLen <- pkeySize pkey+         withDigestCtxPtr ctx $ \ ctxPtr ->+             withPKeyPtr pkey $ \ pkeyPtr ->+                 allocaArray maxLen $ \ bufPtr ->+                     alloca $ \ bufLenPtr ->+                         do _SignFinal ctxPtr bufPtr bufLenPtr pkeyPtr+                                 >>= failIf (/= 1)+                            bufLen <- liftM fromIntegral $ peek bufLenPtr+                            peekCStringLen (bufPtr, bufLen)+++-- |@'sign'@ generates a signature from a stream of data. The string+-- must not contain any letters which aren't in the range of U+0000 -+-- U+00FF.+sign :: Digest    -- ^ message digest algorithm to use+     -> PKey      -- ^ private key to sign the message digest+     -> String    -- ^ input string+     -> IO String -- ^ the result signature+sign md pkey input+    = signLBS md pkey $ L8.pack input++-- |@'signBS'@ generates a signature from a chunk of data.+signBS :: Digest     -- ^ message digest algorithm to use+       -> PKey       -- ^ private key to sign the message digest+       -> ByteString -- ^ input string+       -> IO String  -- ^ the result signature+signBS md pkey input+    = do ctx <- digestStrictly md input+         signFinal ctx pkey++-- |@'signLBS'@ generates a signature from a stream of data.+signLBS :: Digest         -- ^ message digest algorithm to use+        -> PKey           -- ^ private key to sign the message digest+        -> LazyByteString -- ^ input string+        -> IO String      -- ^ the result signature+signLBS md pkey input+    = do ctx <- digestLazily md input+         signFinal ctx pkey
+ OpenSSL/EVP/Verify.hsc view
@@ -0,0 +1,76 @@+{- -*- haskell -*- -}++-- |Message verification using asymmetric cipher and message digest+-- algorithm. This is an opposite of "OpenSSL.EVP.Sign".++module OpenSSL.EVP.Verify+    ( VerifyStatus(..)+    , verify+    , verifyBS+    , verifyLBS+    )+    where++import           Control.Monad+import           Data.ByteString.Base+import qualified Data.ByteString.Char8 as B8+import qualified Data.ByteString.Lazy.Char8 as L8+import           Data.Typeable+import           Foreign+import           Foreign.C+import           OpenSSL.EVP.Digest+import           OpenSSL.EVP.PKey+import           OpenSSL.Utils++-- |@'VerifyStatus'@ represents a result of verification.+data VerifyStatus = VerifySuccess+                  | VerifyFailure+                    deriving (Show, Eq, Typeable)+++foreign import ccall unsafe "EVP_VerifyFinal"+        _VerifyFinal :: Ptr EVP_MD_CTX -> Ptr CChar -> CUInt -> Ptr EVP_PKEY -> IO Int+++verifyFinalBS :: DigestCtx -> String -> PKey -> IO VerifyStatus+verifyFinalBS ctx sig pkey+    = withDigestCtxPtr ctx $ \ ctxPtr ->+      withCStringLen sig $ \ (buf, len) ->+      withPKeyPtr pkey $ \ pkeyPtr ->+      _VerifyFinal ctxPtr buf (fromIntegral len) pkeyPtr >>= interpret+    where+      interpret :: Int -> IO VerifyStatus+      interpret 1 = return VerifySuccess+      interpret 0 = return VerifyFailure+      interpret _ = raiseOpenSSLError++-- |@'verify'@ verifies a signature and a stream of data. The string+-- must not contain any letters which aren't in the range of U+0000 -+-- U+00FF.+verify :: Digest          -- ^ message digest algorithm to use+       -> String          -- ^ message signature+       -> PKey            -- ^ public key to verify the signature+       -> String          -- ^ input string to verify+       -> IO VerifyStatus -- ^ the result of verification+verify md sig pkey input+    = verifyLBS md sig pkey (L8.pack input)++-- |@'verifyBS'@ verifies a signature and a chunk of data.+verifyBS :: Digest          -- ^ message digest algorithm to use+         -> String          -- ^ message signature+         -> PKey            -- ^ public key to verify the signature+         -> ByteString      -- ^ input string to verify+         -> IO VerifyStatus -- ^ the result of verification+verifyBS md sig pkey input+    = do ctx <- digestStrictly md input+         verifyFinalBS ctx sig pkey++-- |@'verifyLBS'@ verifies a signature of a stream of data.+verifyLBS :: Digest          -- ^ message digest algorithm to use+          -> String          -- ^ message signature+          -> PKey            -- ^ public key to verify the signature+          -> LazyByteString  -- ^ input string to verify+          -> IO VerifyStatus -- ^ the result of verification+verifyLBS md sig pkey input+    = do ctx <- digestLazily md input+         verifyFinalBS ctx sig pkey
+ OpenSSL/Objects.hsc view
@@ -0,0 +1,69 @@+{- -*- haskell -*- -}++-- #hide++#include "HsOpenSSL.h"++module OpenSSL.Objects+    ( ObjNameType(..)+    , getObjNames+    )+    where++import           Data.IORef+import           Foreign+import           Foreign.C+++type ObjName  = Ptr OBJ_NAME+data OBJ_NAME++type DoAllCallback = ObjName -> Ptr () -> IO ()+++foreign import ccall safe "OBJ_NAME_do_all"+        _NAME_do_all :: Int -> FunPtr DoAllCallback -> Ptr () -> IO ()++foreign import ccall safe "OBJ_NAME_do_all_sorted"+        _NAME_do_all_sorted :: Int -> FunPtr DoAllCallback -> Ptr () -> IO ()++foreign import ccall "wrapper"+        mkDoAllCallback :: DoAllCallback -> IO (FunPtr DoAllCallback)+++data ObjNameType = MDMethodType+                 | CipherMethodType+                 | PKeyMethodType+                 | CompMethodType++objNameTypeToInt :: ObjNameType -> Int+objNameTypeToInt MDMethodType     = #const OBJ_NAME_TYPE_MD_METH+objNameTypeToInt CipherMethodType = #const OBJ_NAME_TYPE_CIPHER_METH+objNameTypeToInt PKeyMethodType   = #const OBJ_NAME_TYPE_PKEY_METH+objNameTypeToInt CompMethodType   = #const OBJ_NAME_TYPE_COMP_METH+++iterateObjNames :: ObjNameType -> Bool -> (ObjName -> IO ()) -> IO ()+iterateObjNames nameType wantSorted cb+    = do cbPtr <- mkDoAllCallback $ \ name _ -> cb name+         let action = if wantSorted then+                          _NAME_do_all_sorted+                      else+                          _NAME_do_all+         action (objNameTypeToInt nameType) cbPtr nullPtr+         freeHaskellFunPtr cbPtr+++objNameStr :: ObjName -> IO String+objNameStr name+    = do strPtr <- (#peek OBJ_NAME, name) name+         peekCString strPtr+++getObjNames :: ObjNameType -> Bool -> IO [String]+getObjNames nameType wantSorted+    = do listRef <- newIORef []+         iterateObjNames nameType wantSorted $ \ name ->+             do nameStr <- objNameStr name+                modifyIORef listRef (++ [nameStr])+         readIORef listRef
+ OpenSSL/PEM.hsc view
@@ -0,0 +1,459 @@+{- -*- haskell -*- -}++-- |An interface to PEM routines.++module OpenSSL.PEM+    ( -- * Password supply+      PemPasswordCallback+    , PemPasswordRWState(..)+    , PemPasswordSupply(..)++      -- * Private key+    , writePKCS8PrivateKey+    , readPrivateKey++      -- * Public key+    , writePublicKey+    , readPublicKey++      -- * X.509 certificate+    , writeX509+    , readX509++      -- * PKCS#10 certificate request+    , PemX509ReqFormat(..)+    , writeX509Req+    , readX509Req++      -- * Certificate Revocation List+    , writeCRL+    , readCRL++      -- * PKCS#7 structure+    , writePkcs7+    , readPkcs7+    )+    where++import           Control.Exception+import           Control.Monad+import           Foreign+import           Foreign.C+import           OpenSSL.BIO+import           OpenSSL.EVP.Cipher+import           OpenSSL.EVP.PKey+import           OpenSSL.PKCS7+import           OpenSSL.Utils+import           OpenSSL.X509+import           OpenSSL.X509.Request+import           OpenSSL.X509.Revocation+import           Prelude hiding (catch)+import           System.IO+++-- |@'PemPasswordCallback'@ represents a callback function to supply a+-- password.+type PemPasswordCallback+    =  Int                -- ^ maximum length of the password to be+                          --   accepted+    -> PemPasswordRWState -- ^ context+    -> IO String          -- ^ the result password++type PemPasswordCallback' = Ptr CChar -> Int -> Int -> Ptr () -> IO Int+++-- |@'PemPasswordRWState'@ represents a context of+-- 'PemPasswordCallback'.+data PemPasswordRWState = PwRead  -- ^ The callback was called to get+                                  --   a password to read something+                                  --   encrypted.+                        | PwWrite -- ^ The callback was called to get+                                  --   a password to encrypt+                                  --   something.++-- |@'PemPasswordSupply'@ represents a way to supply password.+--+-- FIXME: using PwTTY causes an error but I don't know why:+-- \"error:0906406D:PEM routines:DEF_CALLBACK:problems getting+-- password\"+data PemPasswordSupply = PwNone       -- ^ no password+                       | PwStr String -- ^ password in a static string+                       | PwCallback PemPasswordCallback -- ^ get a+                                                        --   password+                                                        --   by a+                                                        --   callback+                       | PwTTY        -- ^ read a password from TTY+++foreign import ccall "wrapper"+        mkPemPasswordCallback :: PemPasswordCallback' -> IO (FunPtr PemPasswordCallback')+++rwflagToState :: Int -> PemPasswordRWState+rwflagToState 0 = PwRead+rwflagToState 1 = PwWrite+++callPasswordCB :: PemPasswordCallback -> PemPasswordCallback'+callPasswordCB cb buf bufLen rwflag _+    = let mode = rwflagToState rwflag+          try  = do passStr <- cb bufLen mode+                    let passLen = length passStr++                    when (passLen > bufLen)+                         $ failForTooLongPassword bufLen++                    pokeArray buf $ map (toEnum . fromEnum) passStr+                    return passLen+      in+        try `catch` \ exc ->+            do hPutStrLn stderr $ show exc+               return 0 -- zero indicates an error+    where+      failForTooLongPassword :: Int -> IO a+      failForTooLongPassword len+          = fail ("callPasswordCB: the password which the callback returned is too long: "+                  ++ "it must be at most " ++ show len ++ " bytes.")+++{- PKCS#8 -------------------------------------------------------------------- -}++foreign import ccall safe "PEM_write_bio_PKCS8PrivateKey"+        _write_bio_PKCS8PrivateKey :: Ptr BIO_+                                   -> Ptr EVP_PKEY+                                   -> Ptr EVP_CIPHER+                                   -> Ptr CChar+                                   -> Int+                                   -> FunPtr PemPasswordCallback'+                                   -> Ptr a+                                   -> IO Int++writePKCS8PrivateKey' :: BIO+                      -> PKey+                      -> Maybe (Cipher, PemPasswordSupply)+                      -> IO ()+writePKCS8PrivateKey' bio pkey encryption+    = withBioPtr bio   $ \ bioPtr  ->+      withPKeyPtr pkey $ \ pkeyPtr ->+      do ret <- case encryption of+                  Nothing+                      -> _write_bio_PKCS8PrivateKey bioPtr pkeyPtr nullPtr nullPtr 0 nullFunPtr nullPtr++                  Just (_, PwNone)+                      -> _write_bio_PKCS8PrivateKey bioPtr pkeyPtr nullPtr nullPtr 0 nullFunPtr nullPtr++                  Just (cipher, PwStr passStr)+                      -> withCStringLen passStr $ \ (passPtr, passLen) ->+                         withCipherPtr cipher   $ \ cipherPtr          ->+                         _write_bio_PKCS8PrivateKey bioPtr pkeyPtr cipherPtr passPtr passLen nullFunPtr nullPtr++                  Just (cipher, PwCallback cb)+                      -> withCipherPtr cipher $ \ cipherPtr ->+                         do cbPtr <- mkPemPasswordCallback $ callPasswordCB cb+                            ret   <- _write_bio_PKCS8PrivateKey bioPtr pkeyPtr cipherPtr nullPtr 0 cbPtr nullPtr+                            freeHaskellFunPtr cbPtr+                            return ret+               +                  Just (cipher, PwTTY)+                      -> withCipherPtr cipher $ \ cipherPtr ->+                         _write_bio_PKCS8PrivateKey bioPtr pkeyPtr cipherPtr nullPtr 0 nullFunPtr nullPtr+         failIf (/= 1) ret+         return ()++-- |@'writePKCS8PrivateKey'@ writes a private key to PEM string in+-- PKCS#8 format.+writePKCS8PrivateKey+    :: PKey      -- ^ private key to write+    -> Maybe (Cipher, PemPasswordSupply) -- ^ Either (symmetric cipher+                                         --   algorithm, password+                                         --   supply) or @Nothing@. If+                                         --   @Nothing@ is given the+                                         --   private key is not+                                         --   encrypted.+    -> IO String -- ^ the result PEM string+writePKCS8PrivateKey pkey encryption+    = do mem <- newMem+         writePKCS8PrivateKey' mem pkey encryption+         bioRead mem+++foreign import ccall safe "PEM_read_bio_PrivateKey"+        _read_bio_PrivateKey :: Ptr BIO_+                             -> Ptr (Ptr EVP_PKEY)+                             -> FunPtr PemPasswordCallback'+                             -> Ptr ()+                             -> IO (Ptr EVP_PKEY)++readPrivateKey' :: BIO -> PemPasswordSupply -> IO PKey+readPrivateKey' bio supply+    = withBioPtr bio $ \ bioPtr ->+      do pkeyPtr <- case supply of+                      PwNone+                          -> withCString "" $ \ strPtr ->+                             _read_bio_PrivateKey bioPtr nullPtr nullFunPtr (unsafeCoercePtr strPtr)+                                +                      PwStr passStr+                          -> do cbPtr <- mkPemPasswordCallback $+                                         callPasswordCB $ \ _ _ ->+                                         return passStr+                                pkeyPtr <- _read_bio_PrivateKey bioPtr nullPtr cbPtr nullPtr +                                freeHaskellFunPtr cbPtr+                                return pkeyPtr+                      PwCallback cb+                          -> do cbPtr <- mkPemPasswordCallback $ callPasswordCB cb+                                pkeyPtr <- _read_bio_PrivateKey bioPtr nullPtr cbPtr nullPtr +                                freeHaskellFunPtr cbPtr+                                return pkeyPtr+                      PwTTY+                          -> _read_bio_PrivateKey bioPtr nullPtr nullFunPtr nullPtr +         failIfNull pkeyPtr+         wrapPKeyPtr pkeyPtr++-- |@'readPrivateKey' pem supply@ reads a private key in PEM string.+readPrivateKey :: String -> PemPasswordSupply -> IO PKey+readPrivateKey pemStr supply+    = do mem <- newConstMem pemStr+         readPrivateKey' mem supply+++{- Public Key ---------------------------------------------------------------- -}++foreign import ccall unsafe "PEM_write_bio_PUBKEY"+        _write_bio_PUBKEY :: Ptr BIO_ -> Ptr EVP_PKEY -> IO Int++foreign import ccall unsafe "PEM_read_bio_PUBKEY"+        _read_bio_PUBKEY :: Ptr BIO_+                         -> Ptr (Ptr EVP_PKEY)+                         -> FunPtr PemPasswordCallback'+                         -> Ptr ()+                         -> IO (Ptr EVP_PKEY)+++writePublicKey' :: BIO -> PKey -> IO ()+writePublicKey' bio pkey+    = withBioPtr bio   $ \ bioPtr  ->+      withPKeyPtr pkey $ \ pkeyPtr ->+      _write_bio_PUBKEY bioPtr pkeyPtr >>= failIf (/= 1) >> return ()++-- |@'writePublicKey' pubkey@ writes a public to PEM string.+writePublicKey :: PKey -> IO String+writePublicKey pkey+    = do mem <- newMem+         writePublicKey' mem pkey+         bioRead mem++-- Why the heck PEM_read_bio_PUBKEY takes pem_password_cb? Is there+-- any form of encrypted public key?+readPublicKey' :: BIO -> IO PKey+readPublicKey' bio+    = withBioPtr bio $ \ bioPtr ->+      withCString "" $ \ passPtr ->+      _read_bio_PUBKEY bioPtr nullPtr nullFunPtr (unsafeCoercePtr passPtr)+           >>= failIfNull+           >>= wrapPKeyPtr++-- |@'readPublicKey' pem@ reads a public key in PEM string.+readPublicKey :: String -> IO PKey+readPublicKey pemStr+    = newConstMem pemStr >>= readPublicKey'+++{- X.509 certificate --------------------------------------------------------- -}++foreign import ccall unsafe "PEM_write_bio_X509_AUX"+        _write_bio_X509_AUX :: Ptr BIO_+                            -> Ptr X509_+                            -> IO Int++foreign import ccall safe "PEM_read_bio_X509_AUX"+        _read_bio_X509_AUX :: Ptr BIO_+                           -> Ptr (Ptr X509_)+                           -> FunPtr PemPasswordCallback'+                           -> Ptr ()+                           -> IO (Ptr X509_)++writeX509' :: BIO -> X509 -> IO ()+writeX509' bio x509+    = withBioPtr bio   $ \ bioPtr  ->+      withX509Ptr x509 $ \ x509Ptr ->+      _write_bio_X509_AUX bioPtr x509Ptr+           >>= failIf (/= 1)+           >>  return ()++-- |@'writeX509' cert@ writes an X.509 certificate to PEM string.+writeX509 :: X509 -> IO String+writeX509 x509+    = do mem <- newMem+         writeX509' mem x509+         bioRead mem+++-- I believe X.509 isn't encrypted.+readX509' :: BIO -> IO X509+readX509' bio+    = withBioPtr bio $ \ bioPtr ->+      withCString "" $ \ passPtr ->+      _read_bio_X509_AUX bioPtr nullPtr nullFunPtr (unsafeCoercePtr passPtr)+           >>= failIfNull+           >>= wrapX509++-- |@'readX509' pem@ reads an X.509 certificate in PEM string.+readX509 :: String -> IO X509+readX509 pemStr+    = newConstMem pemStr >>= readX509'+++{- PKCS#10 certificate request ----------------------------------------------- -}++foreign import ccall unsafe "PEM_write_bio_X509_REQ"+        _write_bio_X509_REQ :: Ptr BIO_+                            -> Ptr X509_REQ+                            -> IO Int++foreign import ccall unsafe "PEM_write_bio_X509_REQ_NEW"+        _write_bio_X509_REQ_NEW :: Ptr BIO_+                                -> Ptr X509_REQ+                                -> IO Int++foreign import ccall safe "PEM_read_bio_X509_REQ"+        _read_bio_X509_REQ :: Ptr BIO_+                           -> Ptr (Ptr X509_REQ)+                           -> FunPtr PemPasswordCallback'+                           -> Ptr ()+                           -> IO (Ptr X509_REQ)++-- |@'PemX509ReqFormat'@ represents format of PKCS#10 certificate+-- request.+data PemX509ReqFormat+    = ReqNewFormat -- ^ The new format, whose header is \"NEW+                   --   CERTIFICATE REQUEST\".+    | ReqOldFormat -- ^ The old format, whose header is \"CERTIFICATE+                   --   REQUEST\".+++writeX509Req' :: BIO -> X509Req -> PemX509ReqFormat -> IO ()+writeX509Req' bio req format+    = withBioPtr bio     $ \ bioPtr ->+      withX509ReqPtr req $ \ reqPtr ->+      writer bioPtr reqPtr+                 >>= failIf (/= 1)+                 >>  return ()+    where+      writer = case format of+                 ReqNewFormat -> _write_bio_X509_REQ_NEW+                 ReqOldFormat -> _write_bio_X509_REQ++-- |@'writeX509Req'@ writes a PKCS#10 certificate request to PEM+-- string.+writeX509Req :: X509Req          -- ^ request+             -> PemX509ReqFormat -- ^ format+             -> IO String        -- ^ the result PEM string+writeX509Req req format+    = do mem <- newMem+         writeX509Req' mem req format+         bioRead mem+++readX509Req' :: BIO -> IO X509Req+readX509Req' bio+    = withBioPtr bio $ \ bioPtr ->+      withCString "" $ \ passPtr ->+      _read_bio_X509_REQ bioPtr nullPtr nullFunPtr (unsafeCoercePtr passPtr)+           >>= failIfNull+           >>= wrapX509Req++-- |@'readX509Req'@ reads a PKCS#10 certificate request in PEM string.+readX509Req :: String -> IO X509Req+readX509Req pemStr+    = newConstMem pemStr >>= readX509Req'+++{- Certificate Revocation List ----------------------------------------------- -}++foreign import ccall unsafe "PEM_write_bio_X509_CRL"+        _write_bio_X509_CRL :: Ptr BIO_+                            -> Ptr X509_CRL+                            -> IO Int++foreign import ccall safe "PEM_read_bio_X509_CRL"+        _read_bio_X509_CRL :: Ptr BIO_+                           -> Ptr (Ptr X509_CRL)+                           -> FunPtr PemPasswordCallback'+                           -> Ptr ()+                           -> IO (Ptr X509_CRL)+++writeCRL' :: BIO -> CRL -> IO ()+writeCRL' bio crl+    = withBioPtr bio $ \ bioPtr ->+      withCRLPtr crl $ \ crlPtr ->+      _write_bio_X509_CRL bioPtr crlPtr+           >>= failIf (/= 1)+           >>  return ()++-- |@'writeCRL' crl@ writes a Certificate Revocation List to PEM+-- string.+writeCRL :: CRL -> IO String+writeCRL crl+    = do mem <- newMem+         writeCRL' mem crl+         bioRead mem+++readCRL' :: BIO -> IO CRL+readCRL' bio+    = withBioPtr bio $ \ bioPtr ->+      withCString "" $ \ passPtr ->+      _read_bio_X509_CRL bioPtr nullPtr nullFunPtr (unsafeCoercePtr passPtr)+           >>= failIfNull+           >>= wrapCRL++-- |@'readCRL' pem@ reads a Certificate Revocation List in PEM string.+readCRL :: String -> IO CRL+readCRL pemStr+    = newConstMem pemStr >>= readCRL'+++{- PKCS#7 -------------------------------------------------------------------- -}++foreign import ccall unsafe "PEM_write_bio_PKCS7"+        _write_bio_PKCS7 :: Ptr BIO_+                         -> Ptr PKCS7+                         -> IO Int++foreign import ccall safe "PEM_read_bio_PKCS7"+        _read_bio_PKCS7 :: Ptr BIO_+                        -> Ptr (Ptr PKCS7)+                        -> FunPtr PemPasswordCallback'+                        -> Ptr ()+                        -> IO (Ptr PKCS7)+++writePkcs7' :: BIO -> Pkcs7 -> IO ()+writePkcs7' bio pkcs7+    = withBioPtr bio     $ \ bioPtr ->+      withPkcs7Ptr pkcs7 $ \ pkcs7Ptr ->+      _write_bio_PKCS7 bioPtr pkcs7Ptr+           >>= failIf (/= 1)+           >>  return ()++-- |@'writePkcs7' p7@ writes a PKCS#7 structure to PEM string.+writePkcs7 :: Pkcs7 -> IO String+writePkcs7 pkcs7+    = do mem <- newMem+         writePkcs7' mem pkcs7+         bioRead mem+++readPkcs7' :: BIO -> IO Pkcs7+readPkcs7' bio+    = withBioPtr bio $ \ bioPtr ->+      withCString "" $ \ passPtr ->+      _read_bio_PKCS7 bioPtr nullPtr nullFunPtr (unsafeCoercePtr passPtr)+           >>= failIfNull+           >>= wrapPkcs7Ptr++-- |@'readPkcs7' pem@ reads a PKCS#7 structure in PEM string.+readPkcs7 :: String -> IO Pkcs7+readPkcs7 pemStr+    = newConstMem pemStr >>= readPkcs7'
+ OpenSSL/PKCS7.hsc view
@@ -0,0 +1,419 @@+{- -*- haskell -*- -}++-- #prune++-- |An interface to PKCS#7 structure and S\/MIME message.++#include "HsOpenSSL.h"++module OpenSSL.PKCS7+    ( -- * Types+      Pkcs7+    , PKCS7 -- private+    , Pkcs7Flag(..)+    , Pkcs7VerifyStatus(..)+    , wrapPkcs7Ptr -- private+    , withPkcs7Ptr -- private++      -- * Encryption and Signing+    , pkcs7Sign+    , pkcs7Verify+    , pkcs7Encrypt+    , pkcs7Decrypt++      -- * S\/MIME+    , writeSmime+    , readSmime+    )+    where++import           Data.List+import           Data.Traversable+import           Data.Typeable+import           Foreign+import           Foreign.C+import           OpenSSL.BIO+import           OpenSSL.EVP.Cipher+import           OpenSSL.EVP.PKey+import           OpenSSL.Stack+import           OpenSSL.Utils+import           OpenSSL.X509+import           OpenSSL.X509.Store+++{- PKCS#7 -------------------------------------------------------------------- -}++-- |@'Pkcs7'@ represents an abstract PKCS#7 structure. The concrete+-- type of structure is hidden in the object: such polymorphism isn't+-- very haskellish but please get it out of your mind since OpenSSL is+-- written in C.+newtype Pkcs7 = Pkcs7 (ForeignPtr PKCS7)+data    PKCS7++-- |@'Pkcs7Flag'@ is a set of flags that are used in many operations+-- related to PKCS#7.+data Pkcs7Flag = Pkcs7Text+               | Pkcs7NoCerts+               | Pkcs7NoSigs+               | Pkcs7NoChain+               | Pkcs7NoIntern+               | Pkcs7NoVerify+               | Pkcs7Detached+               | Pkcs7Binary+               | Pkcs7NoAttr+               | Pkcs7NoSmimeCap+               | Pkcs7NoOldMimeType+               | Pkcs7CRLFEOL+                 deriving (Show, Eq, Typeable)++flagToInt :: Pkcs7Flag -> Int+flagToInt Pkcs7Text          = #const PKCS7_TEXT+flagToInt Pkcs7NoCerts       = #const PKCS7_NOCERTS+flagToInt Pkcs7NoSigs        = #const PKCS7_NOSIGS+flagToInt Pkcs7NoChain       = #const PKCS7_NOCHAIN+flagToInt Pkcs7NoIntern      = #const PKCS7_NOINTERN+flagToInt Pkcs7NoVerify      = #const PKCS7_NOVERIFY+flagToInt Pkcs7Detached      = #const PKCS7_DETACHED+flagToInt Pkcs7Binary        = #const PKCS7_BINARY+flagToInt Pkcs7NoAttr        = #const PKCS7_NOATTR+flagToInt Pkcs7NoSmimeCap    = #const PKCS7_NOSMIMECAP+flagToInt Pkcs7NoOldMimeType = #const PKCS7_NOOLDMIMETYPE+flagToInt Pkcs7CRLFEOL       = #const PKCS7_CRLFEOL++-- |@'Pkcs7VerifyStatus'@ represents a result of PKCS#7+-- verification. See 'pkcs7Verify'.+data Pkcs7VerifyStatus+    = Pkcs7VerifySuccess (Maybe String) -- ^ Nothing if the PKCS#7+                                        --   signature was a detached+                                        --   signature, and @Just content@+                                        --   if it wasn't.+    | Pkcs7VerifyFailure+      deriving (Show, Eq, Typeable)+++flagListToInt :: [Pkcs7Flag] -> Int+flagListToInt = foldl' (.|.) 0 . map flagToInt+++foreign import ccall "&PKCS7_free"+        _free :: FunPtr (Ptr PKCS7 -> IO ())++foreign import ccall "HsOpenSSL_PKCS7_is_detached"+        _is_detached :: Ptr PKCS7 -> IO CLong++foreign import ccall "PKCS7_sign"+        _sign :: Ptr X509_ -> Ptr EVP_PKEY -> Ptr STACK -> Ptr BIO_ -> Int -> IO (Ptr PKCS7)++foreign import ccall "PKCS7_verify"+        _verify :: Ptr PKCS7 -> Ptr STACK -> Ptr X509_STORE -> Ptr BIO_ -> Ptr BIO_ -> Int -> IO Int++foreign import ccall "PKCS7_encrypt"+        _encrypt :: Ptr STACK -> Ptr BIO_ -> Ptr EVP_CIPHER -> Int -> IO (Ptr PKCS7)++foreign import ccall "PKCS7_decrypt"+        _decrypt :: Ptr PKCS7 -> Ptr EVP_PKEY -> Ptr X509_ -> Ptr BIO_ -> Int -> IO Int+++wrapPkcs7Ptr :: Ptr PKCS7 -> IO Pkcs7+wrapPkcs7Ptr p7Ptr = newForeignPtr _free p7Ptr >>= return . Pkcs7+++withPkcs7Ptr :: Pkcs7 -> (Ptr PKCS7 -> IO a) -> IO a+withPkcs7Ptr (Pkcs7 pkcs7) = withForeignPtr pkcs7+++isDetachedSignature :: Pkcs7 -> IO Bool+isDetachedSignature pkcs7+    = withPkcs7Ptr pkcs7 $ \ pkcs7Ptr ->+      _is_detached pkcs7Ptr+           >>= return . (== 1)+++pkcs7Sign' :: X509 -> PKey -> [X509] -> BIO -> [Pkcs7Flag] -> IO Pkcs7+pkcs7Sign' signCert pkey certs input flagList+    = withX509Ptr signCert $ \ signCertPtr ->+      withPKeyPtr pkey     $ \ pkeyPtr     ->+      withX509Stack certs  $ \ certStack   ->+      withBioPtr input     $ \ inputPtr    ->+      _sign signCertPtr pkeyPtr certStack inputPtr (flagListToInt flagList)+           >>= failIfNull+           >>= wrapPkcs7Ptr++-- |@'pkcs7Sign'@ creates a PKCS#7 signedData structure.+pkcs7Sign :: X509        -- ^ certificate to sign with+          -> PKey        -- ^ corresponding private key+          -> [X509]      -- ^ optional additional set of certificates+                         --   to include in the PKCS#7 structure (for+                         --   example any intermediate CAs in the+                         --   chain)+          -> String      -- ^ data to be signed+          -> [Pkcs7Flag] -- ^ An optional set of flags:+                         -- +                         --   ['Pkcs7Text'] Many S\/MIME clients+                         --   expect the signed content to include+                         --   valid MIME headers. If the 'Pkcs7Text'+                         --   flag is set MIME headers for type+                         --   \"text\/plain\" are prepended to the+                         --   data.+                         --+                         --   ['Pkcs7NoCerts'] If 'Pkcs7NoCerts' is+                         --   set the signer's certificate will not be+                         --   included in the PKCS#7 structure, the+                         --   signer's certificate must still be+                         --   supplied in the parameter though. This+                         --   can reduce the size of the signature if+                         --   the signer's certificate can be obtained+                         --   by other means: for example a previously+                         --   signed message.+                         --+                         --   ['Pkcs7Detached'] The data being signed+                         --   is included in the PKCS#7 structure,+                         --   unless 'Pkcs7Detached' is set in which+                         --   case it is ommited. This is used for+                         --   PKCS#7 detached signatures which are+                         --   used in S\/MIME plaintext signed message+                         --   for example.+                         --+                         --   ['Pkcs7Binary'] Normally the supplied+                         --   content is translated into MIME+                         --   canonical format (as required by the+                         --   S\/MIME specifications) but if+                         --   'Pkcs7Binary' is set no translation+                         --   occurs. This option should be uesd if+                         --   the supplied data is in binary format+                         --   otherwise the translation will corrupt+                         --   it.+                         --+                         --   ['Pkcs7NoAttr']+                         --+                         --   ['Pkcs7NoSmimeCap'] The signedData+                         --   structure includes several PKCS#7+                         --   authenticatedAttributes including the+                         --   signing time, the PKCS#7 content type+                         --   and the supported list of ciphers in an+                         --   SMIMECapabilities attribute. If+                         --   'Pkcs7NoAttr' is set then no+                         --   authenticatedAttributes will be used. If+                         --   Pkcs7NoSmimeCap is set then just the+                         --   SMIMECapabilities are omitted.+          -> IO Pkcs7+pkcs7Sign signCert pkey certs input flagList+    = do mem <- newConstMem input+         pkcs7Sign' signCert pkey certs mem flagList+++pkcs7Verify' :: Pkcs7 -> [X509] -> X509Store -> Maybe BIO -> [Pkcs7Flag] -> IO (Maybe BIO, Bool)+pkcs7Verify' pkcs7 certs store inData flagList+    = withPkcs7Ptr pkcs7     $ \ pkcs7Ptr  ->+      withX509Stack certs    $ \ certStack ->+      withX509StorePtr store $ \ storePtr  ->+      withBioPtr' inData     $ \ inDataPtr ->+      do isDetached <- isDetachedSignature pkcs7+         outData    <- if isDetached then+                           return Nothing+                       else+                           newMem >>= return . Just+         withBioPtr' outData $ \ outDataPtr ->+             _verify pkcs7Ptr certStack storePtr inDataPtr outDataPtr (flagListToInt flagList)+                  >>= interpret outData+    where+      interpret :: Maybe BIO -> Int -> IO (Maybe BIO, Bool)+      interpret bio 1 = return (bio    , True )+      interpret _   _ = return (Nothing, False)++-- |@'pkcs7Verify'@ verifies a PKCS#7 signedData structure.+pkcs7Verify :: Pkcs7           -- ^ A PKCS#7 structure to verify.+            -> [X509]          -- ^ Set of certificates in which to+                               --   search for the signer's+                               --   certificate.+            -> X509Store       -- ^ Trusted certificate store (used+                               --   for chain verification).+            -> Maybe String    -- ^ Signed data if the content is not+                               --   present in the PKCS#7 structure+                               --   (that is it is detached).+            -> [Pkcs7Flag]     -- ^ An optional set of flags:+                               -- +                               --   ['Pkcs7NoIntern'] If+                               --   'Pkcs7NoIntern' is set the+                               --   certificates in the message itself+                               --   are not searched when locating the+                               --   signer's certificate. This means+                               --   that all the signers certificates+                               --   must be in the second argument+                               --   (['X509']).+                               --+                               --   ['Pkcs7Text'] If the 'Pkcs7Text'+                               --   flag is set MIME headers for type+                               --   \"text\/plain\" are deleted from+                               --   the content. If the content is not+                               --   of type \"text\/plain\" then an+                               --   error is returned.+                               --+                               --   ['Pkcs7NoVerify'] If+                               --   'Pkcs7NoVerify' is set the+                               --   signer's certificates are not+                               --   chain verified.+                               --+                               --   ['Pkcs7NoChain'] If 'Pkcs7NoChain'+                               --   is set then the certificates+                               --   contained in the message are not+                               --   used as untrusted CAs. This means+                               --   that the whole verify chain (apart+                               --   from the signer's certificate)+                               --   must be contained in the trusted+                               --   store.+                               --+                               --   ['Pkcs7NoSigs'] If 'Pkcs7NoSigs'+                               --   is set then the signatures on the+                               --   data are not checked.+            -> IO Pkcs7VerifyStatus+pkcs7Verify pkcs7 certs store inData flagList+    = do inDataBio               <- forM inData newConstMem+         (outDataBio, isSuccess) <- pkcs7Verify' pkcs7 certs store inDataBio flagList+         if isSuccess then+             do outData <- forM outDataBio bioRead+                return $ Pkcs7VerifySuccess outData+           else+             return Pkcs7VerifyFailure+++pkcs7Encrypt' :: [X509] -> BIO -> Cipher -> [Pkcs7Flag] -> IO Pkcs7+pkcs7Encrypt' certs input cipher flagList+    = withX509Stack certs  $ \ certsPtr  ->+      withBioPtr    input  $ \ inputPtr  ->+      withCipherPtr cipher $ \ cipherPtr ->+      _encrypt certsPtr inputPtr cipherPtr (flagListToInt flagList)+           >>= failIfNull+           >>= wrapPkcs7Ptr++-- |@'pkcs7Encrypt'@ creates a PKCS#7 envelopedData structure.+pkcs7Encrypt :: [X509]      -- ^ A list of recipient certificates.+             -> String      -- ^ The content to be encrypted.+             -> Cipher      -- ^ The symmetric cipher to use.+             -> [Pkcs7Flag] -- ^ An optional set of flags:+                            --+                            --   ['Pkcs7Text'] If the 'Pkcs7Text' flag+                            --   is set MIME headers for type+                            --   \"text\/plain\" are prepended to the+                            --   data.+                            --+                            --   ['Pkcs7Binary'] Normally the supplied+                            --   content is translated into MIME+                            --   canonical format (as required by the+                            --   S\/MIME specifications) if+                            --   'Pkcs7Binary' is set no translation+                            --   occurs. This option should be used if+                            --   the supplied data is in binary format+                            --   otherwise the translation will+                            --   corrupt it. If 'Pkcs7Binary' is set+                            --   then 'Pkcs7Text' is ignored.+             -> IO Pkcs7+pkcs7Encrypt certs input cipher flagList+    = do mem <- newConstMem input+         pkcs7Encrypt' certs mem cipher flagList+++pkcs7Decrypt' :: Pkcs7 -> PKey -> X509 -> BIO -> [Pkcs7Flag] -> IO ()+pkcs7Decrypt' pkcs7 pkey cert output flagList+    = withPkcs7Ptr pkcs7  $ \ pkcs7Ptr  ->+      withPKeyPtr  pkey   $ \ pkeyPtr   ->+      withX509Ptr  cert   $ \ certPtr   ->+      withBioPtr   output $ \ outputPtr ->+      _decrypt pkcs7Ptr pkeyPtr certPtr outputPtr (flagListToInt flagList)+           >>= failIf (/= 1)+           >>  return ()++-- |@'pkcs7Decrypt'@ decrypts content from PKCS#7 envelopedData+-- structure.+pkcs7Decrypt :: Pkcs7       -- ^ The PKCS#7 structure to decrypt.+             -> PKey        -- ^ The private key of the recipient.+             -> X509        -- ^ The recipient's certificate.+             -> [Pkcs7Flag] -- ^ An optional set of flags:+                            --+                            --   ['Pkcs7Text'] If the 'Pkcs7Text' flag+                            --   is set MIME headers for type+                            --   \"text\/plain\" are deleted from the+                            --   content. If the content is not of+                            --   type \"text\/plain\" then an error is+                            --   thrown.+             -> IO String   -- ^ The decrypted content.+pkcs7Decrypt pkcs7 pkey cert flagList+    = do mem <- newMem+         pkcs7Decrypt' pkcs7 pkey cert mem flagList+         bioRead mem+++{- S/MIME -------------------------------------------------------------------- -}++foreign import ccall unsafe "SMIME_write_PKCS7"+        _SMIME_write_PKCS7 :: Ptr BIO_ -> Ptr PKCS7 -> Ptr BIO_ -> Int -> IO Int++foreign import ccall unsafe "SMIME_read_PKCS7"+        _SMIME_read_PKCS7 :: Ptr BIO_ -> Ptr (Ptr BIO_) -> IO (Ptr PKCS7)++-- |@'writeSmime'@ writes PKCS#7 structure to S\/MIME message.+writeSmime :: Pkcs7        -- ^ A PKCS#7 structure to be written.+           -> Maybe String -- ^ If cleartext signing+                           --   (multipart\/signed) is being used then+                           --   the signed data must be supplied here.+           -> [Pkcs7Flag]  -- ^ An optional set of flags:+                           --+                           --   ['Pkcs7Detached'] If 'Pkcs7Detached'+                           --   is set then cleartext signing will be+                           --   used, this option only makes sense for+                           --   signedData where 'Pkcs7Detached' is+                           --   also set when 'pkcs7Sign' is also+                           --   called.+                           --+                           --   ['Pkcs7Text'] If the 'Pkcs7Text' flag+                           --   is set MIME headers for type+                           --   \"text\/plain\" are added to the+                           --   content, this only makes sense if+                           --   'Pkcs7Detached' is also set.+           -> IO String    -- ^ The result S\/MIME message.+writeSmime pkcs7 dataStr flagList+    = do outBio  <- newMem+         dataBio <- forM dataStr newConstMem+         writeSmime' outBio pkcs7 dataBio flagList+         bioRead outBio+++writeSmime' :: BIO -> Pkcs7 -> Maybe BIO -> [Pkcs7Flag] -> IO ()+writeSmime' outBio pkcs7 dataBio flagList+    = withBioPtr   outBio  $ \ outBioPtr  ->+      withPkcs7Ptr pkcs7   $ \ pkcs7Ptr   ->+      withBioPtr'  dataBio $ \ dataBioPtr ->+      _SMIME_write_PKCS7 outBioPtr pkcs7Ptr dataBioPtr (flagListToInt flagList)+           >>= failIf (/= 1)+           >>  return ()++-- |@'readSmime'@ parses S\/MIME message.+readSmime :: String -- ^ The message to be read.+          -> IO (Pkcs7, Maybe String) -- ^ (The result PKCS#7+                                      --   structure, @Just content@+                                      --   if the PKCS#7 structure was+                                      --   a cleartext signature and+                                      --   @Nothing@ if it wasn't.)+readSmime input+    = do inBio           <- newConstMem input+         (pkcs7, outBio) <- readSmime' inBio+         output          <- forM outBio bioRead+         return (pkcs7, output)+++readSmime' :: BIO -> IO (Pkcs7, Maybe BIO)+readSmime' inBio+    = withBioPtr inBio $ \ inBioPtr     ->+      alloca           $ \ outBioPtrPtr ->+      do poke outBioPtrPtr nullPtr++         pkcs7     <- _SMIME_read_PKCS7 inBioPtr outBioPtrPtr+                      >>= failIfNull+                      >>= wrapPkcs7Ptr+         outBioPtr <- peek outBioPtrPtr+         outBio    <- if outBioPtr == nullPtr then+                          return Nothing+                      else+                          wrapBioPtr outBioPtr >>= return . Just++         return (pkcs7, outBio)
+ OpenSSL/RSA.hsc view
@@ -0,0 +1,152 @@+{- -*- haskell -*- -}++-- #prune++-- |An interface to RSA public key generator.++#include "HsOpenSSL.h"++module OpenSSL.RSA+    ( -- * Type+      RSA+    , RSA_ -- private+    , withRSAPtr -- private++      -- * Generating keypair+    , RSAGenKeyCallback+    , generateKey++      -- * Exploring keypair+    , rsaN+    , rsaE+    , rsaD+    , rsaP+    , rsaQ+    , rsaDMP1+    , rsaDMQ1+    , rsaIQMP+    )+    where++import           Control.Monad+import           Foreign+import           OpenSSL.BN+import           OpenSSL.Utils++-- |@'RSA'@ is an opaque object that represents either RSA public key+-- or public\/private keypair.+newtype RSA  = RSA (ForeignPtr RSA_)+data    RSA_+++foreign import ccall unsafe "&RSA_free"+        _free :: FunPtr (Ptr RSA_ -> IO ())+++withRSAPtr :: RSA -> (Ptr RSA_ -> IO a) -> IO a+withRSAPtr (RSA rsa) = withForeignPtr rsa+++{- generation --------------------------------------------------------------- -}++-- |@'RSAGenKeyCallback'@ represents a callback function to get+-- informed the progress of RSA key generation.+--+-- * @callback 0 i@ is called after generating the @i@-th potential+--   prime number.+--+-- * While the number is being tested for primality, @callback 1 j@ is+--   called after the @j@-th iteration (j = 0, 1, ...).+--+-- * When the @n@-th randomly generated prime is rejected as not+--   suitable for the key, @callback 2 n@ is called.+--+-- * When a random @p@ has been found with @p@-1 relatively prime to+--   @e@, it is called as @callback 3 0@.+--+-- * The process is then repeated for prime @q@ with @callback 3 1@.+type RSAGenKeyCallback = Int -> Int -> IO ()++type RSAGenKeyCallback' = Int -> Int -> Ptr () -> IO ()+++foreign import ccall "wrapper"+        mkGenKeyCallback :: RSAGenKeyCallback' -> IO (FunPtr RSAGenKeyCallback')++foreign import ccall safe "RSA_generate_key"+        _generate_key :: Int -> Int -> FunPtr RSAGenKeyCallback' -> Ptr a -> IO (Ptr RSA_)++-- |@'generateKey'@ generates an RSA keypair.+generateKey :: Int    -- ^ The number of bits of the public modulus+                      --   (i.e. key size). Key sizes with @n < 1024@+                      --   should be considered insecure.+            -> Int    -- ^ The public exponent. It is an odd number,+                      --   typically 3, 17 or 65537.+            -> Maybe RSAGenKeyCallback -- ^ A callback function.+            -> IO RSA -- ^ The generated keypair.++generateKey nbits e Nothing+    = do ptr <- _generate_key nbits e nullFunPtr nullPtr+         failIfNull ptr+         newForeignPtr _free ptr >>= return . RSA++generateKey nbits e (Just cb)+    = do cbPtr <- mkGenKeyCallback+                  $ \ arg1 arg2 _ -> cb arg1 arg2+         ptr   <- _generate_key nbits e cbPtr nullPtr+         freeHaskellFunPtr cbPtr+         failIfNull ptr+         newForeignPtr _free ptr >>= return . RSA+++{- exploration -------------------------------------------------------------- -}++peekRSAPublic :: (Ptr RSA_ -> IO (Ptr BIGNUM)) -> RSA -> IO Integer+peekRSAPublic peeker rsa+    = withRSAPtr rsa $ \ rsaPtr ->+      do bn <- peeker rsaPtr+         when (bn == nullPtr) $ fail "peekRSAPublic: got a nullPtr"+         peekBN bn+++peekRSAPrivate :: (Ptr RSA_ -> IO (Ptr BIGNUM)) -> RSA -> IO (Maybe Integer)+peekRSAPrivate peeker rsa+    = withRSAPtr rsa $ \ rsaPtr ->+      do bn <- peeker rsaPtr+         if bn == nullPtr then+             return Nothing+           else+             peekBN bn >>= return . Just++-- |@'rsaN' pubKey@ returns the public modulus of the key.+rsaN :: RSA -> IO Integer+rsaN = peekRSAPublic (#peek RSA, n)++-- |@'rsaE' pubKey@ returns the public exponent of the key.+rsaE :: RSA -> IO Integer+rsaE = peekRSAPublic (#peek RSA, e)++-- |@'rsaD' privKey@ returns the private exponent of the key. If+-- @privKey@ is not really a private key, the result is @Nothing@.+rsaD :: RSA -> IO (Maybe Integer)+rsaD = peekRSAPrivate (#peek RSA, d)++-- |@'rsaP' privkey@ returns the secret prime factor @p@ of the key.+rsaP :: RSA -> IO (Maybe Integer)+rsaP = peekRSAPrivate (#peek RSA, p)++-- |@'rsaQ' privkey@ returns the secret prime factor @q@ of the key.+rsaQ :: RSA -> IO (Maybe Integer)+rsaQ = peekRSAPrivate (#peek RSA, q)++-- |@'rsaDMP1' privkey@ returns @d mod (p-1)@ of the key.+rsaDMP1 :: RSA -> IO (Maybe Integer)+rsaDMP1 = peekRSAPrivate (#peek RSA, dmp1)++-- |@'rsaDMQ1' privkey@ returns @d mod (q-1)@ of the key.+rsaDMQ1 :: RSA -> IO (Maybe Integer)+rsaDMQ1 = peekRSAPrivate (#peek RSA, dmq1)++-- |@'rsaIQMP' privkey@ returns @q^-1 mod p@ of the key.+rsaIQMP :: RSA -> IO (Maybe Integer)+rsaIQMP = peekRSAPrivate (#peek RSA, iqmp)
+ OpenSSL/SSL.hsc view
@@ -0,0 +1,15 @@+{- -*- haskell -*- -}++-- #hide++module OpenSSL.SSL+    ( loadErrorStrings+    , addAllAlgorithms+    )+    where++foreign import ccall unsafe "SSL_load_error_strings"+        loadErrorStrings :: IO ()++foreign import ccall unsafe "HsOpenSSL_OpenSSL_add_all_algorithms"+        addAllAlgorithms :: IO ()
+ OpenSSL/Stack.hsc view
@@ -0,0 +1,64 @@+{- -*- haskell -*- -}++-- #hide++module OpenSSL.Stack+    ( STACK+    , mapStack+    , withStack+    , withForeignStack+    )+    where++import           Control.Exception+import           Foreign+import           OpenSSL.Utils+++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 Int++foreign import ccall unsafe "sk_value"+        skValue :: Ptr STACK -> Int -> IO (Ptr ())+++mapStack :: (Ptr a -> IO b) -> Ptr STACK -> IO [b]+mapStack m st+    = do num <- skNum st+         mapM (\ i -> skValue st i >>= return . unsafeCoercePtr >>= m)+                  $ take num [0..]+++newStack :: [Ptr a] -> IO (Ptr STACK)+newStack values+    = do st <- skNewNull+         mapM_ (skPush st . unsafeCoercePtr) values+         return st+++withStack :: [Ptr a] -> (Ptr STACK -> IO b) -> IO b+withStack values f+    = bracket (newStack values) skFree f+++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/Utils.hs view
@@ -0,0 +1,38 @@+{- -*- haskell -*- -}++-- #hide++module OpenSSL.Utils+    ( failIfNull+    , failIf+    , raiseOpenSSLError++    , unsafeCoercePtr+    )+    where++import           Foreign+import           GHC.Base+import           OpenSSL.ERR+++failIfNull :: Ptr a -> IO (Ptr a)+failIfNull ptr+    = if ptr == nullPtr then+          raiseOpenSSLError+      else+          return ptr+++failIf :: (a -> Bool) -> a -> IO a+failIf f a+    | f a       = raiseOpenSSLError+    | otherwise = return a+++raiseOpenSSLError :: IO a+raiseOpenSSLError = getError >>= errorString >>= fail+++unsafeCoercePtr :: Ptr a -> Ptr b+unsafeCoercePtr = unsafeCoerce#
+ OpenSSL/X509.hsc view
@@ -0,0 +1,372 @@+{- -*- haskell -*- -}++-- #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++    , 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           Foreign+import           Foreign.C+import           OpenSSL.ASN1+import           OpenSSL.BIO+import           OpenSSL.EVP.Digest+import           OpenSSL.EVP.PKey+import           OpenSSL.EVP.Verify+import           OpenSSL.Utils+import           OpenSSL.Stack+import           OpenSSL.X509.Name++-- |@'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 Int++foreign import ccall unsafe "X509_cmp"+        _cmp :: Ptr X509_ -> Ptr X509_ -> IO Int++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 Int++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 Int++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 Int++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 Int++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 Int++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 Int++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 Int++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 Int++foreign import ccall unsafe "X509_verify"+        _verify :: Ptr X509_ -> Ptr EVP_PKEY -> IO Int++-- |@'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 x509Ptr = newForeignPtr _free x509Ptr >>= return . X509+++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) = unsafeForeignPtrToPtr x509+++touchX509 :: X509 -> IO ()+touchX509 (X509 x509) = touchForeignPtr x509++-- |@'compareX509' cert1 cert2@ compares two certificates.+compareX509 :: X509 -> X509 -> IO Ordering+compareX509 cert1 cert2+    = withX509Ptr cert1 $ \ cert1Ptr ->+      withX509Ptr cert2 $ \ cert2Ptr ->+      _cmp cert1Ptr cert2Ptr >>= return . interpret+    where+      interpret :: Int -> Ordering+      interpret n+          | n > 0     = GT+          | n < 0     = LT+          | otherwise = EQ++-- |@'signX509'@ signs a certificate with an issuer private key.+signX509 :: X509         -- ^ The certificate to be signed.+         -> PKey         -- ^ 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 pkey mDigest+    = withX509Ptr x509 $ \ x509Ptr ->+      withPKeyPtr pkey $ \ pkeyPtr ->+      do digest <- case mDigest of+                     Just md -> return md+                     Nothing -> pkeyDefaultMD pkey+         withMDPtr digest $ \ digestPtr ->+             _sign x509Ptr pkeyPtr digestPtr+                  >>= failIf (== 0)+         return ()++-- |@'verifyX509'@ verifies a signature of certificate with an issuer+-- public key.+verifyX509 :: X509 -- ^ The certificate to be verified.+           -> PKey -- ^ The public key to verify with.+           -> IO VerifyStatus+verifyX509 x509 pkey+    = withX509Ptr x509 $ \ x509Ptr ->+      withPKeyPtr pkey $ \ pkeyPtr ->+      _verify x509Ptr pkeyPtr+           >>= interpret+    where+      interpret :: Int -> 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 PKey+getPublicKey x509+    = withX509Ptr x509 $ \ x509Ptr ->+      _get_pubkey x509Ptr+           >>= failIfNull+           >>= wrapPKeyPtr++-- |@'setPublicKey' cert pubkey@ updates the public key of the subject+-- of certificate.+setPublicKey :: X509 -> PKey -> IO ()+setPublicKey x509 pkey+    = withX509Ptr x509 $ \ x509Ptr ->+      withPKeyPtr pkey $ \ 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/Name.hsc view
@@ -0,0 +1,86 @@+{- -*- haskell -*- -}++-- #hide++#include "HsOpenSSL.h"++module OpenSSL.X509.Name+    ( X509_NAME++    , allocaX509Name+    , withX509Name+    , peekX509Name+    )+    where++import           Control.Exception+import           Foreign+import           Foreign.C+import           OpenSSL.ASN1+import           OpenSSL.Utils+++data X509_NAME+data X509_NAME_ENTRY++foreign import ccall unsafe "X509_NAME_new"+        _new :: IO (Ptr X509_NAME)++foreign import ccall unsafe "X509_NAME_free"+        _free :: Ptr X509_NAME -> IO ()++foreign import ccall unsafe "X509_NAME_add_entry_by_txt"+        _add_entry_by_txt :: Ptr X509_NAME -> CString -> Int -> Ptr CChar -> Int -> Int -> Int -> IO Int++foreign import ccall unsafe "X509_NAME_entry_count"+        _entry_count :: Ptr X509_NAME -> IO Int++foreign import ccall unsafe "X509_NAME_get_entry"+        _get_entry :: Ptr X509_NAME -> Int -> IO (Ptr X509_NAME_ENTRY)++foreign import ccall unsafe "X509_NAME_ENTRY_get_object"+        _ENTRY_get_object :: Ptr X509_NAME_ENTRY -> IO (Ptr ASN1_OBJECT)++foreign import ccall unsafe "X509_NAME_ENTRY_get_data"+        _ENTRY_get_data :: Ptr X509_NAME_ENTRY -> IO (Ptr ASN1_STRING)+++allocaX509Name :: (Ptr X509_NAME -> IO a) -> IO a+allocaX509Name m+    = bracket _new _free m+++withX509Name :: [(String, String)] -> (Ptr X509_NAME -> IO a) -> IO a+withX509Name name m+    = allocaX509Name $ \ namePtr ->+      do mapM_ (addEntry namePtr) name+         m namePtr+    where+      addEntry :: Ptr X509_NAME -> (String, String) -> IO ()+      addEntry namePtr (key, val)+          = withCString    key $ \ keyPtr ->+            withCStringLen val $ \ (valPtr, valLen) ->+            _add_entry_by_txt namePtr keyPtr (#const MBSTRING_UTF8) valPtr valLen (-1) 0+                 >>= failIf (/= 1)+                 >>  return ()+++peekX509Name :: Ptr X509_NAME -> Bool -> IO [(String, String)]+peekX509Name namePtr wantLongName+    = do count <- _entry_count namePtr >>= failIf (< 0)+         mapM peekEntry $ take count [0..]+    where+      peekEntry :: Int -> IO (String, String)+      peekEntry n+          = do ent <- _get_entry namePtr n  >>= failIfNull+               obj <- _ENTRY_get_object ent >>= failIfNull+               dat <- _ENTRY_get_data   ent >>= failIfNull++               nid <- obj2nid obj+               key <- if wantLongName then+                          nid2ln nid+                      else+                          nid2sn nid+               val <- peekASN1String dat++               return (key, val)
+ OpenSSL/X509/Request.hsc view
@@ -0,0 +1,249 @@+{- -*- haskell -*- -}++-- #prune++-- |An interface to PKCS#10 certificate request.++module OpenSSL.X509.Request+    ( -- * Type+      X509Req+    , X509_REQ -- private++      -- * Functions to manipulate request+    , newX509Req+    , wrapX509Req -- private+    , withX509ReqPtr -- private++    , signX509Req+    , verifyX509Req++    , printX509Req++    , makeX509FromReq++      -- * Accessors+    , getVersion+    , setVersion++    , getSubjectName+    , setSubjectName++    , getPublicKey+    , setPublicKey+    )+    where++import           Control.Monad+import           Foreign+import           Foreign.C+import           OpenSSL.BIO+import           OpenSSL.EVP.Digest+import           OpenSSL.EVP.PKey+import           OpenSSL.EVP.Verify+import           OpenSSL.Utils+import           OpenSSL.X509 (X509)+import qualified OpenSSL.X509 as Cert+import           OpenSSL.X509.Name++-- |@'X509Req'@ is an opaque object that represents PKCS#10+-- certificate request.+newtype X509Req  = X509Req (ForeignPtr X509_REQ)+data    X509_REQ+++foreign import ccall unsafe "X509_REQ_new"+        _new :: IO (Ptr X509_REQ)++foreign import ccall unsafe "&X509_REQ_free"+        _free :: FunPtr (Ptr X509_REQ -> IO ())++foreign import ccall unsafe "X509_REQ_sign"+        _sign :: Ptr X509_REQ -> Ptr EVP_PKEY -> Ptr EVP_MD -> IO Int++foreign import ccall unsafe "X509_REQ_verify"+        _verify :: Ptr X509_REQ -> Ptr EVP_PKEY -> IO Int++foreign import ccall unsafe "X509_REQ_print"+        _print :: Ptr BIO_ -> Ptr X509_REQ -> IO Int++foreign import ccall unsafe "HsOpenSSL_X509_REQ_get_version"+        _get_version :: Ptr X509_REQ -> IO CLong++foreign import ccall unsafe "X509_REQ_set_version"+        _set_version :: Ptr X509_REQ -> CLong -> IO Int++foreign import ccall unsafe "HsOpenSSL_X509_REQ_get_subject_name"+        _get_subject_name :: Ptr X509_REQ -> IO (Ptr X509_NAME)++foreign import ccall unsafe "X509_REQ_set_subject_name"+        _set_subject_name :: Ptr X509_REQ -> Ptr X509_NAME -> IO Int++foreign import ccall unsafe "X509_REQ_get_pubkey"+        _get_pubkey :: Ptr X509_REQ -> IO (Ptr EVP_PKEY)++foreign import ccall unsafe "X509_REQ_set_pubkey"+        _set_pubkey :: Ptr X509_REQ -> Ptr EVP_PKEY -> IO Int++-- |@'newX509Req'@ creates an empty certificate request. You must set+-- the following properties to and sign it (see 'signX509Req') to+-- actually use the certificate request.+--+--  [/Version/] See 'setVersion'.+--+--  [/Subject Name/] See 'setSubjectName'.+--+--  [/Public Key/] See 'setPublicKey'.+--+newX509Req :: IO X509Req+newX509Req = _new >>= wrapX509Req+++wrapX509Req :: Ptr X509_REQ -> IO X509Req+wrapX509Req reqPtr = newForeignPtr _free reqPtr >>= return . X509Req+++withX509ReqPtr :: X509Req -> (Ptr X509_REQ -> IO a) -> IO a+withX509ReqPtr (X509Req req) = withForeignPtr req++-- |@'signX509Req'@ signs a certificate request with a subject private+-- key.+signX509Req :: X509Req      -- ^ The request to be signed.+            -> PKey         -- ^ 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 ()+signX509Req req pkey mDigest+    = withX509ReqPtr req  $ \ reqPtr  ->+      withPKeyPtr    pkey $ \ pkeyPtr ->+      do digest <- case mDigest of+                     Just md -> return md+                     Nothing -> pkeyDefaultMD pkey+         withMDPtr digest $ \ digestPtr ->+             _sign reqPtr pkeyPtr digestPtr+                  >>= failIf (== 0)+         return ()++-- |@'verifyX509Req'@ verifies a signature of certificate request with+-- a subject public key.+verifyX509Req :: X509Req -- ^ The request to be verified.+              -> PKey    -- ^ The public key to verify with.+              -> IO VerifyStatus+verifyX509Req req pkey+    = withX509ReqPtr req  $ \ reqPtr  ->+      withPKeyPtr    pkey $ \ pkeyPtr ->+      _verify reqPtr pkeyPtr+           >>= interpret+    where+      interpret :: Int -> IO VerifyStatus+      interpret 1 = return VerifySuccess+      interpret 0 = return VerifyFailure+      interpret _ = raiseOpenSSLError++-- |@'printX509Req' req@ translates a certificate request into+-- human-readable format.+printX509Req :: X509Req -> IO String+printX509Req req+    = do mem <- newMem+         withBioPtr mem $ \ memPtr ->+             withX509ReqPtr req $ \ reqPtr ->+                 _print memPtr reqPtr+                      >>= failIf (/= 1)+         bioRead mem++-- |@'getVersion' req@ returns the version number of certificate+-- request.+getVersion :: X509Req -> IO Int+getVersion req+    = withX509ReqPtr req $ \ reqPtr ->+      liftM fromIntegral $ _get_version reqPtr++-- |@'setVersion' req ver@ updates the version number of certificate+-- request.+setVersion :: X509Req -> Int -> IO ()+setVersion req ver+    = withX509ReqPtr req $ \ reqPtr ->+      _set_version reqPtr (fromIntegral ver)+           >>= failIf (/= 1)+           >>  return ()++-- |@'getSubjectName' req wantLongName@ returns the subject name of+-- certificate request. See 'OpenSSL.X509.getSubjectName' of+-- "OpenSSL.X509".+getSubjectName :: X509Req -> Bool -> IO [(String, String)]+getSubjectName req wantLongName+    = withX509ReqPtr req $ \ reqPtr ->+      do namePtr <- _get_subject_name reqPtr+         peekX509Name namePtr wantLongName++-- |@'setSubjectName' req name@ updates the subject name of+-- certificate request. See 'OpenSSL.X509.setSubjectName' of+-- "OpenSSL.X509".+setSubjectName :: X509Req -> [(String, String)] -> IO ()+setSubjectName req subject+    = withX509ReqPtr req $ \ reqPtr ->+      withX509Name subject $ \ namePtr ->+      _set_subject_name reqPtr namePtr+           >>= failIf (/= 1)+           >>  return ()++-- |@'getPublicKey' req@ returns the public key of the subject of+-- certificate request.+getPublicKey :: X509Req -> IO PKey+getPublicKey req+    = withX509ReqPtr req $ \ reqPtr ->+      _get_pubkey reqPtr+           >>= failIfNull+           >>= wrapPKeyPtr++-- |@'setPublicKey' req@ updates the public key of the subject of+-- certificate request.+setPublicKey :: X509Req -> PKey -> IO ()+setPublicKey req pkey+    = withX509ReqPtr req  $ \ reqPtr  ->+      withPKeyPtr    pkey $ \ pkeyPtr ->+      _set_pubkey reqPtr pkeyPtr+           >>= failIf (/= 1)+           >>  return ()+++-- |@'makeX509FromReq' req cert@ creates an empty X.509 certificate+-- and copies as much data from the request as possible. The resulting+-- certificate doesn't have the following data and it isn't signed so+-- you must fill them and sign it yourself.+--+--   * Serial number+--+--   * Validity (Not Before and Not After)+--+-- Example:+--+-- > import Data.Time.Clock+-- >+-- > genCert :: X509 -> EvpPKey -> Integer -> Int -> X509Req -> IO X509+-- > genCert caCert caKey serial days req+-- >     = do cert <- makeX509FromReq req caCert+-- >          now  <- getCurrentTime+-- >          setSerialNumber cert serial+-- >          setNotBefore cert $ addUTCTime (-1) now+-- >          setNotAfter  cert $ addUTCTime (days * 24 * 60 * 60) now+-- >          signX509 cert caKey Nothing+-- >          return cert+--+makeX509FromReq :: X509Req+                -> X509+                -> IO X509+makeX509FromReq req caCert+    = do reqPubKey <- getPublicKey req+         verified  <- verifyX509Req req reqPubKey++         when (verified == VerifyFailure)+                  $ fail "makeX509FromReq: the request isn't properly signed by its own key."++         cert <- Cert.newX509+         Cert.setVersion cert 2 -- Version 2 means X509 v3. It's confusing.+         Cert.setIssuerName  cert =<< Cert.getSubjectName caCert False+         Cert.setSubjectName cert =<< getSubjectName req False+         Cert.setPublicKey   cert =<< getPublicKey req++         return cert
+ OpenSSL/X509/Revocation.hsc view
@@ -0,0 +1,324 @@+{- -*- haskell -*- -}++-- #prune++-- |An interface to Certificate Revocation List.++#include "HsOpenSSL.h"++module OpenSSL.X509.Revocation+    ( -- * Types+      CRL+    , X509_CRL -- privae+    , RevokedCertificate(..)++      -- * Functions to manipulate revocation list+    , newCRL+    , wrapCRL -- private+    , withCRLPtr -- private++    , signCRL+    , verifyCRL++    , printCRL++    , sortCRL++      -- * Accessors+    , getVersion+    , setVersion++    , getLastUpdate+    , setLastUpdate++    , getNextUpdate+    , setNextUpdate++    , getIssuerName+    , setIssuerName++    , getRevokedList+    , addRevoked+    )+    where++import           Control.Monad+import           Data.Time.Clock+import           Data.Typeable+import           Foreign+import           Foreign.C+import           OpenSSL.ASN1+import           OpenSSL.BIO+import           OpenSSL.EVP.Digest+import           OpenSSL.EVP.PKey+import           OpenSSL.EVP.Verify+import           OpenSSL.Stack+import           OpenSSL.Utils+import           OpenSSL.X509.Name++-- |@'CRL'@ is an opaque object that represents Certificate Revocation+-- List.+newtype CRL          = CRL (ForeignPtr X509_CRL)+data    X509_CRL+data    X509_REVOKED++-- |@'RevokedCertificate'@ represents a revoked certificate in a+-- list. Each certificates are supposed to be distinguishable by+-- issuer name and serial number, so it is sufficient to have only+-- serial number on each entries.+data RevokedCertificate+    = RevokedCertificate {+        revSerialNumber   :: Integer+      , revRevocationDate :: UTCTime+      }+    deriving (Show, Eq, Typeable)+++foreign import ccall unsafe "X509_CRL_new"+        _new :: IO (Ptr X509_CRL)++foreign import ccall unsafe "&X509_CRL_free"+        _free :: FunPtr (Ptr X509_CRL -> IO ())++foreign import ccall unsafe "X509_CRL_sign"+        _sign :: Ptr X509_CRL -> Ptr EVP_PKEY -> Ptr EVP_MD -> IO Int++foreign import ccall unsafe "X509_CRL_verify"+        _verify :: Ptr X509_CRL -> Ptr EVP_PKEY -> IO Int++foreign import ccall unsafe "X509_CRL_print"+        _print :: Ptr BIO_ -> Ptr X509_CRL -> IO Int++foreign import ccall unsafe "HsOpenSSL_X509_CRL_get_version"+        _get_version :: Ptr X509_CRL -> IO CLong++foreign import ccall unsafe "X509_CRL_set_version"+        _set_version :: Ptr X509_CRL -> CLong -> IO Int++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 Int++foreign import ccall unsafe "HsOpenSSL_X509_CRL_get_nextUpdate"+        _get_nextUpdate :: Ptr X509_CRL -> IO (Ptr ASN1_TIME)++foreign import ccall unsafe "X509_CRL_set_nextUpdate"+        _set_nextUpdate :: Ptr X509_CRL -> Ptr ASN1_TIME -> IO Int++foreign import ccall unsafe "HsOpenSSL_X509_CRL_get_issuer"+        _get_issuer_name :: Ptr X509_CRL -> IO (Ptr X509_NAME)++foreign import ccall unsafe "X509_CRL_set_issuer_name"+        _set_issuer_name :: Ptr X509_CRL -> Ptr X509_NAME -> IO Int++foreign import ccall unsafe "HsOpenSSL_X509_CRL_get_REVOKED"+        _get_REVOKED :: Ptr X509_CRL -> IO (Ptr STACK)++foreign import ccall unsafe "X509_CRL_add0_revoked"+        _add0_revoked :: Ptr X509_CRL -> Ptr X509_REVOKED -> IO Int++foreign import ccall unsafe "X509_CRL_sort"+        _sort :: Ptr X509_CRL -> IO Int++++foreign import ccall unsafe "X509_REVOKED_new"+        _new_revoked :: IO (Ptr X509_REVOKED)++foreign import ccall unsafe "X509_REVOKED_free"+        freeRevoked :: Ptr X509_REVOKED -> IO ()++foreign import ccall unsafe "X509_REVOKED_set_serialNumber"+        _set_serialNumber :: Ptr X509_REVOKED -> Ptr ASN1_INTEGER -> IO Int++foreign import ccall unsafe "X509_REVOKED_set_revocationDate"+        _set_revocationDate :: Ptr X509_REVOKED -> Ptr ASN1_TIME -> IO Int++-- |@'newCRL'@ creates an empty revocation list. You must set the+-- following properties to and sign it (see 'signCRL') to actually use+-- the revocation list. If you have any certificates to be listed, you+-- must of course add them (see 'addRevoked') before signing the list.+--+--   [/Version/] See 'setVersion'.+--+--   [/Last Update/] See 'setLastUpdate'.+--+--   [/Next Update/] See 'setNextUpdate'.+--+--   [/Issuer Name/] See 'setIssuerName'.+--+newCRL :: IO CRL+newCRL = _new >>= wrapCRL+++wrapCRL :: Ptr X509_CRL -> IO CRL+wrapCRL crlPtr = newForeignPtr _free crlPtr >>= return . CRL+++withCRLPtr :: CRL -> (Ptr X509_CRL -> IO a) -> IO a+withCRLPtr (CRL crl) = withForeignPtr crl++-- |@'signCRL'@ signs a revocation list with an issuer private key.+signCRL :: CRL          -- ^ The revocation list to be signed.+        -> PKey         -- ^ 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 ()+signCRL crl pkey mDigest+    = withCRLPtr crl   $ \ crlPtr  ->+      withPKeyPtr pkey $ \ pkeyPtr ->+      do digest <- case mDigest of+                     Just md -> return md+                     Nothing -> pkeyDefaultMD pkey+         withMDPtr digest $ \ digestPtr ->+             _sign crlPtr pkeyPtr digestPtr+                  >>= failIf (== 0)+         return ()++-- |@'verifyCRL'@ verifies a signature of revocation list with an+-- issuer public key.+verifyCRL :: CRL -> PKey -> IO VerifyStatus+verifyCRL crl pkey+    = withCRLPtr crl   $ \ crlPtr ->+      withPKeyPtr pkey $ \ pkeyPtr ->+      _verify crlPtr pkeyPtr+           >>= interpret+    where+      interpret :: Int -> IO VerifyStatus+      interpret 1 = return VerifySuccess+      interpret 0 = return VerifyFailure+      interpret _ = raiseOpenSSLError++-- |@'printCRL'@ translates a revocation list into human-readable+-- format.+printCRL :: CRL -> IO String+printCRL crl+    = do mem <- newMem+         withBioPtr mem $ \ memPtr ->+             withCRLPtr crl $ \ crlPtr ->+                 _print memPtr crlPtr+                      >>= failIf (/= 1)+         bioRead mem++-- |@'getVersion' crl@ returns the version number of revocation list.+getVersion :: CRL -> IO Int+getVersion crl+    = withCRLPtr crl $ \ crlPtr ->+      liftM fromIntegral $ _get_version crlPtr++-- |@'setVersion' crl ver@ updates the version number of revocation+-- list.+setVersion :: CRL -> Int -> IO ()+setVersion crl ver+    = withCRLPtr crl $ \ crlPtr ->+      _set_version crlPtr (fromIntegral ver)+           >>= failIf (/= 1)+           >>  return ()++-- |@'getLastUpdate' crl@ returns the time when the revocation list+-- has last been updated.+getLastUpdate :: CRL -> IO UTCTime+getLastUpdate crl+    = withCRLPtr crl $ \ crlPtr ->+      _get_lastUpdate crlPtr+           >>= peekASN1Time++-- |@'setLastUpdate' crl utc@ updates the time when the revocation+-- list has last been updated.+setLastUpdate :: CRL -> UTCTime -> IO ()+setLastUpdate crl utc+    = withCRLPtr crl $ \ crlPtr ->+      withASN1Time utc $ \ time ->+      _set_lastUpdate crlPtr time+           >>= failIf (/= 1)+           >>  return ()++-- |@'getNextUpdate' crl@ returns the time when the revocation list+-- will next be updated.+getNextUpdate :: CRL -> IO UTCTime+getNextUpdate crl+    = withCRLPtr crl $ \ crlPtr ->+      _get_nextUpdate crlPtr+           >>= peekASN1Time++-- |@'setNextUpdate' crl utc@ updates the time when the revocation+-- list will next be updated.+setNextUpdate :: CRL -> UTCTime -> IO ()+setNextUpdate crl utc+    = withCRLPtr crl $ \ crlPtr ->+      withASN1Time utc $ \ time ->+      _set_nextUpdate crlPtr time+           >>= failIf (/= 1)+           >>  return ()++-- |@'getIssuerName' crl wantLongName@ returns the issuer name of+-- revocation list. See 'OpenSSL.X509.getIssuerName' of+-- "OpenSSL.X509".+getIssuerName :: CRL -> Bool -> IO [(String, String)]+getIssuerName crl wantLongName+    = withCRLPtr crl $ \ crlPtr ->+      do namePtr <- _get_issuer_name crlPtr+         peekX509Name namePtr wantLongName++-- |@'setIssuerName' crl name@ updates the issuer name of revocation+-- list. See 'OpenSSL.X509.setIssuerName' of "OpenSSL.X509".+setIssuerName :: CRL -> [(String, String)] -> IO ()+setIssuerName crl issuer+    = withCRLPtr crl  $ \ crlPtr  ->+      withX509Name issuer $ \ namePtr ->+      _set_issuer_name crlPtr namePtr+           >>= failIf (/= 1)+           >>  return ()++-- |@'getRevokedList' crl@ returns the list of revoked certificates.+getRevokedList :: CRL -> IO [RevokedCertificate]+getRevokedList crl+    = withCRLPtr crl $ \ crlPtr ->+      do stRevoked <- _get_REVOKED crlPtr+         mapStack peekRevoked stRevoked+    where+      peekRevoked :: Ptr X509_REVOKED -> IO RevokedCertificate+      peekRevoked rev+          = do serial <- peekASN1Integer =<< (#peek X509_REVOKED, serialNumber  ) rev+               date   <- peekASN1Time    =<< (#peek X509_REVOKED, revocationDate) rev+               return RevokedCertificate {+                            revSerialNumber   = serial+                          , revRevocationDate = date+                          }++newRevoked :: RevokedCertificate -> IO (Ptr X509_REVOKED)+newRevoked revoked+    = do revPtr  <- _new_revoked++         seriRet <- withASN1Integer (revSerialNumber revoked) $ \ serialPtr ->+                    _set_serialNumber revPtr serialPtr++         dateRet <- withASN1Time (revRevocationDate revoked) $ \ datePtr ->+                    _set_revocationDate revPtr datePtr++         if seriRet /= 1 || dateRet /= 1 then+             freeRevoked revPtr >> raiseOpenSSLError+           else+             return revPtr++-- |@'addRevoked' crl revoked@ add the certificate to the revocation+-- list.+addRevoked :: CRL -> RevokedCertificate -> IO ()+addRevoked crl revoked+    = withCRLPtr crl $ \ crlPtr ->+      do revPtr <- newRevoked revoked+         ret    <- _add0_revoked crlPtr revPtr+         case ret of+           1 -> return ()+           _ -> freeRevoked revPtr >> raiseOpenSSLError++-- |@'sortCRL' crl@ sorts the certificates in the revocation list.+sortCRL :: CRL -> IO ()+sortCRL crl+    = withCRLPtr crl $ \ crlPtr ->+      _sort crlPtr+           >>= failIf (/= 1)+           >>  return ()
+ OpenSSL/X509/Store.hsc view
@@ -0,0 +1,71 @@+{- -*- haskell -*- -}++-- #prune++-- |An interface to X.509 certificate store.++module OpenSSL.X509.Store+    ( X509Store+    , X509_STORE -- private++    , newX509Store+    , withX509StorePtr -- private++    , addCertToStore+    , addCRLToStore+    )+    where++import           Foreign+import           OpenSSL.X509+import           OpenSSL.X509.Revocation+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 :: FunPtr (Ptr X509_STORE -> IO ())++foreign import ccall unsafe "X509_STORE_add_cert"+        _add_cert :: Ptr X509_STORE -> Ptr X509_ -> IO Int++foreign import ccall unsafe "X509_STORE_add_crl"+        _add_crl :: Ptr X509_STORE -> Ptr X509_CRL -> IO Int++-- |@'newX509Store'@ creates an empty X.509 certificate store.+newX509Store :: IO X509Store+newX509Store = _new+               >>= failIfNull+               >>= newForeignPtr _free+               >>= return . X509Store+++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 ()
+ Setup.hs view
@@ -0,0 +1,4 @@+#!/usr/bin/env runghc++import Distribution.Simple+main = defaultMainWithHooks defaultUserHooks
+ cbits/HsOpenSSL.c view
@@ -0,0 +1,183 @@+#include <pthread.h>+#include "HsOpenSSL.h"++/* OpenSSL ********************************************************************/+void HsOpenSSL_OpenSSL_add_all_algorithms() {+    OpenSSL_add_all_algorithms();+}++void HsOpenSSL_OPENSSL_free(void* ptr) {+    OPENSSL_free(ptr);+}++/* BIO ************************************************************************/+void HsOpenSSL_BIO_set_flags(BIO* bio, int flags) {+    BIO_set_flags(bio, flags);+}++int HsOpenSSL_BIO_flush(BIO* bio) {+    return BIO_flush(bio);+}++int HsOpenSSL_BIO_reset(BIO* bio) {+    return BIO_reset(bio);+}++int HsOpenSSL_BIO_eof(BIO* bio) {+    return BIO_eof(bio);+}++int HsOpenSSL_BIO_set_md(BIO* bio, EVP_MD* md) {+    return BIO_set_md(bio, md);+}++int HsOpenSSL_BIO_set_buffer_size(BIO* bio, int bufSize) {+    return BIO_set_buffer_size(bio, bufSize);+}++int HsOpenSSL_BIO_should_retry(BIO* bio) {+    return BIO_should_retry(bio);+}++int HsOpenSSL_BIO_FLAGS_BASE64_NO_NL() {+    return BIO_FLAGS_BASE64_NO_NL;+}++/* EVP ************************************************************************/+int HsOpenSSL_EVP_MD_size(EVP_MD* md) {+    return EVP_MD_size(md);+}++int HsOpenSSL_EVP_CIPHER_CTX_block_size(EVP_CIPHER_CTX* ctx) {+    return EVP_CIPHER_CTX_block_size(ctx);+}++int HsOpenSSL_EVP_CIPHER_iv_length(EVP_CIPHER* cipher) {+    return EVP_CIPHER_iv_length(cipher);+}++/* X509 ***********************************************************************/+long HsOpenSSL_X509_get_version(X509* x509) {+    return X509_get_version(x509);+}++ASN1_TIME* HsOpenSSL_X509_get_notBefore(X509* x509) {+    return X509_get_notBefore(x509);+}++ASN1_TIME* HsOpenSSL_X509_get_notAfter(X509* x509) {+    return X509_get_notAfter(x509);+}++long HsOpenSSL_X509_REQ_get_version(X509_REQ* req) {+    return X509_REQ_get_version(req);+}++X509_NAME* HsOpenSSL_X509_REQ_get_subject_name(X509_REQ* req) {+    return X509_REQ_get_subject_name(req);+}++long HsOpenSSL_X509_CRL_get_version(X509_CRL* crl) {+    return X509_CRL_get_version(crl);+}++ASN1_TIME* HsOpenSSL_X509_CRL_get_lastUpdate(X509_CRL* crl) {+    return X509_CRL_get_lastUpdate(crl);+}++ASN1_TIME* HsOpenSSL_X509_CRL_get_nextUpdate(X509_CRL* crl) {+    return X509_CRL_get_nextUpdate(crl);+}++X509_NAME* HsOpenSSL_X509_CRL_get_issuer(X509_CRL* crl) {+    return X509_CRL_get_issuer(crl);+}++STACK_OF(X509_REVOKED)* HsOpenSSL_X509_CRL_get_REVOKED(X509_CRL* crl) {+    return X509_CRL_get_REVOKED(crl);+}+++/* PKCS#7 *********************************************************************/+long HsOpenSSL_PKCS7_is_detached(PKCS7* pkcs7) {+    return PKCS7_is_detached(pkcs7);+}+++/* ASN1 ***********************************************************************/+ASN1_INTEGER* HsOpenSSL_M_ASN1_INTEGER_new() {+    return M_ASN1_INTEGER_new();+}++void HsOpenSSL_M_ASN1_INTEGER_free(ASN1_INTEGER* intPtr) {+    M_ASN1_INTEGER_free(intPtr);+}++ASN1_INTEGER* HsOpenSSL_M_ASN1_TIME_new() {+    return M_ASN1_TIME_new();+}++void HsOpenSSL_M_ASN1_TIME_free(ASN1_TIME* timePtr) {+    M_ASN1_TIME_free(timePtr);+}++/* Threads ********************************************************************/+static pthread_mutex_t* mutex_at;++struct CRYPTO_dynlock_value {+    pthread_mutex_t mutex;+};++static void HsOpenSSL_lockingCallback(int mode, int n, const char* file, int line) {+    if (mode & CRYPTO_LOCK) {+        pthread_mutex_lock(&mutex_at[n]);+    }+    else {+        pthread_mutex_unlock(&mutex_at[n]);+    }+}++static unsigned long HsOpenSSL_idCallback() {+    return (unsigned long)pthread_self();+}++static struct CRYPTO_dynlock_value* HsOpenSSL_dynlockCreateCallback(const char* file, int line) {+    struct CRYPTO_dynlock_value* val;++    val = OPENSSL_malloc(sizeof(struct CRYPTO_dynlock_value));+    pthread_mutex_init(&val->mutex, NULL);++    return val;+}++static void HsOpenSSL_dynlockLockCallback(int mode, struct CRYPTO_dynlock_value* val, const char* file, int line) {+    if (mode & CRYPTO_LOCK) {+        pthread_mutex_lock(&val->mutex);+    }+    else {+        pthread_mutex_unlock(&val->mutex);+    }+}++static void HsOpenSSL_dynlockDestroyCallback(struct CRYPTO_dynlock_value* val, const char* file, int line) {+    pthread_mutex_destroy(&val->mutex);+    OPENSSL_free(val);+}++void HsOpenSSL_setupMutex() {+    int i;+    +    mutex_at = OPENSSL_malloc(CRYPTO_num_locks() * sizeof(pthread_mutex_t));++    for (i = 0; i < CRYPTO_num_locks(); i++) {+        pthread_mutex_init(&mutex_at[i], NULL);+    }++    CRYPTO_set_locking_callback(HsOpenSSL_lockingCallback);+    CRYPTO_set_id_callback(HsOpenSSL_idCallback);+    +    CRYPTO_set_dynlock_create_callback(HsOpenSSL_dynlockCreateCallback);+    CRYPTO_set_dynlock_lock_callback(HsOpenSSL_dynlockLockCallback);+    CRYPTO_set_dynlock_destroy_callback(HsOpenSSL_dynlockDestroyCallback);+}+
+ cbits/HsOpenSSL.h view
@@ -0,0 +1,63 @@+#ifndef HSOPENSSL_H_INCLUDED+#define HSOPENSSL_H_INCLUDED+#include <openssl/asn1.h>+#include <openssl/bio.h>+#include <openssl/bn.h>+#include <openssl/err.h>+#include <openssl/evp.h>+#include <openssl/objects.h>+#include <openssl/opensslconf.h>+#include <openssl/pem.h>+#include <openssl/pkcs7.h>+#include <openssl/ssl.h>+#include <openssl/stack.h>+#include <openssl/x509.h>+#include <openssl/x509_vfy.h>+#include <openssl/x509v3.h>++/* OpenSSL ********************************************************************/+void HsOpenSSL_OpenSSL_add_all_algorithms();+void HsOpenSSL_OPENSSL_free(void* ptr);++/* BIO ************************************************************************/+void HsOpenSSL_BIO_set_flags(BIO* bio, int flags);+int HsOpenSSL_BIO_flush(BIO* bio);+int HsOpenSSL_BIO_reset(BIO* bio);+int HsOpenSSL_BIO_eof(BIO* bio);+int HsOpenSSL_BIO_set_md(BIO* bio, EVP_MD* md);+int HsOpenSSL_BIO_set_buffer_size(BIO* bio, int bufSize);+int HsOpenSSL_BIO_should_retry(BIO* bio);+int HsOpenSSL_BIO_FLAGS_BASE64_NO_NL();++/* EVP ************************************************************************/+int HsOpenSSL_EVP_MD_size(EVP_MD* md);+int HsOpenSSL_EVP_CIPHER_CTX_block_size(EVP_CIPHER_CTX* ctx);+int HsOpenSSL_EVP_CIPHER_iv_length(EVP_CIPHER* cipher);++/* X509 ***********************************************************************/+long HsOpenSSL_X509_get_version(X509* x509);+ASN1_TIME* HsOpenSSL_X509_get_notBefore(X509* x509);+ASN1_TIME* HsOpenSSL_X509_get_notAfter(X509* x509);++long HsOpenSSL_X509_REQ_get_version(X509_REQ* req);+X509_NAME* HsOpenSSL_X509_REQ_get_subject_name(X509_REQ* req);++long HsOpenSSL_X509_CRL_get_version(X509_CRL* crl);+ASN1_TIME* HsOpenSSL_X509_CRL_get_lastUpdate(X509_CRL* crl);+ASN1_TIME* HsOpenSSL_X509_CRL_get_nextUpdate(X509_CRL* crl);+X509_NAME* HsOpenSSL_X509_CRL_get_issuer(X509_CRL* crl);+STACK_OF(X509_REVOKED)* HsOpenSSL_X509_CRL_get_REVOKED(X509_CRL* crl);++/* PKCS#7 *********************************************************************/+long HsOpenSSL_PKCS7_is_detached(PKCS7* pkcs7);++/* ASN1 ***********************************************************************/+ASN1_INTEGER* HsOpenSSL_M_ASN1_INTEGER_new();+void HsOpenSSL_M_ASN1_INTEGER_free(ASN1_INTEGER* intPtr);+ASN1_INTEGER* HsOpenSSL_M_ASN1_TIME_new();+void HsOpenSSL_M_ASN1_TIME_free(ASN1_TIME* timePtr);++/* Threads ********************************************************************/+void HsOpenSSL_setupMutex();++#endif
+ configure view
@@ -0,0 +1,2794 @@+#! /bin/sh+# Guess values for system-dependent variables and create Makefiles.+# Generated by GNU Autoconf 2.60.+#+# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,+# 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.+# This configure script is free software; the Free Software Foundation+# gives unlimited permission to copy, distribute and modify it.+## --------------------- ##+## M4sh Initialization.  ##+## --------------------- ##++# Be Bourne compatible+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then+  emulate sh+  NULLCMD=:+  # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which+  # is contrary to our usage.  Disable this feature.+  alias -g '${1+"$@"}'='"$@"'+  setopt NO_GLOB_SUBST+else+  case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac+fi+BIN_SH=xpg4; export BIN_SH # for Tru64+DUALCASE=1; export DUALCASE # for MKS sh+++# PATH needs CR+# Avoid depending upon Character Ranges.+as_cr_letters='abcdefghijklmnopqrstuvwxyz'+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'+as_cr_Letters=$as_cr_letters$as_cr_LETTERS+as_cr_digits='0123456789'+as_cr_alnum=$as_cr_Letters$as_cr_digits++# The user is always right.+if test "${PATH_SEPARATOR+set}" != set; then+  echo "#! /bin/sh" >conf$$.sh+  echo  "exit 0"   >>conf$$.sh+  chmod +x conf$$.sh+  if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then+    PATH_SEPARATOR=';'+  else+    PATH_SEPARATOR=:+  fi+  rm -f conf$$.sh+fi++# Support unset when possible.+if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then+  as_unset=unset+else+  as_unset=false+fi+++# IFS+# We need space, tab and new line, in precisely that order.  Quoting is+# there to prevent editors from complaining about space-tab.+# (If _AS_PATH_WALK were called with IFS unset, it would disable word+# splitting by setting IFS to empty value.)+as_nl='+'+IFS=" ""	$as_nl"++# Find who we are.  Look in the path if we contain no directory separator.+case $0 in+  *[\\/]* ) as_myself=$0 ;;+  *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR+for as_dir in $PATH+do+  IFS=$as_save_IFS+  test -z "$as_dir" && as_dir=.+  test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break+done+IFS=$as_save_IFS++     ;;+esac+# We did not find ourselves, most probably we were run as `sh COMMAND'+# in which case we are not to be found in the path.+if test "x$as_myself" = x; then+  as_myself=$0+fi+if test ! -f "$as_myself"; then+  echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2+  { (exit 1); exit 1; }+fi++# Work around bugs in pre-3.0 UWIN ksh.+for as_var in ENV MAIL MAILPATH+do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var+done+PS1='$ '+PS2='> '+PS4='+ '++# NLS nuisances.+for as_var in \+  LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \+  LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \+  LC_TELEPHONE LC_TIME+do+  if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then+    eval $as_var=C; export $as_var+  else+    ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var+  fi+done++# Required to use basename.+if expr a : '\(a\)' >/dev/null 2>&1 &&+   test "X`expr 00001 : '.*\(...\)'`" = X001; then+  as_expr=expr+else+  as_expr=false+fi++if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then+  as_basename=basename+else+  as_basename=false+fi+++# Name of the executable.+as_me=`$as_basename -- "$0" ||+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \+	 X"$0" : 'X\(//\)$' \| \+	 X"$0" : 'X\(/\)' \| . 2>/dev/null ||+echo X/"$0" |+    sed '/^.*\/\([^/][^/]*\)\/*$/{+	    s//\1/+	    q+	  }+	  /^X\/\(\/\/\)$/{+	    s//\1/+	    q+	  }+	  /^X\/\(\/\).*/{+	    s//\1/+	    q+	  }+	  s/.*/./; q'`++# CDPATH.+$as_unset CDPATH+++if test "x$CONFIG_SHELL" = x; then+  if (eval ":") 2>/dev/null; then+  as_have_required=yes+else+  as_have_required=no+fi++  if test $as_have_required = yes && 	 (eval ":+(as_func_return () {+  (exit \$1)+}+as_func_success () {+  as_func_return 0+}+as_func_failure () {+  as_func_return 1+}+as_func_ret_success () {+  return 0+}+as_func_ret_failure () {+  return 1+}++exitcode=0+if as_func_success; then+  :+else+  exitcode=1+  echo as_func_success failed.+fi++if as_func_failure; then+  exitcode=1+  echo as_func_failure succeeded.+fi++if as_func_ret_success; then+  :+else+  exitcode=1+  echo as_func_ret_success failed.+fi++if as_func_ret_failure; then+  exitcode=1+  echo as_func_ret_failure succeeded.+fi++if ( set x; as_func_ret_success y && test x = \"\$1\" ); then+  :+else+  exitcode=1+  echo positional parameters were not saved.+fi++test \$exitcode = 0) || { (exit 1); exit 1; }++(+  as_lineno_1=\$LINENO+  as_lineno_2=\$LINENO+  test \"x\$as_lineno_1\" != \"x\$as_lineno_2\" &&+  test \"x\`expr \$as_lineno_1 + 1\`\" = \"x\$as_lineno_2\") || { (exit 1); exit 1; }+") 2> /dev/null; then+  :+else+  as_candidate_shells=+    as_save_IFS=$IFS; IFS=$PATH_SEPARATOR+for as_dir in /usr/bin/posix$PATH_SEPARATOR/bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH+do+  IFS=$as_save_IFS+  test -z "$as_dir" && as_dir=.+  case $as_dir in+	 /*)+	   for as_base in sh bash ksh sh5; do+	     as_candidate_shells="$as_candidate_shells $as_dir/$as_base"+	   done;;+       esac+done+IFS=$as_save_IFS+++      for as_shell in $as_candidate_shells $SHELL; do+	 # Try only shells that exist, to save several forks.+	 if { test -f "$as_shell" || test -f "$as_shell.exe"; } &&+		{ ("$as_shell") 2> /dev/null <<\_ASEOF+# Be Bourne compatible+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then+  emulate sh+  NULLCMD=:+  # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which+  # is contrary to our usage.  Disable this feature.+  alias -g '${1+"$@"}'='"$@"'+  setopt NO_GLOB_SUBST+else+  case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac+fi+BIN_SH=xpg4; export BIN_SH # for Tru64+DUALCASE=1; export DUALCASE # for MKS sh++:+_ASEOF+}; then+  CONFIG_SHELL=$as_shell+	       as_have_required=yes+	       if { "$as_shell" 2> /dev/null <<\_ASEOF+# Be Bourne compatible+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then+  emulate sh+  NULLCMD=:+  # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which+  # is contrary to our usage.  Disable this feature.+  alias -g '${1+"$@"}'='"$@"'+  setopt NO_GLOB_SUBST+else+  case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac+fi+BIN_SH=xpg4; export BIN_SH # for Tru64+DUALCASE=1; export DUALCASE # for MKS sh++:+(as_func_return () {+  (exit $1)+}+as_func_success () {+  as_func_return 0+}+as_func_failure () {+  as_func_return 1+}+as_func_ret_success () {+  return 0+}+as_func_ret_failure () {+  return 1+}++exitcode=0+if as_func_success; then+  :+else+  exitcode=1+  echo as_func_success failed.+fi++if as_func_failure; then+  exitcode=1+  echo as_func_failure succeeded.+fi++if as_func_ret_success; then+  :+else+  exitcode=1+  echo as_func_ret_success failed.+fi++if as_func_ret_failure; then+  exitcode=1+  echo as_func_ret_failure succeeded.+fi++if ( set x; as_func_ret_success y && test x = "$1" ); then+  :+else+  exitcode=1+  echo positional parameters were not saved.+fi++test $exitcode = 0) || { (exit 1); exit 1; }++(+  as_lineno_1=$LINENO+  as_lineno_2=$LINENO+  test "x$as_lineno_1" != "x$as_lineno_2" &&+  test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2") || { (exit 1); exit 1; }++_ASEOF+}; then+  break+fi++fi++      done++      if test "x$CONFIG_SHELL" != x; then+  for as_var in BASH_ENV ENV+        do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var+        done+        export CONFIG_SHELL+        exec "$CONFIG_SHELL" "$as_myself" ${1+"$@"}+fi+++    if test $as_have_required = no; then+  echo This script requires a shell more modern than all the+      echo shells that I found on your system.  Please install a+      echo modern shell, or manually run the script under such a+      echo shell if you do have one.+      { (exit 1); exit 1; }+fi+++fi++fi++++(eval "as_func_return () {+  (exit \$1)+}+as_func_success () {+  as_func_return 0+}+as_func_failure () {+  as_func_return 1+}+as_func_ret_success () {+  return 0+}+as_func_ret_failure () {+  return 1+}++exitcode=0+if as_func_success; then+  :+else+  exitcode=1+  echo as_func_success failed.+fi++if as_func_failure; then+  exitcode=1+  echo as_func_failure succeeded.+fi++if as_func_ret_success; then+  :+else+  exitcode=1+  echo as_func_ret_success failed.+fi++if as_func_ret_failure; then+  exitcode=1+  echo as_func_ret_failure succeeded.+fi++if ( set x; as_func_ret_success y && test x = \"\$1\" ); then+  :+else+  exitcode=1+  echo positional parameters were not saved.+fi++test \$exitcode = 0") || {+  echo No shell found that supports shell functions.+  echo Please tell autoconf@gnu.org about your system,+  echo including any error possibly output before this+  echo message+}++++  as_lineno_1=$LINENO+  as_lineno_2=$LINENO+  test "x$as_lineno_1" != "x$as_lineno_2" &&+  test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2" || {++  # Create $as_me.lineno as a copy of $as_myself, but with $LINENO+  # uniformly replaced by the line number.  The first 'sed' inserts a+  # line-number line after each line using $LINENO; the second 'sed'+  # does the real work.  The second script uses 'N' to pair each+  # line-number line with the line containing $LINENO, and appends+  # trailing '-' during substitution so that $LINENO is not a special+  # case at line end.+  # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the+  # scripts with optimization help from Paolo Bonzini.  Blame Lee+  # E. McMahon (1931-1989) for sed's syntax.  :-)+  sed -n '+    p+    /[$]LINENO/=+  ' <$as_myself |+    sed '+      s/[$]LINENO.*/&-/+      t lineno+      b+      :lineno+      N+      :loop+      s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/+      t loop+      s/-\n.*//+    ' >$as_me.lineno &&+  chmod +x "$as_me.lineno" ||+    { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2+   { (exit 1); exit 1; }; }++  # Don't try to exec as it changes $[0], causing all sort of problems+  # (the dirname of $[0] is not the place where we might find the+  # original and so on.  Autoconf is especially sensitive to this).+  . "./$as_me.lineno"+  # Exit status is that of the last command.+  exit+}+++if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then+  as_dirname=dirname+else+  as_dirname=false+fi++ECHO_C= ECHO_N= ECHO_T=+case `echo -n x` in+-n*)+  case `echo 'x\c'` in+  *c*) ECHO_T='	';;	# ECHO_T is single tab character.+  *)   ECHO_C='\c';;+  esac;;+*)+  ECHO_N='-n';;+esac++if expr a : '\(a\)' >/dev/null 2>&1 &&+   test "X`expr 00001 : '.*\(...\)'`" = X001; then+  as_expr=expr+else+  as_expr=false+fi++rm -f conf$$ conf$$.exe conf$$.file+if test -d conf$$.dir; then+  rm -f conf$$.dir/conf$$.file+else+  rm -f conf$$.dir+  mkdir conf$$.dir+fi+echo >conf$$.file+if ln -s conf$$.file conf$$ 2>/dev/null; then+  as_ln_s='ln -s'+  # ... but there are two gotchas:+  # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.+  # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.+  # In both cases, we have to default to `cp -p'.+  ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||+    as_ln_s='cp -p'+elif ln conf$$.file conf$$ 2>/dev/null; then+  as_ln_s=ln+else+  as_ln_s='cp -p'+fi+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file+rmdir conf$$.dir 2>/dev/null++if mkdir -p . 2>/dev/null; then+  as_mkdir_p=:+else+  test -d ./-p && rmdir ./-p+  as_mkdir_p=false+fi++# Find out whether ``test -x'' works.  Don't use a zero-byte file, as+# systems may use methods other than mode bits to determine executability.+cat >conf$$.file <<_ASEOF+#! /bin/sh+exit 0+_ASEOF+chmod +x conf$$.file+if test -x conf$$.file >/dev/null 2>&1; then+  as_executable_p="test -x"+else+  as_executable_p=:+fi+rm -f conf$$.file++# Sed expression to map a string onto a valid CPP name.+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"++# Sed expression to map a string onto a valid variable name.+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"++++exec 7<&0 </dev/null 6>&1++# Name of the host.+# hostname on some systems (SVR3.2, Linux) returns a bogus exit status,+# so uname gets run too.+ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`++#+# Initializations.+#+ac_default_prefix=/usr/local+ac_clean_files=+ac_config_libobj_dir=.+LIBOBJS=+cross_compiling=no+subdirs=+MFLAGS=+MAKEFLAGS=+SHELL=${CONFIG_SHELL-/bin/sh}++# Identity of this package.+PACKAGE_NAME=+PACKAGE_TARNAME=+PACKAGE_VERSION=+PACKAGE_STRING=+PACKAGE_BUGREPORT=++ac_unique_file="HsOpenSSL"+ac_unique_file="OpenSSL/SSL.hsc"+ac_subst_vars='SHELL+PATH_SEPARATOR+PACKAGE_NAME+PACKAGE_TARNAME+PACKAGE_VERSION+PACKAGE_STRING+PACKAGE_BUGREPORT+exec_prefix+prefix+program_transform_name+bindir+sbindir+libexecdir+datarootdir+datadir+sysconfdir+sharedstatedir+localstatedir+includedir+oldincludedir+docdir+infodir+htmldir+dvidir+pdfdir+psdir+libdir+localedir+mandir+DEFS+ECHO_C+ECHO_N+ECHO_T+LIBS+build_alias+host_alias+target_alias+PKG_CONFIG+OPENSSL_CFLAGS+OPENSSL_LIBS+LIBOBJS+LTLIBOBJS'+ac_subst_files=''+      ac_precious_vars='build_alias+host_alias+target_alias+PKG_CONFIG+OPENSSL_CFLAGS+OPENSSL_LIBS'+++# Initialize some variables set by options.+ac_init_help=+ac_init_version=false+# The variables have the same names as the options, with+# dashes changed to underlines.+cache_file=/dev/null+exec_prefix=NONE+no_create=+no_recursion=+prefix=NONE+program_prefix=NONE+program_suffix=NONE+program_transform_name=s,x,x,+silent=+site=+srcdir=+verbose=+x_includes=NONE+x_libraries=NONE++# Installation directory options.+# These are left unexpanded so users can "make install exec_prefix=/foo"+# and all the variables that are supposed to be based on exec_prefix+# by default will actually change.+# Use braces instead of parens because sh, perl, etc. also accept them.+# (The list follows the same order as the GNU Coding Standards.)+bindir='${exec_prefix}/bin'+sbindir='${exec_prefix}/sbin'+libexecdir='${exec_prefix}/libexec'+datarootdir='${prefix}/share'+datadir='${datarootdir}'+sysconfdir='${prefix}/etc'+sharedstatedir='${prefix}/com'+localstatedir='${prefix}/var'+includedir='${prefix}/include'+oldincludedir='/usr/include'+docdir='${datarootdir}/doc/${PACKAGE}'+infodir='${datarootdir}/info'+htmldir='${docdir}'+dvidir='${docdir}'+pdfdir='${docdir}'+psdir='${docdir}'+libdir='${exec_prefix}/lib'+localedir='${datarootdir}/locale'+mandir='${datarootdir}/man'++ac_prev=+ac_dashdash=+for ac_option+do+  # If the previous option needs an argument, assign it.+  if test -n "$ac_prev"; then+    eval $ac_prev=\$ac_option+    ac_prev=+    continue+  fi++  case $ac_option in+  *=*)	ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;;+  *)	ac_optarg=yes ;;+  esac++  # Accept the important Cygnus configure options, so we can diagnose typos.++  case $ac_dashdash$ac_option in+  --)+    ac_dashdash=yes ;;++  -bindir | --bindir | --bindi | --bind | --bin | --bi)+    ac_prev=bindir ;;+  -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)+    bindir=$ac_optarg ;;++  -build | --build | --buil | --bui | --bu)+    ac_prev=build_alias ;;+  -build=* | --build=* | --buil=* | --bui=* | --bu=*)+    build_alias=$ac_optarg ;;++  -cache-file | --cache-file | --cache-fil | --cache-fi \+  | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)+    ac_prev=cache_file ;;+  -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \+  | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)+    cache_file=$ac_optarg ;;++  --config-cache | -C)+    cache_file=config.cache ;;++  -datadir | --datadir | --datadi | --datad)+    ac_prev=datadir ;;+  -datadir=* | --datadir=* | --datadi=* | --datad=*)+    datadir=$ac_optarg ;;++  -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \+  | --dataroo | --dataro | --datar)+    ac_prev=datarootdir ;;+  -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \+  | --dataroot=* | --dataroo=* | --dataro=* | --datar=*)+    datarootdir=$ac_optarg ;;++  -disable-* | --disable-*)+    ac_feature=`expr "x$ac_option" : 'x-*disable-\(.*\)'`+    # Reject names that are not valid shell variable names.+    expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null &&+      { echo "$as_me: error: invalid feature name: $ac_feature" >&2+   { (exit 1); exit 1; }; }+    ac_feature=`echo $ac_feature | sed 's/-/_/g'`+    eval enable_$ac_feature=no ;;++  -docdir | --docdir | --docdi | --doc | --do)+    ac_prev=docdir ;;+  -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*)+    docdir=$ac_optarg ;;++  -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv)+    ac_prev=dvidir ;;+  -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*)+    dvidir=$ac_optarg ;;++  -enable-* | --enable-*)+    ac_feature=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`+    # Reject names that are not valid shell variable names.+    expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null &&+      { echo "$as_me: error: invalid feature name: $ac_feature" >&2+   { (exit 1); exit 1; }; }+    ac_feature=`echo $ac_feature | sed 's/-/_/g'`+    eval enable_$ac_feature=\$ac_optarg ;;++  -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \+  | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \+  | --exec | --exe | --ex)+    ac_prev=exec_prefix ;;+  -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \+  | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \+  | --exec=* | --exe=* | --ex=*)+    exec_prefix=$ac_optarg ;;++  -gas | --gas | --ga | --g)+    # Obsolete; use --with-gas.+    with_gas=yes ;;++  -help | --help | --hel | --he | -h)+    ac_init_help=long ;;+  -help=r* | --help=r* | --hel=r* | --he=r* | -hr*)+    ac_init_help=recursive ;;+  -help=s* | --help=s* | --hel=s* | --he=s* | -hs*)+    ac_init_help=short ;;++  -host | --host | --hos | --ho)+    ac_prev=host_alias ;;+  -host=* | --host=* | --hos=* | --ho=*)+    host_alias=$ac_optarg ;;++  -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht)+    ac_prev=htmldir ;;+  -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \+  | --ht=*)+    htmldir=$ac_optarg ;;++  -includedir | --includedir | --includedi | --included | --include \+  | --includ | --inclu | --incl | --inc)+    ac_prev=includedir ;;+  -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \+  | --includ=* | --inclu=* | --incl=* | --inc=*)+    includedir=$ac_optarg ;;++  -infodir | --infodir | --infodi | --infod | --info | --inf)+    ac_prev=infodir ;;+  -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)+    infodir=$ac_optarg ;;++  -libdir | --libdir | --libdi | --libd)+    ac_prev=libdir ;;+  -libdir=* | --libdir=* | --libdi=* | --libd=*)+    libdir=$ac_optarg ;;++  -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \+  | --libexe | --libex | --libe)+    ac_prev=libexecdir ;;+  -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \+  | --libexe=* | --libex=* | --libe=*)+    libexecdir=$ac_optarg ;;++  -localedir | --localedir | --localedi | --localed | --locale)+    ac_prev=localedir ;;+  -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*)+    localedir=$ac_optarg ;;++  -localstatedir | --localstatedir | --localstatedi | --localstated \+  | --localstate | --localstat | --localsta | --localst | --locals)+    ac_prev=localstatedir ;;+  -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \+  | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*)+    localstatedir=$ac_optarg ;;++  -mandir | --mandir | --mandi | --mand | --man | --ma | --m)+    ac_prev=mandir ;;+  -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)+    mandir=$ac_optarg ;;++  -nfp | --nfp | --nf)+    # Obsolete; use --without-fp.+    with_fp=no ;;++  -no-create | --no-create | --no-creat | --no-crea | --no-cre \+  | --no-cr | --no-c | -n)+    no_create=yes ;;++  -no-recursion | --no-recursion | --no-recursio | --no-recursi \+  | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)+    no_recursion=yes ;;++  -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \+  | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \+  | --oldin | --oldi | --old | --ol | --o)+    ac_prev=oldincludedir ;;+  -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \+  | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \+  | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)+    oldincludedir=$ac_optarg ;;++  -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)+    ac_prev=prefix ;;+  -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)+    prefix=$ac_optarg ;;++  -program-prefix | --program-prefix | --program-prefi | --program-pref \+  | --program-pre | --program-pr | --program-p)+    ac_prev=program_prefix ;;+  -program-prefix=* | --program-prefix=* | --program-prefi=* \+  | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)+    program_prefix=$ac_optarg ;;++  -program-suffix | --program-suffix | --program-suffi | --program-suff \+  | --program-suf | --program-su | --program-s)+    ac_prev=program_suffix ;;+  -program-suffix=* | --program-suffix=* | --program-suffi=* \+  | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)+    program_suffix=$ac_optarg ;;++  -program-transform-name | --program-transform-name \+  | --program-transform-nam | --program-transform-na \+  | --program-transform-n | --program-transform- \+  | --program-transform | --program-transfor \+  | --program-transfo | --program-transf \+  | --program-trans | --program-tran \+  | --progr-tra | --program-tr | --program-t)+    ac_prev=program_transform_name ;;+  -program-transform-name=* | --program-transform-name=* \+  | --program-transform-nam=* | --program-transform-na=* \+  | --program-transform-n=* | --program-transform-=* \+  | --program-transform=* | --program-transfor=* \+  | --program-transfo=* | --program-transf=* \+  | --program-trans=* | --program-tran=* \+  | --progr-tra=* | --program-tr=* | --program-t=*)+    program_transform_name=$ac_optarg ;;++  -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd)+    ac_prev=pdfdir ;;+  -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*)+    pdfdir=$ac_optarg ;;++  -psdir | --psdir | --psdi | --psd | --ps)+    ac_prev=psdir ;;+  -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*)+    psdir=$ac_optarg ;;++  -q | -quiet | --quiet | --quie | --qui | --qu | --q \+  | -silent | --silent | --silen | --sile | --sil)+    silent=yes ;;++  -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)+    ac_prev=sbindir ;;+  -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \+  | --sbi=* | --sb=*)+    sbindir=$ac_optarg ;;++  -sharedstatedir | --sharedstatedir | --sharedstatedi \+  | --sharedstated | --sharedstate | --sharedstat | --sharedsta \+  | --sharedst | --shareds | --shared | --share | --shar \+  | --sha | --sh)+    ac_prev=sharedstatedir ;;+  -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \+  | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \+  | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \+  | --sha=* | --sh=*)+    sharedstatedir=$ac_optarg ;;++  -site | --site | --sit)+    ac_prev=site ;;+  -site=* | --site=* | --sit=*)+    site=$ac_optarg ;;++  -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)+    ac_prev=srcdir ;;+  -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)+    srcdir=$ac_optarg ;;++  -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \+  | --syscon | --sysco | --sysc | --sys | --sy)+    ac_prev=sysconfdir ;;+  -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \+  | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)+    sysconfdir=$ac_optarg ;;++  -target | --target | --targe | --targ | --tar | --ta | --t)+    ac_prev=target_alias ;;+  -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)+    target_alias=$ac_optarg ;;++  -v | -verbose | --verbose | --verbos | --verbo | --verb)+    verbose=yes ;;++  -version | --version | --versio | --versi | --vers | -V)+    ac_init_version=: ;;++  -with-* | --with-*)+    ac_package=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`+    # Reject names that are not valid shell variable names.+    expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null &&+      { echo "$as_me: error: invalid package name: $ac_package" >&2+   { (exit 1); exit 1; }; }+    ac_package=`echo $ac_package| sed 's/-/_/g'`+    eval with_$ac_package=\$ac_optarg ;;++  -without-* | --without-*)+    ac_package=`expr "x$ac_option" : 'x-*without-\(.*\)'`+    # Reject names that are not valid shell variable names.+    expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null &&+      { echo "$as_me: error: invalid package name: $ac_package" >&2+   { (exit 1); exit 1; }; }+    ac_package=`echo $ac_package | sed 's/-/_/g'`+    eval with_$ac_package=no ;;++  --x)+    # Obsolete; use --with-x.+    with_x=yes ;;++  -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \+  | --x-incl | --x-inc | --x-in | --x-i)+    ac_prev=x_includes ;;+  -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \+  | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)+    x_includes=$ac_optarg ;;++  -x-libraries | --x-libraries | --x-librarie | --x-librari \+  | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)+    ac_prev=x_libraries ;;+  -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \+  | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)+    x_libraries=$ac_optarg ;;++  -*) { echo "$as_me: error: unrecognized option: $ac_option+Try \`$0 --help' for more information." >&2+   { (exit 1); exit 1; }; }+    ;;++  *=*)+    ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='`+    # Reject names that are not valid shell variable names.+    expr "x$ac_envvar" : ".*[^_$as_cr_alnum]" >/dev/null &&+      { echo "$as_me: error: invalid variable name: $ac_envvar" >&2+   { (exit 1); exit 1; }; }+    eval $ac_envvar=\$ac_optarg+    export $ac_envvar ;;++  *)+    # FIXME: should be removed in autoconf 3.0.+    echo "$as_me: WARNING: you should use --build, --host, --target" >&2+    expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&+      echo "$as_me: WARNING: invalid host type: $ac_option" >&2+    : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}+    ;;++  esac+done++if test -n "$ac_prev"; then+  ac_option=--`echo $ac_prev | sed 's/_/-/g'`+  { echo "$as_me: error: missing argument to $ac_option" >&2+   { (exit 1); exit 1; }; }+fi++# Be sure to have absolute directory names.+for ac_var in	exec_prefix prefix bindir sbindir libexecdir datarootdir \+		datadir sysconfdir sharedstatedir localstatedir includedir \+		oldincludedir docdir infodir htmldir dvidir pdfdir psdir \+		libdir localedir mandir+do+  eval ac_val=\$$ac_var+  case $ac_val in+    [\\/$]* | ?:[\\/]* )  continue;;+    NONE | '' ) case $ac_var in *prefix ) continue;; esac;;+  esac+  { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2+   { (exit 1); exit 1; }; }+done++# There might be people who depend on the old broken behavior: `$host'+# used to hold the argument of --host etc.+# FIXME: To remove some day.+build=$build_alias+host=$host_alias+target=$target_alias++# FIXME: To remove some day.+if test "x$host_alias" != x; then+  if test "x$build_alias" = x; then+    cross_compiling=maybe+    echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host.+    If a cross compiler is detected then cross compile mode will be used." >&2+  elif test "x$build_alias" != "x$host_alias"; then+    cross_compiling=yes+  fi+fi++ac_tool_prefix=+test -n "$host_alias" && ac_tool_prefix=$host_alias-++test "$silent" = yes && exec 6>/dev/null+++ac_pwd=`pwd` && test -n "$ac_pwd" &&+ac_ls_di=`ls -di .` &&+ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` ||+  { echo "$as_me: error: Working directory cannot be determined" >&2+   { (exit 1); exit 1; }; }+test "X$ac_ls_di" = "X$ac_pwd_ls_di" ||+  { echo "$as_me: error: pwd does not report name of working directory" >&2+   { (exit 1); exit 1; }; }+++# Find the source files, if location was not specified.+if test -z "$srcdir"; then+  ac_srcdir_defaulted=yes+  # Try the directory containing this script, then the parent directory.+  ac_confdir=`$as_dirname -- "$0" ||+$as_expr X"$0" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \+	 X"$0" : 'X\(//\)[^/]' \| \+	 X"$0" : 'X\(//\)$' \| \+	 X"$0" : 'X\(/\)' \| . 2>/dev/null ||+echo X"$0" |+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{+	    s//\1/+	    q+	  }+	  /^X\(\/\/\)[^/].*/{+	    s//\1/+	    q+	  }+	  /^X\(\/\/\)$/{+	    s//\1/+	    q+	  }+	  /^X\(\/\).*/{+	    s//\1/+	    q+	  }+	  s/.*/./; q'`+  srcdir=$ac_confdir+  if test ! -r "$srcdir/$ac_unique_file"; then+    srcdir=..+  fi+else+  ac_srcdir_defaulted=no+fi+if test ! -r "$srcdir/$ac_unique_file"; then+  test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .."+  { echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2+   { (exit 1); exit 1; }; }+fi+ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work"+ac_abs_confdir=`(+	cd "$srcdir" && test -r "./$ac_unique_file" || { echo "$as_me: error: $ac_msg" >&2+   { (exit 1); exit 1; }; }+	pwd)`+# When building in place, set srcdir=.+if test "$ac_abs_confdir" = "$ac_pwd"; then+  srcdir=.+fi+# Remove unnecessary trailing slashes from srcdir.+# Double slashes in file names in object file debugging info+# mess up M-x gdb in Emacs.+case $srcdir in+*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;;+esac+for ac_var in $ac_precious_vars; do+  eval ac_env_${ac_var}_set=\${${ac_var}+set}+  eval ac_env_${ac_var}_value=\$${ac_var}+  eval ac_cv_env_${ac_var}_set=\${${ac_var}+set}+  eval ac_cv_env_${ac_var}_value=\$${ac_var}+done++#+# Report the --help message.+#+if test "$ac_init_help" = "long"; then+  # Omit some internal or obsolete options to make the list less imposing.+  # This message is too long to be a string in the A/UX 3.1 sh.+  cat <<_ACEOF+\`configure' configures this package to adapt to many kinds of systems.++Usage: $0 [OPTION]... [VAR=VALUE]...++To assign environment variables (e.g., CC, CFLAGS...), specify them as+VAR=VALUE.  See below for descriptions of some of the useful variables.++Defaults for the options are specified in brackets.++Configuration:+  -h, --help              display this help and exit+      --help=short        display options specific to this package+      --help=recursive    display the short help of all the included packages+  -V, --version           display version information and exit+  -q, --quiet, --silent   do not print \`checking...' messages+      --cache-file=FILE   cache test results in FILE [disabled]+  -C, --config-cache      alias for \`--cache-file=config.cache'+  -n, --no-create         do not create output files+      --srcdir=DIR        find the sources in DIR [configure dir or \`..']++Installation directories:+  --prefix=PREFIX         install architecture-independent files in PREFIX+			  [$ac_default_prefix]+  --exec-prefix=EPREFIX   install architecture-dependent files in EPREFIX+			  [PREFIX]++By default, \`make install' will install all the files in+\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc.  You can specify+an installation prefix other than \`$ac_default_prefix' using \`--prefix',+for instance \`--prefix=\$HOME'.++For better control, use the options below.++Fine tuning of the installation directories:+  --bindir=DIR           user executables [EPREFIX/bin]+  --sbindir=DIR          system admin executables [EPREFIX/sbin]+  --libexecdir=DIR       program executables [EPREFIX/libexec]+  --sysconfdir=DIR       read-only single-machine data [PREFIX/etc]+  --sharedstatedir=DIR   modifiable architecture-independent data [PREFIX/com]+  --localstatedir=DIR    modifiable single-machine data [PREFIX/var]+  --libdir=DIR           object code libraries [EPREFIX/lib]+  --includedir=DIR       C header files [PREFIX/include]+  --oldincludedir=DIR    C header files for non-gcc [/usr/include]+  --datarootdir=DIR      read-only arch.-independent data root [PREFIX/share]+  --datadir=DIR          read-only architecture-independent data [DATAROOTDIR]+  --infodir=DIR          info documentation [DATAROOTDIR/info]+  --localedir=DIR        locale-dependent data [DATAROOTDIR/locale]+  --mandir=DIR           man documentation [DATAROOTDIR/man]+  --docdir=DIR           documentation root [DATAROOTDIR/doc/PACKAGE]+  --htmldir=DIR          html documentation [DOCDIR]+  --dvidir=DIR           dvi documentation [DOCDIR]+  --pdfdir=DIR           pdf documentation [DOCDIR]+  --psdir=DIR            ps documentation [DOCDIR]+_ACEOF++  cat <<\_ACEOF+_ACEOF+fi++if test -n "$ac_init_help"; then++  cat <<\_ACEOF++Some influential environment variables:+  PKG_CONFIG  path to pkg-config utility+  OPENSSL_CFLAGS+              C compiler flags for OPENSSL, overriding pkg-config+  OPENSSL_LIBS+              linker flags for OPENSSL, overriding pkg-config++Use these variables to override the choices made by `configure' or to help+it to find libraries and programs with nonstandard names/locations.++_ACEOF+ac_status=$?+fi++if test "$ac_init_help" = "recursive"; then+  # If there are subdirs, report their specific --help.+  for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue+    test -d "$ac_dir" || continue+    ac_builddir=.++case "$ac_dir" in+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;+*)+  ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`+  # A ".." for each directory in $ac_dir_suffix.+  ac_top_builddir_sub=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,/..,g;s,/,,'`+  case $ac_top_builddir_sub in+  "") ac_top_builddir_sub=. ac_top_build_prefix= ;;+  *)  ac_top_build_prefix=$ac_top_builddir_sub/ ;;+  esac ;;+esac+ac_abs_top_builddir=$ac_pwd+ac_abs_builddir=$ac_pwd$ac_dir_suffix+# for backward compatibility:+ac_top_builddir=$ac_top_build_prefix++case $srcdir in+  .)  # We are building in place.+    ac_srcdir=.+    ac_top_srcdir=$ac_top_builddir_sub+    ac_abs_top_srcdir=$ac_pwd ;;+  [\\/]* | ?:[\\/]* )  # Absolute name.+    ac_srcdir=$srcdir$ac_dir_suffix;+    ac_top_srcdir=$srcdir+    ac_abs_top_srcdir=$srcdir ;;+  *) # Relative name.+    ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix+    ac_top_srcdir=$ac_top_build_prefix$srcdir+    ac_abs_top_srcdir=$ac_pwd/$srcdir ;;+esac+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix++    cd "$ac_dir" || { ac_status=$?; continue; }+    # Check for guested configure.+    if test -f "$ac_srcdir/configure.gnu"; then+      echo &&+      $SHELL "$ac_srcdir/configure.gnu" --help=recursive+    elif test -f "$ac_srcdir/configure"; then+      echo &&+      $SHELL "$ac_srcdir/configure" --help=recursive+    else+      echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2+    fi || ac_status=$?+    cd "$ac_pwd" || { ac_status=$?; break; }+  done+fi++test -n "$ac_init_help" && exit $ac_status+if $ac_init_version; then+  cat <<\_ACEOF+configure+generated by GNU Autoconf 2.60++Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,+2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.+This configure script is free software; the Free Software Foundation+gives unlimited permission to copy, distribute and modify it.+_ACEOF+  exit+fi+cat >config.log <<_ACEOF+This file contains any messages produced by compilers while+running configure, to aid debugging if configure makes a mistake.++It was created by $as_me, which was+generated by GNU Autoconf 2.60.  Invocation command line was++  $ $0 $@++_ACEOF+exec 5>>config.log+{+cat <<_ASUNAME+## --------- ##+## Platform. ##+## --------- ##++hostname = `(hostname || uname -n) 2>/dev/null | sed 1q`+uname -m = `(uname -m) 2>/dev/null || echo unknown`+uname -r = `(uname -r) 2>/dev/null || echo unknown`+uname -s = `(uname -s) 2>/dev/null || echo unknown`+uname -v = `(uname -v) 2>/dev/null || echo unknown`++/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown`+/bin/uname -X     = `(/bin/uname -X) 2>/dev/null     || echo unknown`++/bin/arch              = `(/bin/arch) 2>/dev/null              || echo unknown`+/usr/bin/arch -k       = `(/usr/bin/arch -k) 2>/dev/null       || echo unknown`+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown`+/usr/bin/hostinfo      = `(/usr/bin/hostinfo) 2>/dev/null      || echo unknown`+/bin/machine           = `(/bin/machine) 2>/dev/null           || echo unknown`+/usr/bin/oslevel       = `(/usr/bin/oslevel) 2>/dev/null       || echo unknown`+/bin/universe          = `(/bin/universe) 2>/dev/null          || echo unknown`++_ASUNAME++as_save_IFS=$IFS; IFS=$PATH_SEPARATOR+for as_dir in $PATH+do+  IFS=$as_save_IFS+  test -z "$as_dir" && as_dir=.+  echo "PATH: $as_dir"+done+IFS=$as_save_IFS++} >&5++cat >&5 <<_ACEOF+++## ----------- ##+## Core tests. ##+## ----------- ##++_ACEOF+++# Keep a trace of the command line.+# Strip out --no-create and --no-recursion so they do not pile up.+# Strip out --silent because we don't want to record it for future runs.+# Also quote any args containing shell meta-characters.+# Make two passes to allow for proper duplicate-argument suppression.+ac_configure_args=+ac_configure_args0=+ac_configure_args1=+ac_must_keep_next=false+for ac_pass in 1 2+do+  for ac_arg+  do+    case $ac_arg in+    -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;;+    -q | -quiet | --quiet | --quie | --qui | --qu | --q \+    | -silent | --silent | --silen | --sile | --sil)+      continue ;;+    *\'*)+      ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;+    esac+    case $ac_pass in+    1) ac_configure_args0="$ac_configure_args0 '$ac_arg'" ;;+    2)+      ac_configure_args1="$ac_configure_args1 '$ac_arg'"+      if test $ac_must_keep_next = true; then+	ac_must_keep_next=false # Got value, back to normal.+      else+	case $ac_arg in+	  *=* | --config-cache | -C | -disable-* | --disable-* \+	  | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \+	  | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \+	  | -with-* | --with-* | -without-* | --without-* | --x)+	    case "$ac_configure_args0 " in+	      "$ac_configure_args1"*" '$ac_arg' "* ) continue ;;+	    esac+	    ;;+	  -* ) ac_must_keep_next=true ;;+	esac+      fi+      ac_configure_args="$ac_configure_args '$ac_arg'"+      ;;+    esac+  done+done+$as_unset ac_configure_args0 || test "${ac_configure_args0+set}" != set || { ac_configure_args0=; export ac_configure_args0; }+$as_unset ac_configure_args1 || test "${ac_configure_args1+set}" != set || { ac_configure_args1=; export ac_configure_args1; }++# When interrupted or exit'd, cleanup temporary files, and complete+# config.log.  We remove comments because anyway the quotes in there+# would cause problems or look ugly.+# WARNING: Use '\'' to represent an apostrophe within the trap.+# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug.+trap 'exit_status=$?+  # Save into config.log some information that might help in debugging.+  {+    echo++    cat <<\_ASBOX+## ---------------- ##+## Cache variables. ##+## ---------------- ##+_ASBOX+    echo+    # The following way of writing the cache mishandles newlines in values,+(+  for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do+    eval ac_val=\$$ac_var+    case $ac_val in #(+    *${as_nl}*)+      case $ac_var in #(+      *_cv_*) { echo "$as_me:$LINENO: WARNING: Cache variable $ac_var contains a newline." >&5+echo "$as_me: WARNING: Cache variable $ac_var contains a newline." >&2;} ;;+      esac+      case $ac_var in #(+      _ | IFS | as_nl) ;; #(+      *) $as_unset $ac_var ;;+      esac ;;+    esac+  done+  (set) 2>&1 |+    case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #(+    *${as_nl}ac_space=\ *)+      sed -n \+	"s/'\''/'\''\\\\'\'''\''/g;+	  s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p"+      ;; #(+    *)+      sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"+      ;;+    esac |+    sort+)+    echo++    cat <<\_ASBOX+## ----------------- ##+## Output variables. ##+## ----------------- ##+_ASBOX+    echo+    for ac_var in $ac_subst_vars+    do+      eval ac_val=\$$ac_var+      case $ac_val in+      *\'\''*) ac_val=`echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;+      esac+      echo "$ac_var='\''$ac_val'\''"+    done | sort+    echo++    if test -n "$ac_subst_files"; then+      cat <<\_ASBOX+## ------------------- ##+## File substitutions. ##+## ------------------- ##+_ASBOX+      echo+      for ac_var in $ac_subst_files+      do+	eval ac_val=\$$ac_var+	case $ac_val in+	*\'\''*) ac_val=`echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;+	esac+	echo "$ac_var='\''$ac_val'\''"+      done | sort+      echo+    fi++    if test -s confdefs.h; then+      cat <<\_ASBOX+## ----------- ##+## confdefs.h. ##+## ----------- ##+_ASBOX+      echo+      cat confdefs.h+      echo+    fi+    test "$ac_signal" != 0 &&+      echo "$as_me: caught signal $ac_signal"+    echo "$as_me: exit $exit_status"+  } >&5+  rm -f core *.core core.conftest.* &&+    rm -f -r conftest* confdefs* conf$$* $ac_clean_files &&+    exit $exit_status+' 0+for ac_signal in 1 2 13 15; do+  trap 'ac_signal='$ac_signal'; { (exit 1); exit 1; }' $ac_signal+done+ac_signal=0++# confdefs.h avoids OS command line length limits that DEFS can exceed.+rm -f -r conftest* confdefs.h++# Predefined preprocessor variables.++cat >>confdefs.h <<_ACEOF+#define PACKAGE_NAME "$PACKAGE_NAME"+_ACEOF+++cat >>confdefs.h <<_ACEOF+#define PACKAGE_TARNAME "$PACKAGE_TARNAME"+_ACEOF+++cat >>confdefs.h <<_ACEOF+#define PACKAGE_VERSION "$PACKAGE_VERSION"+_ACEOF+++cat >>confdefs.h <<_ACEOF+#define PACKAGE_STRING "$PACKAGE_STRING"+_ACEOF+++cat >>confdefs.h <<_ACEOF+#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT"+_ACEOF+++# Let the site file select an alternate cache file if it wants to.+# Prefer explicitly selected file to automatically selected ones.+if test -n "$CONFIG_SITE"; then+  set x "$CONFIG_SITE"+elif test "x$prefix" != xNONE; then+  set x "$prefix/share/config.site" "$prefix/etc/config.site"+else+  set x "$ac_default_prefix/share/config.site" \+	"$ac_default_prefix/etc/config.site"+fi+shift+for ac_site_file+do+  if test -r "$ac_site_file"; then+    { echo "$as_me:$LINENO: loading site script $ac_site_file" >&5+echo "$as_me: loading site script $ac_site_file" >&6;}+    sed 's/^/| /' "$ac_site_file" >&5+    . "$ac_site_file"+  fi+done++if test -r "$cache_file"; then+  # Some versions of bash will fail to source /dev/null (special+  # files actually), so we avoid doing that.+  if test -f "$cache_file"; then+    { echo "$as_me:$LINENO: loading cache $cache_file" >&5+echo "$as_me: loading cache $cache_file" >&6;}+    case $cache_file in+      [\\/]* | ?:[\\/]* ) . "$cache_file";;+      *)                      . "./$cache_file";;+    esac+  fi+else+  { echo "$as_me:$LINENO: creating cache $cache_file" >&5+echo "$as_me: creating cache $cache_file" >&6;}+  >$cache_file+fi++# Check that the precious variables saved in the cache have kept the same+# value.+ac_cache_corrupted=false+for ac_var in $ac_precious_vars; do+  eval ac_old_set=\$ac_cv_env_${ac_var}_set+  eval ac_new_set=\$ac_env_${ac_var}_set+  eval ac_old_val=\$ac_cv_env_${ac_var}_value+  eval ac_new_val=\$ac_env_${ac_var}_value+  case $ac_old_set,$ac_new_set in+    set,)+      { echo "$as_me:$LINENO: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5+echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}+      ac_cache_corrupted=: ;;+    ,set)+      { echo "$as_me:$LINENO: error: \`$ac_var' was not set in the previous run" >&5+echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}+      ac_cache_corrupted=: ;;+    ,);;+    *)+      if test "x$ac_old_val" != "x$ac_new_val"; then+	{ echo "$as_me:$LINENO: error: \`$ac_var' has changed since the previous run:" >&5+echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}+	{ echo "$as_me:$LINENO:   former value:  $ac_old_val" >&5+echo "$as_me:   former value:  $ac_old_val" >&2;}+	{ echo "$as_me:$LINENO:   current value: $ac_new_val" >&5+echo "$as_me:   current value: $ac_new_val" >&2;}+	ac_cache_corrupted=:+      fi;;+  esac+  # Pass precious variables to config.status.+  if test "$ac_new_set" = set; then+    case $ac_new_val in+    *\'*) ac_arg=$ac_var=`echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;+    *) ac_arg=$ac_var=$ac_new_val ;;+    esac+    case " $ac_configure_args " in+      *" '$ac_arg' "*) ;; # Avoid dups.  Use of quotes ensures accuracy.+      *) ac_configure_args="$ac_configure_args '$ac_arg'" ;;+    esac+  fi+done+if $ac_cache_corrupted; then+  { echo "$as_me:$LINENO: error: changes in the environment can compromise the build" >&5+echo "$as_me: error: changes in the environment can compromise the build" >&2;}+  { { echo "$as_me:$LINENO: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5+echo "$as_me: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&2;}+   { (exit 1); exit 1; }; }+fi++++++++++++++++++ac_ext=c+ac_cpp='$CPP $CPPFLAGS'+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'+ac_compiler_gnu=$ac_cv_c_compiler_gnu++++++++if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then+	if test -n "$ac_tool_prefix"; then+  # Extract the first word of "${ac_tool_prefix}pkg-config", so it can be a program name with args.+set dummy ${ac_tool_prefix}pkg-config; ac_word=$2+{ echo "$as_me:$LINENO: checking for $ac_word" >&5+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }+if test "${ac_cv_path_PKG_CONFIG+set}" = set; then+  echo $ECHO_N "(cached) $ECHO_C" >&6+else+  case $PKG_CONFIG in+  [\\/]* | ?:[\\/]*)+  ac_cv_path_PKG_CONFIG="$PKG_CONFIG" # Let the user override the test with a path.+  ;;+  *)+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR+for as_dir in $PATH+do+  IFS=$as_save_IFS+  test -z "$as_dir" && as_dir=.+  for ac_exec_ext in '' $ac_executable_extensions; do+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then+    ac_cv_path_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext"+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5+    break 2+  fi+done+done+IFS=$as_save_IFS++  ;;+esac+fi+PKG_CONFIG=$ac_cv_path_PKG_CONFIG+if test -n "$PKG_CONFIG"; then+  { echo "$as_me:$LINENO: result: $PKG_CONFIG" >&5+echo "${ECHO_T}$PKG_CONFIG" >&6; }+else+  { echo "$as_me:$LINENO: result: no" >&5+echo "${ECHO_T}no" >&6; }+fi+++fi+if test -z "$ac_cv_path_PKG_CONFIG"; then+  ac_pt_PKG_CONFIG=$PKG_CONFIG+  # Extract the first word of "pkg-config", so it can be a program name with args.+set dummy pkg-config; ac_word=$2+{ echo "$as_me:$LINENO: checking for $ac_word" >&5+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }+if test "${ac_cv_path_ac_pt_PKG_CONFIG+set}" = set; then+  echo $ECHO_N "(cached) $ECHO_C" >&6+else+  case $ac_pt_PKG_CONFIG in+  [\\/]* | ?:[\\/]*)+  ac_cv_path_ac_pt_PKG_CONFIG="$ac_pt_PKG_CONFIG" # Let the user override the test with a path.+  ;;+  *)+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR+for as_dir in $PATH+do+  IFS=$as_save_IFS+  test -z "$as_dir" && as_dir=.+  for ac_exec_ext in '' $ac_executable_extensions; do+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then+    ac_cv_path_ac_pt_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext"+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5+    break 2+  fi+done+done+IFS=$as_save_IFS++  ;;+esac+fi+ac_pt_PKG_CONFIG=$ac_cv_path_ac_pt_PKG_CONFIG+if test -n "$ac_pt_PKG_CONFIG"; then+  { echo "$as_me:$LINENO: result: $ac_pt_PKG_CONFIG" >&5+echo "${ECHO_T}$ac_pt_PKG_CONFIG" >&6; }+else+  { echo "$as_me:$LINENO: result: no" >&5+echo "${ECHO_T}no" >&6; }+fi++  if test "x$ac_pt_PKG_CONFIG" = x; then+    PKG_CONFIG=""+  else+    case $cross_compiling:$ac_tool_warned in+yes:)+{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools+whose name does not start with the host triplet.  If you think this+configuration is useful to you, please write to autoconf@gnu.org." >&5+echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools+whose name does not start with the host triplet.  If you think this+configuration is useful to you, please write to autoconf@gnu.org." >&2;}+ac_tool_warned=yes ;;+esac+    PKG_CONFIG=$ac_pt_PKG_CONFIG+  fi+else+  PKG_CONFIG="$ac_cv_path_PKG_CONFIG"+fi++fi+if test -n "$PKG_CONFIG"; then+	_pkg_min_version=0.9.0+	{ echo "$as_me:$LINENO: checking pkg-config is at least version $_pkg_min_version" >&5+echo $ECHO_N "checking pkg-config is at least version $_pkg_min_version... $ECHO_C" >&6; }+	if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then+		{ echo "$as_me:$LINENO: result: yes" >&5+echo "${ECHO_T}yes" >&6; }+	else+		{ echo "$as_me:$LINENO: result: no" >&5+echo "${ECHO_T}no" >&6; }+		PKG_CONFIG=""+	fi++fi++pkg_failed=no+{ echo "$as_me:$LINENO: checking for OPENSSL" >&5+echo $ECHO_N "checking for OPENSSL... $ECHO_C" >&6; }++if test -n "$PKG_CONFIG"; then+    if test -n "$OPENSSL_CFLAGS"; then+        pkg_cv_OPENSSL_CFLAGS="$OPENSSL_CFLAGS"+    else+        if test -n "$PKG_CONFIG" && \+    { (echo "$as_me:$LINENO: \$PKG_CONFIG --exists --print-errors \"openssl >= 0.9.7l\"") >&5+  ($PKG_CONFIG --exists --print-errors "openssl >= 0.9.7l") 2>&5+  ac_status=$?+  echo "$as_me:$LINENO: \$? = $ac_status" >&5+  (exit $ac_status); }; then+  pkg_cv_OPENSSL_CFLAGS=`$PKG_CONFIG --cflags "openssl >= 0.9.7l" 2>/dev/null`+else+  pkg_failed=yes+fi+    fi+else+	pkg_failed=untried+fi+if test -n "$PKG_CONFIG"; then+    if test -n "$OPENSSL_LIBS"; then+        pkg_cv_OPENSSL_LIBS="$OPENSSL_LIBS"+    else+        if test -n "$PKG_CONFIG" && \+    { (echo "$as_me:$LINENO: \$PKG_CONFIG --exists --print-errors \"openssl >= 0.9.7l\"") >&5+  ($PKG_CONFIG --exists --print-errors "openssl >= 0.9.7l") 2>&5+  ac_status=$?+  echo "$as_me:$LINENO: \$? = $ac_status" >&5+  (exit $ac_status); }; then+  pkg_cv_OPENSSL_LIBS=`$PKG_CONFIG --libs "openssl >= 0.9.7l" 2>/dev/null`+else+  pkg_failed=yes+fi+    fi+else+	pkg_failed=untried+fi++++if test $pkg_failed = yes; then++if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then+        _pkg_short_errors_supported=yes+else+        _pkg_short_errors_supported=no+fi+        if test $_pkg_short_errors_supported = yes; then+	        OPENSSL_PKG_ERRORS=`$PKG_CONFIG --short-errors --errors-to-stdout --print-errors "openssl >= 0.9.7l"`+        else+	        OPENSSL_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors "openssl >= 0.9.7l"`+        fi+	# Put the nasty error message in config.log where it belongs+	echo "$OPENSSL_PKG_ERRORS" >&5++	{ echo "$as_me:$LINENO: result: no" >&5+echo "${ECHO_T}no" >&6; }+                { { echo "$as_me:$LINENO: error: openssl >= 0.9.7l is required to build this package." >&5+echo "$as_me: error: openssl >= 0.9.7l is required to build this package." >&2;}+   { (exit 1); exit 1; }; }+elif test $pkg_failed = untried; then+	{ { echo "$as_me:$LINENO: error: openssl >= 0.9.7l is required to build this package." >&5+echo "$as_me: error: openssl >= 0.9.7l is required to build this package." >&2;}+   { (exit 1); exit 1; }; }+else+	OPENSSL_CFLAGS=$pkg_cv_OPENSSL_CFLAGS+	OPENSSL_LIBS=$pkg_cv_OPENSSL_LIBS+        { echo "$as_me:$LINENO: result: yes" >&5+echo "${ECHO_T}yes" >&6; }+	:+fi++ac_config_files="$ac_config_files HsOpenSSL.buildinfo"++cat >confcache <<\_ACEOF+# This file is a shell script that caches the results of configure+# tests run on this system so they can be shared between configure+# scripts and configure runs, see configure's option --config-cache.+# It is not useful on other systems.  If it contains results you don't+# want to keep, you may remove or edit it.+#+# config.status only pays attention to the cache file if you give it+# the --recheck option to rerun configure.+#+# `ac_cv_env_foo' variables (set or unset) will be overridden when+# loading this file, other *unset* `ac_cv_foo' will be assigned the+# following values.++_ACEOF++# The following way of writing the cache mishandles newlines in values,+# but we know of no workaround that is simple, portable, and efficient.+# So, we kill variables containing newlines.+# Ultrix sh set writes to stderr and can't be redirected directly,+# and sets the high bit in the cache file unless we assign to the vars.+(+  for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do+    eval ac_val=\$$ac_var+    case $ac_val in #(+    *${as_nl}*)+      case $ac_var in #(+      *_cv_*) { echo "$as_me:$LINENO: WARNING: Cache variable $ac_var contains a newline." >&5+echo "$as_me: WARNING: Cache variable $ac_var contains a newline." >&2;} ;;+      esac+      case $ac_var in #(+      _ | IFS | as_nl) ;; #(+      *) $as_unset $ac_var ;;+      esac ;;+    esac+  done++  (set) 2>&1 |+    case $as_nl`(ac_space=' '; set) 2>&1` in #(+    *${as_nl}ac_space=\ *)+      # `set' does not quote correctly, so add quotes (double-quote+      # substitution turns \\\\ into \\, and sed turns \\ into \).+      sed -n \+	"s/'/'\\\\''/g;+	  s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"+      ;; #(+    *)+      # `set' quotes correctly as required by POSIX, so do not add quotes.+      sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"+      ;;+    esac |+    sort+) |+  sed '+     /^ac_cv_env_/b end+     t clear+     :clear+     s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/+     t end+     s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/+     :end' >>confcache+if diff "$cache_file" confcache >/dev/null 2>&1; then :; else+  if test -w "$cache_file"; then+    test "x$cache_file" != "x/dev/null" &&+      { echo "$as_me:$LINENO: updating cache $cache_file" >&5+echo "$as_me: updating cache $cache_file" >&6;}+    cat confcache >$cache_file+  else+    { echo "$as_me:$LINENO: not updating unwritable cache $cache_file" >&5+echo "$as_me: not updating unwritable cache $cache_file" >&6;}+  fi+fi+rm -f confcache++test "x$prefix" = xNONE && prefix=$ac_default_prefix+# Let make expand exec_prefix.+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'++# Transform confdefs.h into DEFS.+# Protect against shell expansion while executing Makefile rules.+# Protect against Makefile macro expansion.+#+# If the first sed substitution is executed (which looks for macros that+# take arguments), then branch to the quote section.  Otherwise,+# look for a macro that doesn't take arguments.+ac_script='+t clear+:clear+s/^[	 ]*#[	 ]*define[	 ][	 ]*\([^	 (][^	 (]*([^)]*)\)[	 ]*\(.*\)/-D\1=\2/g+t quote+s/^[	 ]*#[	 ]*define[	 ][	 ]*\([^	 ][^	 ]*\)[	 ]*\(.*\)/-D\1=\2/g+t quote+b any+:quote+s/[	 `~#$^&*(){}\\|;'\''"<>?]/\\&/g+s/\[/\\&/g+s/\]/\\&/g+s/\$/$$/g+H+:any+${+	g+	s/^\n//+	s/\n/ /g+	p+}+'+DEFS=`sed -n "$ac_script" confdefs.h`+++ac_libobjs=+ac_ltlibobjs=+for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue+  # 1. Remove the extension, and $U if already installed.+  ac_script='s/\$U\././;s/\.o$//;s/\.obj$//'+  ac_i=`echo "$ac_i" | sed "$ac_script"`+  # 2. Prepend LIBOBJDIR.  When used with automake>=1.10 LIBOBJDIR+  #    will be set to the directory where LIBOBJS objects are built.+  ac_libobjs="$ac_libobjs \${LIBOBJDIR}$ac_i\$U.$ac_objext"+  ac_ltlibobjs="$ac_ltlibobjs \${LIBOBJDIR}$ac_i"'$U.lo'+done+LIBOBJS=$ac_libobjs++LTLIBOBJS=$ac_ltlibobjs++++: ${CONFIG_STATUS=./config.status}+ac_clean_files_save=$ac_clean_files+ac_clean_files="$ac_clean_files $CONFIG_STATUS"+{ echo "$as_me:$LINENO: creating $CONFIG_STATUS" >&5+echo "$as_me: creating $CONFIG_STATUS" >&6;}+cat >$CONFIG_STATUS <<_ACEOF+#! $SHELL+# Generated by $as_me.+# Run this file to recreate the current configuration.+# Compiler output produced by configure, useful for debugging+# configure, is in config.log if it exists.++debug=false+ac_cs_recheck=false+ac_cs_silent=false+SHELL=\${CONFIG_SHELL-$SHELL}+_ACEOF++cat >>$CONFIG_STATUS <<\_ACEOF+## --------------------- ##+## M4sh Initialization.  ##+## --------------------- ##++# Be Bourne compatible+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then+  emulate sh+  NULLCMD=:+  # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which+  # is contrary to our usage.  Disable this feature.+  alias -g '${1+"$@"}'='"$@"'+  setopt NO_GLOB_SUBST+else+  case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac+fi+BIN_SH=xpg4; export BIN_SH # for Tru64+DUALCASE=1; export DUALCASE # for MKS sh+++# PATH needs CR+# Avoid depending upon Character Ranges.+as_cr_letters='abcdefghijklmnopqrstuvwxyz'+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'+as_cr_Letters=$as_cr_letters$as_cr_LETTERS+as_cr_digits='0123456789'+as_cr_alnum=$as_cr_Letters$as_cr_digits++# The user is always right.+if test "${PATH_SEPARATOR+set}" != set; then+  echo "#! /bin/sh" >conf$$.sh+  echo  "exit 0"   >>conf$$.sh+  chmod +x conf$$.sh+  if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then+    PATH_SEPARATOR=';'+  else+    PATH_SEPARATOR=:+  fi+  rm -f conf$$.sh+fi++# Support unset when possible.+if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then+  as_unset=unset+else+  as_unset=false+fi+++# IFS+# We need space, tab and new line, in precisely that order.  Quoting is+# there to prevent editors from complaining about space-tab.+# (If _AS_PATH_WALK were called with IFS unset, it would disable word+# splitting by setting IFS to empty value.)+as_nl='+'+IFS=" ""	$as_nl"++# Find who we are.  Look in the path if we contain no directory separator.+case $0 in+  *[\\/]* ) as_myself=$0 ;;+  *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR+for as_dir in $PATH+do+  IFS=$as_save_IFS+  test -z "$as_dir" && as_dir=.+  test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break+done+IFS=$as_save_IFS++     ;;+esac+# We did not find ourselves, most probably we were run as `sh COMMAND'+# in which case we are not to be found in the path.+if test "x$as_myself" = x; then+  as_myself=$0+fi+if test ! -f "$as_myself"; then+  echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2+  { (exit 1); exit 1; }+fi++# Work around bugs in pre-3.0 UWIN ksh.+for as_var in ENV MAIL MAILPATH+do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var+done+PS1='$ '+PS2='> '+PS4='+ '++# NLS nuisances.+for as_var in \+  LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \+  LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \+  LC_TELEPHONE LC_TIME+do+  if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then+    eval $as_var=C; export $as_var+  else+    ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var+  fi+done++# Required to use basename.+if expr a : '\(a\)' >/dev/null 2>&1 &&+   test "X`expr 00001 : '.*\(...\)'`" = X001; then+  as_expr=expr+else+  as_expr=false+fi++if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then+  as_basename=basename+else+  as_basename=false+fi+++# Name of the executable.+as_me=`$as_basename -- "$0" ||+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \+	 X"$0" : 'X\(//\)$' \| \+	 X"$0" : 'X\(/\)' \| . 2>/dev/null ||+echo X/"$0" |+    sed '/^.*\/\([^/][^/]*\)\/*$/{+	    s//\1/+	    q+	  }+	  /^X\/\(\/\/\)$/{+	    s//\1/+	    q+	  }+	  /^X\/\(\/\).*/{+	    s//\1/+	    q+	  }+	  s/.*/./; q'`++# CDPATH.+$as_unset CDPATH++++  as_lineno_1=$LINENO+  as_lineno_2=$LINENO+  test "x$as_lineno_1" != "x$as_lineno_2" &&+  test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2" || {++  # Create $as_me.lineno as a copy of $as_myself, but with $LINENO+  # uniformly replaced by the line number.  The first 'sed' inserts a+  # line-number line after each line using $LINENO; the second 'sed'+  # does the real work.  The second script uses 'N' to pair each+  # line-number line with the line containing $LINENO, and appends+  # trailing '-' during substitution so that $LINENO is not a special+  # case at line end.+  # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the+  # scripts with optimization help from Paolo Bonzini.  Blame Lee+  # E. McMahon (1931-1989) for sed's syntax.  :-)+  sed -n '+    p+    /[$]LINENO/=+  ' <$as_myself |+    sed '+      s/[$]LINENO.*/&-/+      t lineno+      b+      :lineno+      N+      :loop+      s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/+      t loop+      s/-\n.*//+    ' >$as_me.lineno &&+  chmod +x "$as_me.lineno" ||+    { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2+   { (exit 1); exit 1; }; }++  # Don't try to exec as it changes $[0], causing all sort of problems+  # (the dirname of $[0] is not the place where we might find the+  # original and so on.  Autoconf is especially sensitive to this).+  . "./$as_me.lineno"+  # Exit status is that of the last command.+  exit+}+++if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then+  as_dirname=dirname+else+  as_dirname=false+fi++ECHO_C= ECHO_N= ECHO_T=+case `echo -n x` in+-n*)+  case `echo 'x\c'` in+  *c*) ECHO_T='	';;	# ECHO_T is single tab character.+  *)   ECHO_C='\c';;+  esac;;+*)+  ECHO_N='-n';;+esac++if expr a : '\(a\)' >/dev/null 2>&1 &&+   test "X`expr 00001 : '.*\(...\)'`" = X001; then+  as_expr=expr+else+  as_expr=false+fi++rm -f conf$$ conf$$.exe conf$$.file+if test -d conf$$.dir; then+  rm -f conf$$.dir/conf$$.file+else+  rm -f conf$$.dir+  mkdir conf$$.dir+fi+echo >conf$$.file+if ln -s conf$$.file conf$$ 2>/dev/null; then+  as_ln_s='ln -s'+  # ... but there are two gotchas:+  # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.+  # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.+  # In both cases, we have to default to `cp -p'.+  ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||+    as_ln_s='cp -p'+elif ln conf$$.file conf$$ 2>/dev/null; then+  as_ln_s=ln+else+  as_ln_s='cp -p'+fi+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file+rmdir conf$$.dir 2>/dev/null++if mkdir -p . 2>/dev/null; then+  as_mkdir_p=:+else+  test -d ./-p && rmdir ./-p+  as_mkdir_p=false+fi++# Find out whether ``test -x'' works.  Don't use a zero-byte file, as+# systems may use methods other than mode bits to determine executability.+cat >conf$$.file <<_ASEOF+#! /bin/sh+exit 0+_ASEOF+chmod +x conf$$.file+if test -x conf$$.file >/dev/null 2>&1; then+  as_executable_p="test -x"+else+  as_executable_p=:+fi+rm -f conf$$.file++# Sed expression to map a string onto a valid CPP name.+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"++# Sed expression to map a string onto a valid variable name.+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"+++exec 6>&1++# Save the log message, to keep $[0] and so on meaningful, and to+# report actual input values of CONFIG_FILES etc. instead of their+# values after options handling.+ac_log="+This file was extended by $as_me, which was+generated by GNU Autoconf 2.60.  Invocation command line was++  CONFIG_FILES    = $CONFIG_FILES+  CONFIG_HEADERS  = $CONFIG_HEADERS+  CONFIG_LINKS    = $CONFIG_LINKS+  CONFIG_COMMANDS = $CONFIG_COMMANDS+  $ $0 $@++on `(hostname || uname -n) 2>/dev/null | sed 1q`+"++_ACEOF++cat >>$CONFIG_STATUS <<_ACEOF+# Files that config.status was made for.+config_files="$ac_config_files"++_ACEOF++cat >>$CONFIG_STATUS <<\_ACEOF+ac_cs_usage="\+\`$as_me' instantiates files from templates according to the+current configuration.++Usage: $0 [OPTIONS] [FILE]...++  -h, --help       print this help, then exit+  -V, --version    print version number, then exit+  -q, --quiet      do not print progress messages+  -d, --debug      don't remove temporary files+      --recheck    update $as_me by reconfiguring in the same conditions+  --file=FILE[:TEMPLATE]+		   instantiate the configuration file FILE++Configuration files:+$config_files++Report bugs to <bug-autoconf@gnu.org>."++_ACEOF+cat >>$CONFIG_STATUS <<_ACEOF+ac_cs_version="\\+config.status+configured by $0, generated by GNU Autoconf 2.60,+  with options \\"`echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\"++Copyright (C) 2006 Free Software Foundation, Inc.+This config.status script is free software; the Free Software Foundation+gives unlimited permission to copy, distribute and modify it."++ac_pwd='$ac_pwd'+srcdir='$srcdir'+_ACEOF++cat >>$CONFIG_STATUS <<\_ACEOF+# If no file are specified by the user, then we need to provide default+# value.  By we need to know if files were specified by the user.+ac_need_defaults=:+while test $# != 0+do+  case $1 in+  --*=*)+    ac_option=`expr "X$1" : 'X\([^=]*\)='`+    ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'`+    ac_shift=:+    ;;+  *)+    ac_option=$1+    ac_optarg=$2+    ac_shift=shift+    ;;+  esac++  case $ac_option in+  # Handling of the options.+  -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)+    ac_cs_recheck=: ;;+  --version | --versio | --versi | --vers | --ver | --ve | --v | -V )+    echo "$ac_cs_version"; exit ;;+  --debug | --debu | --deb | --de | --d | -d )+    debug=: ;;+  --file | --fil | --fi | --f )+    $ac_shift+    CONFIG_FILES="$CONFIG_FILES $ac_optarg"+    ac_need_defaults=false;;+  --he | --h |  --help | --hel | -h )+    echo "$ac_cs_usage"; exit ;;+  -q | -quiet | --quiet | --quie | --qui | --qu | --q \+  | -silent | --silent | --silen | --sile | --sil | --si | --s)+    ac_cs_silent=: ;;++  # This is an error.+  -*) { echo "$as_me: error: unrecognized option: $1+Try \`$0 --help' for more information." >&2+   { (exit 1); exit 1; }; } ;;++  *) ac_config_targets="$ac_config_targets $1"+     ac_need_defaults=false ;;++  esac+  shift+done++ac_configure_extra_args=++if $ac_cs_silent; then+  exec 6>/dev/null+  ac_configure_extra_args="$ac_configure_extra_args --silent"+fi++_ACEOF+cat >>$CONFIG_STATUS <<_ACEOF+if \$ac_cs_recheck; then+  echo "running CONFIG_SHELL=$SHELL $SHELL $0 "$ac_configure_args \$ac_configure_extra_args " --no-create --no-recursion" >&6+  CONFIG_SHELL=$SHELL+  export CONFIG_SHELL+  exec $SHELL "$0"$ac_configure_args \$ac_configure_extra_args --no-create --no-recursion+fi++_ACEOF+cat >>$CONFIG_STATUS <<\_ACEOF+exec 5>>config.log+{+  echo+  sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX+## Running $as_me. ##+_ASBOX+  echo "$ac_log"+} >&5++_ACEOF+cat >>$CONFIG_STATUS <<_ACEOF+_ACEOF++cat >>$CONFIG_STATUS <<\_ACEOF++# Handling of arguments.+for ac_config_target in $ac_config_targets+do+  case $ac_config_target in+    "HsOpenSSL.buildinfo") CONFIG_FILES="$CONFIG_FILES HsOpenSSL.buildinfo" ;;++  *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5+echo "$as_me: error: invalid argument: $ac_config_target" >&2;}+   { (exit 1); exit 1; }; };;+  esac+done+++# If the user did not use the arguments to specify the items to instantiate,+# then the envvar interface is used.  Set only those that are not.+# We use the long form for the default assignment because of an extremely+# bizarre bug on SunOS 4.1.3.+if $ac_need_defaults; then+  test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files+fi++# Have a temporary directory for convenience.  Make it in the build tree+# simply because there is no reason against having it here, and in addition,+# creating and moving files from /tmp can sometimes cause problems.+# Hook for its removal unless debugging.+# Note that there is a small window in which the directory will not be cleaned:+# after its creation but before its name has been assigned to `$tmp'.+$debug ||+{+  tmp=+  trap 'exit_status=$?+  { test -z "$tmp" || test ! -d "$tmp" || rm -fr "$tmp"; } && exit $exit_status+' 0+  trap '{ (exit 1); exit 1; }' 1 2 13 15+}+# Create a (secure) tmp directory for tmp files.++{+  tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` &&+  test -n "$tmp" && test -d "$tmp"+}  ||+{+  tmp=./conf$$-$RANDOM+  (umask 077 && mkdir "$tmp")+} ||+{+   echo "$me: cannot create a temporary directory in ." >&2+   { (exit 1); exit 1; }+}++#+# Set up the sed scripts for CONFIG_FILES section.+#++# No need to generate the scripts if there are no CONFIG_FILES.+# This happens for instance when ./config.status config.h+if test -n "$CONFIG_FILES"; then++_ACEOF++++ac_delim='%!_!# '+for ac_last_try in false false false false false :; do+  cat >conf$$subs.sed <<_ACEOF+SHELL!$SHELL$ac_delim+PATH_SEPARATOR!$PATH_SEPARATOR$ac_delim+PACKAGE_NAME!$PACKAGE_NAME$ac_delim+PACKAGE_TARNAME!$PACKAGE_TARNAME$ac_delim+PACKAGE_VERSION!$PACKAGE_VERSION$ac_delim+PACKAGE_STRING!$PACKAGE_STRING$ac_delim+PACKAGE_BUGREPORT!$PACKAGE_BUGREPORT$ac_delim+exec_prefix!$exec_prefix$ac_delim+prefix!$prefix$ac_delim+program_transform_name!$program_transform_name$ac_delim+bindir!$bindir$ac_delim+sbindir!$sbindir$ac_delim+libexecdir!$libexecdir$ac_delim+datarootdir!$datarootdir$ac_delim+datadir!$datadir$ac_delim+sysconfdir!$sysconfdir$ac_delim+sharedstatedir!$sharedstatedir$ac_delim+localstatedir!$localstatedir$ac_delim+includedir!$includedir$ac_delim+oldincludedir!$oldincludedir$ac_delim+docdir!$docdir$ac_delim+infodir!$infodir$ac_delim+htmldir!$htmldir$ac_delim+dvidir!$dvidir$ac_delim+pdfdir!$pdfdir$ac_delim+psdir!$psdir$ac_delim+libdir!$libdir$ac_delim+localedir!$localedir$ac_delim+mandir!$mandir$ac_delim+DEFS!$DEFS$ac_delim+ECHO_C!$ECHO_C$ac_delim+ECHO_N!$ECHO_N$ac_delim+ECHO_T!$ECHO_T$ac_delim+LIBS!$LIBS$ac_delim+build_alias!$build_alias$ac_delim+host_alias!$host_alias$ac_delim+target_alias!$target_alias$ac_delim+PKG_CONFIG!$PKG_CONFIG$ac_delim+OPENSSL_CFLAGS!$OPENSSL_CFLAGS$ac_delim+OPENSSL_LIBS!$OPENSSL_LIBS$ac_delim+LIBOBJS!$LIBOBJS$ac_delim+LTLIBOBJS!$LTLIBOBJS$ac_delim+_ACEOF++  if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 42; then+    break+  elif $ac_last_try; then+    { { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5+echo "$as_me: error: could not make $CONFIG_STATUS" >&2;}+   { (exit 1); exit 1; }; }+  else+    ac_delim="$ac_delim!$ac_delim _$ac_delim!! "+  fi+done++ac_eof=`sed -n '/^CEOF[0-9]*$/s/CEOF/0/p' conf$$subs.sed`+if test -n "$ac_eof"; then+  ac_eof=`echo "$ac_eof" | sort -nru | sed 1q`+  ac_eof=`expr $ac_eof + 1`+fi++cat >>$CONFIG_STATUS <<_ACEOF+cat >"\$tmp/subs-1.sed" <<\CEOF$ac_eof+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b end+_ACEOF+sed '+s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g+s/^/s,@/; s/!/@,|#_!!_#|/+:n+t n+s/'"$ac_delim"'$/,g/; t+s/$/\\/; p+N; s/^.*\n//; s/[,\\&]/\\&/g; s/@/@|#_!!_#|/g; b n+' >>$CONFIG_STATUS <conf$$subs.sed+rm -f conf$$subs.sed+cat >>$CONFIG_STATUS <<_ACEOF+:end+s/|#_!!_#|//g+CEOF$ac_eof+_ACEOF+++# VPATH may cause trouble with some makes, so we remove $(srcdir),+# ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and+# trailing colons and then remove the whole line if VPATH becomes empty+# (actually we leave an empty line to preserve line numbers).+if test "x$srcdir" = x.; then+  ac_vpsub='/^[	 ]*VPATH[	 ]*=/{+s/:*\$(srcdir):*/:/+s/:*\${srcdir}:*/:/+s/:*@srcdir@:*/:/+s/^\([^=]*=[	 ]*\):*/\1/+s/:*$//+s/^[^=]*=[	 ]*$//+}'+fi++cat >>$CONFIG_STATUS <<\_ACEOF+fi # test -n "$CONFIG_FILES"+++for ac_tag in  :F $CONFIG_FILES+do+  case $ac_tag in+  :[FHLC]) ac_mode=$ac_tag; continue;;+  esac+  case $ac_mode$ac_tag in+  :[FHL]*:*);;+  :L* | :C*:*) { { echo "$as_me:$LINENO: error: Invalid tag $ac_tag." >&5+echo "$as_me: error: Invalid tag $ac_tag." >&2;}+   { (exit 1); exit 1; }; };;+  :[FH]-) ac_tag=-:-;;+  :[FH]*) ac_tag=$ac_tag:$ac_tag.in;;+  esac+  ac_save_IFS=$IFS+  IFS=:+  set x $ac_tag+  IFS=$ac_save_IFS+  shift+  ac_file=$1+  shift++  case $ac_mode in+  :L) ac_source=$1;;+  :[FH])+    ac_file_inputs=+    for ac_f+    do+      case $ac_f in+      -) ac_f="$tmp/stdin";;+      *) # Look for the file first in the build tree, then in the source tree+	 # (if the path is not absolute).  The absolute path cannot be DOS-style,+	 # because $ac_f cannot contain `:'.+	 test -f "$ac_f" ||+	   case $ac_f in+	   [\\/$]*) false;;+	   *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";;+	   esac ||+	   { { echo "$as_me:$LINENO: error: cannot find input file: $ac_f" >&5+echo "$as_me: error: cannot find input file: $ac_f" >&2;}+   { (exit 1); exit 1; }; };;+      esac+      ac_file_inputs="$ac_file_inputs $ac_f"+    done++    # Let's still pretend it is `configure' which instantiates (i.e., don't+    # use $as_me), people would be surprised to read:+    #    /* config.h.  Generated by config.status.  */+    configure_input="Generated from "`IFS=:+	  echo $* | sed 's|^[^:]*/||;s|:[^:]*/|, |g'`" by configure."+    if test x"$ac_file" != x-; then+      configure_input="$ac_file.  $configure_input"+      { echo "$as_me:$LINENO: creating $ac_file" >&5+echo "$as_me: creating $ac_file" >&6;}+    fi++    case $ac_tag in+    *:-:* | *:-) cat >"$tmp/stdin";;+    esac+    ;;+  esac++  ac_dir=`$as_dirname -- "$ac_file" ||+$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \+	 X"$ac_file" : 'X\(//\)[^/]' \| \+	 X"$ac_file" : 'X\(//\)$' \| \+	 X"$ac_file" : 'X\(/\)' \| . 2>/dev/null ||+echo X"$ac_file" |+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{+	    s//\1/+	    q+	  }+	  /^X\(\/\/\)[^/].*/{+	    s//\1/+	    q+	  }+	  /^X\(\/\/\)$/{+	    s//\1/+	    q+	  }+	  /^X\(\/\).*/{+	    s//\1/+	    q+	  }+	  s/.*/./; q'`+  { as_dir="$ac_dir"+  case $as_dir in #(+  -*) as_dir=./$as_dir;;+  esac+  test -d "$as_dir" || { $as_mkdir_p && mkdir -p "$as_dir"; } || {+    as_dirs=+    while :; do+      case $as_dir in #(+      *\'*) as_qdir=`echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #(+      *) as_qdir=$as_dir;;+      esac+      as_dirs="'$as_qdir' $as_dirs"+      as_dir=`$as_dirname -- "$as_dir" ||+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \+	 X"$as_dir" : 'X\(//\)[^/]' \| \+	 X"$as_dir" : 'X\(//\)$' \| \+	 X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||+echo X"$as_dir" |+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{+	    s//\1/+	    q+	  }+	  /^X\(\/\/\)[^/].*/{+	    s//\1/+	    q+	  }+	  /^X\(\/\/\)$/{+	    s//\1/+	    q+	  }+	  /^X\(\/\).*/{+	    s//\1/+	    q+	  }+	  s/.*/./; q'`+      test -d "$as_dir" && break+    done+    test -z "$as_dirs" || eval "mkdir $as_dirs"+  } || test -d "$as_dir" || { { echo "$as_me:$LINENO: error: cannot create directory $as_dir" >&5+echo "$as_me: error: cannot create directory $as_dir" >&2;}+   { (exit 1); exit 1; }; }; }+  ac_builddir=.++case "$ac_dir" in+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;+*)+  ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`+  # A ".." for each directory in $ac_dir_suffix.+  ac_top_builddir_sub=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,/..,g;s,/,,'`+  case $ac_top_builddir_sub in+  "") ac_top_builddir_sub=. ac_top_build_prefix= ;;+  *)  ac_top_build_prefix=$ac_top_builddir_sub/ ;;+  esac ;;+esac+ac_abs_top_builddir=$ac_pwd+ac_abs_builddir=$ac_pwd$ac_dir_suffix+# for backward compatibility:+ac_top_builddir=$ac_top_build_prefix++case $srcdir in+  .)  # We are building in place.+    ac_srcdir=.+    ac_top_srcdir=$ac_top_builddir_sub+    ac_abs_top_srcdir=$ac_pwd ;;+  [\\/]* | ?:[\\/]* )  # Absolute name.+    ac_srcdir=$srcdir$ac_dir_suffix;+    ac_top_srcdir=$srcdir+    ac_abs_top_srcdir=$srcdir ;;+  *) # Relative name.+    ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix+    ac_top_srcdir=$ac_top_build_prefix$srcdir+    ac_abs_top_srcdir=$ac_pwd/$srcdir ;;+esac+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix+++  case $ac_mode in+  :F)+  #+  # CONFIG_FILE+  #++_ACEOF++cat >>$CONFIG_STATUS <<\_ACEOF+# If the template does not know about datarootdir, expand it.+# FIXME: This hack should be removed a few years after 2.60.+ac_datarootdir_hack=; ac_datarootdir_seen=++case `sed -n '/datarootdir/ {+  p+  q+}+/@datadir@/p+/@docdir@/p+/@infodir@/p+/@localedir@/p+/@mandir@/p+' $ac_file_inputs` in+*datarootdir*) ac_datarootdir_seen=yes;;+*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*)+  { echo "$as_me:$LINENO: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5+echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;}+_ACEOF+cat >>$CONFIG_STATUS <<_ACEOF+  ac_datarootdir_hack='+  s&@datadir@&$datadir&g+  s&@docdir@&$docdir&g+  s&@infodir@&$infodir&g+  s&@localedir@&$localedir&g+  s&@mandir@&$mandir&g+    s&\\\${datarootdir}&$datarootdir&g' ;;+esac+_ACEOF++# Neutralize VPATH when `$srcdir' = `.'.+# Shell code in configure.ac might set extrasub.+# FIXME: do we really want to maintain this feature?+cat >>$CONFIG_STATUS <<_ACEOF+  sed "$ac_vpsub+$extrasub+_ACEOF+cat >>$CONFIG_STATUS <<\_ACEOF+:t+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b+s&@configure_input@&$configure_input&;t t+s&@top_builddir@&$ac_top_builddir_sub&;t t+s&@srcdir@&$ac_srcdir&;t t+s&@abs_srcdir@&$ac_abs_srcdir&;t t+s&@top_srcdir@&$ac_top_srcdir&;t t+s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t+s&@builddir@&$ac_builddir&;t t+s&@abs_builddir@&$ac_abs_builddir&;t t+s&@abs_top_builddir@&$ac_abs_top_builddir&;t t+$ac_datarootdir_hack+" $ac_file_inputs | sed -f "$tmp/subs-1.sed" >$tmp/out++test -z "$ac_datarootdir_hack$ac_datarootdir_seen" &&+  { ac_out=`sed -n '/\${datarootdir}/p' "$tmp/out"`; test -n "$ac_out"; } &&+  { ac_out=`sed -n '/^[	 ]*datarootdir[	 ]*:*=/p' "$tmp/out"`; test -z "$ac_out"; } &&+  { echo "$as_me:$LINENO: WARNING: $ac_file contains a reference to the variable \`datarootdir'+which seems to be undefined.  Please make sure it is defined." >&5+echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir'+which seems to be undefined.  Please make sure it is defined." >&2;}++  rm -f "$tmp/stdin"+  case $ac_file in+  -) cat "$tmp/out"; rm -f "$tmp/out";;+  *) rm -f "$ac_file"; mv "$tmp/out" $ac_file;;+  esac+ ;;++++  esac++done # for ac_tag+++{ (exit 0); exit 0; }+_ACEOF+chmod +x $CONFIG_STATUS+ac_clean_files=$ac_clean_files_save+++# configure is writing to config.log, and then calls config.status.+# config.status does its own redirection, appending to config.log.+# Unfortunately, on DOS this fails, as config.log is still kept open+# by configure, so config.status won't be able to write to it; its+# output is simply discarded.  So we exec the FD to /dev/null,+# effectively closing config.log, so it can be properly (re)opened and+# appended to by config.status.  When coming back to configure, we+# need to make the FD available again.+if test "$no_create" != yes; then+  ac_cs_success=:+  ac_config_status_args=+  test "$silent" = yes &&+    ac_config_status_args="$ac_config_status_args --quiet"+  exec 5>/dev/null+  $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false+  exec 5>>config.log+  # Use ||, not &&, to avoid exiting from the if with $? = 1, which+  # would make configure fail if this is the last instruction.+  $ac_cs_success || { (exit 1); exit 1; }+fi
+ configure.ac view
@@ -0,0 +1,12 @@+AC_INIT([HsOpenSSL], [], [phonohawk@ps.sakura.ne.jp])++AC_CONFIG_SRCDIR([OpenSSL/SSL.hsc])++PKG_CHECK_MODULES(+        [OPENSSL], [openssl >= 0.9.7l], [],+        [AC_MSG_ERROR([openssl >= 0.9.7l is required to build this package.])])++AC_CONFIG_FILES([+        HsOpenSSL.buildinfo+])+AC_OUTPUT
+ examples/GenRSAKey.hs view
@@ -0,0 +1,48 @@+import Control.Monad hiding (join)+import OpenSSL+import OpenSSL.BN+import OpenSSL.BIO+import OpenSSL.EVP.PKey+import OpenSSL.PEM+import OpenSSL.RSA+import System.IO+import Text.Printf++main = withOpenSSL $+       do let keyBits = 512+              keyE    = 65537++          printf "Generating RSA key-pair, nbits = %d, e = %d:\n" keyBits keyE+          +          rsa  <- generateKey keyBits keyE $ Just $ \ phase _ ->+                  do hPutChar stdout $ case phase of+                                         0 -> '.'+                                         1 -> '+'+                                         2 -> '*'+                                         3 -> '\n'+                                         n -> head $ show n+                     hFlush stdout++          printf "Done.\n"+          +          n    <- rsaN rsa+          e    <- rsaE rsa+          d    <- rsaD rsa+          p    <- rsaP rsa+          q    <- rsaQ rsa+          dmp1 <- rsaDMP1 rsa+          dmq1 <- rsaDMQ1 rsa+          iqmp <- rsaIQMP rsa++          printf "n (public modulus) = %s\n" (show n)+          printf "e (public exponent) = %s\n" (show e)+          printf "d (private exponent) = %s\n" (show d)+          printf "p (secret prime factor) = %s\n" (show p)+          printf "q (secret prime factor) = %s\n" (show q)+          printf "dmp1 (d mod (p-1)) = %s\n" (show dmp1)+          printf "dmq1 (d mod (q-1)) = %s\n" (show dmq1)+          printf "iqmp (q^-1 mod p) = %s\n" (show iqmp)++          let pkey = newPKeyRSA rsa+          writePKCS8PrivateKey pkey Nothing >>= putStr+          -- writePublicKey pkey >>= putStr
+ examples/HelloWorld.hs view
@@ -0,0 +1,43 @@+import Control.Monad+import Data.List+import Data.Maybe+import OpenSSL+import OpenSSL.BN+import OpenSSL.EVP.Cipher+import OpenSSL.EVP.Open+import OpenSSL.EVP.PKey+import OpenSSL.EVP.Seal+import OpenSSL.PEM+import OpenSSL.RSA+import Text.Printf+++main = withOpenSSL $+       do putStrLn "cipher: DES-CBC"+          des <- liftM fromJust $ getCipherByName "DES-CBC"++          putStrLn "generating RSA keypair..."+          pkey <- liftM newPKeyRSA $ generateKey 512 65537 Nothing++          let plainText = "Hello, world!"+          putStrLn ("plain text to encrypt: " ++ plainText)++          putStrLn ""++          putStrLn "encrypting..."+          (encrypted, [encKey], iv) <- seal des [pkey] plainText+          +          putStrLn ("encrypted symmetric key: " ++ binToHex encKey)+          putStrLn ("IV: " ++ binToHex iv)+          putStrLn ("encrypted message: " ++ binToHex encrypted)++          putStrLn ""++          putStrLn "decrypting..."+          let decrypted = open des encKey iv pkey encrypted++          putStrLn ("decrypted message: " ++ decrypted)+++binToHex :: String -> String+binToHex bin = concat $ intersperse ":" $ map (printf "%02x" . fromEnum) bin
+ examples/Makefile view
@@ -0,0 +1,15 @@+GHCFLAGS = -O2 -fglasgow-exts++build:+	ghc $(GHCFLAGS) --make GenRSAKey+	ghc $(GHCFLAGS) --make HelloWorld+	ghc $(GHCFLAGS) --make PKCS7++run: build+	./PKCS7+#	./HelloWorld++clean:+	rm -f HelloWorld GenRSAKey PKCS7 *.hi *.o++.PHONY: build run clean
+ examples/PKCS7.hs view
@@ -0,0 +1,38 @@+import Control.Monad+import Data.Time.Clock+import Data.Time.Calendar+import Data.Maybe+import OpenSSL+import OpenSSL.PKCS7+import OpenSSL.EVP.Cipher+import OpenSSL.EVP.PKey+import OpenSSL.PEM+import OpenSSL.RSA+import OpenSSL.X509+import OpenSSL.X509.Store++main = withOpenSSL $+       do pkey <- liftM newPKeyRSA $ generateKey 512 65537 Nothing+          cert <- genCert pkey++          pkcs7 <- pkcs7Sign cert pkey [] "Hello, world!" [Pkcs7NoCerts]++          store <- newX509Store+          addCertToStore store cert++          pkcs7Verify pkcs7 [cert] store Nothing [] >>= print+          return ()+++genCert :: PKey -> IO X509+genCert pkey+    = do x509 <- newX509+         setVersion x509 2+         setSerialNumber x509 1+         setIssuerName  x509 [("C", "JP")]+         setSubjectName x509 [("C", "JP")]+         setNotBefore x509 =<< liftM (addUTCTime (-1)) getCurrentTime+         setNotAfter  x509 =<< liftM (addUTCTime (365 * 24 * 60 * 60)) getCurrentTime+         setPublicKey x509 pkey+         signX509 x509 pkey Nothing+         return x509