module OpenSSL.EVP.PKey
( PublicKey(..)
, KeyPair(..)
, SomePublicKey
, SomeKeyPair
)
where
import Data.Typeable
import Data.Maybe
import Foreign
import Foreign.C
import OpenSSL.DSA
import OpenSSL.EVP.Digest
import OpenSSL.EVP.Internal
import OpenSSL.RSA
import OpenSSL.Utils
class (Eq k, Typeable k, PKey k) => PublicKey k where
fromPublicKey :: k -> SomePublicKey
fromPublicKey = SomePublicKey
toPublicKey :: SomePublicKey -> Maybe k
toPublicKey (SomePublicKey pk) = cast pk
class PublicKey a => KeyPair a where
fromKeyPair :: a -> SomeKeyPair
fromKeyPair = SomeKeyPair
toKeyPair :: SomeKeyPair -> Maybe a
toKeyPair (SomeKeyPair pk) = cast pk
getType :: Ptr EVP_PKEY -> IO CInt
getType = ((\hsc_ptr -> peekByteOff hsc_ptr 0))
withConcretePubKey :: VaguePKey -> (forall k. PublicKey k => k -> IO a) -> IO a
withConcretePubKey pk f
= withPKeyPtr pk $ \ pkeyPtr ->
do pkeyType <- getType pkeyPtr
case pkeyType of
(6)
-> do rsaPtr <- _get1_RSA pkeyPtr
Just rsa <- absorbRSAPtr rsaPtr
f (rsa :: RSAPubKey)
(116)
-> do dsaPtr <- _get1_DSA pkeyPtr
Just dsa <- absorbDSAPtr dsaPtr
f (dsa :: DSAPubKey)
_ -> fail ("withConcretePubKey: unsupported EVP_PKEY type: " ++ show pkeyType)
withConcreteKeyPair :: VaguePKey -> (forall k. KeyPair k => k -> IO a) -> IO a
withConcreteKeyPair pk f
= withPKeyPtr pk $ \ pkeyPtr ->
do pkeyType <- getType pkeyPtr
case pkeyType of
(6)
-> do rsaPtr <- _get1_RSA pkeyPtr
Just rsa <- absorbRSAPtr rsaPtr
f (rsa :: RSAKeyPair)
(116)
-> do dsaPtr <- _get1_DSA pkeyPtr
Just dsa <- absorbDSAPtr dsaPtr
f (dsa :: DSAKeyPair)
_ -> fail ("withConcreteKeyPair: unsupported EVP_PKEY type: " ++ show pkeyType)
data SomePublicKey = forall k. PublicKey k => SomePublicKey !k
deriving Typeable
instance Eq SomePublicKey where
(SomePublicKey a) == (SomePublicKey b)
= case cast b of
Just c -> a == c
Nothing -> False
instance PublicKey SomePublicKey where
fromPublicKey = id
toPublicKey = Just
instance PKey SomePublicKey where
toPKey (SomePublicKey k) = toPKey k
pkeySize (SomePublicKey k) = pkeySize k
pkeyDefaultMD (SomePublicKey k) = pkeyDefaultMD k
fromPKey pk
= withConcretePubKey pk (return . Just . SomePublicKey)
data SomeKeyPair = forall k. KeyPair k => SomeKeyPair !k
deriving Typeable
instance Eq SomeKeyPair where
(SomeKeyPair a) == (SomeKeyPair b)
= case cast b of
Just c -> a == c
Nothing -> False
instance PublicKey SomeKeyPair where
fromPublicKey (SomeKeyPair k)
= SomePublicKey k
toPublicKey _ = Nothing
instance KeyPair SomeKeyPair where
fromKeyPair = id
toKeyPair = Just
instance PKey SomeKeyPair where
toPKey (SomeKeyPair k) = toPKey k
pkeySize (SomeKeyPair k) = pkeySize k
pkeyDefaultMD (SomeKeyPair k) = pkeyDefaultMD k
fromPKey pk
= withConcreteKeyPair pk (return . Just . SomeKeyPair)
foreign import ccall unsafe "EVP_PKEY_get1_RSA"
_get1_RSA :: Ptr EVP_PKEY -> IO (Ptr RSA)
foreign import ccall unsafe "EVP_PKEY_set1_RSA"
_set1_RSA :: Ptr EVP_PKEY -> Ptr RSA -> IO CInt
rsaToPKey :: RSAKey k => k -> IO VaguePKey
rsaToPKey rsa
= withRSAPtr rsa $ \rsaPtr ->
createPKey $ \pkeyPtr ->
_set1_RSA pkeyPtr rsaPtr >>= failIf_ (/= 1)
rsaFromPKey :: RSAKey k => VaguePKey -> IO (Maybe k)
rsaFromPKey pk
= withPKeyPtr pk $ \ pkeyPtr ->
do pkeyType <- getType pkeyPtr
case pkeyType of
(6)
-> _get1_RSA pkeyPtr >>= absorbRSAPtr
_ -> return Nothing
instance PublicKey RSAPubKey
instance PKey RSAPubKey where
toPKey = rsaToPKey
fromPKey = rsaFromPKey
pkeySize = rsaSize
pkeyDefaultMD _ = return . fromJust =<< getDigestByName "sha1"
instance KeyPair RSAKeyPair
instance PublicKey RSAKeyPair
instance PKey RSAKeyPair where
toPKey = rsaToPKey
fromPKey = rsaFromPKey
pkeySize = rsaSize
pkeyDefaultMD _ = return . fromJust =<< getDigestByName "sha1"
foreign import ccall unsafe "EVP_PKEY_get1_DSA"
_get1_DSA :: Ptr EVP_PKEY -> IO (Ptr DSA)
foreign import ccall unsafe "EVP_PKEY_set1_DSA"
_set1_DSA :: Ptr EVP_PKEY -> Ptr DSA -> IO CInt
dsaToPKey :: DSAKey k => k -> IO VaguePKey
dsaToPKey dsa
= withDSAPtr dsa $ \dsaPtr ->
createPKey $ \pkeyPtr ->
_set1_DSA pkeyPtr dsaPtr >>= failIf_ (/= 1)
dsaFromPKey :: DSAKey k => VaguePKey -> IO (Maybe k)
dsaFromPKey pk
= withPKeyPtr pk $ \ pkeyPtr ->
do pkeyType <- getType pkeyPtr
case pkeyType of
(116)
-> _get1_DSA pkeyPtr >>= absorbDSAPtr
_ -> return Nothing
instance PublicKey DSAPubKey
instance PKey DSAPubKey where
toPKey = dsaToPKey
fromPKey = dsaFromPKey
pkeySize = dsaSize
pkeyDefaultMD _ = return . fromJust =<< getDigestByName "dss1"
instance KeyPair DSAKeyPair
instance PublicKey DSAKeyPair
instance PKey DSAKeyPair where
toPKey = dsaToPKey
fromPKey = dsaFromPKey
pkeySize = dsaSize
pkeyDefaultMD _ = return . fromJust =<< getDigestByName "dss1"