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 +29/−0
- HsOpenSSL.buildinfo.in +2/−0
- HsOpenSSL.cabal +63/−0
- OpenSSL.hsc +78/−0
- OpenSSL/ASN1.hsc +166/−0
- OpenSSL/BIO.hsc +477/−0
- OpenSSL/BN.hsc +64/−0
- OpenSSL/ERR.hsc +37/−0
- OpenSSL/EVP/Base64.hsc +138/−0
- OpenSSL/EVP/Cipher.hsc +221/−0
- OpenSSL/EVP/Digest.hsc +175/−0
- OpenSSL/EVP/Open.hsc +79/−0
- OpenSSL/EVP/PKey.hsc +102/−0
- OpenSSL/EVP/Seal.hsc +134/−0
- OpenSSL/EVP/Sign.hsc +67/−0
- OpenSSL/EVP/Verify.hsc +76/−0
- OpenSSL/Objects.hsc +69/−0
- OpenSSL/PEM.hsc +459/−0
- OpenSSL/PKCS7.hsc +419/−0
- OpenSSL/RSA.hsc +152/−0
- OpenSSL/SSL.hsc +15/−0
- OpenSSL/Stack.hsc +64/−0
- OpenSSL/Utils.hs +38/−0
- OpenSSL/X509.hsc +372/−0
- OpenSSL/X509/Name.hsc +86/−0
- OpenSSL/X509/Request.hsc +249/−0
- OpenSSL/X509/Revocation.hsc +324/−0
- OpenSSL/X509/Store.hsc +71/−0
- Setup.hs +4/−0
- cbits/HsOpenSSL.c +183/−0
- cbits/HsOpenSSL.h +63/−0
- configure +2794/−0
- configure.ac +12/−0
- examples/GenRSAKey.hs +48/−0
- examples/HelloWorld.hs +43/−0
- examples/Makefile +15/−0
- examples/PKCS7.hs +38/−0
+ 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