1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152
|
{-# LANGUAGE CPP #-}
{-# LANGUAGE EmptyDataDecls #-}
{-# LANGUAGE ForeignFunctionInterface #-}
{-# LANGUAGE CApiFFI #-}
module OpenSSL.ASN1
( ASN1_OBJECT
, obj2nid
, nid2sn
, nid2ln
, ASN1_STRING
, peekASN1String
, ASN1_INTEGER
, peekASN1Integer
, withASN1Integer
, ASN1_TIME
, peekASN1Time
, withASN1Time
)
where
#include "HsOpenSSL.h"
import Control.Exception
import Data.Time.Clock
import Data.Time.Clock.POSIX
import Data.Time.Format
import Foreign
import Foreign.C
import OpenSSL.BIO
import OpenSSL.BN
import OpenSSL.Utils
#if !MIN_VERSION_time(1,5,0)
import System.Locale
#endif
{- ASN1_OBJECT --------------------------------------------------------------- -}
data {-# CTYPE "openssl/asn1.h" "ASN1_OBJECT" #-} ASN1_OBJECT
foreign import capi unsafe "openssl/objects.h OBJ_obj2nid"
obj2nid :: Ptr ASN1_OBJECT -> IO CInt
foreign import capi unsafe "openssl/objects.h OBJ_nid2sn"
_nid2sn :: CInt -> IO CString
foreign import capi unsafe "openssl/objects.h OBJ_nid2ln"
_nid2ln :: CInt -> IO CString
nid2sn :: CInt -> IO String
nid2sn nid = _nid2sn nid >>= peekCString
nid2ln :: CInt -> IO String
nid2ln nid = _nid2ln nid >>= peekCString
{- ASN1_STRING --------------------------------------------------------------- -}
data {-# CTYPE "openssl/asn1.h" "ASN1_STRING" #-} ASN1_STRING
peekASN1String :: Ptr ASN1_STRING -> IO String
peekASN1String strPtr
= do buf <- (#peek ASN1_STRING, data ) strPtr
len <- (#peek ASN1_STRING, length) strPtr :: IO CInt
peekCStringLen (buf, fromIntegral len)
{- ASN1_INTEGER -------------------------------------------------------------- -}
data {-# CTYPE "openssl/asn1.h" "ASN1_INTEGER" #-} ASN1_INTEGER
foreign import capi unsafe "HsOpenSSL.h HsOpenSSL_M_ASN1_INTEGER_new"
_ASN1_INTEGER_new :: IO (Ptr ASN1_INTEGER)
foreign import capi unsafe "HsOpenSSL.h HsOpenSSL_M_ASN1_INTEGER_free"
_ASN1_INTEGER_free :: Ptr ASN1_INTEGER -> IO ()
foreign import capi unsafe "openssl/asn1.h ASN1_INTEGER_to_BN"
_ASN1_INTEGER_to_BN :: Ptr ASN1_INTEGER -> Ptr BIGNUM -> IO (Ptr BIGNUM)
foreign import capi unsafe "openssl/asn1.h BN_to_ASN1_INTEGER"
_BN_to_ASN1_INTEGER :: Ptr BIGNUM -> Ptr ASN1_INTEGER -> IO (Ptr ASN1_INTEGER)
peekASN1Integer :: Ptr ASN1_INTEGER -> IO Integer
peekASN1Integer intPtr
= allocaBN $ \ bn ->
do _ASN1_INTEGER_to_BN intPtr (unwrapBN bn)
>>= failIfNull_
peekBN bn
allocaASN1Integer :: (Ptr ASN1_INTEGER -> IO a) -> IO a
allocaASN1Integer
= bracket _ASN1_INTEGER_new _ASN1_INTEGER_free
withASN1Integer :: Integer -> (Ptr ASN1_INTEGER -> IO a) -> IO a
withASN1Integer int m
= withBN int $ \ bn ->
allocaASN1Integer $ \ intPtr ->
do _BN_to_ASN1_INTEGER (unwrapBN bn) intPtr
>>= failIfNull_
m intPtr
{- ASN1_TIME ---------------------------------------------------------------- -}
data {-# CTYPE "openssl/asn1.h" "ASN1_TIME" #-} ASN1_TIME
foreign import capi unsafe "HsOpenSSL.h HsOpenSSL_M_ASN1_TIME_new"
_ASN1_TIME_new :: IO (Ptr ASN1_TIME)
foreign import capi unsafe "HsOpenSSL.h HsOpenSSL_M_ASN1_TIME_free"
_ASN1_TIME_free :: Ptr ASN1_TIME -> IO ()
foreign import capi unsafe "openssl/asn1.h ASN1_TIME_set"
_ASN1_TIME_set :: Ptr ASN1_TIME -> CTime -> IO (Ptr ASN1_TIME)
foreign import capi unsafe "openssl/asn1.h ASN1_TIME_print"
_ASN1_TIME_print :: Ptr BIO_ -> Ptr ASN1_TIME -> IO CInt
peekASN1Time :: Ptr ASN1_TIME -> IO UTCTime -- asn1/t_x509.c
peekASN1Time time
= do bio <- newMem
withBioPtr bio $ \ bioPtr ->
_ASN1_TIME_print bioPtr time
>>= failIf_ (/= 1)
timeStr <- bioRead bio
#if MIN_VERSION_time(1,5,0)
case parseTimeM True defaultTimeLocale "%b %e %H:%M:%S %Y %Z" timeStr of
#else
case parseTime defaultTimeLocale "%b %e %H:%M:%S %Y %Z" timeStr of
#endif
Just utc -> return utc
Nothing -> fail ("peekASN1Time: failed to parse time string: " ++ timeStr)
allocaASN1Time :: (Ptr ASN1_TIME -> IO a) -> IO a
allocaASN1Time
= bracket _ASN1_TIME_new _ASN1_TIME_free
withASN1Time :: UTCTime -> (Ptr ASN1_TIME -> IO a) -> IO a
withASN1Time utc m
= allocaASN1Time $ \ time ->
do _ASN1_TIME_set time (fromIntegral (round $ utcTimeToPOSIXSeconds utc :: Integer))
>>= failIfNull_
m time
|