module OpenSSL.RSA
(
RSA
, RSA_
, withRSAPtr
, RSAGenKeyCallback
, generateKey
, rsaN
, rsaE
, rsaD
, rsaP
, rsaQ
, rsaDMP1
, rsaDMQ1
, rsaIQMP
)
where
import Control.Monad
import Foreign
import Foreign.C
import OpenSSL.BN
import OpenSSL.Utils
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
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 :: CInt -> CInt -> FunPtr RSAGenKeyCallback' -> Ptr a -> IO (Ptr RSA_)
generateKey :: Int
-> Int
-> Maybe RSAGenKeyCallback
-> IO RSA
generateKey nbits e Nothing
= do ptr <- _generate_key (fromIntegral nbits) (fromIntegral 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 (fromIntegral nbits) (fromIntegral e) cbPtr nullPtr
freeHaskellFunPtr cbPtr
failIfNull ptr
newForeignPtr _free ptr >>= return . RSA
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 (wrapBN 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 (wrapBN bn) >>= return . Just
rsaN :: RSA -> IO Integer
rsaN = peekRSAPublic ((\hsc_ptr -> peekByteOff hsc_ptr 16))
rsaE :: RSA -> IO Integer
rsaE = peekRSAPublic ((\hsc_ptr -> peekByteOff hsc_ptr 20))
rsaD :: RSA -> IO (Maybe Integer)
rsaD = peekRSAPrivate ((\hsc_ptr -> peekByteOff hsc_ptr 24))
rsaP :: RSA -> IO (Maybe Integer)
rsaP = peekRSAPrivate ((\hsc_ptr -> peekByteOff hsc_ptr 28))
rsaQ :: RSA -> IO (Maybe Integer)
rsaQ = peekRSAPrivate ((\hsc_ptr -> peekByteOff hsc_ptr 32))
rsaDMP1 :: RSA -> IO (Maybe Integer)
rsaDMP1 = peekRSAPrivate ((\hsc_ptr -> peekByteOff hsc_ptr 36))
rsaDMQ1 :: RSA -> IO (Maybe Integer)
rsaDMQ1 = peekRSAPrivate ((\hsc_ptr -> peekByteOff hsc_ptr 40))
rsaIQMP :: RSA -> IO (Maybe Integer)
rsaIQMP = peekRSAPrivate ((\hsc_ptr -> peekByteOff hsc_ptr 44))