{-# LINE 1 "OpenSSL/RSA.hsc" #-}
{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE EmptyDataDecls #-}
{-# LANGUAGE ForeignFunctionInterface #-}
{-# OPTIONS_HADDOCK prune #-}
module OpenSSL.RSA
(
RSAKey(..)
, RSAPubKey
, RSAKeyPair
, RSA
, RSAGenKeyCallback
, generateRSAKey
, generateRSAKey'
, rsaD
, rsaP
, rsaQ
, rsaDMP1
, rsaDMQ1
, rsaIQMP
, rsaCopyPublic
, rsaKeyPairFinalize
)
where
import Control.Monad
{-# LINE 34 "OpenSSL/RSA.hsc" #-}
import Data.Typeable
{-# LINE 37 "OpenSSL/RSA.hsc" #-}
import Foreign.C.Types (CInt(..))
{-# LINE 41 "OpenSSL/RSA.hsc" #-}
import Foreign.ForeignPtr (ForeignPtr, finalizeForeignPtr, newForeignPtr, withForeignPtr)
import Foreign.Ptr (FunPtr, Ptr, freeHaskellFunPtr, nullFunPtr, nullPtr)
import Foreign.Storable (Storable(..))
{-# LINE 47 "OpenSSL/RSA.hsc" #-}
import OpenSSL.BN
import OpenSSL.Utils
import System.IO.Unsafe (unsafePerformIO)
newtype RSAPubKey = RSAPubKey (ForeignPtr RSA)
deriving Typeable
newtype RSAKeyPair = RSAKeyPair (ForeignPtr RSA)
deriving Typeable
data RSA
class RSAKey k where
rsaSize :: k -> Int
rsaSize rsa
= unsafePerformIO $
withRSAPtr rsa $ \ rsaPtr ->
fmap fromIntegral (_size rsaPtr)
rsaN :: k -> Integer
rsaN = peekI rsa_n
rsaE :: k -> Integer
rsaE = peekI rsa_e
withRSAPtr :: k -> (Ptr RSA -> IO a) -> IO a
peekRSAPtr :: Ptr RSA -> IO (Maybe k)
absorbRSAPtr :: Ptr RSA -> IO (Maybe k)
instance RSAKey RSAPubKey where
withRSAPtr (RSAPubKey fp) = withForeignPtr fp
peekRSAPtr rsaPtr = _pubDup rsaPtr >>= absorbRSAPtr
absorbRSAPtr rsaPtr = fmap (Just . RSAPubKey) (newForeignPtr _free rsaPtr)
instance RSAKey RSAKeyPair where
withRSAPtr (RSAKeyPair fp) = withForeignPtr fp
peekRSAPtr rsaPtr
= do hasP <- hasRSAPrivateKey rsaPtr
if hasP then
_privDup rsaPtr >>= absorbRSAPtr
else
return Nothing
absorbRSAPtr rsaPtr
= do hasP <- hasRSAPrivateKey rsaPtr
if hasP then
fmap (Just . RSAKeyPair) (newForeignPtr _free rsaPtr)
else
return Nothing
hasRSAPrivateKey :: Ptr RSA -> IO Bool
hasRSAPrivateKey rsaPtr
= do d <- rsa_d rsaPtr
p <- rsa_p rsaPtr
q <- rsa_q rsaPtr
return (d /= nullPtr && p /= nullPtr && q /= nullPtr)
foreign import ccall unsafe "&RSA_free"
_free :: FunPtr (Ptr RSA -> IO ())
foreign import ccall unsafe "RSAPublicKey_dup"
_pubDup :: Ptr RSA -> IO (Ptr RSA)
foreign import ccall unsafe "RSAPrivateKey_dup"
_privDup :: Ptr RSA -> IO (Ptr RSA)
foreign import ccall unsafe "RSA_size"
_size :: Ptr RSA -> IO CInt
rsaCopyPublic :: RSAKey key => key -> IO RSAPubKey
rsaCopyPublic key = withRSAPtr key (fmap RSAPubKey . (newForeignPtr _free =<<) . _pubDup)
rsaKeyPairFinalize :: RSAKeyPair -> IO ()
rsaKeyPairFinalize (RSAKeyPair fp) = finalizeForeignPtr fp
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)
generateRSAKey :: Int
-> Int
-> Maybe RSAGenKeyCallback
-> IO RSAKeyPair
generateRSAKey nbits e Nothing
= do ptr <- _generate_key (fromIntegral nbits) (fromIntegral e) nullFunPtr nullPtr
failIfNull_ ptr
fmap RSAKeyPair (newForeignPtr _free ptr)
generateRSAKey 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
fmap RSAKeyPair (newForeignPtr _free ptr)
generateRSAKey' :: Int
-> Int
-> IO RSAKeyPair
generateRSAKey' nbits e
= generateRSAKey nbits e Nothing
rsa_n, rsa_e, rsa_d, rsa_p, rsa_q :: Ptr RSA -> IO (Ptr BIGNUM)
rsa_dmp1, rsa_dmq1, rsa_iqmp :: Ptr RSA -> IO (Ptr BIGNUM)
{-# LINE 254 "OpenSSL/RSA.hsc" #-}
rsa_n = ((\hsc_ptr -> peekByteOff hsc_ptr 32))
{-# LINE 256 "OpenSSL/RSA.hsc" #-}
rsa_e = ((\hsc_ptr -> peekByteOff hsc_ptr 40))
{-# LINE 257 "OpenSSL/RSA.hsc" #-}
rsa_d = ((\hsc_ptr -> peekByteOff hsc_ptr 48))
{-# LINE 258 "OpenSSL/RSA.hsc" #-}
rsa_p = ((\hsc_ptr -> peekByteOff hsc_ptr 56))
{-# LINE 259 "OpenSSL/RSA.hsc" #-}
rsa_q = ((\hsc_ptr -> peekByteOff hsc_ptr 64))
{-# LINE 260 "OpenSSL/RSA.hsc" #-}
rsa_dmp1 = ((\hsc_ptr -> peekByteOff hsc_ptr 72))
{-# LINE 261 "OpenSSL/RSA.hsc" #-}
rsa_dmq1 = ((\hsc_ptr -> peekByteOff hsc_ptr 80))
{-# LINE 262 "OpenSSL/RSA.hsc" #-}
rsa_iqmp = ((\hsc_ptr -> peekByteOff hsc_ptr 88))
{-# LINE 263 "OpenSSL/RSA.hsc" #-}
{-# LINE 265 "OpenSSL/RSA.hsc" #-}
peekI :: RSAKey a => (Ptr RSA -> IO (Ptr BIGNUM)) -> a -> Integer
peekI peeker rsa
= unsafePerformIO $
withRSAPtr rsa $ \ rsaPtr ->
do bn <- peeker rsaPtr
when (bn == nullPtr) $ fail "peekI: got a nullPtr"
peekBN (wrapBN bn)
peekMI :: RSAKey a => (Ptr RSA -> IO (Ptr BIGNUM)) -> a -> Maybe Integer
peekMI peeker rsa
= unsafePerformIO $
withRSAPtr rsa $ \ rsaPtr ->
do bn <- peeker rsaPtr
if bn == nullPtr then
return Nothing
else
fmap Just (peekBN (wrapBN bn))
rsaD :: RSAKeyPair -> Integer
rsaD = peekI rsa_d
rsaP :: RSAKeyPair -> Integer
rsaP = peekI rsa_p
rsaQ :: RSAKeyPair -> Integer
rsaQ = peekI rsa_q
rsaDMP1 :: RSAKeyPair -> Maybe Integer
rsaDMP1 = peekMI rsa_dmp1
rsaDMQ1 :: RSAKeyPair -> Maybe Integer
rsaDMQ1 = peekMI rsa_dmq1
rsaIQMP :: RSAKeyPair -> Maybe Integer
rsaIQMP = peekMI rsa_iqmp
instance Eq RSAPubKey where
a == b
= rsaN a == rsaN b &&
rsaE a == rsaE b
instance Eq RSAKeyPair where
a == b
= rsaN a == rsaN b &&
rsaE a == rsaE b &&
rsaD a == rsaD b &&
rsaP a == rsaP b &&
rsaQ a == rsaQ b
instance Ord RSAPubKey where
a `compare` b
| rsaN a < rsaN b = LT
| rsaN a > rsaN b = GT
| rsaE a < rsaE b = LT
| rsaE a > rsaE b = GT
| otherwise = EQ
instance Ord RSAKeyPair where
a `compare` b
| rsaN a < rsaN b = LT
| rsaN a > rsaN b = GT
| rsaE a < rsaE b = LT
| rsaE a > rsaE b = GT
| rsaD a < rsaD b = LT
| rsaD a > rsaD b = GT
| rsaP a < rsaP b = LT
| rsaP a > rsaP b = GT
| rsaQ a < rsaQ b = LT
| rsaQ a > rsaQ b = GT
| otherwise = EQ
instance Show RSAPubKey where
show a
= concat [ "RSAPubKey {"
, "rsaN = ", show (rsaN a), ", "
, "rsaE = ", show (rsaE a)
, "}"
]
instance Show RSAKeyPair where
show a
= concat [ "RSAKeyPair {"
, "rsaN = ", show (rsaN a), ", "
, "rsaE = ", show (rsaE a), ", "
, "rsaD = ", show (rsaD a), ", "
, "rsaP = ", show (rsaP a), ", "
, "rsaQ = ", show (rsaQ a)
, "}"
]