-- | Get the parameters for the mathematical part of SPAKE2 from the protocol specification.
getParams :: Protocol group hashAlgorithm -> Math.Params group
getParams Protocol{group, relation} =
  case relation of
    Symmetric{bothSides} -> mkParams bothSides bothSides
    Asymmetric{sideA, sideB, us} ->
      case us of
        SideA -> mkParams sideA sideB
        SideB -> mkParams sideB sideA

  where
    mkParams ours theirs =
      Math.Params
      { Math.group = group
      , Math.ourBlind = blind ours
      , Math.theirBlind = blind theirs
      }

-- | Perform an entire SPAKE2 exchange.
--
-- Given a SPAKE2 protocol that has all of the parameters for this exchange,
-- generate a one-off message from this side and receive a one off message
-- from the other.
--
-- Once we are done, return a key shared between both sides for a single
-- session.
--
-- Note: as per the SPAKE2 definition, the session key is not guaranteed
-- to actually /work/. If the other side has failed to authenticate, you will
-- still get a session key. Therefore, you must exchange some other message
-- that has been encrypted using this key in order to confirm that the session
-- key is indeed shared.
--
-- Note: the "send" and "receive" actions are performed 'concurrently'. If you
-- have ordering requirements, consider using a 'TVar' or 'MVar' to coordinate,
-- or implementing your own equivalent of 'spake2Exchange'.
--
-- If the message received from the other side cannot be parsed, return a
-- 'MessageError'.
--
-- Since 0.4.0.
getParams :: Protocol group hashAlgorithm -> Math.Params group
getParams Protocol{group, relation} =
  case relation of
    Symmetric{bothSides} -> mkParams bothSides bothSides
    Asymmetric{sideA, sideB, us} ->
      case us of
        SideA -> mkParams sideA sideB
        SideB -> mkParams sideB sideA

  where
    mkParams ours theirs =
      Math.Params
      { Math.group = group
      , Math.ourBlind = blind ours
      , Math.theirBlind = blind theirs
      }

-- | Perform an entire SPAKE2 exchange.
--
-- Given a SPAKE2 protocol that has all of the parameters for this exchange,
-- generate a one-off message from this side and receive a one off message
-- from the other.
--
-- Once we are done, return a key shared between both sides for a single
-- session.
--
-- Note: as per the SPAKE2 definition, the session key is not guaranteed
-- to actually /work/. If the other side has failed to authenticate, you will
-- still get a session key. Therefore, you must exchange some other message
-- that has been encrypted using this key in order to confirm that the session
-- key is indeed shared.
--
-- Note: the "send" and "receive" actions are performed 'concurrently'. If you
-- have ordering requirements, consider using a 'TVar' or 'MVar' to coordinate,
-- or implementing your own equivalent of 'spake2Exchange'.
--
-- If the message received from the other side cannot be parsed, return a
-- 'MessageError'.
--
-- Since 0.4.0.
getParams Protocol{group, relation} =
  case relation of
    Symmetric{bothSides} -> mkParams bothSides bothSides
    Asymmetric{sideA, sideB, us} ->
      case us of
        SideA -> mkParams sideA sideB
        SideB -> mkParams sideB sideA

  where
    mkParams ours theirs =
      Math.Params
      { Math.group = group
      , Math.ourBlind = blind ours
      , Math.theirBlind = blind theirs
      }

-- | Perform an entire SPAKE2 exchange.
--
-- Given a SPAKE2 protocol that has all of the parameters for this exchange,
-- generate a one-off message from this side and receive a one off message
-- from the other.
--
-- Once we are done, return a key shared between both sides for a single
-- session.
--
-- Note: as per the SPAKE2 definition, the session key is not guaranteed
-- to actually /work/. If the other side has failed to authenticate, you will
-- still get a session key. Therefore, you must exchange some other message
-- that has been encrypted using this key in order to confirm that the session
-- key is indeed shared.
--
-- Note: the "send" and "receive" actions are performed 'concurrently'. If you
-- have ordering requirements, consider using a 'TVar' or 'MVar' to coordinate,
-- or implementing your own equivalent of 'spake2Exchange'.
--
-- If the message received from the other side cannot be parsed, return a
-- 'MessageError'.
--
-- Since 0.4.0.