Skip to content
This repository has been archived by the owner on Jan 18, 2020. It is now read-only.

Commit

Permalink
I think I have entirely written the document.
Browse files Browse the repository at this point in the history
darcs-hash:20070704165813-62b54-9f54272f65ceafd80add86cb0be18b6d6cc59065.gz
  • Loading branch information
depressed-pho committed Jul 4, 2007
1 parent 2fb4c2a commit 2e1ce26
Show file tree
Hide file tree
Showing 21 changed files with 937 additions and 377 deletions.
17 changes: 6 additions & 11 deletions OpenSSL.hsc
Expand Up @@ -22,8 +22,8 @@
-- [/Key generation of DSA and Diffie-Hellman algorithms/] Only RSA
-- keys can currently be generated.
--
-- [/X.509 certificate handling/] No operations related to X.509 are
-- currently supported. They should be supported in the future.
-- [/X.509 v3 extension handling/] It shoule be supported in the
-- future.
--
-- [/HMAC message authentication/]
--
Expand All @@ -33,21 +33,16 @@
-- [/pseudo-random number generator/] rand(3) functionalities are
-- uncovered, but OpenSSL works very well by default.
--
-- [/API to ASN.1, PKCS\#7 and PKCS\#12 functionalities/] They
-- should be covered someday, but there seems no documents for those
-- APIs.
-- [/API to PKCS\#12 functionality/] It should be covered someday.
--
-- [/BIO/] BIO isn't needed because we are Haskell hackers.
-- [/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?
--
-- [/bn(3), buffer(3), lhash(3), objects(3), stack(3) and txt_db(3)/]
-- These internal functions are rarely used by application
-- programmers.
--
-- So if you find out some features you want aren't supported, you
-- must write your own patch. Happy hacking.
-- must write your own patch (then please. Happy hacking.

#include "HsOpenSSL.h"

Expand Down
4 changes: 4 additions & 0 deletions OpenSSL/ASN1.hsc
@@ -1,5 +1,9 @@
{- -*- haskell -*- -}

-- #hide

#include "HsOpenSSL.h"

module OpenSSL.ASN1
( ASN1_OBJECT
, obj2nid
Expand Down
4 changes: 2 additions & 2 deletions OpenSSL/BIO.hsc
Expand Up @@ -90,11 +90,11 @@ import System.IO.Unsafe

{- bio ---------------------------------------------------------------------- -}

data BIO_METHOD = BIO_METHOD
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_ = BIO_
data BIO_

foreign import ccall unsafe "BIO_new"
_new :: Ptr BIO_METHOD -> IO (Ptr BIO_)
Expand Down
26 changes: 20 additions & 6 deletions OpenSSL/EVP/Base64.hsc
@@ -1,10 +1,16 @@
{- -*- haskell -*- -}

-- |An interface to Base64 codec.

#include "HsOpenSSL.h"

module OpenSSL.EVP.Base64
( encodeBase64
( -- * Encoding
encodeBase64
, encodeBase64BS
, encodeBase64LBS

-- * Decoding
, decodeBase64
, decodeBase64BS
, decodeBase64LBS
Expand Down Expand Up @@ -53,14 +59,19 @@ encodeBlock inBS
inputLen = B.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
Expand Down Expand Up @@ -98,15 +109,18 @@ decodeBlock inBS
createAndTrim (B.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
Expand Down
116 changes: 66 additions & 50 deletions OpenSSL/EVP/Cipher.hsc
@@ -1,17 +1,23 @@
{- -*- haskell -*- -}

-- #prune

-- |An interface to symmetric cipher algorithms.

#include "HsOpenSSL.h"

module OpenSSL.EVP.Cipher
( EvpCipher
, EVP_CIPHER
, withCipherPtr
( Cipher
, EVP_CIPHER -- private
, withCipherPtr -- private

, getCipherByName
, getCipherNames

, cipherIvLength -- private

, EvpCipherCtx
, EVP_CIPHER_CTX
, CipherCtx -- private
, EVP_CIPHER_CTX -- private
, newCtx -- private
, withCipherCtxPtr -- private

Expand Down Expand Up @@ -40,8 +46,10 @@ import System.IO.Unsafe

{- EVP_CIPHER ---------------------------------------------------------------- -}

newtype EvpCipher = EvpCipher (Ptr EVP_CIPHER)
data EVP_CIPHER = 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"
Expand All @@ -52,32 +60,35 @@ foreign import ccall unsafe "HsOpenSSL_EVP_CIPHER_iv_length"
_iv_length :: Ptr EVP_CIPHER -> Int


withCipherPtr :: EvpCipher -> (Ptr EVP_CIPHER -> IO a) -> IO a
withCipherPtr (EvpCipher cipher) f = f cipher

withCipherPtr :: Cipher -> (Ptr EVP_CIPHER -> IO a) -> IO a
withCipherPtr (Cipher cipher) f = f cipher

getCipherByName :: String -> IO (Maybe EvpCipher)
-- |@'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 $ EvpCipher ptr

return $ Just $ Cipher ptr

-- |@'getCipherNames'@ returns a list of name of symmetric cipher
-- algorithms.
getCipherNames :: IO [String]
getCipherNames = getObjNames CipherMethodType True


cipherIvLength :: EvpCipher -> Int
cipherIvLength (EvpCipher cipher) = _iv_length cipher
cipherIvLength :: Cipher -> Int
cipherIvLength (Cipher cipher) = _iv_length cipher


{- EVP_CIPHER_CTX ------------------------------------------------------------ -}

newtype EvpCipherCtx = EvpCipherCtx (ForeignPtr EVP_CIPHER_CTX)
data EVP_CIPHER_CTX = EVP_CIPHER_CTX
newtype CipherCtx = CipherCtx (ForeignPtr EVP_CIPHER_CTX)
data EVP_CIPHER_CTX


foreign import ccall unsafe "EVP_CIPHER_CTX_init"
Expand All @@ -90,22 +101,22 @@ foreign import ccall unsafe "HsOpenSSL_EVP_CIPHER_CTX_block_size"
_ctx_block_size :: Ptr EVP_CIPHER_CTX -> Int


newCtx :: IO EvpCipherCtx
newCtx :: IO CipherCtx
newCtx = do ctx <- mallocForeignPtrBytes (#size EVP_CIPHER_CTX)
withForeignPtr ctx $ \ ctxPtr ->
_ctx_init ctxPtr
addForeignPtrFinalizer _ctx_cleanup ctx
return $ EvpCipherCtx ctx
return $ CipherCtx ctx


withCipherCtxPtr :: EvpCipherCtx -> (Ptr EVP_CIPHER_CTX -> IO a) -> IO a
withCipherCtxPtr (EvpCipherCtx ctx) = withForeignPtr ctx
withCipherCtxPtr :: CipherCtx -> (Ptr EVP_CIPHER_CTX -> IO a) -> IO a
withCipherCtxPtr (CipherCtx ctx) = withForeignPtr ctx


{- encrypt/decrypt ----------------------------------------------------------- -}

data CryptoMode = Encrypt
| Decrypt
-- |@CryptoMode@ represents instruction to 'cipher' and such like.
data CryptoMode = Encrypt | Decrypt


foreign import ccall unsafe "EVP_CipherInit"
Expand All @@ -123,8 +134,8 @@ cryptoModeToInt Encrypt = 1
cryptoModeToInt Decrypt = 0


cipherInit :: EvpCipher -> String -> String -> CryptoMode -> IO EvpCipherCtx
cipherInit (EvpCipher c) key iv mode
cipherInit :: Cipher -> String -> String -> CryptoMode -> IO CipherCtx
cipherInit (Cipher c) key iv mode
= do ctx <- newCtx
withCipherCtxPtr ctx $ \ ctxPtr ->
withCString key $ \ keyPtr ->
Expand All @@ -134,7 +145,7 @@ cipherInit (EvpCipher c) key iv mode
return ctx


cipherUpdateBS :: EvpCipherCtx -> ByteString -> IO ByteString
cipherUpdateBS :: CipherCtx -> ByteString -> IO ByteString
cipherUpdateBS ctx inBS
= withCipherCtxPtr ctx $ \ ctxPtr ->
unsafeUseAsCStringLen inBS $ \ (inBuf, inLen) ->
Expand All @@ -145,7 +156,7 @@ cipherUpdateBS ctx inBS
>> peek outLenPtr


cipherFinalBS :: EvpCipherCtx -> IO ByteString
cipherFinalBS :: CipherCtx -> IO ByteString
cipherFinalBS ctx
= withCipherCtxPtr ctx $ \ ctxPtr ->
createAndTrim (_ctx_block_size ctxPtr) $ \ outBuf ->
Expand All @@ -154,47 +165,52 @@ cipherFinalBS ctx
>>= failIf (/= 1)
>> peek outLenPtr


cipher :: EvpCipher
-> String
-> String
-> CryptoMode
-> String
-> IO String
-- |@'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 :: EvpCipher
-> String
-> String
-> CryptoMode
-> ByteString
-> IO ByteString
-- |@'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 :: EvpCipher
-> String
-> String
-> CryptoMode
-> LazyByteString
-> IO LazyByteString
-- |@'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 :: EvpCipherCtx -> ByteString -> IO ByteString
cipherStrictly :: CipherCtx -> ByteString -> IO ByteString
cipherStrictly ctx input
= do output' <- cipherUpdateBS ctx input
output'' <- cipherFinalBS ctx
return $ B.append output' output''


cipherLazily :: EvpCipherCtx -> LazyByteString -> IO LazyByteString
cipherLazily :: CipherCtx -> LazyByteString -> IO LazyByteString

cipherLazily ctx (LPS [])
= cipherFinalBS ctx >>= \ bs -> (return . LPS) [bs]
Expand Down

0 comments on commit 2e1ce26

Please sign in to comment.