-- | -- Module : Data.Certificate.X509.Ext -- License : BSD-style -- Maintainer : Vincent Hanquez -- Stability : experimental -- Portability : unknown -- -- extension processing module. -- 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]) -- | key usage flag that is found in the key usage extension field. data ExtKeyUsageFlag = KeyUsage_digitalSignature -- (0) | KeyUsage_nonRepudiation -- (1) recent X.509 ver have renamed this bit to contentCommitment | KeyUsage_keyEncipherment -- (2) | KeyUsage_dataEncipherment -- (3) | KeyUsage_keyAgreement -- (4) | KeyUsage_keyCertSign -- (5) | KeyUsage_cRLSign -- (6) | KeyUsage_encipherOnly -- (7) | KeyUsage_decipherOnly -- (8) deriving (Show,Eq,Ord,Enum) -- RFC 5280 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] -- | known X509v3 extensions data Ext = ExtBasicConstraints Bool | ExtKeyUsage [ExtKeyUsageFlag] | ExtSubjectKeyId L.ByteString | ExtAuthorityKeyId B.ByteString deriving (Show,Eq) -- | try decoding a certificateExt tuple into a known extension. 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 -- basic constraints decodeBasicConstraints [Start Sequence,Boolean b,End Sequence] = Just (ExtBasicConstraints b) decodeBasicConstraints _ = Nothing -- subject key id decodeSubjectKeyId [OctetString o] = Just (ExtSubjectKeyId o) decodeSubjectKeyId _ = Nothing -- key usage 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..(nb-1)] $ \i -> do let isSet = bitArrayGetBit bits i if isSet then [toEnum $ fromIntegral i] else []