webauthn-0.1.0.0: src/Crypto/WebAuthn/Cose/Internal/Registry.hs
{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
-- | Stability: internal
-- This module contains definitions for [COSE registry](https://www.iana.org/assignments/cose/cose.xhtml)
-- entries that are relevant for Webauthn COSE public keys. All the types in
-- this module implement the 'Serialise' class, mapping them to the respective
-- CBOR values/labels.
--
-- This modules sometimes uses this
-- [CBOR Grammar](https://datatracker.ietf.org/doc/html/draft-ietf-cose-rfc8152bis-struct-13#section-1.4)
-- to describe CBOR value types corresponding to CBOR parameters
module Crypto.WebAuthn.Cose.Internal.Registry
( -- * COSE Key Types
CoseKeyType (..),
-- * COSE Parameters
CoseKeyCommonParameter (..),
CoseKeyTypeParameterOKP (..),
CoseKeyTypeParameterEC2 (..),
CoseKeyTypeParameterRSA (..),
parameterCount,
-- * COSE Elliptic Curves
CoseEllipticCurveOKP (..),
CoseEllipticCurveEC2 (..),
)
where
import Codec.CBOR.Decoding (decodeIntCanonical)
import Codec.CBOR.Encoding (encodeInt)
import Codec.Serialise (Serialise)
import Codec.Serialise.Class (decode, encode)
-- | [(spec)](https://www.iana.org/assignments/cose/cose.xhtml#key-common-parameters)
-- All the entries from the [COSE Key Common Parameters registry](https://www.iana.org/assignments/cose/cose.xhtml#key-common-parameters)
-- that are needed for Webauthn public keys
data CoseKeyCommonParameter
= -- | [(spec)](https://datatracker.ietf.org/doc/html/draft-ietf-cose-rfc8152bis-struct-15#section-7.1)
--
-- * COSE value type: tstr / int
-- * Value registry: 'CoseKeyType'
-- * Description: Identification of the key type
--
-- This parameter is used to identify the family of keys for this
-- structure and, thus, the set of key-type-specific parameters to be
-- found. The key type MUST be included as part of the trust decision
-- process.
CoseKeyCommonParameterKty
| -- | [(spec)](https://datatracker.ietf.org/doc/html/draft-ietf-cose-rfc8152bis-struct-15#section-7.1)
--
-- * COSE value type: tstr / int
-- * Value registry: 'Crypto.WebAuthn.Cose.Algorithm.CoseSignAlg'
-- * Description: Key usage restriction to this algorithm
--
-- This parameter is used to restrict the algorithm that is used
-- with the key.
CoseKeyCommonParameterAlg
deriving (Eq, Show, Bounded, Enum)
-- | Serialises the parameters using the @Label@ column from the
-- [COSE Key Common Parameters registry](https://www.iana.org/assignments/cose/cose.xhtml#key-common-parameters)
instance Serialise CoseKeyCommonParameter where
encode CoseKeyCommonParameterKty = encodeInt 1
encode CoseKeyCommonParameterAlg = encodeInt 3
decode =
decodeIntCanonical >>= \case
1 -> pure CoseKeyCommonParameterKty
3 -> pure CoseKeyCommonParameterAlg
value -> fail $ "Unknown COSE key common parameter " <> show value
-- | [(spec)](https://www.iana.org/assignments/cose/cose.xhtml#key-type)
-- All the entries from the [COSE Key Types registry](https://www.iana.org/assignments/cose/cose.xhtml#key-type)
-- that are known to be needed for Webauthn public keys
data CoseKeyType
= -- | [(spec)](https://datatracker.ietf.org/doc/html/draft-ietf-cose-rfc8152bis-algs-12#section-7.2)
-- Octet Key Pair.
-- See 'CoseKeyTypeParameterOKP' for the parameters specific to this key type.
CoseKeyTypeOKP
| -- | [(spec)](https://datatracker.ietf.org/doc/html/draft-ietf-cose-rfc8152bis-algs-12#section-7.1.1)
-- Elliptic Curve Keys w/ x- and y-coordinate pair.
-- See 'CoseKeyTypeParameterEC2' for the parameters specific to this key type.
CoseKeyTypeEC2
| -- | [(spec)](https://www.rfc-editor.org/rfc/rfc8230.html#section-4)
-- RSA Key.
-- See 'CoseKeyTypeParameterRSA' for the parameters specific to this key type.
CoseKeyTypeRSA
deriving (Eq, Show)
-- | Serialises the key type using the @Value@ column from the
-- [COSE Key Types registry](https://www.iana.org/assignments/cose/cose.xhtml#key-type)
instance Serialise CoseKeyType where
encode CoseKeyTypeOKP = encodeInt 1
encode CoseKeyTypeEC2 = encodeInt 2
encode CoseKeyTypeRSA = encodeInt 3
decode =
decodeIntCanonical >>= \case
1 -> pure CoseKeyTypeOKP
2 -> pure CoseKeyTypeEC2
3 -> pure CoseKeyTypeRSA
value -> fail $ "Unknown COSE key type " <> show value
-- | [(spec)](https://www.iana.org/assignments/cose/cose.xhtml#key-type-parameters)
-- All the entries from the [COSE Key Type Parameters registry](https://www.iana.org/assignments/cose/cose.xhtml#key-type-parameters)
-- for key type 'CoseKeyTypeOKP' (aka @Key Type@ is @1@) that are required for
-- public keys
data CoseKeyTypeParameterOKP
= -- | [(spec)](https://datatracker.ietf.org/doc/html/draft-ietf-cose-rfc8152bis-algs-12#section-7.2)
--
-- * COSE value type: int / tstr
-- * Value registry: 'CoseEllipticCurveOKP'
-- * Description: EC identifier
--
-- This contains an identifier of the curve to be used with the key.
CoseKeyTypeParameterOKPCrv
| -- | [(spec)](https://datatracker.ietf.org/doc/html/draft-ietf-cose-rfc8152bis-algs-12#section-7.2)
--
-- * COSE value type: bstr
-- * Description: Public Key
--
-- This contains the public key. The byte string contains the public key as defined by the algorithm.
CoseKeyTypeParameterOKPX
deriving (Eq, Show, Bounded, Enum)
-- | Serialises the parameters using the @Label@ column from the
-- [COSE Key Type Parameters registry](https://www.iana.org/assignments/cose/cose.xhtml#key-type-parameters)
instance Serialise CoseKeyTypeParameterOKP where
encode CoseKeyTypeParameterOKPCrv = encodeInt (-1)
encode CoseKeyTypeParameterOKPX = encodeInt (-2)
decode =
decodeIntCanonical >>= \case
-1 -> pure CoseKeyTypeParameterOKPCrv
-2 -> pure CoseKeyTypeParameterOKPX
value -> fail $ "Unknown COSE key type parameter " <> show value <> " for key type OKP"
-- | Elliptic curves for key type 'CoseKeyTypeOKP' from the
-- [COSE Elliptic Curves registry](https://www.iana.org/assignments/cose/cose.xhtml#elliptic-curves),
-- limited to the ones that are currently needed for Webauthn
data CoseEllipticCurveOKP
= -- | [(spec)](https://datatracker.ietf.org/doc/html/draft-ietf-cose-rfc8152bis-algs-12#section-7.1)
-- Ed25519 for use w/ EdDSA only
CoseEllipticCurveEd25519
deriving (Eq, Show)
-- | Serialises COSE Elliptic Curves using the @Value@ column from the
-- [COSE Elliptic Curves registry](https://www.iana.org/assignments/cose/cose.xhtml#elliptic-curves).
instance Serialise CoseEllipticCurveOKP where
encode CoseEllipticCurveEd25519 = encodeInt 6
decode =
decodeIntCanonical >>= \case
6 -> pure CoseEllipticCurveEd25519
value -> fail $ "Unknown COSE elliptic curve " <> show value <> " for key type OKP"
-- | [(spec)](https://www.iana.org/assignments/cose/cose.xhtml#key-type-parameters)
-- All the entries from the [COSE Key Type Parameters registry](https://www.iana.org/assignments/cose/cose.xhtml#key-type-parameters)
-- for key type 'CoseKeyTypeEC2' (aka @Key Type@ is @2@) that are required for
-- public keys
data CoseKeyTypeParameterEC2
= -- | [(spec)](https://datatracker.ietf.org/doc/html/draft-ietf-cose-rfc8152bis-algs-12#section-7.1.1)
--
-- * COSE value type: int / tstr
-- * Value registry: 'CoseEllipticCurveEC2'
-- * Description: EC identifier
--
-- This contains an identifier of the curve to be used with the key.
CoseKeyTypeParameterEC2Crv
| -- | [(spec)](https://datatracker.ietf.org/doc/html/draft-ietf-cose-rfc8152bis-algs-12#section-7.1.1)
--
-- * COSE value type: bstr
-- * Description: x-coordinate
--
-- This contains the x-coordinate for the EC point. The integer is
-- converted to a byte string as defined in [SEC1]. Leading zero
-- octets MUST be preserved.
CoseKeyTypeParameterEC2X
| -- | [(spec)](https://datatracker.ietf.org/doc/html/draft-ietf-cose-rfc8152bis-algs-12#section-7.1.1)
--
-- * COSE value type: bstr / bool
-- * Description: y-coordinate
--
-- This contains either the sign bit or the value of the
-- y-coordinate for the EC point. When encoding the value y, the
-- integer is converted to an byte string (as defined in
-- [SEC1](https://datatracker.ietf.org/doc/html/draft-ietf-cose-rfc8152bis-algs-12#ref-SEC1))
-- and encoded as a CBOR bstr. Leading zero octets MUST be
-- preserved. The compressed point encoding is also supported.
-- Compute the sign bit as laid out in the Elliptic-Curve-Point-to-
-- Octet-String Conversion function of
-- [SEC1](https://datatracker.ietf.org/doc/html/draft-ietf-cose-rfc8152bis-algs-12#ref-SEC1).
-- If the sign bit is zero, then encode y as a CBOR false value;
-- otherwise, encode y as a CBOR true value.
-- The encoding of the infinity point is not supported.
CoseKeyTypeParameterEC2Y
deriving (Eq, Show, Bounded, Enum)
-- | Serialises the parameters using the @Label@ column from the
-- [COSE Key Type Parameters registry](https://www.iana.org/assignments/cose/cose.xhtml#key-type-parameters)
instance Serialise CoseKeyTypeParameterEC2 where
encode CoseKeyTypeParameterEC2Crv = encodeInt (-1)
encode CoseKeyTypeParameterEC2X = encodeInt (-2)
encode CoseKeyTypeParameterEC2Y = encodeInt (-3)
decode =
decodeIntCanonical >>= \case
-1 -> pure CoseKeyTypeParameterEC2Crv
-2 -> pure CoseKeyTypeParameterEC2X
-3 -> pure CoseKeyTypeParameterEC2Y
value -> fail $ "Unknown COSE key type parameter " <> show value <> " for key type EC2"
-- | Elliptic curves for key type 'CoseKeyTypeEC2' from the
-- [COSE Elliptic Curves registry](https://www.iana.org/assignments/cose/cose.xhtml#elliptic-curves),
-- limited to the ones that are currently needed for Webauthn
data CoseEllipticCurveEC2
= -- | [(spec)](https://datatracker.ietf.org/doc/html/draft-ietf-cose-rfc8152bis-algs-12#section-7.1)
-- NIST P-256 also known as secp256r1
CoseEllipticCurveEC2P256
| -- | [(spec)](https://datatracker.ietf.org/doc/html/draft-ietf-cose-rfc8152bis-algs-12#section-7.1)
-- NIST P-384 also known as secp384r1
CoseEllipticCurveEC2P384
| -- | [(spec)](https://datatracker.ietf.org/doc/html/draft-ietf-cose-rfc8152bis-algs-12#section-7.1)
-- NIST P-521 also known as secp521r1
CoseEllipticCurveEC2P521
deriving (Eq, Show)
-- | Serialises COSE Elliptic Curves using the @Value@ column from the
-- [COSE Elliptic Curves registry](https://www.iana.org/assignments/cose/cose.xhtml#elliptic-curves).
instance Serialise CoseEllipticCurveEC2 where
encode CoseEllipticCurveEC2P256 = encodeInt 1
encode CoseEllipticCurveEC2P384 = encodeInt 2
encode CoseEllipticCurveEC2P521 = encodeInt 3
decode =
decodeIntCanonical >>= \case
1 -> pure CoseEllipticCurveEC2P256
2 -> pure CoseEllipticCurveEC2P384
3 -> pure CoseEllipticCurveEC2P521
value -> fail $ "Unknown COSE elliptic curve " <> show value <> " for key type EC2"
-- | [(spec)](https://www.iana.org/assignments/cose/cose.xhtml#key-type-parameters)
-- All the entries from the [COSE Key Type Parameters registry](https://www.iana.org/assignments/cose/cose.xhtml#key-type-parameters)
-- for key type 'CoseKeyTypeRSA' (aka @Key Type@ is @3@) that are required for
-- public keys
data CoseKeyTypeParameterRSA
= -- | [(spec)](https://www.rfc-editor.org/rfc/rfc8230.html#section-4)
--
-- * COSE value type: bstr
-- * Description: the RSA modulus n
--
-- The RSA modulus n is a product of u distinct odd primes
-- r_i, i = 1, 2, ..., u, where u >= 2
--
-- All numeric key parameters are encoded in an unsigned big-endian
-- representation as an octet sequence using the CBOR byte string
-- type (major type 2). The octet sequence MUST utilize the minimum
-- number of octets needed to represent the value. For instance, the
-- value 32,768 is represented as the CBOR byte sequence 0b010_00010,
-- 0x80 0x00 (major type 2, additional information 2 for the length).
CoseKeyTypeParameterRSAN
| -- | [(spec)](https://www.rfc-editor.org/rfc/rfc8230.html#section-4)
--
-- * COSE value type: bstr
-- * Description: the RSA public exponent e
--
-- The RSA public exponent e is an integer between 3 and n - 1 satisfying
-- GCD(e,\lambda(n)) = 1, where \lambda(n) = LCM(r_1 - 1, ..., r_u - 1)
--
-- All numeric key parameters are encoded in an unsigned big-endian
-- representation as an octet sequence using the CBOR byte string
-- type (major type 2). The octet sequence MUST utilize the minimum
-- number of octets needed to represent the value. For instance, the
-- value 32,768 is represented as the CBOR byte sequence 0b010_00010,
-- 0x80 0x00 (major type 2, additional information 2 for the length).
CoseKeyTypeParameterRSAE
deriving (Eq, Show, Bounded, Enum)
-- | Serialises the parameters using the @Label@ column from the
-- [COSE Key Type Parameters registry](https://www.iana.org/assignments/cose/cose.xhtml#key-type-parameters)
instance Serialise CoseKeyTypeParameterRSA where
encode CoseKeyTypeParameterRSAN = encodeInt (-1)
encode CoseKeyTypeParameterRSAE = encodeInt (-2)
decode =
decodeIntCanonical >>= \case
-1 -> pure CoseKeyTypeParameterRSAN
-2 -> pure CoseKeyTypeParameterRSAE
value -> fail $ "Unknown COSE key type parameter " <> show value <> " for key type RSA"
-- | The number of parameters for a 'CoseKeyType' relevant for Webauthn public
-- keys
parameterCount :: CoseKeyType -> Word
parameterCount CoseKeyTypeOKP = cardinality @CoseKeyCommonParameter + cardinality @CoseKeyTypeParameterOKP
parameterCount CoseKeyTypeEC2 = cardinality @CoseKeyCommonParameter + cardinality @CoseKeyTypeParameterEC2
parameterCount CoseKeyTypeRSA = cardinality @CoseKeyCommonParameter + cardinality @CoseKeyTypeParameterRSA
-- | A utility function for getting the number of constructors for a type
-- that implements both 'Bounded' and 'Enum'
cardinality :: forall a b. (Bounded a, Enum a, Num b) => b
cardinality = fromIntegral $ 1 + fromEnum @a maxBound - fromEnum @a minBound