{-# LANGUAGE PatternSynonyms #-}
{-# LANGUAGE RecordWildCards #-}

-- | Stability: experimental
-- This module contains a partial implementation of the
-- [COSE_Key](https://datatracker.ietf.org/doc/html/rfc8152#section-7) format,
-- limited to what is needed for Webauthn, and in a structured way.
module Crypto.WebAuthn.Cose.PublicKey
  ( -- * Public key
    UncheckedPublicKey (..),
    checkPublicKey,
    PublicKey (PublicKey),

    -- * COSE Elliptic Curves
    CoseCurveEdDSA (..),
    coordinateSizeEdDSA,
    CoseCurveECDSA (..),
    toCryptCurveECDSA,
    fromCryptCurveECDSA,
    coordinateSizeECDSA,
  )
where

import qualified Crypto.PubKey.ECC.Prim as ECC
import qualified Crypto.PubKey.ECC.Types as ECC
import qualified Crypto.PubKey.Ed25519 as Ed25519
import Crypto.WebAuthn.Internal.ToJSONOrphans ()
import Data.Aeson (ToJSON)
import qualified Data.ByteString as BS
import qualified Data.ByteString.Base16 as Base16
import Data.Text (Text)
import qualified Data.Text as Text
import qualified Data.Text.Encoding as Text
import GHC.Generics (Generic)

-- | [(spec)](https://www.w3.org/TR/webauthn-2/#credentialpublickey)
-- A structured representation of a [COSE_Key](https://datatracker.ietf.org/doc/html/rfc8152#section-7)
-- limited to what is know to be necessary for Webauthn public keys for the
-- [credentialPublicKey](https://www.w3.org/TR/webauthn-2/#credentialpublickey) field,
-- and without any signing algorithm parameters like hashes. Due to the raw
-- nature of parameters, this type is labeled as unchecked. Parameters are
-- checked by using the 'checkPublicKey' function, returning a t'PublicKey'
-- type.
data UncheckedPublicKey
  = -- | [(spec)](https://datatracker.ietf.org/doc/html/draft-ietf-cose-rfc8152bis-algs-12#section-2.2)
    -- EdDSA Signature Algorithm
    --
    -- [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)
    PublicKeyEdDSA
      { -- | [(spec)](https://datatracker.ietf.org/doc/html/draft-ietf-cose-rfc8152bis-algs-12#section-7.2)
        -- The elliptic curve to use
        UncheckedPublicKey -> CoseCurveEdDSA
eddsaCurve :: CoseCurveEdDSA,
        -- | [(spec)](https://datatracker.ietf.org/doc/html/draft-ietf-cose-rfc8152bis-algs-12#section-7.2)
        -- This contains the public key bytes.
        UncheckedPublicKey -> ByteString
eddsaX :: BS.ByteString
      }
  | -- | [(spec)](https://datatracker.ietf.org/doc/html/draft-ietf-cose-rfc8152bis-algs-12#section-2.1)
    -- ECDSA Signature Algorithm
    --
    -- 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)
    PublicKeyECDSA
      { -- | [(spec)](https://datatracker.ietf.org/doc/html/draft-ietf-cose-rfc8152bis-algs-12#section-7.1.1)
        -- The elliptic curve to use
        UncheckedPublicKey -> CoseCurveECDSA
ecdsaCurve :: CoseCurveECDSA,
        -- | [(spec)](https://datatracker.ietf.org/doc/html/draft-ietf-cose-rfc8152bis-algs-12#section-7.1.1)
        -- 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.
        UncheckedPublicKey -> Integer
ecdsaX :: Integer,
        -- | [(spec)](https://datatracker.ietf.org/doc/html/draft-ietf-cose-rfc8152bis-algs-12#section-7.1.1)
        -- This contains 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.
        UncheckedPublicKey -> Integer
ecdsaY :: Integer
      }
  | -- | [(spec)](https://www.rfc-editor.org/rfc/rfc8812.html#section-2)
    -- [RSASSA-PKCS1-v1_5](https://www.rfc-editor.org/rfc/rfc8017#section-8.2) Signature Algorithm
    --
    -- 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)
    PublicKeyRSA
      { -- | [(spec)](https://www.rfc-editor.org/rfc/rfc8230.html#section-4)
        -- The RSA modulus n is a product of u distinct odd primes
        -- r_i, i = 1, 2, ..., u, where u >= 2
        UncheckedPublicKey -> Integer
rsaN :: Integer,
        -- | [(spec)](https://www.rfc-editor.org/rfc/rfc8230.html#section-4)
        -- 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)
        UncheckedPublicKey -> Integer
rsaE :: Integer
      }
  deriving (UncheckedPublicKey -> UncheckedPublicKey -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: UncheckedPublicKey -> UncheckedPublicKey -> Bool
$c/= :: UncheckedPublicKey -> UncheckedPublicKey -> Bool
== :: UncheckedPublicKey -> UncheckedPublicKey -> Bool
$c== :: UncheckedPublicKey -> UncheckedPublicKey -> Bool
Eq, Int -> UncheckedPublicKey -> ShowS
[UncheckedPublicKey] -> ShowS
UncheckedPublicKey -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [UncheckedPublicKey] -> ShowS
$cshowList :: [UncheckedPublicKey] -> ShowS
show :: UncheckedPublicKey -> String
$cshow :: UncheckedPublicKey -> String
showsPrec :: Int -> UncheckedPublicKey -> ShowS
$cshowsPrec :: Int -> UncheckedPublicKey -> ShowS
Show, forall x. Rep UncheckedPublicKey x -> UncheckedPublicKey
forall x. UncheckedPublicKey -> Rep UncheckedPublicKey x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep UncheckedPublicKey x -> UncheckedPublicKey
$cfrom :: forall x. UncheckedPublicKey -> Rep UncheckedPublicKey x
Generic, [UncheckedPublicKey] -> Encoding
[UncheckedPublicKey] -> Value
UncheckedPublicKey -> Encoding
UncheckedPublicKey -> Value
forall a.
(a -> Value)
-> (a -> Encoding)
-> ([a] -> Value)
-> ([a] -> Encoding)
-> ToJSON a
toEncodingList :: [UncheckedPublicKey] -> Encoding
$ctoEncodingList :: [UncheckedPublicKey] -> Encoding
toJSONList :: [UncheckedPublicKey] -> Value
$ctoJSONList :: [UncheckedPublicKey] -> Value
toEncoding :: UncheckedPublicKey -> Encoding
$ctoEncoding :: UncheckedPublicKey -> Encoding
toJSON :: UncheckedPublicKey -> Value
$ctoJSON :: UncheckedPublicKey -> Value
ToJSON)

-- | Same as 'UncheckedPublicKey', but checked to be valid using
-- 'checkPublicKey'.
newtype PublicKey = CheckedPublicKey UncheckedPublicKey
  deriving newtype (PublicKey -> PublicKey -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: PublicKey -> PublicKey -> Bool
$c/= :: PublicKey -> PublicKey -> Bool
== :: PublicKey -> PublicKey -> Bool
$c== :: PublicKey -> PublicKey -> Bool
Eq, Int -> PublicKey -> ShowS
[PublicKey] -> ShowS
PublicKey -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [PublicKey] -> ShowS
$cshowList :: [PublicKey] -> ShowS
show :: PublicKey -> String
$cshow :: PublicKey -> String
showsPrec :: Int -> PublicKey -> ShowS
$cshowsPrec :: Int -> PublicKey -> ShowS
Show, [PublicKey] -> Encoding
[PublicKey] -> Value
PublicKey -> Encoding
PublicKey -> Value
forall a.
(a -> Value)
-> (a -> Encoding)
-> ([a] -> Value)
-> ([a] -> Encoding)
-> ToJSON a
toEncodingList :: [PublicKey] -> Encoding
$ctoEncodingList :: [PublicKey] -> Encoding
toJSONList :: [PublicKey] -> Value
$ctoJSONList :: [PublicKey] -> Value
toEncoding :: PublicKey -> Encoding
$ctoEncoding :: PublicKey -> Encoding
toJSON :: PublicKey -> Value
$ctoJSON :: PublicKey -> Value
ToJSON)

-- | Returns the 'UncheckedPublicKey' for a t'PublicKey'
pattern PublicKey :: UncheckedPublicKey -> PublicKey
pattern $mPublicKey :: forall {r}.
PublicKey -> (UncheckedPublicKey -> r) -> ((# #) -> r) -> r
PublicKey k <- CheckedPublicKey k

{-# COMPLETE PublicKey #-}

-- | Checks whether an 'UncheckedPublicKey' is valid. This is the only way to construct a t'PublicKey'
checkPublicKey :: UncheckedPublicKey -> Either Text PublicKey
checkPublicKey :: UncheckedPublicKey -> Either Text PublicKey
checkPublicKey key :: UncheckedPublicKey
key@PublicKeyEdDSA {ByteString
CoseCurveEdDSA
eddsaX :: ByteString
eddsaCurve :: CoseCurveEdDSA
eddsaX :: UncheckedPublicKey -> ByteString
eddsaCurve :: UncheckedPublicKey -> CoseCurveEdDSA
..}
  | Int
actualSize forall a. Eq a => a -> a -> Bool
== Int
expectedSize = forall a b. b -> Either a b
Right forall a b. (a -> b) -> a -> b
$ UncheckedPublicKey -> PublicKey
CheckedPublicKey UncheckedPublicKey
key
  | Bool
otherwise =
      forall a b. a -> Either a b
Left forall a b. (a -> b) -> a -> b
$
        Text
"EdDSA public key for curve "
          forall a. Semigroup a => a -> a -> a
<> String -> Text
Text.pack (forall a. Show a => a -> String
show CoseCurveEdDSA
eddsaCurve)
          forall a. Semigroup a => a -> a -> a
<> Text
" didn't have the expected size of "
          forall a. Semigroup a => a -> a -> a
<> String -> Text
Text.pack (forall a. Show a => a -> String
show Int
expectedSize)
          forall a. Semigroup a => a -> a -> a
<> Text
" bytes, it has "
          forall a. Semigroup a => a -> a -> a
<> String -> Text
Text.pack (forall a. Show a => a -> String
show Int
actualSize)
          forall a. Semigroup a => a -> a -> a
<> Text
" bytes instead: "
          forall a. Semigroup a => a -> a -> a
<> ByteString -> Text
Text.decodeUtf8 (ByteString -> ByteString
Base16.encode ByteString
eddsaX)
  where
    actualSize :: Int
actualSize = ByteString -> Int
BS.length ByteString
eddsaX
    expectedSize :: Int
expectedSize = CoseCurveEdDSA -> Int
coordinateSizeEdDSA CoseCurveEdDSA
eddsaCurve
checkPublicKey key :: UncheckedPublicKey
key@PublicKeyECDSA {Integer
CoseCurveECDSA
ecdsaY :: Integer
ecdsaX :: Integer
ecdsaCurve :: CoseCurveECDSA
ecdsaY :: UncheckedPublicKey -> Integer
ecdsaX :: UncheckedPublicKey -> Integer
ecdsaCurve :: UncheckedPublicKey -> CoseCurveECDSA
..}
  | Curve -> Point -> Bool
ECC.isPointValid Curve
curve Point
point = forall a b. b -> Either a b
Right forall a b. (a -> b) -> a -> b
$ UncheckedPublicKey -> PublicKey
CheckedPublicKey UncheckedPublicKey
key
  | Bool
otherwise =
      forall a b. a -> Either a b
Left forall a b. (a -> b) -> a -> b
$
        Text
"ECDSA public key point is not valid for curve "
          forall a. Semigroup a => a -> a -> a
<> String -> Text
Text.pack (forall a. Show a => a -> String
show CoseCurveECDSA
ecdsaCurve)
          forall a. Semigroup a => a -> a -> a
<> Text
": "
          forall a. Semigroup a => a -> a -> a
<> String -> Text
Text.pack (forall a. Show a => a -> String
show Point
point)
  where
    curve :: Curve
curve = CurveName -> Curve
ECC.getCurveByName (CoseCurveECDSA -> CurveName
toCryptCurveECDSA CoseCurveECDSA
ecdsaCurve)
    point :: Point
point = Integer -> Integer -> Point
ECC.Point Integer
ecdsaX Integer
ecdsaY
checkPublicKey UncheckedPublicKey
key = forall a b. b -> Either a b
Right forall a b. (a -> b) -> a -> b
$ UncheckedPublicKey -> PublicKey
CheckedPublicKey UncheckedPublicKey
key

-- | COSE elliptic curves that can be used with EdDSA
data CoseCurveEdDSA
  = -- | [(spec)](https://datatracker.ietf.org/doc/html/draft-ietf-cose-rfc8152bis-algs-12#section-7.1)
    -- Ed25519 for use w/ EdDSA only
    CoseCurveEd25519
  deriving (CoseCurveEdDSA -> CoseCurveEdDSA -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: CoseCurveEdDSA -> CoseCurveEdDSA -> Bool
$c/= :: CoseCurveEdDSA -> CoseCurveEdDSA -> Bool
== :: CoseCurveEdDSA -> CoseCurveEdDSA -> Bool
$c== :: CoseCurveEdDSA -> CoseCurveEdDSA -> Bool
Eq, Int -> CoseCurveEdDSA -> ShowS
[CoseCurveEdDSA] -> ShowS
CoseCurveEdDSA -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [CoseCurveEdDSA] -> ShowS
$cshowList :: [CoseCurveEdDSA] -> ShowS
show :: CoseCurveEdDSA -> String
$cshow :: CoseCurveEdDSA -> String
showsPrec :: Int -> CoseCurveEdDSA -> ShowS
$cshowsPrec :: Int -> CoseCurveEdDSA -> ShowS
Show, Int -> CoseCurveEdDSA
CoseCurveEdDSA -> Int
CoseCurveEdDSA -> [CoseCurveEdDSA]
CoseCurveEdDSA -> CoseCurveEdDSA
CoseCurveEdDSA -> CoseCurveEdDSA -> [CoseCurveEdDSA]
CoseCurveEdDSA
-> CoseCurveEdDSA -> CoseCurveEdDSA -> [CoseCurveEdDSA]
forall a.
(a -> a)
-> (a -> a)
-> (Int -> a)
-> (a -> Int)
-> (a -> [a])
-> (a -> a -> [a])
-> (a -> a -> [a])
-> (a -> a -> a -> [a])
-> Enum a
enumFromThenTo :: CoseCurveEdDSA
-> CoseCurveEdDSA -> CoseCurveEdDSA -> [CoseCurveEdDSA]
$cenumFromThenTo :: CoseCurveEdDSA
-> CoseCurveEdDSA -> CoseCurveEdDSA -> [CoseCurveEdDSA]
enumFromTo :: CoseCurveEdDSA -> CoseCurveEdDSA -> [CoseCurveEdDSA]
$cenumFromTo :: CoseCurveEdDSA -> CoseCurveEdDSA -> [CoseCurveEdDSA]
enumFromThen :: CoseCurveEdDSA -> CoseCurveEdDSA -> [CoseCurveEdDSA]
$cenumFromThen :: CoseCurveEdDSA -> CoseCurveEdDSA -> [CoseCurveEdDSA]
enumFrom :: CoseCurveEdDSA -> [CoseCurveEdDSA]
$cenumFrom :: CoseCurveEdDSA -> [CoseCurveEdDSA]
fromEnum :: CoseCurveEdDSA -> Int
$cfromEnum :: CoseCurveEdDSA -> Int
toEnum :: Int -> CoseCurveEdDSA
$ctoEnum :: Int -> CoseCurveEdDSA
pred :: CoseCurveEdDSA -> CoseCurveEdDSA
$cpred :: CoseCurveEdDSA -> CoseCurveEdDSA
succ :: CoseCurveEdDSA -> CoseCurveEdDSA
$csucc :: CoseCurveEdDSA -> CoseCurveEdDSA
Enum, CoseCurveEdDSA
forall a. a -> a -> Bounded a
maxBound :: CoseCurveEdDSA
$cmaxBound :: CoseCurveEdDSA
minBound :: CoseCurveEdDSA
$cminBound :: CoseCurveEdDSA
Bounded, forall x. Rep CoseCurveEdDSA x -> CoseCurveEdDSA
forall x. CoseCurveEdDSA -> Rep CoseCurveEdDSA x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep CoseCurveEdDSA x -> CoseCurveEdDSA
$cfrom :: forall x. CoseCurveEdDSA -> Rep CoseCurveEdDSA x
Generic, [CoseCurveEdDSA] -> Encoding
[CoseCurveEdDSA] -> Value
CoseCurveEdDSA -> Encoding
CoseCurveEdDSA -> Value
forall a.
(a -> Value)
-> (a -> Encoding)
-> ([a] -> Value)
-> ([a] -> Encoding)
-> ToJSON a
toEncodingList :: [CoseCurveEdDSA] -> Encoding
$ctoEncodingList :: [CoseCurveEdDSA] -> Encoding
toJSONList :: [CoseCurveEdDSA] -> Value
$ctoJSONList :: [CoseCurveEdDSA] -> Value
toEncoding :: CoseCurveEdDSA -> Encoding
$ctoEncoding :: CoseCurveEdDSA -> Encoding
toJSON :: CoseCurveEdDSA -> Value
$ctoJSON :: CoseCurveEdDSA -> Value
ToJSON)

-- | Returns the size of a coordinate point for a specific EdDSA curve in bytes.
coordinateSizeEdDSA :: CoseCurveEdDSA -> Int
coordinateSizeEdDSA :: CoseCurveEdDSA -> Int
coordinateSizeEdDSA CoseCurveEdDSA
CoseCurveEd25519 = Int
Ed25519.publicKeySize

-- | COSE elliptic curves that can be used with ECDSA
data CoseCurveECDSA
  = -- | [(spec)](https://datatracker.ietf.org/doc/html/draft-ietf-cose-rfc8152bis-algs-12#section-7.1)
    -- NIST P-256 also known as secp256r1
    CoseCurveP256
  | -- | [(spec)](https://datatracker.ietf.org/doc/html/draft-ietf-cose-rfc8152bis-algs-12#section-7.1)
    -- NIST P-384 also known as secp384r1
    CoseCurveP384
  | -- | [(spec)](https://datatracker.ietf.org/doc/html/draft-ietf-cose-rfc8152bis-algs-12#section-7.1)
    -- NIST P-521 also known as secp521r1
    CoseCurveP521
  deriving (CoseCurveECDSA -> CoseCurveECDSA -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: CoseCurveECDSA -> CoseCurveECDSA -> Bool
$c/= :: CoseCurveECDSA -> CoseCurveECDSA -> Bool
== :: CoseCurveECDSA -> CoseCurveECDSA -> Bool
$c== :: CoseCurveECDSA -> CoseCurveECDSA -> Bool
Eq, Int -> CoseCurveECDSA -> ShowS
[CoseCurveECDSA] -> ShowS
CoseCurveECDSA -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [CoseCurveECDSA] -> ShowS
$cshowList :: [CoseCurveECDSA] -> ShowS
show :: CoseCurveECDSA -> String
$cshow :: CoseCurveECDSA -> String
showsPrec :: Int -> CoseCurveECDSA -> ShowS
$cshowsPrec :: Int -> CoseCurveECDSA -> ShowS
Show, Int -> CoseCurveECDSA
CoseCurveECDSA -> Int
CoseCurveECDSA -> [CoseCurveECDSA]
CoseCurveECDSA -> CoseCurveECDSA
CoseCurveECDSA -> CoseCurveECDSA -> [CoseCurveECDSA]
CoseCurveECDSA
-> CoseCurveECDSA -> CoseCurveECDSA -> [CoseCurveECDSA]
forall a.
(a -> a)
-> (a -> a)
-> (Int -> a)
-> (a -> Int)
-> (a -> [a])
-> (a -> a -> [a])
-> (a -> a -> [a])
-> (a -> a -> a -> [a])
-> Enum a
enumFromThenTo :: CoseCurveECDSA
-> CoseCurveECDSA -> CoseCurveECDSA -> [CoseCurveECDSA]
$cenumFromThenTo :: CoseCurveECDSA
-> CoseCurveECDSA -> CoseCurveECDSA -> [CoseCurveECDSA]
enumFromTo :: CoseCurveECDSA -> CoseCurveECDSA -> [CoseCurveECDSA]
$cenumFromTo :: CoseCurveECDSA -> CoseCurveECDSA -> [CoseCurveECDSA]
enumFromThen :: CoseCurveECDSA -> CoseCurveECDSA -> [CoseCurveECDSA]
$cenumFromThen :: CoseCurveECDSA -> CoseCurveECDSA -> [CoseCurveECDSA]
enumFrom :: CoseCurveECDSA -> [CoseCurveECDSA]
$cenumFrom :: CoseCurveECDSA -> [CoseCurveECDSA]
fromEnum :: CoseCurveECDSA -> Int
$cfromEnum :: CoseCurveECDSA -> Int
toEnum :: Int -> CoseCurveECDSA
$ctoEnum :: Int -> CoseCurveECDSA
pred :: CoseCurveECDSA -> CoseCurveECDSA
$cpred :: CoseCurveECDSA -> CoseCurveECDSA
succ :: CoseCurveECDSA -> CoseCurveECDSA
$csucc :: CoseCurveECDSA -> CoseCurveECDSA
Enum, CoseCurveECDSA
forall a. a -> a -> Bounded a
maxBound :: CoseCurveECDSA
$cmaxBound :: CoseCurveECDSA
minBound :: CoseCurveECDSA
$cminBound :: CoseCurveECDSA
Bounded, forall x. Rep CoseCurveECDSA x -> CoseCurveECDSA
forall x. CoseCurveECDSA -> Rep CoseCurveECDSA x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep CoseCurveECDSA x -> CoseCurveECDSA
$cfrom :: forall x. CoseCurveECDSA -> Rep CoseCurveECDSA x
Generic, [CoseCurveECDSA] -> Encoding
[CoseCurveECDSA] -> Value
CoseCurveECDSA -> Encoding
CoseCurveECDSA -> Value
forall a.
(a -> Value)
-> (a -> Encoding)
-> ([a] -> Value)
-> ([a] -> Encoding)
-> ToJSON a
toEncodingList :: [CoseCurveECDSA] -> Encoding
$ctoEncodingList :: [CoseCurveECDSA] -> Encoding
toJSONList :: [CoseCurveECDSA] -> Value
$ctoJSONList :: [CoseCurveECDSA] -> Value
toEncoding :: CoseCurveECDSA -> Encoding
$ctoEncoding :: CoseCurveECDSA -> Encoding
toJSON :: CoseCurveECDSA -> Value
$ctoJSON :: CoseCurveECDSA -> Value
ToJSON)

-- | Converts a 'Cose.CoseCurveECDSA' to an 'ECC.CurveName'. The inverse
-- function is 'fromCryptCurveECDSA'
toCryptCurveECDSA :: CoseCurveECDSA -> ECC.CurveName
toCryptCurveECDSA :: CoseCurveECDSA -> CurveName
toCryptCurveECDSA CoseCurveECDSA
CoseCurveP256 = CurveName
ECC.SEC_p256r1
toCryptCurveECDSA CoseCurveECDSA
CoseCurveP384 = CurveName
ECC.SEC_p384r1
toCryptCurveECDSA CoseCurveECDSA
CoseCurveP521 = CurveName
ECC.SEC_p521r1

-- | Tries to converts a 'ECC.CurveName' to an 'Cose.CoseCurveECDSA'. The inverse
-- function is 'toCryptCurveECDSA'
fromCryptCurveECDSA :: ECC.CurveName -> Either Text CoseCurveECDSA
fromCryptCurveECDSA :: CurveName -> Either Text CoseCurveECDSA
fromCryptCurveECDSA CurveName
ECC.SEC_p256r1 = forall a b. b -> Either a b
Right CoseCurveECDSA
CoseCurveP256
fromCryptCurveECDSA CurveName
ECC.SEC_p384r1 = forall a b. b -> Either a b
Right CoseCurveECDSA
CoseCurveP384
fromCryptCurveECDSA CurveName
ECC.SEC_p521r1 = forall a b. b -> Either a b
Right CoseCurveECDSA
CoseCurveP521
fromCryptCurveECDSA CurveName
curve =
  forall a b. a -> Either a b
Left forall a b. (a -> b) -> a -> b
$
    Text
"Curve "
      forall a. Semigroup a => a -> a -> a
<> String -> Text
Text.pack (forall a. Show a => a -> String
show CurveName
curve)
      forall a. Semigroup a => a -> a -> a
<> Text
" is not a supported COSE ECDSA public key curve"

-- | Returns the size of a coordinate point for a specific ECDSA curve in bytes.
coordinateSizeECDSA :: CoseCurveECDSA -> Int
coordinateSizeECDSA :: CoseCurveECDSA -> Int
coordinateSizeECDSA CoseCurveECDSA
curve = Int
byteSize
  where
    bitSize :: Int
bitSize = Curve -> Int
ECC.curveSizeBits (CurveName -> Curve
ECC.getCurveByName (CoseCurveECDSA -> CurveName
toCryptCurveECDSA CoseCurveECDSA
curve))
    byteSize :: Int
byteSize = (Int
bitSize forall a. Num a => a -> a -> a
+ Int
7) forall a. Integral a => a -> a -> a
`div` Int
8