-- | ASN1 utils for TLS
module Network.TLS.Util.ASN1 (
    decodeASN1Object,
    encodeASN1Object,
) where

import Data.ASN1.BinaryEncoding (DER (..))
import Data.ASN1.Encoding (decodeASN1', encodeASN1')
import Data.ASN1.Types (ASN1Object, fromASN1, toASN1)
import Network.TLS.Imports

-- | Attempt to decode a bytestring representing
-- an DER ASN.1 serialized object into the object.
decodeASN1Object
    :: ASN1Object a
    => String
    -> ByteString
    -> Either String a
decodeASN1Object :: forall a. ASN1Object a => String -> ByteString -> Either String a
decodeASN1Object String
name ByteString
bs =
    case DER -> ByteString -> Either ASN1Error [ASN1]
forall a.
ASN1Decoding a =>
a -> ByteString -> Either ASN1Error [ASN1]
decodeASN1' DER
DER ByteString
bs of
        Left ASN1Error
e -> String -> Either String a
forall a b. a -> Either a b
Left (String
name String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
": cannot decode ASN1: " String -> String -> String
forall a. [a] -> [a] -> [a]
++ ASN1Error -> String
forall a. Show a => a -> String
show ASN1Error
e)
        Right [ASN1]
asn1 -> case [ASN1] -> Either String (a, [ASN1])
forall a. ASN1Object a => [ASN1] -> Either String (a, [ASN1])
fromASN1 [ASN1]
asn1 of
            Left String
e -> String -> Either String a
forall a b. a -> Either a b
Left (String
name String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
": cannot parse ASN1: " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String -> String
forall a. Show a => a -> String
show String
e)
            Right (a
d, [ASN1]
_) -> a -> Either String a
forall a b. b -> Either a b
Right a
d

-- | Encode an ASN.1 Object to the DER serialized bytestring
encodeASN1Object
    :: ASN1Object a
    => a
    -> ByteString
encodeASN1Object :: forall a. ASN1Object a => a -> ByteString
encodeASN1Object a
obj = DER -> [ASN1] -> ByteString
forall a. ASN1Encoding a => a -> [ASN1] -> ByteString
encodeASN1' DER
DER ([ASN1] -> ByteString) -> [ASN1] -> ByteString
forall a b. (a -> b) -> a -> b
$ a -> ASN1S
forall a. ASN1Object a => a -> ASN1S
toASN1 a
obj []