module Data.Certificate.X509.Ext
( CertificateExt
, Ext(..)
, ExtKeyUsageFlag(..)
, extDecode
) where
import qualified Data.ByteString as B
import qualified Data.ByteString.Lazy as L
import Data.ASN1.DER
import Data.ASN1.BitArray
import Data.Certificate.X509.Internal
type CertificateExt = (OID, Bool, [ASN1])
data ExtKeyUsageFlag =
KeyUsage_digitalSignature
| KeyUsage_nonRepudiation
| KeyUsage_keyEncipherment
| KeyUsage_dataEncipherment
| KeyUsage_keyAgreement
| KeyUsage_keyCertSign
| KeyUsage_cRLSign
| KeyUsage_encipherOnly
| KeyUsage_decipherOnly
deriving (Show,Eq,Ord,Enum)
oidSubjectKeyId, oidKeyUsage, oidBasicConstraints, oidDistributionPoints,
oidPolicies, oidPoliciesMapping, oidAuthorityKeyId :: OID
oidSubjectKeyId = [2,5,29,14]
oidKeyUsage = [2,5,29,15]
oidBasicConstraints = [2,5,29,19]
oidDistributionPoints = [2,5,29,31]
oidPolicies = [2,5,29,32]
oidPoliciesMapping = [2,5,29,33]
oidAuthorityKeyId = [2,5,29,35]
data Ext =
ExtBasicConstraints Bool
| ExtKeyUsage [ExtKeyUsageFlag]
| ExtSubjectKeyId L.ByteString
| ExtAuthorityKeyId B.ByteString
deriving (Show,Eq)
extDecode :: CertificateExt -> Maybe Ext
extDecode (oid, _, asn1)
| oid == oidBasicConstraints = decodeBasicConstraints asn1
| oid == oidSubjectKeyId = decodeSubjectKeyId asn1
| oid == oidAuthorityKeyId = decodeAuthorityKeyId asn1
| oid == oidKeyUsage = decodeKeyUsage asn1
| otherwise = Nothing
where
decodeBasicConstraints [Start Sequence,Boolean b,End Sequence] =
Just (ExtBasicConstraints b)
decodeBasicConstraints _ = Nothing
decodeSubjectKeyId [OctetString o] =
Just (ExtSubjectKeyId o)
decodeSubjectKeyId _ = Nothing
decodeKeyUsage [BitString bits] = Just $ ExtKeyUsage $ bitsToFlags bits
decodeKeyUsage _ = Nothing
decodeAuthorityKeyId [Start Sequence,Other Context 0 keyid,End Sequence] = Just $ ExtAuthorityKeyId keyid
decodeAuthorityKeyId _ = Nothing
bitsToFlags bits =
let nb = bitArrayLength bits in
concat $ flip map [0..(nb1)] $ \i -> do
let isSet = bitArrayGetBit bits i
if isSet then [toEnum $ fromIntegral i] else []