{-# LANGUAGE PatternSynonyms #-} -- | Stability: experimental -- 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.SignAlg ( -- * COSE Algorithms CoseSignAlg ( .., CoseAlgorithmEdDSA, CoseAlgorithmES256, CoseAlgorithmES384, CoseAlgorithmES512, CoseAlgorithmRS256, CoseAlgorithmRS384, CoseAlgorithmRS512, CoseAlgorithmRS1 ), fromCoseSignAlg, toCoseSignAlg, -- * Hash Algorithms CoseHashAlgECDSA (..), CoseHashAlgRSA (..), ) where import Codec.CBOR.Decoding (decodeIntCanonical) import Codec.CBOR.Encoding (encodeInt) import Codec.Serialise (Serialise) import Codec.Serialise.Class (decode, encode) import Data.Aeson (ToJSON) import Data.Text (Text) import qualified Data.Text as Text import GHC.Generics (Generic) -- | [(spec)](https://www.iana.org/assignments/cose/cose.xhtml#algorithms) -- All the entries from the [COSE Algorithms registry](https://www.iana.org/assignments/cose/cose.xhtml#algorithms) -- limited to the ones that are currently needed for Webauthn. Notably we only -- care about asymmetric signature algorithms data CoseSignAlg = -- | [(spec)](https://datatracker.ietf.org/doc/html/draft-ietf-cose-rfc8152bis-algs-12#section-2.2) -- EdDSA -- -- [RFC8032](https://datatracker.ietf.org/doc/html/rfc8032) describes the elliptic curve signature scheme Edwards-curve -- Digital Signature Algorithm (EdDSA). In that document, the signature -- algorithm is instantiated using parameters for edwards25519 and -- edwards448 curves. The document additionally describes two variants -- of the EdDSA algorithm: Pure EdDSA, where no hash function is applied -- to the content before signing, and HashEdDSA, where a hash function -- is applied to the content before signing and the result of that hash -- function is signed. For EdDSA, the content to be signed (either the -- message or the pre-hash value) is processed twice inside of the -- signature algorithm. For use with COSE, only the pure EdDSA version -- is used. -- -- Security considerations are [here](https://datatracker.ietf.org/doc/html/draft-ietf-cose-rfc8152bis-algs-12#section-2.2.1) CoseSignAlgEdDSA | -- | [(spec)](https://datatracker.ietf.org/doc/html/draft-ietf-cose-rfc8152bis-algs-12#section-2.1) -- ECDSA -- -- ECDSA [DSS] defines a signature algorithm using ECC. Implementations -- SHOULD use a deterministic version of ECDSA such as the one defined -- in [RFC6979]. -- -- The ECDSA signature algorithm is parameterized with a hash function -- (h). In the event that the length of the hash function output is -- greater than the group of the key, the leftmost bytes of the hash -- output are used. -- ECDSA w/ SHA-256 -- -- This document defines ECDSA to work only with the curves P-256, -- P-384, and P-521. Future documents may define it to work with other -- curves and points in the future. -- -- In order to promote interoperability, it is suggested that SHA-256 be -- used only with curve P-256, SHA-384 be used only with curve P-384, -- and SHA-512 be used with curve P-521. This is aligned with the -- recommendation in [Section 4 of RFC5480](https://datatracker.ietf.org/doc/html/rfc5480#section-4) -- -- Security considerations are [here](https://datatracker.ietf.org/doc/html/draft-ietf-cose-rfc8152bis-algs-12#section-2.1.1) CoseSignAlgECDSA CoseHashAlgECDSA | -- | [(spec)](https://www.rfc-editor.org/rfc/rfc8812.html#section-2) -- The RSASSA-PKCS1-v1_5 signature algorithm is defined in -- [RFC8017](https://www.rfc-editor.org/rfc/rfc8812.html#RFC8017). -- The RSASSA-PKCS1-v1_5 signature algorithm is parameterized with a hash function (h). -- -- A key of size 2048 bits or larger MUST be used with these algorithms. -- -- Security considerations are [here](https://www.rfc-editor.org/rfc/rfc8812.html#section-5) CoseSignAlgRSA CoseHashAlgRSA deriving (Eq, Show, Ord, Generic, ToJSON) -- | Hash algorithms that can be used with the ECDSA signature algorithm data CoseHashAlgECDSA = -- | SHA-256 CoseHashAlgECDSASHA256 | -- | SHA-384 CoseHashAlgECDSASHA384 | -- | SHA-512 CoseHashAlgECDSASHA512 deriving (Eq, Show, Ord, Enum, Bounded, Generic, ToJSON) -- | Hash algorithms that can be used with the RSA signature algorithm data CoseHashAlgRSA = -- | SHA-1 (deprecated) CoseHashAlgRSASHA1 | -- | SHA-256 CoseHashAlgRSASHA256 | -- | SHA-384 CoseHashAlgRSASHA384 | -- | SHA-512 CoseHashAlgRSASHA512 deriving (Eq, Show, Ord, Enum, Bounded, Generic, ToJSON) -- | [(spec)](https://datatracker.ietf.org/doc/html/draft-ietf-cose-rfc8152bis-algs-12#section-2.2) -- [Cose Algorithm registry](https://www.iana.org/assignments/cose/cose.xhtml#algorithms) -- entry @EdDSA@. Alias for 'CoseSignAlgEdDSA' -- -- * Name: EdDSA -- * Description: EdDSA -- * Recommended: Yes pattern CoseAlgorithmEdDSA :: CoseSignAlg pattern CoseAlgorithmEdDSA = CoseSignAlgEdDSA -- | [(spec)](https://datatracker.ietf.org/doc/html/draft-ietf-cose-rfc8152bis-algs-12#section-2.1) -- [Cose Algorithm registry](https://www.iana.org/assignments/cose/cose.xhtml#algorithms) -- entry @ES256@. Alias for @'CoseSignAlgECDSA' 'CoseHashAlgECDSASHA256'@ -- -- * Name: ES256 -- * Description: ECDSA w/ SHA-256 -- * Recommended: Yes pattern CoseAlgorithmES256 :: CoseSignAlg pattern CoseAlgorithmES256 = CoseSignAlgECDSA CoseHashAlgECDSASHA256 -- | [(spec)](https://datatracker.ietf.org/doc/html/draft-ietf-cose-rfc8152bis-algs-12#section-2.1) -- [Cose Algorithm registry](https://www.iana.org/assignments/cose/cose.xhtml#algorithms) -- entry @ES384@. Alias for @'CoseSignAlgECDSA' 'CoseHashAlgECDSASHA384'@ -- -- * Name: ES384 -- * Description: ECDSA w/ SHA-384 -- * Recommended: Yes pattern CoseAlgorithmES384 :: CoseSignAlg pattern CoseAlgorithmES384 = CoseSignAlgECDSA CoseHashAlgECDSASHA384 -- | [(spec)](https://datatracker.ietf.org/doc/html/draft-ietf-cose-rfc8152bis-algs-12#section-2.1) -- [Cose Algorithm registry](https://www.iana.org/assignments/cose/cose.xhtml#algorithms) -- entry @ES512@. Alias for @'CoseSignAlgECDSA' 'CoseHashAlgECDSASHA512'@ -- -- * Name: ES512 -- * Description: ECDSA w/ SHA-512 -- * Recommended: Yes pattern CoseAlgorithmES512 :: CoseSignAlg pattern CoseAlgorithmES512 = CoseSignAlgECDSA CoseHashAlgECDSASHA512 -- | [(spec)](https://www.rfc-editor.org/rfc/rfc8812.html#section-2) -- [Cose Algorithm registry](https://www.iana.org/assignments/cose/cose.xhtml#algorithms) -- entry @RS256@. Alias for @'CoseSignAlgRSA' 'CoseHashAlgRSASHA256'@ -- -- * Name: RS256 -- * Description: RSASSA-PKCS1-v1_5 using SHA-256 -- * Recommended: No pattern CoseAlgorithmRS256 :: CoseSignAlg pattern CoseAlgorithmRS256 = CoseSignAlgRSA CoseHashAlgRSASHA256 -- | [(spec)](https://www.rfc-editor.org/rfc/rfc8812.html#section-2) -- [Cose Algorithm registry](https://www.iana.org/assignments/cose/cose.xhtml#algorithms) -- entry @RS384@. Alias for @'CoseSignAlgRSA' 'CoseHashAlgRSASHA384'@ -- -- * Name: RS384 -- * Description: RSASSA-PKCS1-v1_5 using SHA-384 -- * Recommended: No pattern CoseAlgorithmRS384 :: CoseSignAlg pattern CoseAlgorithmRS384 = CoseSignAlgRSA CoseHashAlgRSASHA384 -- | [(spec)](https://www.rfc-editor.org/rfc/rfc8812.html#section-2) -- [Cose Algorithm registry](https://www.iana.org/assignments/cose/cose.xhtml#algorithms) -- entry @RS512@. Alias for @'CoseSignAlgRSA' 'CoseHashAlgRSASHA512'@ -- -- * Name: RS512 -- * Description: RSASSA-PKCS1-v1_5 using SHA-512 -- * Recommended: No pattern CoseAlgorithmRS512 :: CoseSignAlg pattern CoseAlgorithmRS512 = CoseSignAlgRSA CoseHashAlgRSASHA512 -- | [(spec)](https://www.rfc-editor.org/rfc/rfc8812.html#section-2) -- [Cose Algorithm registry](https://www.iana.org/assignments/cose/cose.xhtml#algorithms) -- entry @RS1@. Alias for @'CoseSignAlgRSA' 'CoseHashAlgRSASHA1'@ -- -- * Name: RS1 -- * Description: RSASSA-PKCS1-v1_5 using SHA-1 -- * Recommended: Deprecated pattern CoseAlgorithmRS1 :: CoseSignAlg pattern CoseAlgorithmRS1 = CoseSignAlgRSA CoseHashAlgRSASHA1 -- | Serialises COSE Algorithms using the @Value@ column from the -- [COSE Algorithms registry](https://www.iana.org/assignments/cose/cose.xhtml#algorithms). -- This uses the 'fromCoseSignAlg' and 'toCoseSignAlg' functions to do the -- encoding and decoding respectively. instance Serialise CoseSignAlg where encode = encodeInt . fromCoseSignAlg decode = do int <- decodeIntCanonical case toCoseSignAlg int of Right res -> pure res Left err -> fail $ Text.unpack err -- | Converts a 'CoseSignAlg' to the corresponding integer value from the -- [COSE Algorithms registry](https://www.iana.org/assignments/cose/cose.xhtml#algorithms). -- The inverse operation is 'toCoseSignAlg' fromCoseSignAlg :: Num p => CoseSignAlg -> p fromCoseSignAlg (CoseSignAlgRSA CoseHashAlgRSASHA1) = -65535 fromCoseSignAlg (CoseSignAlgRSA CoseHashAlgRSASHA512) = -259 fromCoseSignAlg (CoseSignAlgRSA CoseHashAlgRSASHA384) = -258 fromCoseSignAlg (CoseSignAlgRSA CoseHashAlgRSASHA256) = -257 fromCoseSignAlg (CoseSignAlgECDSA CoseHashAlgECDSASHA512) = -36 fromCoseSignAlg (CoseSignAlgECDSA CoseHashAlgECDSASHA384) = -35 fromCoseSignAlg CoseSignAlgEdDSA = -8 fromCoseSignAlg (CoseSignAlgECDSA CoseHashAlgECDSASHA256) = -7 -- | Converts an integer value to the corresponding 'CoseSignAlg' from the -- [COSE Algorithms registry](https://www.iana.org/assignments/cose/cose.xhtml#algorithms). -- Returns an error if the integer doesn't represent a known algorithm. -- The inverse operation is 'fromCoseSignAlg' toCoseSignAlg :: (Eq a, Num a, Show a) => a -> Either Text CoseSignAlg toCoseSignAlg (-65535) = pure (CoseSignAlgRSA CoseHashAlgRSASHA1) toCoseSignAlg (-259) = pure (CoseSignAlgRSA CoseHashAlgRSASHA512) toCoseSignAlg (-258) = pure (CoseSignAlgRSA CoseHashAlgRSASHA384) toCoseSignAlg (-257) = pure (CoseSignAlgRSA CoseHashAlgRSASHA256) toCoseSignAlg (-36) = pure (CoseSignAlgECDSA CoseHashAlgECDSASHA512) toCoseSignAlg (-35) = pure (CoseSignAlgECDSA CoseHashAlgECDSASHA384) toCoseSignAlg (-8) = pure CoseSignAlgEdDSA toCoseSignAlg (-7) = pure (CoseSignAlgECDSA CoseHashAlgECDSASHA256) toCoseSignAlg value = Left $ "Unknown COSE algorithm value " <> Text.pack (show value)