module Network.GnuTLS.GnuTLS (-- * Enumerations CipherAlgorithm(..), KxAlgorithm(..), ParamsType(..), CredentialsType(..), MacAlgorithm(..), DigestAlgorithm(..), CompressionMethod(..), ConnectionEnd(..), AlertLevel(..), AlertDescription(..), HandshakeDescription(..), CertificateStatus(..), CertificateRequest(..), CloseRequest(..), Protocol(..), CertificateType(..), X509CertificateFormat(..), PkAlgorithm(..), SignAlgorithm(..), -- * Types Session, DH, RSA, AnonymousServerCredentials, AnonymousClientCredentials, Server, Client, Transport, CertificateCredentials,Datum(..), -- * Priority SetPriority(..), setDefaultPriority, setDefaultExportPriority, -- * Credentials SetCredentials(..), Clear(..), -- * Creating connections tlsClient, tlsServer, -- * Session Accessors priorities, credentials, dhPrimeBits, transport, handle, clientCert, #ifdef NETWORK_ALT sock, #endif -- * Managing connection handshake, rehandshake, bye, setMaxHandshakePacketLength, -- * Querying connection attributes serverWantedAuth, verifyPeer, isResumed, getAlert, getCipher, getKx, getMac, getCompression, getCertificateType, getProtocol, getCredentialsType, #ifndef COMPAT_GNUTLS_1_0 getServerCredentialsType, getClientCredentialsType, #endif getPeersCertificatesRaw, -- * Sending and receiving data tlsSend, tlsSendString, tlsRecv, tlsRecvString, tlsCheckPending, -- * Certificate functions certificateCredentials, freeKeys, freeCas, freeCaNames, freeCrls, certificateTrustFile, certificateCrlFile, certificateKeyFile, -- * Miscellaneous anonymousServerCredentials, anonymousClientCredentials, SetDHParams(..), CredParameter(..), newDH, newRSA,cipherKeySize,cipherSuiteName, version, gnutlsGlobalInit ) where import Control.Concurrent import Data.Bits((.&.), (.|.)) import Data.IORef(newIORef, readIORef) import Foreign import Foreign.C import qualified Foreign.Concurrent as FC import Foreign.Ptr import System.IO import System.IO.Unsafe import Network.GnuTLS.Attributes import Network.GnuTLS.Internals import Network.GnuTLS.RefCount #ifdef NETWORK_ALT import Network.Alt #endif #include {#context prefix = "gnutls" #} -------------------------------------------------------------------------------- ------------------------------ Types --------------------------------------- -------------------------------------------------------------------------------- data DH = DH (ForeignPtr ())! RefCount data RSA = RSA (ForeignPtr ())! RefCount data AnonymousServerCredentials = ASC (ForeignPtr ())! RefCount data AnonymousClientCredentials = ACC (ForeignPtr ())! RefCount data CertificateCredentials = CC (ForeignPtr ())! RefCount data Server data Client type Transport = Ptr () -> Int -> Ptr CInt -> IO Int withDH (DH fp _) = withForeignPtr fp withRSA (RSA fp _) = withForeignPtr fp withAnonymousServerCredentials (ASC fp _) = withForeignPtr fp withAnonymousClientCredentials (ACC fp _) = withForeignPtr fp withCertificateCredentials (CC fp _) = withForeignPtr fp -------------------------------------------------------------------------------- ------------------------- Show Functions ----------------------------------- -------------------------------------------------------------------------------- instance Show AlertDescription where show a = unsafePerformIO $ gnutlsAlertGetName a {#fun unsafe gnutls_alert_get_name as ^ {enumCInt `AlertDescription'} -> `String' safePeekCString* #} instance Show CipherAlgorithm where show a = unsafePerformIO $ gnutlsCipherGetName a {#fun unsafe gnutls_cipher_get_name as ^ {enumCInt `CipherAlgorithm'} -> `String' safePeekCString* #} instance Show MacAlgorithm where show a = unsafePerformIO $ gnutlsMacGetName a {#fun unsafe gnutls_mac_get_name as ^ {enumCInt `MacAlgorithm'} -> `String' safePeekCString* #} instance Show CompressionMethod where show a = unsafePerformIO $ gnutlsCompressionGetName a {#fun unsafe gnutls_compression_get_name as ^ {enumCInt `CompressionMethod'} -> `String' safePeekCString* #} instance Show KxAlgorithm where show a = unsafePerformIO $ gnutlsKxGetName a {#fun unsafe gnutls_kx_get_name as ^ {enumCInt `KxAlgorithm'} -> `String' safePeekCString* #} instance Show CertificateType where show a = unsafePerformIO $ gnutlsCertificateTypeGetName a {#fun unsafe gnutls_certificate_type_get_name as ^ {enumCInt `CertificateType'} -> `String' safePeekCString* #} instance Show Protocol where show a = unsafePerformIO $ gnutlsProtocolGetName a {#fun unsafe gnutls_protocol_get_name as ^ {enumCInt `Protocol'} -> `String' safePeekCString* #} instance Show PkAlgorithm where show a = unsafePerformIO $ gnutlsPkAlgorithmGetName a {#fun unsafe gnutls_pk_algorithm_get_name as ^ {enumCInt `PkAlgorithm'} -> `String' safePeekCString* #} instance Show SignAlgorithm where show a = unsafePerformIO $ gnutlsSignAlgorithmGetName a {#fun unsafe gnutls_sign_algorithm_get_name as ^ {enumCInt `SignAlgorithm'} -> `String' safePeekCString* #} -------------------------------------------------------------------------------- -------------------------- Set Priority ------------------------------------ -------------------------------------------------------------------------------- setpwrap :: Enum e => (Ptr () -> Ptr CInt -> IO CInt) -> Session t -> [e] -> IO () setpwrap comp s x = do withEnumList0 x $ \e -> do withSession s $ \p -> do comp p e >>= throwGnutlsIf -- | Set the priority of the specified category. -- On servers this means the set of acceptable values, -- on clients it sets the priorities. class SetPriority a where setPriority :: Session t -> [a] -> IO () instance SetPriority CipherAlgorithm where setPriority = setpwrap {#call unsafe gnutls_cipher_set_priority #} instance SetPriority MacAlgorithm where setPriority = setpwrap {#call unsafe gnutls_mac_set_priority #} instance SetPriority CompressionMethod where setPriority = setpwrap {#call unsafe gnutls_compression_set_priority #} instance SetPriority KxAlgorithm where setPriority = setpwrap {#call unsafe gnutls_kx_set_priority #} instance SetPriority Protocol where setPriority = setpwrap {#call unsafe gnutls_protocol_set_priority #} instance SetPriority CertificateType where setPriority = setpwrap {#call unsafe gnutls_certificate_type_set_priority #} -- | Set default priorities. This is called whenever a new 'Session' is created to -- ensure sensible defaults. {#fun gnutls_set_default_priority as setDefaultPriority {withSession* `Session t'} -> `()' #} -- | Set default priorities conforming with various export regulations. -- /Includes weak algorithms./ {#fun gnutls_set_default_export_priority as setDefaultExportPriority {withSession* `Session t'} -> `()' #} -------------------------------------------------------------------------------- ------------------------ Setting Credentials ------------------------------- -------------------------------------------------------------------------------- -- | Set the credentials associated with a session. class SetCredentials st a where setCredentials :: Session st -> a -> IO () instance SetCredentials st a => SetCredentials st (IO a) where setCredentials s c = setCredentials s =<< c instance SetCredentials Server AnonymousServerCredentials where setCredentials s (ASC a rc) = setcred_ s CrdAnon (castForeignPtr a) instance SetCredentials Client AnonymousClientCredentials where setCredentials s (ACC a rc) = setcred_ s CrdAnon (castForeignPtr a) instance SetCredentials t CertificateCredentials where setCredentials s (CC a rc) = setcred_ s CrdCertificate (castForeignPtr a) setcred_ :: Session t -> CredentialsType -> ForeignPtr a -> IO () setcred_ (Session sfp refc) ct fp = do withForeignPtr sfp $ \sptr -> do withForeignPtr fp $ \dptr -> do {#call gnutls_credentials_set #} sptr (enumCInt ct) (castPtr dptr) >>= throwGnutlsIf addRefFinalizer refc (touchForeignPtr fp) -- | Used to clear all credentials associated with a session. data Clear = Clear instance SetCredentials t Clear where setCredentials s _ = withSession s (\s -> {#call gnutls_credentials_clear #} s >> return ()) -------------------------------------------------------------------------------- --------------------------- Session Creation ------------------------------- -------------------------------------------------------------------------------- tlsClient :: [AttrOp (Session Client)] -> IO (Session Client) tlsClient p = do s <- newSession Client set s p return s tlsServer :: [AttrOp (Session Server)] -> IO (Session Server) tlsServer p = do s <- newSession Server set s p return s newSession :: ConnectionEnd -> IO (Session t) newSession ce = gnutlsGlobalInit >> alloca (\err -> do let efun b l e = putStrLn "TLS pull/push functions not set" >> return 0 ef1 <- newStablePtr efun ef2 <- newStablePtr efun sp <- init_session_wrap (enumCInt ce) ef1 ef2 err peek err >>= throwGnutlsIf rc <- newRefCount (replace_transport_stable_ptrs sp stableNull stableNull >> gnutls_deinit sp) ps <- FC.newForeignPtr sp (freeRef rc) return $ Session ps rc) stableNull = castPtrToStablePtr nullPtr foreign import ccall unsafe "TLS.h gnutls_init" gnutls_init :: Ptr (Ptr ()) -> CInt -> IO CInt foreign import ccall unsafe "TLS.h gnutls_deinit" gnutls_deinit :: Ptr () -> IO () foreign import ccall unsafe "TLS.h init_session_wrap" init_session_wrap :: CInt -> StablePtr Transport -> StablePtr Transport -> Ptr CInt -> IO (Ptr ()) #c #ifdef COMPAT_GNUTLS_1_0 typedef gnutls_transport_ptr gnutls_transport_ptr_t; typedef gnutls_connection_end gnutls_connection_end_t; typedef gnutls_session gnutls_session_t; typedef gnutls_dh_params gnutls_dh_params_t; typedef gnutls_rsa_params gnutls_rsa_params_t; typedef gnutls_anon_server_credentials gnutls_anon_server_credentials_t; typedef gnutls_anon_client_credentials gnutls_anon_client_credentials_t; typedef gnutls_certificate_credentials gnutls_certificate_credentials_t; #endif gnutls_session_t init_session_wrap(gnutls_connection_end_t con_end, void *sptr1, void *sptr2, int *err); #endc -------------------------------------------------------------------------------- ------------------------- Session Accessors -------------------------------- -------------------------------------------------------------------------------- priorities :: SetPriority a => WriteAttr (Session t) [a] priorities = writeAttr setPriority credentials :: SetCredentials t a => WriteAttr (Session t) a credentials = writeAttr setCredentials dhPrimeBits :: ReadWriteAttr (Session t) Int Int dhPrimeBits = newAttr get set where get s = withSession s {#call gnutls_dh_get_prime_bits #} >>= return . fromIntegral set s v = withSession s (\sp -> {#call gnutls_dh_set_prime_bits #} sp (fromIntegral v)) transport :: ReadWriteAttr (Session t) (Transport,Transport) (Transport,Transport) transport = newAttr gnutls_transport_get_ptr2 set where set s (a,b) = do a' <- newStablePtr a b' <- newStablePtr b withSession s $ \sp -> replace_transport_stable_ptrs sp a' b' {#fun unsafe gnutls_transport_get_ptr2 {withSession* `Session t', alloca- `Transport' ptrDeS*, alloca- `Transport' ptrDeS*} -> `()' #} foreign import ccall "replace_transport_stable_ptrs" replace_transport_stable_ptrs :: Ptr () -> StablePtr Transport -> StablePtr Transport -> IO () #c void replace_transport_stable_ptrs(gnutls_session_t session, void *p1, void *p2); #endc #ifdef NETWORK_ALT sock :: WriteAttr (Session t) Socket sock = writeAttr ss where rf sfd buf len err = recv sfd buf len `catch` ef err sf sfd buf len err = send sfd buf len `catch` ef err ef err _ = do (Errno iv) <- getErrno; poke err iv; return (-1) ss (Session sfp sr) sfd = do rf' <- newStablePtr $ rf sfd sf' <- newStablePtr $ sf sfd withForeignPtr sfp $ \p -> replace_transport_stable_ptrs p rf' sf' addRefFinalizer sr (close sfd) #endif /* NETWORK_ALT */ handle :: WriteAttr (Session t) Handle handle = writeAttr ss where rf hdl buf len err = (hGetBuf hdl buf (fromIntegral len)) `catch` ef err sf hdl buf len err = (hPutBuf hdl buf (fromIntegral len) >> return len) `catch` ef err ef err _ = do (Errno iv) <- getErrno; poke err iv; return (-1) ss (Session sfp sr) hdl = do rf' <- newStablePtr $ rf hdl sf' <- newStablePtr $ sf hdl hSetBuffering hdl NoBuffering withForeignPtr sfp $ \p -> replace_transport_stable_ptrs p rf' sf' addRefFinalizer sr (hClose hdl) -------------------------------------------------------------------------------- ----------------------------- Session Actions ------------------------------- -------------------------------------------------------------------------------- -- | Terminates the current TLS connection, which has been succesfully established -- with 'handshake'. Notifies the peer with an alert that the connection is closing. {#fun gnutls_bye as bye {withSession* `Session t',enumCInt `CloseRequest'} -> `()' throwGnutlsIf* #} -- | Perform a handshake with the peer and initialize a TLS\/SSL connection. -- Note that after the handshake completes applications /must/ check -- whether a high enough level of confidentiality was established. {#fun gnutls_handshake as handshake {withSession* `Session t'} -> `' throwGnutlsIf* #} -- | Tells the client that we want to renogotiate the handshake. If the function -- succeeds then 'handshake' can be called again on the connection. {#fun gnutls_rehandshake as rehandshake {withSession* `Session Server'} -> `' throwGnutlsIf* #} -- | Set the maximum size of a handshake request. Larger requests are ignored. -- Defaults to 16kb which should be large enough. {#fun gnutls_handshake_set_max_packet_length as setMaxHandshakePacketLength {withSession* `Session t', fromIntegral `Int'} -> `()' #} -- | Set whether we want to do client authentication. clientCert :: WriteAttr (Session Server) CertificateRequest clientCert = writeAttr p where p s v = withSession s $ \sp -> {#call unsafe gnutls_certificate_server_set_request #} sp (enumCInt v) -------------------------------------------------------------------------------- ---------------------------- Session Getters -------------------------------- -------------------------------------------------------------------------------- serverWantedAuth :: Session Client -> IO Bool serverWantedAuth s = withSession s $ \sp -> do iv <- {#call gnutls_certificate_client_get_request_status #} sp throwGnutlsIfNeg iv return (iv /= 0) verifyPeer :: Session t -> IO [CertificateStatus] verifyPeer ses = do withSession ses $ \sp -> do alloca $ \stat -> do {#call gnutls_certificate_verify_peers2 #} sp stat >>= throwGnutlsIf ci <- peekEnum stat return $ filter (\e -> fromEnum e .&. ci /= 0) [CertInvalid, CertRevoked, CertSignerNotFound, CertSignerNotCa] -- | Test whether this session is a resumed one. {#fun gnutls_session_is_resumed as isResumed {withSession* `Session t'} -> `Bool' isNotZero #} isNotZero :: CInt -> Bool isNotZero 0 = False isNotZero _ = True -- | Return the value of the last alert received - undefined if no alert has been received. {#fun unsafe gnutls_alert_get as getAlert {withSession* `Session t'} -> `AlertDescription' cintEnum #} -- | Return the currently used cipher. {#fun unsafe gnutls_cipher_get as getCipher {withSession* `Session t'} -> `CipherAlgorithm' cintEnum #} -- | Return the key exchange algorithm used in the last handshake. {#fun unsafe gnutls_kx_get as getKx {withSession* `Session t'} -> `KxAlgorithm' cintEnum #} -- | Return the mac algorithm currently used. {#fun unsafe gnutls_mac_get as getMac {withSession* `Session t'} -> `MacAlgorithm' cintEnum #} -- | Return the compression method currently used. {#fun unsafe gnutls_compression_get as getCompression {withSession* `Session t'} -> `CompressionMethod' cintEnum #} -- | Return the currently used certificate type. {#fun unsafe gnutls_certificate_type_get as getCertificateType {withSession* `Session t'} -> `CertificateType' cintEnum #} -- | Return the currently used protocol version. {#fun unsafe gnutls_protocol_get_version as getProtocol {withSession* `Session t'} -> `Protocol' cintEnum #} -- | Return type of credentials for the current authentication schema. {#fun gnutls_auth_get_type as getCredentialsType {withSession* `Session t'} -> `CredentialsType' cintEnum #} #ifndef COMPAT_GNUTLS_1_0 -- | Return the type of credentials used for authenticating the server. Available with GnuTLS 1.2. {#fun gnutls_auth_server_get_type as getServerCredentialsType {withSession* `Session t'} -> `CredentialsType' cintEnum #} -- | Return the type of credentials used for authenticating the client. Available with GnuTLS 1.2. {#fun gnutls_auth_client_get_type as getClientCredentialsType {withSession* `Session t'} -> `CredentialsType' cintEnum #} #endif -- | Get the certificate chain of the peer. -- In the case of X509 will return DER encoded certificate list -- beginning with the peers key and continuing in the issuer chain. -- With OpenPGP a single key will be returned in the raw format. getPeersCertificatesRaw :: Session t -> IO [(Ptr CChar,Int)] getPeersCertificatesRaw ses = do withSession ses $ \sp -> alloca $ \lenp -> do res <- {#call gnutls_certificate_get_peers #} sp lenp if res == nullPtr then return [] else do len <- peek lenp peekDatumArray (fromIntegral len - 1) res -------------------------------------------------------------------------------- ---------------------------- Read/Write Data -------------------------------- -------------------------------------------------------------------------------- {#fun gnutls_record_send as tlsSend {withSession* `Session t', castPtr `Ptr a', fromIntegral `Int' } -> `Int' throwGnutlsIfNeg* #} tlsSendString :: Session t -> String -> IO () tlsSendString ses str = withCStringLen str $ \(ptr,len) -> loop ptr len where loop ptr len = do r <- tlsSend ses ptr len case len-r of x | x > 0 -> loop (plusPtr ptr r) x | True -> return () {#fun gnutls_record_check_pending as tlsCheckPending {withSession* `Session t'} -> `Int' fromIntegral #} {#fun gnutls_record_recv as tlsRecv {withSession* `Session t', castPtr `Ptr a', fromIntegral `Int'} -> `Int' throwGnutlsIfNeg* #} tlsRecvString :: Session t -> IO String tlsRecvString ses = allocaBytes 1024 $ \ptr -> do r <- tlsRecv ses ptr 1024 peekCAStringLen (ptr,r) -------------------------------------------------------------------------------- --------------------- Anonymous Server Credentials ------------------------- -------------------------------------------------------------------------------- anonymousServerCredentials :: IO AnonymousServerCredentials anonymousServerCredentials = alloca $ \ptr -> do gnutls_anon_allocate_server_credentials ptr >>= throwGnutlsIf raw<- peek ptr rc <- newRefCount $ gnutls_anon_free_server_credentials raw fp <- FC.newForeignPtr raw $ freeRef rc return $ ASC fp rc foreign import ccall safe "TLS.h gnutls_anon_free_server_credentials" gnutls_anon_free_server_credentials :: Ptr () -> IO () foreign import ccall safe "TLS.h gnutls_anon_allocate_server_credentials" gnutls_anon_allocate_server_credentials :: Ptr (Ptr ()) -> IO CInt class SetDHParams a where setDHParams :: a -> DH -> IO () instance SetDHParams AnonymousServerCredentials where setDHParams asc@(ASC _ rc) dh@(DH _ refc) = do gnutls_anon_set_server_dh_params asc dh allocRef refc addRefFinalizer rc $ freeRef refc {#fun gnutls_anon_set_server_dh_params {withAnonymousServerCredentials* `AnonymousServerCredentials', withDH* `DH'} -> `()' #} -------------------------------------------------------------------------------- --------------------- Anonymous Client Credentials ------------------------- -------------------------------------------------------------------------------- anonymousClientCredentials :: IO AnonymousClientCredentials anonymousClientCredentials = alloca $ \ptr -> do gnutls_anon_allocate_client_credentials ptr >>= throwGnutlsIf raw<- peek ptr rc <- newRefCount $ gnutls_anon_free_client_credentials raw fp <- FC.newForeignPtr raw $ freeRef rc return $ ACC fp rc foreign import ccall safe "TLS.h gnutls_anon_free_client_credentials" gnutls_anon_free_client_credentials :: Ptr () -> IO () foreign import ccall safe "TLS.h gnutls_anon_allocate_client_credentials" gnutls_anon_allocate_client_credentials :: Ptr (Ptr ()) -> IO CInt -------------------------------------------------------------------------------- ----------------------- Certificate Credentials ---------------------------- -------------------------------------------------------------------------------- certificateCredentials :: IO CertificateCredentials certificateCredentials = alloca $ \ptr -> do gnutls_certificate_allocate_credentials ptr >>= throwGnutlsIf raw<- peek ptr rc <- newRefCount $ gnutls_certificate_free_credentials raw fp <- FC.newForeignPtr raw $ freeRef rc return $ CC fp rc foreign import ccall safe "TLS.h gnutls_certificate_free_credentials" gnutls_certificate_free_credentials :: Ptr () -> IO () foreign import ccall safe "TLS.h gnutls_certificate_allocate_credentials" gnutls_certificate_allocate_credentials :: Ptr (Ptr ()) -> IO CInt {#fun gnutls_certificate_free_keys as freeKeys {withCertificateCredentials* `CertificateCredentials'} -> `()' #} {#fun gnutls_certificate_free_cas as freeCas {withCertificateCredentials* `CertificateCredentials'} -> `()' #} {#fun gnutls_certificate_free_ca_names as freeCaNames {withCertificateCredentials* `CertificateCredentials'} -> `()' #} {#fun gnutls_certificate_free_crls as freeCrls {withCertificateCredentials* `CertificateCredentials'} -> `()' #} instance SetDHParams CertificateCredentials where setDHParams cc@(CC _ rc) dh@(DH _ refc) = do gnutls_certificate_set_dh_params cc dh allocRef refc addRefFinalizer rc $ freeRef refc {#fun gnutls_certificate_set_dh_params {withCertificateCredentials* `CertificateCredentials', withDH* `DH'} -> `()' #} {#fun gnutls_certificate_set_x509_trust_file as certificateTrustFile {withCertificateCredentials* `CertificateCredentials', withCAString* `FilePath', enumCInt `X509CertificateFormat'} -> `Int' throwGnutlsIfNeg* #} {#fun gnutls_certificate_set_x509_crl_file as certificateCrlFile {withCertificateCredentials* `CertificateCredentials', withCAString* `FilePath', enumCInt `X509CertificateFormat'} -> `Int' throwGnutlsIfNeg* #} {#fun gnutls_certificate_set_x509_key_file as certificateKeyFile {withCertificateCredentials* `CertificateCredentials', withCAString* `FilePath', withCAString* `FilePath', enumCInt `X509CertificateFormat'} -> `Int' throwGnutlsIfNeg* #} {- void gnutls_certificate_set_rsa_export_params (gnutls_certificate_credentials_t res, gnutls_rsa_params_t rsa_params); void gnutls_certificate_set_verify_flags (gnutls_certificate_credentials_t res, unsigned int flags); void gnutls_certificate_set_verify_limits (gnutls_certificate_credentials_t res, unsigned int max_bits, unsigned int max_depth); int gnutls_certificate_set_x509_trust_mem (gnutls_certificate_credentials_t res, const gnutls_datum_t *CA, gnutls_x509_crt_fmt_t type); int gnutls_certificate_set_x509_trust (gnutls_certificate_credentials_t res, gnutls_x509_crt_t *ca_list, int ca_list_size); int gnutls_certificate_set_x509_crl_mem (gnutls_certificate_credentials_t res, const gnutls_datum_t *CRL, gnutls_x509_crt_fmt_t type); int gnutls_certificate_set_x509_crl (gnutls_certificate_credentials_t res, gnutls_x509_crl_t *crl_list, int crl_list_size); int gnutls_certificate_set_x509_key_mem (gnutls_certificate_credentials_t res, const gnutls_datum_t *CERT, const gnutls_datum_t *KEY, gnutls_x509_crt_fmt_t type); int gnutls_certificate_set_x509_key (gnutls_certificate_credentials_t res, gnutls_x509_crt_t *cert_list, int cert_list_size, gnutls_x509_privkey_t key); -} -------------------------------------------------------------------------------- ------------------------- DH and RSA Parameters ---------------------------- -------------------------------------------------------------------------------- class CredParameter a where -- | Generate a new key with the given number of bits. generate :: a -> Int -> IO () newDH :: IO DH newDH = alloca $ \ptr -> do gnutls_dh_params_init ptr >>= throwGnutlsIf raw<- peek ptr rc <- newRefCount (gnutls_dh_params_deinit raw) fp <- FC.newForeignPtr raw (freeRef rc) return $ DH fp rc foreign import ccall safe "TLS.h gnutls_dh_params_deinit" gnutls_dh_params_deinit :: Ptr () -> IO () foreign import ccall safe "TLS.h gnutls_dh_params_init" gnutls_dh_params_init :: Ptr (Ptr ()) -> IO CInt instance CredParameter DH where generate a i = withDH a (\ap -> {#call gnutls_dh_params_generate2 #} ap (fromIntegral i) >>= throwGnutlsIf) newRSA :: IO RSA newRSA = alloca $ \ptr -> do gnutls_rsa_params_init ptr >>= throwGnutlsIf raw<- peek ptr rc <- newRefCount (gnutls_rsa_params_deinit raw) fp <- FC.newForeignPtr raw (freeRef rc) return $ RSA fp rc foreign import ccall safe "TLS.h gnutls_rsa_params_deinit" gnutls_rsa_params_deinit :: Ptr () -> IO () foreign import ccall safe "TLS.h gnutls_rsa_params_init" gnutls_rsa_params_init :: Ptr (Ptr ()) -> IO CInt instance CredParameter RSA where generate a i = withRSA a (\ap -> {#call gnutls_rsa_params_generate2 #} ap (fromIntegral i) >>= throwGnutlsIf) -------------------------------------------------------------------------------- --------------------------- Miscellaneous ---------------------------------- -------------------------------------------------------------------------------- -- | Return the cipher's key size in bytes. {#fun pure unsafe gnutls_cipher_get_key_size as cipherKeySize {enumCInt `CipherAlgorithm'} -> `Int' fromIntegral #} -- | Return the name of the ciphersuite. {#fun pure unsafe gnutls_cipher_suite_get_name as cipherSuiteName {enumCInt `KxAlgorithm', enumCInt `CipherAlgorithm', enumCInt `MacAlgorithm'} -> `String' safePeekCString* #} -- | The version of /Gnutls/ used. version = unsafePerformIO $ {#call gnutls_check_version #} nullPtr >>= safePeekCString {-# NOINLINE gnutlsGlobalInitIORef #-} gnutlsGlobalInitIORef = unsafePerformIO $ do gcry_init_helper {#call unsafe gnutls_global_init #} >>= throwGnutlsIf newIORef () gnutlsGlobalInit = readIORef gnutlsGlobalInitIORef foreign import ccall unsafe "gcry_init_helper" gcry_init_helper :: IO ()