module OpenSSL.EVP.Seal
( seal
, sealBS
, sealLBS
)
where
import qualified Data.ByteString.Char8 as B8
import qualified Data.ByteString.Lazy.Char8 as L8
import Foreign
import Foreign.C
import OpenSSL.EVP.Cipher hiding (cipher)
import OpenSSL.EVP.PKey
import OpenSSL.EVP.Internal
import OpenSSL.Utils
foreign import ccall unsafe "EVP_SealInit"
_SealInit :: Ptr EVP_CIPHER_CTX
-> Cipher
-> Ptr (Ptr CChar)
-> Ptr CInt
-> CString
-> Ptr (Ptr EVP_PKEY)
-> CInt
-> IO CInt
sealInit :: Cipher -> [SomePublicKey] -> IO (CipherCtx, [String], String)
sealInit _ []
= fail "sealInit: at least one public key is required"
sealInit cipher pubKeys
= do ctx <- newCipherCtx
encKeyBufs <- mapM mallocEncKeyBuf pubKeys
encKeyBufsPtr <- newArray encKeyBufs
encKeyBufsLenPtr <- mallocArray nKeys
ivPtr <- mallocArray (cipherIvLength cipher)
pkeys <- mapM toPKey pubKeys
pubKeysPtr <- newArray $ map unsafePKeyToPtr pkeys
let cleanup = do mapM_ free encKeyBufs
free encKeyBufsPtr
free encKeyBufsLenPtr
free ivPtr
free pubKeysPtr
mapM_ touchPKey pkeys
ret <- withCipherCtxPtr ctx $ \ ctxPtr ->
_SealInit ctxPtr cipher encKeyBufsPtr encKeyBufsLenPtr ivPtr pubKeysPtr (fromIntegral nKeys)
if ret == 0 then
cleanup >> raiseOpenSSLError
else
do encKeysLen <- peekArray nKeys encKeyBufsLenPtr
encKeys <- mapM peekCStringCLen $ zip encKeyBufs encKeysLen
iv <- peekCString ivPtr
cleanup
return (ctx, encKeys, iv)
where
nKeys :: Int
nKeys = length pubKeys
mallocEncKeyBuf :: (PKey k, Storable a) => k -> IO (Ptr a)
mallocEncKeyBuf = mallocArray . pkeySize
seal :: Cipher
-> [SomePublicKey]
-> String
-> IO (String, [String], String)
seal cipher pubKeys input
= do (output, encKeys, iv) <- sealLBS cipher pubKeys $ L8.pack input
return (L8.unpack output, encKeys, iv)
sealBS :: Cipher
-> [SomePublicKey]
-> B8.ByteString
-> IO (B8.ByteString, [String], String)
sealBS cipher pubKeys input
= do (ctx, encKeys, iv) <- sealInit cipher pubKeys
output <- cipherStrictly ctx input
return (output, encKeys, iv)
sealLBS :: Cipher
-> [SomePublicKey]
-> L8.ByteString
-> IO (L8.ByteString, [String], String)
sealLBS cipher pubKeys input
= do (ctx, encKeys, iv) <- sealInit cipher pubKeys
output <- cipherLazily ctx input
return (output, encKeys, iv)