-- | -- Module : Crypto.Store.CMS.Authenticated -- License : BSD-style -- Maintainer : Olivier Chéron -- Stability : experimental -- Portability : unknown -- -- {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE RecordWildCards #-} module Crypto.Store.CMS.Authenticated ( AuthenticatedData(..) ) where import Control.Applicative import Control.Monad import Data.ASN1.Types import qualified Data.ByteArray as B import Crypto.Cipher.Types import Crypto.Store.ASN1.Generate import Crypto.Store.ASN1.Parse import Crypto.Store.CMS.Algorithms import Crypto.Store.CMS.Attribute import Crypto.Store.CMS.Enveloped import Crypto.Store.CMS.OriginatorInfo import Crypto.Store.CMS.Signed import Crypto.Store.CMS.Type import Crypto.Store.CMS.Util -- | Authenticated content information. data AuthenticatedData content = AuthenticatedData { adOriginatorInfo :: OriginatorInfo -- ^ Optional information about the originator , adRecipientInfos :: [RecipientInfo] -- ^ Information for recipients, allowing to authenticate the content , adMACAlgorithm :: MACAlgorithm -- ^ MAC algorithm , adDigestAlgorithm :: Maybe DigestAlgorithm -- ^ Optional digest algorithm , adContentType :: ContentType -- ^ Inner content type , adEncapsulatedContent :: content -- ^ Encapsulated content , adAuthAttrs :: [Attribute] -- ^ Optional authenticated attributes , adMAC :: MessageAuthenticationCode -- ^ Message authentication code , adUnauthAttrs :: [Attribute] -- ^ Optional unauthenticated attributes } deriving (Show,Eq) instance ProduceASN1Object ASN1P (AuthenticatedData (Encap EncapsulatedContent)) where asn1s AuthenticatedData{..} = asn1Container Sequence (ver . oi . ris . alg . dig . ci . aa . tag . ua) where ver = gIntVal v ris = asn1Container Set (asn1s adRecipientInfos) alg = algorithmASN1S Sequence adMACAlgorithm dig = algorithmMaybeASN1S (Container Context 1) adDigestAlgorithm ci = encapsulatedContentInfoASN1S adContentType adEncapsulatedContent aa = attributesASN1S(Container Context 2) adAuthAttrs tag = gOctetString (B.convert adMAC) ua = attributesASN1S (Container Context 3) adUnauthAttrs oi | adOriginatorInfo == mempty = id | otherwise = originatorInfoASN1S (Container Context 0) adOriginatorInfo v | hasChoiceOther adOriginatorInfo = 3 | otherwise = 0 instance ParseASN1Object [ASN1Event] (AuthenticatedData (Encap EncapsulatedContent)) where parse = onNextContainer Sequence $ do IntVal v <- getNext when (v `notElem` [0, 1, 3]) $ throwParseError ("AuthenticatedData: parsed invalid version: " ++ show v) oi <- parseOriginatorInfo (Container Context 0) <|> return mempty ris <- onNextContainer Set parse alg <- parseAlgorithm Sequence dig <- parseAlgorithmMaybe (Container Context 1) (ct, bs) <- parseEncapsulatedContentInfo aAttrs <- parseAttributes (Container Context 2) OctetString tag <- getNext uAttrs <- parseAttributes (Container Context 3) return AuthenticatedData { adOriginatorInfo = oi , adRecipientInfos = ris , adMACAlgorithm = alg , adDigestAlgorithm = dig , adContentType = ct , adEncapsulatedContent = bs , adAuthAttrs = aAttrs , adMAC = AuthTag $ B.convert tag , adUnauthAttrs = uAttrs }