Project

General

Profile

Actions

Using Maybe Monad for checks

{-# LANGUAGE LambdaCase, RecordWildCards #-}

import Data.Maybe (isJust, mapMaybe)
import Data.List (nub)

data Group = X25519 | Secp384
           deriving (Eq)

data KeyShareData = KeyShareClientHello [Group]
                  | KeyShareHelloRetryRequest Group

data Ext = SupportedGroups [Group]
         | KeyShares KeyShareData

check :: [Ext] -> [Ext] -> Bool
check eCH eHRR = isJust $ do
  sgCH <- exactlyOne $ mapMaybe (\case SupportedGroups gs -> Just gs; _ -> Nothing) eCH
  continueIf $ nub sgCH == sgCH -- no duplicates allowed
  ksCH <- (\case KeyShareClientHello gs -> Just gs; _ -> Nothing) =<<
    exactlyOne (mapMaybe (\case KeyShares ks -> Just ks; _ -> Nothing) eCH)
  ksHRR <- (\case KeyShareHelloRetryRequest g -> Just g; _ -> Nothing) =<<
    exactlyOne (mapMaybe (\case KeyShares ks -> Just ks; _ -> Nothing) eHRR)
  continueIf $ nub ksCH == ksCH -- no duplicates allowed
  continueIf $ ksHRR `elem` sgCH -- group must be supported
  continueIf $ ksHRR `notElem` ksCH -- key share must not have been already sent

exactlyOne :: [a] -> Maybe a
exactlyOne [x] = Just x
exactlyOne _ = Nothing

continueIf :: Bool -> Maybe ()
continueIf True = Just ()
continueIf False = Nothing

Updated by Grigoriy Volkov over 1 year ago · 1 revisions