diff --git a/sbp.cabal b/sbp.cabal
--- a/sbp.cabal
+++ b/sbp.cabal
@@ -1,5 +1,5 @@
 name:                  sbp
-version:               4.12.0
+version:               4.13.0
 synopsis:              SwiftNav's SBP Library
 homepage:              https://github.com/swift-nav/libsbp
 license:               MIT
diff --git a/src/SwiftNav/SBP/Msg.hs b/src/SwiftNav/SBP/Msg.hs
--- a/src/SwiftNav/SBP/Msg.hs
+++ b/src/SwiftNav/SBP/Msg.hs
@@ -85,6 +85,8 @@
    | SBPMsgBootloaderHandshakeResp MsgBootloaderHandshakeResp Msg
    | SBPMsgBootloaderJumpToApp MsgBootloaderJumpToApp Msg
    | SBPMsgCellModemStatus MsgCellModemStatus Msg
+   | SBPMsgCertificateChain MsgCertificateChain Msg
+   | SBPMsgCertificateChainDep MsgCertificateChainDep Msg
    | SBPMsgCommandOutput MsgCommandOutput Msg
    | SBPMsgCommandReq MsgCommandReq Msg
    | SBPMsgCommandResp MsgCommandResp Msg
@@ -96,9 +98,13 @@
    | SBPMsgDgnssStatus MsgDgnssStatus Msg
    | SBPMsgDops MsgDops Msg
    | SBPMsgDopsDepA MsgDopsDepA Msg
-   | SBPMsgEd25519Certificate MsgEd25519Certificate Msg
-   | SBPMsgEd25519Signature MsgEd25519Signature Msg
-   | SBPMsgEd25519SignatureDep MsgEd25519SignatureDep Msg
+   | SBPMsgEcdsaCertificate MsgEcdsaCertificate Msg
+   | SBPMsgEcdsaSignature MsgEcdsaSignature Msg
+   | SBPMsgEcdsaSignatureDepA MsgEcdsaSignatureDepA Msg
+   | SBPMsgEcdsaSignatureDepB MsgEcdsaSignatureDepB Msg
+   | SBPMsgEd25519CertificateDep MsgEd25519CertificateDep Msg
+   | SBPMsgEd25519SignatureDepA MsgEd25519SignatureDepA Msg
+   | SBPMsgEd25519SignatureDepB MsgEd25519SignatureDepB Msg
    | SBPMsgEphemerisBds MsgEphemerisBds Msg
    | SBPMsgEphemerisDepA MsgEphemerisDepA Msg
    | SBPMsgEphemerisDepB MsgEphemerisDepB Msg
@@ -325,6 +331,8 @@
           | _msgSBPType == msgBootloaderHandshakeResp = SBPMsgBootloaderHandshakeResp (decode (fromStrict (unBytes _msgSBPPayload))) m
           | _msgSBPType == msgBootloaderJumpToApp = SBPMsgBootloaderJumpToApp (decode (fromStrict (unBytes _msgSBPPayload))) m
           | _msgSBPType == msgCellModemStatus = SBPMsgCellModemStatus (decode (fromStrict (unBytes _msgSBPPayload))) m
+          | _msgSBPType == msgCertificateChain = SBPMsgCertificateChain (decode (fromStrict (unBytes _msgSBPPayload))) m
+          | _msgSBPType == msgCertificateChainDep = SBPMsgCertificateChainDep (decode (fromStrict (unBytes _msgSBPPayload))) m
           | _msgSBPType == msgCommandOutput = SBPMsgCommandOutput (decode (fromStrict (unBytes _msgSBPPayload))) m
           | _msgSBPType == msgCommandReq = SBPMsgCommandReq (decode (fromStrict (unBytes _msgSBPPayload))) m
           | _msgSBPType == msgCommandResp = SBPMsgCommandResp (decode (fromStrict (unBytes _msgSBPPayload))) m
@@ -336,9 +344,13 @@
           | _msgSBPType == msgDgnssStatus = SBPMsgDgnssStatus (decode (fromStrict (unBytes _msgSBPPayload))) m
           | _msgSBPType == msgDops = SBPMsgDops (decode (fromStrict (unBytes _msgSBPPayload))) m
           | _msgSBPType == msgDopsDepA = SBPMsgDopsDepA (decode (fromStrict (unBytes _msgSBPPayload))) m
-          | _msgSBPType == msgEd25519Certificate = SBPMsgEd25519Certificate (decode (fromStrict (unBytes _msgSBPPayload))) m
-          | _msgSBPType == msgEd25519Signature = SBPMsgEd25519Signature (decode (fromStrict (unBytes _msgSBPPayload))) m
-          | _msgSBPType == msgEd25519SignatureDep = SBPMsgEd25519SignatureDep (decode (fromStrict (unBytes _msgSBPPayload))) m
+          | _msgSBPType == msgEcdsaCertificate = SBPMsgEcdsaCertificate (decode (fromStrict (unBytes _msgSBPPayload))) m
+          | _msgSBPType == msgEcdsaSignature = SBPMsgEcdsaSignature (decode (fromStrict (unBytes _msgSBPPayload))) m
+          | _msgSBPType == msgEcdsaSignatureDepA = SBPMsgEcdsaSignatureDepA (decode (fromStrict (unBytes _msgSBPPayload))) m
+          | _msgSBPType == msgEcdsaSignatureDepB = SBPMsgEcdsaSignatureDepB (decode (fromStrict (unBytes _msgSBPPayload))) m
+          | _msgSBPType == msgEd25519CertificateDep = SBPMsgEd25519CertificateDep (decode (fromStrict (unBytes _msgSBPPayload))) m
+          | _msgSBPType == msgEd25519SignatureDepA = SBPMsgEd25519SignatureDepA (decode (fromStrict (unBytes _msgSBPPayload))) m
+          | _msgSBPType == msgEd25519SignatureDepB = SBPMsgEd25519SignatureDepB (decode (fromStrict (unBytes _msgSBPPayload))) m
           | _msgSBPType == msgEphemerisBds = SBPMsgEphemerisBds (decode (fromStrict (unBytes _msgSBPPayload))) m
           | _msgSBPType == msgEphemerisDepA = SBPMsgEphemerisDepA (decode (fromStrict (unBytes _msgSBPPayload))) m
           | _msgSBPType == msgEphemerisDepB = SBPMsgEphemerisDepB (decode (fromStrict (unBytes _msgSBPPayload))) m
@@ -557,6 +569,8 @@
       encoder (SBPMsgBootloaderHandshakeResp _ m) = put m
       encoder (SBPMsgBootloaderJumpToApp _ m) = put m
       encoder (SBPMsgCellModemStatus _ m) = put m
+      encoder (SBPMsgCertificateChain _ m) = put m
+      encoder (SBPMsgCertificateChainDep _ m) = put m
       encoder (SBPMsgCommandOutput _ m) = put m
       encoder (SBPMsgCommandReq _ m) = put m
       encoder (SBPMsgCommandResp _ m) = put m
@@ -568,9 +582,13 @@
       encoder (SBPMsgDgnssStatus _ m) = put m
       encoder (SBPMsgDops _ m) = put m
       encoder (SBPMsgDopsDepA _ m) = put m
-      encoder (SBPMsgEd25519Certificate _ m) = put m
-      encoder (SBPMsgEd25519Signature _ m) = put m
-      encoder (SBPMsgEd25519SignatureDep _ m) = put m
+      encoder (SBPMsgEcdsaCertificate _ m) = put m
+      encoder (SBPMsgEcdsaSignature _ m) = put m
+      encoder (SBPMsgEcdsaSignatureDepA _ m) = put m
+      encoder (SBPMsgEcdsaSignatureDepB _ m) = put m
+      encoder (SBPMsgEd25519CertificateDep _ m) = put m
+      encoder (SBPMsgEd25519SignatureDepA _ m) = put m
+      encoder (SBPMsgEd25519SignatureDepB _ m) = put m
       encoder (SBPMsgEphemerisBds _ m) = put m
       encoder (SBPMsgEphemerisDepA _ m) = put m
       encoder (SBPMsgEphemerisDepB _ m) = put m
@@ -793,6 +811,8 @@
         | msgType == msgBootloaderHandshakeResp = SBPMsgBootloaderHandshakeResp <$> pure (decode (fromStrict (unBytes payload))) <*> parseJSON obj
         | msgType == msgBootloaderJumpToApp = SBPMsgBootloaderJumpToApp <$> pure (decode (fromStrict (unBytes payload))) <*> parseJSON obj
         | msgType == msgCellModemStatus = SBPMsgCellModemStatus <$> pure (decode (fromStrict (unBytes payload))) <*> parseJSON obj
+        | msgType == msgCertificateChain = SBPMsgCertificateChain <$> pure (decode (fromStrict (unBytes payload))) <*> parseJSON obj
+        | msgType == msgCertificateChainDep = SBPMsgCertificateChainDep <$> pure (decode (fromStrict (unBytes payload))) <*> parseJSON obj
         | msgType == msgCommandOutput = SBPMsgCommandOutput <$> pure (decode (fromStrict (unBytes payload))) <*> parseJSON obj
         | msgType == msgCommandReq = SBPMsgCommandReq <$> pure (decode (fromStrict (unBytes payload))) <*> parseJSON obj
         | msgType == msgCommandResp = SBPMsgCommandResp <$> pure (decode (fromStrict (unBytes payload))) <*> parseJSON obj
@@ -804,9 +824,13 @@
         | msgType == msgDgnssStatus = SBPMsgDgnssStatus <$> pure (decode (fromStrict (unBytes payload))) <*> parseJSON obj
         | msgType == msgDops = SBPMsgDops <$> pure (decode (fromStrict (unBytes payload))) <*> parseJSON obj
         | msgType == msgDopsDepA = SBPMsgDopsDepA <$> pure (decode (fromStrict (unBytes payload))) <*> parseJSON obj
-        | msgType == msgEd25519Certificate = SBPMsgEd25519Certificate <$> pure (decode (fromStrict (unBytes payload))) <*> parseJSON obj
-        | msgType == msgEd25519Signature = SBPMsgEd25519Signature <$> pure (decode (fromStrict (unBytes payload))) <*> parseJSON obj
-        | msgType == msgEd25519SignatureDep = SBPMsgEd25519SignatureDep <$> pure (decode (fromStrict (unBytes payload))) <*> parseJSON obj
+        | msgType == msgEcdsaCertificate = SBPMsgEcdsaCertificate <$> pure (decode (fromStrict (unBytes payload))) <*> parseJSON obj
+        | msgType == msgEcdsaSignature = SBPMsgEcdsaSignature <$> pure (decode (fromStrict (unBytes payload))) <*> parseJSON obj
+        | msgType == msgEcdsaSignatureDepA = SBPMsgEcdsaSignatureDepA <$> pure (decode (fromStrict (unBytes payload))) <*> parseJSON obj
+        | msgType == msgEcdsaSignatureDepB = SBPMsgEcdsaSignatureDepB <$> pure (decode (fromStrict (unBytes payload))) <*> parseJSON obj
+        | msgType == msgEd25519CertificateDep = SBPMsgEd25519CertificateDep <$> pure (decode (fromStrict (unBytes payload))) <*> parseJSON obj
+        | msgType == msgEd25519SignatureDepA = SBPMsgEd25519SignatureDepA <$> pure (decode (fromStrict (unBytes payload))) <*> parseJSON obj
+        | msgType == msgEd25519SignatureDepB = SBPMsgEd25519SignatureDepB <$> pure (decode (fromStrict (unBytes payload))) <*> parseJSON obj
         | msgType == msgEphemerisBds = SBPMsgEphemerisBds <$> pure (decode (fromStrict (unBytes payload))) <*> parseJSON obj
         | msgType == msgEphemerisDepA = SBPMsgEphemerisDepA <$> pure (decode (fromStrict (unBytes payload))) <*> parseJSON obj
         | msgType == msgEphemerisDepB = SBPMsgEphemerisDepB <$> pure (decode (fromStrict (unBytes payload))) <*> parseJSON obj
@@ -1030,6 +1054,8 @@
   toJSON (SBPMsgBootloaderHandshakeResp n m) = toJSON n <<>> toJSON m
   toJSON (SBPMsgBootloaderJumpToApp n m) = toJSON n <<>> toJSON m
   toJSON (SBPMsgCellModemStatus n m) = toJSON n <<>> toJSON m
+  toJSON (SBPMsgCertificateChain n m) = toJSON n <<>> toJSON m
+  toJSON (SBPMsgCertificateChainDep n m) = toJSON n <<>> toJSON m
   toJSON (SBPMsgCommandOutput n m) = toJSON n <<>> toJSON m
   toJSON (SBPMsgCommandReq n m) = toJSON n <<>> toJSON m
   toJSON (SBPMsgCommandResp n m) = toJSON n <<>> toJSON m
@@ -1041,9 +1067,13 @@
   toJSON (SBPMsgDgnssStatus n m) = toJSON n <<>> toJSON m
   toJSON (SBPMsgDops n m) = toJSON n <<>> toJSON m
   toJSON (SBPMsgDopsDepA n m) = toJSON n <<>> toJSON m
-  toJSON (SBPMsgEd25519Certificate n m) = toJSON n <<>> toJSON m
-  toJSON (SBPMsgEd25519Signature n m) = toJSON n <<>> toJSON m
-  toJSON (SBPMsgEd25519SignatureDep n m) = toJSON n <<>> toJSON m
+  toJSON (SBPMsgEcdsaCertificate n m) = toJSON n <<>> toJSON m
+  toJSON (SBPMsgEcdsaSignature n m) = toJSON n <<>> toJSON m
+  toJSON (SBPMsgEcdsaSignatureDepA n m) = toJSON n <<>> toJSON m
+  toJSON (SBPMsgEcdsaSignatureDepB n m) = toJSON n <<>> toJSON m
+  toJSON (SBPMsgEd25519CertificateDep n m) = toJSON n <<>> toJSON m
+  toJSON (SBPMsgEd25519SignatureDepA n m) = toJSON n <<>> toJSON m
+  toJSON (SBPMsgEd25519SignatureDepB n m) = toJSON n <<>> toJSON m
   toJSON (SBPMsgEphemerisBds n m) = toJSON n <<>> toJSON m
   toJSON (SBPMsgEphemerisDepA n m) = toJSON n <<>> toJSON m
   toJSON (SBPMsgEphemerisDepB n m) = toJSON n <<>> toJSON m
@@ -1261,6 +1291,8 @@
   msg f (SBPMsgBootloaderHandshakeResp n m) = SBPMsgBootloaderHandshakeResp n <$> f m
   msg f (SBPMsgBootloaderJumpToApp n m) = SBPMsgBootloaderJumpToApp n <$> f m
   msg f (SBPMsgCellModemStatus n m) = SBPMsgCellModemStatus n <$> f m
+  msg f (SBPMsgCertificateChain n m) = SBPMsgCertificateChain n <$> f m
+  msg f (SBPMsgCertificateChainDep n m) = SBPMsgCertificateChainDep n <$> f m
   msg f (SBPMsgCommandOutput n m) = SBPMsgCommandOutput n <$> f m
   msg f (SBPMsgCommandReq n m) = SBPMsgCommandReq n <$> f m
   msg f (SBPMsgCommandResp n m) = SBPMsgCommandResp n <$> f m
@@ -1272,9 +1304,13 @@
   msg f (SBPMsgDgnssStatus n m) = SBPMsgDgnssStatus n <$> f m
   msg f (SBPMsgDops n m) = SBPMsgDops n <$> f m
   msg f (SBPMsgDopsDepA n m) = SBPMsgDopsDepA n <$> f m
-  msg f (SBPMsgEd25519Certificate n m) = SBPMsgEd25519Certificate n <$> f m
-  msg f (SBPMsgEd25519Signature n m) = SBPMsgEd25519Signature n <$> f m
-  msg f (SBPMsgEd25519SignatureDep n m) = SBPMsgEd25519SignatureDep n <$> f m
+  msg f (SBPMsgEcdsaCertificate n m) = SBPMsgEcdsaCertificate n <$> f m
+  msg f (SBPMsgEcdsaSignature n m) = SBPMsgEcdsaSignature n <$> f m
+  msg f (SBPMsgEcdsaSignatureDepA n m) = SBPMsgEcdsaSignatureDepA n <$> f m
+  msg f (SBPMsgEcdsaSignatureDepB n m) = SBPMsgEcdsaSignatureDepB n <$> f m
+  msg f (SBPMsgEd25519CertificateDep n m) = SBPMsgEd25519CertificateDep n <$> f m
+  msg f (SBPMsgEd25519SignatureDepA n m) = SBPMsgEd25519SignatureDepA n <$> f m
+  msg f (SBPMsgEd25519SignatureDepB n m) = SBPMsgEd25519SignatureDepB n <$> f m
   msg f (SBPMsgEphemerisBds n m) = SBPMsgEphemerisBds n <$> f m
   msg f (SBPMsgEphemerisDepA n m) = SBPMsgEphemerisDepA n <$> f m
   msg f (SBPMsgEphemerisDepB n m) = SBPMsgEphemerisDepB n <$> f m
diff --git a/src/SwiftNav/SBP/Signing.hs b/src/SwiftNav/SBP/Signing.hs
--- a/src/SwiftNav/SBP/Signing.hs
+++ b/src/SwiftNav/SBP/Signing.hs
@@ -29,110 +29,464 @@
 import Data.Word
 import SwiftNav.SBP.TH
 import SwiftNav.SBP.Types
-import SwiftNav.SBP.Gnss
 
 {-# ANN module ("HLint: ignore Use camelCase"::String) #-}
 {-# ANN module ("HLint: ignore Redundant do"::String) #-}
 {-# ANN module ("HLint: ignore Use newtype instead of data"::String) #-}
 
 
-msgEd25519SignatureDep :: Word16
-msgEd25519SignatureDep = 0x0C01
+data UtcTime = UtcTime
+  { _utcTime_year  :: !Word16
+    -- ^ Year
+  , _utcTime_month :: !Word8
+    -- ^ Month (range 1 .. 12)
+  , _utcTime_day   :: !Word8
+    -- ^ days in the month (range 1-31)
+  , _utcTime_hours :: !Word8
+    -- ^ hours of day (range 0-23)
+  , _utcTime_minutes :: !Word8
+    -- ^ minutes of hour (range 0-59)
+  , _utcTime_seconds :: !Word8
+    -- ^ seconds of minute (range 0-60) rounded down
+  , _utcTime_ns    :: !Word32
+    -- ^ nanoseconds of second (range 0-999999999)
+  } deriving ( Show, Read, Eq )
 
-data MsgEd25519SignatureDep = MsgEd25519SignatureDep
-  { _msgEd25519SignatureDep_signature     :: ![Word8]
-    -- ^ ED25519 signature for messages.
-  , _msgEd25519SignatureDep_fingerprint   :: ![Word8]
-    -- ^ SHA-1 fingerprint of the associated certificate.
-  , _msgEd25519SignatureDep_signed_messages :: ![Word32]
-    -- ^ CRCs of signed messages.
+instance Binary UtcTime where
+  get = do
+    _utcTime_year <- getWord16le
+    _utcTime_month <- getWord8
+    _utcTime_day <- getWord8
+    _utcTime_hours <- getWord8
+    _utcTime_minutes <- getWord8
+    _utcTime_seconds <- getWord8
+    _utcTime_ns <- getWord32le
+    pure UtcTime {..}
+
+  put UtcTime {..} = do
+    putWord16le _utcTime_year
+    putWord8 _utcTime_month
+    putWord8 _utcTime_day
+    putWord8 _utcTime_hours
+    putWord8 _utcTime_minutes
+    putWord8 _utcTime_seconds
+    putWord32le _utcTime_ns
+
+$(makeJSON "_utcTime_" ''UtcTime)
+$(makeLenses ''UtcTime)
+
+data ECDSASignature = ECDSASignature
+  { _eCDSASignature_len :: !Word8
+    -- ^ Number of bytes to use of the signature field.  The DER encoded
+    -- signature has a maximum size of 72 bytes but can vary between 70 and 72
+    -- bytes in length.
+  , _eCDSASignature_data :: ![Word8]
+    -- ^ DER encoded ECDSA signature for the messages using SHA-256 as the
+    -- digest algorithm.
   } deriving ( Show, Read, Eq )
 
-instance Binary MsgEd25519SignatureDep where
+instance Binary ECDSASignature where
   get = do
-    _msgEd25519SignatureDep_signature <- replicateM 64 getWord8
-    _msgEd25519SignatureDep_fingerprint <- replicateM 20 getWord8
-    _msgEd25519SignatureDep_signed_messages <- whileM (not <$> isEmpty) getWord32le
-    pure MsgEd25519SignatureDep {..}
+    _eCDSASignature_len <- getWord8
+    _eCDSASignature_data <- replicateM 72 getWord8
+    pure ECDSASignature {..}
 
-  put MsgEd25519SignatureDep {..} = do
-    mapM_ putWord8 _msgEd25519SignatureDep_signature
-    mapM_ putWord8 _msgEd25519SignatureDep_fingerprint
-    mapM_ putWord32le _msgEd25519SignatureDep_signed_messages
+  put ECDSASignature {..} = do
+    putWord8 _eCDSASignature_len
+    mapM_ putWord8 _eCDSASignature_data
 
-$(makeSBP 'msgEd25519SignatureDep ''MsgEd25519SignatureDep)
-$(makeJSON "_msgEd25519SignatureDep_" ''MsgEd25519SignatureDep)
-$(makeLenses ''MsgEd25519SignatureDep)
+$(makeJSON "_eCDSASignature_" ''ECDSASignature)
+$(makeLenses ''ECDSASignature)
 
-msgEd25519Certificate :: Word16
-msgEd25519Certificate = 0x0C02
+msgEcdsaCertificate :: Word16
+msgEcdsaCertificate = 0x0C04
 
-data MsgEd25519Certificate = MsgEd25519Certificate
-  { _msgEd25519Certificate_n_msg           :: !Word8
+-- | SBP class for message MSG_ECDSA_CERTIFICATE (0x0C04).
+--
+-- A DER encoded x.509 ECDSA-256 certificate (using curve secp256r1).
+data MsgEcdsaCertificate = MsgEcdsaCertificate
+  { _msgEcdsaCertificate_n_msg           :: !Word8
+    -- ^ Total number messages that make up the certificate. The first nibble
+    -- (mask 0xF0 or left shifted by 4 bits) is the size of the sequence (n),
+    -- second nibble (mask 0x0F) is the zero-indexed counter (ith packet of
+    -- n).
+  , _msgEcdsaCertificate_certificate_id  :: ![Word8]
+    -- ^ The last 4 bytes of the certificate's SHA-1 fingerprint
+  , _msgEcdsaCertificate_flags           :: !Word8
+  , _msgEcdsaCertificate_certificate_bytes :: ![Word8]
+    -- ^ DER encoded x.509 ECDSA certificate bytes
+  } deriving ( Show, Read, Eq )
+
+instance Binary MsgEcdsaCertificate where
+  get = do
+    _msgEcdsaCertificate_n_msg <- getWord8
+    _msgEcdsaCertificate_certificate_id <- replicateM 4 getWord8
+    _msgEcdsaCertificate_flags <- getWord8
+    _msgEcdsaCertificate_certificate_bytes <- whileM (not <$> isEmpty) getWord8
+    pure MsgEcdsaCertificate {..}
+
+  put MsgEcdsaCertificate {..} = do
+    putWord8 _msgEcdsaCertificate_n_msg
+    mapM_ putWord8 _msgEcdsaCertificate_certificate_id
+    putWord8 _msgEcdsaCertificate_flags
+    mapM_ putWord8 _msgEcdsaCertificate_certificate_bytes
+
+$(makeSBP 'msgEcdsaCertificate ''MsgEcdsaCertificate)
+$(makeJSON "_msgEcdsaCertificate_" ''MsgEcdsaCertificate)
+$(makeLenses ''MsgEcdsaCertificate)
+
+msgCertificateChain :: Word16
+msgCertificateChain = 0x0C09
+
+data MsgCertificateChain = MsgCertificateChain
+  { _msgCertificateChain_root_certificate       :: ![Word8]
+    -- ^ SHA-1 fingerprint of the root certificate
+  , _msgCertificateChain_intermediate_certificate :: ![Word8]
+    -- ^ SHA-1 fingerprint of the intermediate certificate
+  , _msgCertificateChain_corrections_certificate :: ![Word8]
+    -- ^ SHA-1 fingerprint of the corrections certificate
+  , _msgCertificateChain_expiration             :: !UtcTime
+    -- ^ The time after which the signature given is no longer valid.
+    -- Implementors should consult a time source (such as GNSS) to check if
+    -- the current time is later than the expiration time, if the condition is
+    -- true, signatures in the stream should not be considered valid.
+  , _msgCertificateChain_signature              :: !ECDSASignature
+    -- ^ Signature (created by the root certificate) over the concatenation of
+    -- the SBP payload bytes preceding this field. That is, the concatenation
+    -- of `root_certificate`, `intermediate_certificate`,
+    -- `corrections_certificate` and `expiration`.  This certificate chain
+    -- (allow list) can also be validated by fetching it from
+    -- `http(s)://certs.swiftnav.com/chain`.
+  } deriving ( Show, Read, Eq )
+
+instance Binary MsgCertificateChain where
+  get = do
+    _msgCertificateChain_root_certificate <- replicateM 20 getWord8
+    _msgCertificateChain_intermediate_certificate <- replicateM 20 getWord8
+    _msgCertificateChain_corrections_certificate <- replicateM 20 getWord8
+    _msgCertificateChain_expiration <- get
+    _msgCertificateChain_signature <- get
+    pure MsgCertificateChain {..}
+
+  put MsgCertificateChain {..} = do
+    mapM_ putWord8 _msgCertificateChain_root_certificate
+    mapM_ putWord8 _msgCertificateChain_intermediate_certificate
+    mapM_ putWord8 _msgCertificateChain_corrections_certificate
+    put _msgCertificateChain_expiration
+    put _msgCertificateChain_signature
+
+$(makeSBP 'msgCertificateChain ''MsgCertificateChain)
+$(makeJSON "_msgCertificateChain_" ''MsgCertificateChain)
+$(makeLenses ''MsgCertificateChain)
+
+msgCertificateChainDep :: Word16
+msgCertificateChainDep = 0x0C05
+
+data MsgCertificateChainDep = MsgCertificateChainDep
+  { _msgCertificateChainDep_root_certificate       :: ![Word8]
+    -- ^ SHA-1 fingerprint of the root certificate
+  , _msgCertificateChainDep_intermediate_certificate :: ![Word8]
+    -- ^ SHA-1 fingerprint of the intermediate certificate
+  , _msgCertificateChainDep_corrections_certificate :: ![Word8]
+    -- ^ SHA-1 fingerprint of the corrections certificate
+  , _msgCertificateChainDep_expiration             :: !UtcTime
+    -- ^ The certificate chain comprised of three fingerprints: root
+    -- certificate, intermediate certificate and corrections certificate.
+  , _msgCertificateChainDep_signature              :: ![Word8]
+    -- ^ An ECDSA signature (created by the root certificate) over the
+    -- concatenation of the SBP payload bytes preceding this field. That is,
+    -- the concatenation of `root_certificate`, `intermediate_certificate`,
+    -- `corrections_certificate` and `expiration`.  This certificate chain
+    -- (allow list) can also be validated by fetching it from
+    -- `http(s)://certs.swiftnav.com/chain`.
+  } deriving ( Show, Read, Eq )
+
+instance Binary MsgCertificateChainDep where
+  get = do
+    _msgCertificateChainDep_root_certificate <- replicateM 20 getWord8
+    _msgCertificateChainDep_intermediate_certificate <- replicateM 20 getWord8
+    _msgCertificateChainDep_corrections_certificate <- replicateM 20 getWord8
+    _msgCertificateChainDep_expiration <- get
+    _msgCertificateChainDep_signature <- replicateM 64 getWord8
+    pure MsgCertificateChainDep {..}
+
+  put MsgCertificateChainDep {..} = do
+    mapM_ putWord8 _msgCertificateChainDep_root_certificate
+    mapM_ putWord8 _msgCertificateChainDep_intermediate_certificate
+    mapM_ putWord8 _msgCertificateChainDep_corrections_certificate
+    put _msgCertificateChainDep_expiration
+    mapM_ putWord8 _msgCertificateChainDep_signature
+
+$(makeSBP 'msgCertificateChainDep ''MsgCertificateChainDep)
+$(makeJSON "_msgCertificateChainDep_" ''MsgCertificateChainDep)
+$(makeLenses ''MsgCertificateChainDep)
+
+msgEcdsaSignature :: Word16
+msgEcdsaSignature = 0x0C08
+
+-- | SBP class for message MSG_ECDSA_SIGNATURE (0x0C08).
+--
+-- An ECDSA-256 signature using SHA-256 as the message digest algorithm.
+data MsgEcdsaSignature = MsgEcdsaSignature
+  { _msgEcdsaSignature_flags           :: !Word8
+    -- ^ Describes the format of the `signed\_messages` field below.
+  , _msgEcdsaSignature_stream_counter  :: !Word8
+    -- ^ Signature message counter. Zero indexed and incremented with each
+    -- signature message.  The counter will not increment if this message was
+    -- in response to an on demand request.  The counter will roll over after
+    -- 256 messages. Upon connection, the value of the counter may not
+    -- initially be zero.
+  , _msgEcdsaSignature_on_demand_counter :: !Word8
+    -- ^ On demand message counter. Zero indexed and incremented with each
+    -- signature message sent in response to an on demand message. The counter
+    -- will roll over after 256 messages.  Upon connection, the value of the
+    -- counter may not initially be zero.
+  , _msgEcdsaSignature_certificate_id  :: ![Word8]
+    -- ^ The last 4 bytes of the certificate's SHA-1 fingerprint
+  , _msgEcdsaSignature_signature       :: !ECDSASignature
+    -- ^ Signature over the frames of this message group.
+  , _msgEcdsaSignature_signed_messages :: ![Word8]
+    -- ^ CRCs of the messages covered by this signature.  For Skylark, which
+    -- delivers SBP messages wrapped in Swift's proprietary RTCM message,
+    -- these are the 24-bit CRCs from the RTCM message framing. For SBP only
+    -- streams, this will be 16-bit CRCs from the SBP framing.  See the
+    -- `flags` field to determine the type of CRCs covered.
+  } deriving ( Show, Read, Eq )
+
+instance Binary MsgEcdsaSignature where
+  get = do
+    _msgEcdsaSignature_flags <- getWord8
+    _msgEcdsaSignature_stream_counter <- getWord8
+    _msgEcdsaSignature_on_demand_counter <- getWord8
+    _msgEcdsaSignature_certificate_id <- replicateM 4 getWord8
+    _msgEcdsaSignature_signature <- get
+    _msgEcdsaSignature_signed_messages <- whileM (not <$> isEmpty) getWord8
+    pure MsgEcdsaSignature {..}
+
+  put MsgEcdsaSignature {..} = do
+    putWord8 _msgEcdsaSignature_flags
+    putWord8 _msgEcdsaSignature_stream_counter
+    putWord8 _msgEcdsaSignature_on_demand_counter
+    mapM_ putWord8 _msgEcdsaSignature_certificate_id
+    put _msgEcdsaSignature_signature
+    mapM_ putWord8 _msgEcdsaSignature_signed_messages
+
+$(makeSBP 'msgEcdsaSignature ''MsgEcdsaSignature)
+$(makeJSON "_msgEcdsaSignature_" ''MsgEcdsaSignature)
+$(makeLenses ''MsgEcdsaSignature)
+
+msgEcdsaSignatureDepB :: Word16
+msgEcdsaSignatureDepB = 0x0C07
+
+-- | SBP class for message MSG_ECDSA_SIGNATURE_DEP_B (0x0C07).
+--
+-- An ECDSA-256 signature using SHA-256 as the message digest algorithm.
+data MsgEcdsaSignatureDepB = MsgEcdsaSignatureDepB
+  { _msgEcdsaSignatureDepB_flags           :: !Word8
+    -- ^ Describes the format of the `signed\_messages` field below.
+  , _msgEcdsaSignatureDepB_stream_counter  :: !Word8
+    -- ^ Signature message counter. Zero indexed and incremented with each
+    -- signature message.  The counter will not increment if this message was
+    -- in response to an on demand request.  The counter will roll over after
+    -- 256 messages. Upon connection, the value of the counter may not
+    -- initially be zero.
+  , _msgEcdsaSignatureDepB_on_demand_counter :: !Word8
+    -- ^ On demand message counter. Zero indexed and incremented with each
+    -- signature message sent in response to an on demand message. The counter
+    -- will roll over after 256 messages.  Upon connection, the value of the
+    -- counter may not initially be zero.
+  , _msgEcdsaSignatureDepB_certificate_id  :: ![Word8]
+    -- ^ The last 4 bytes of the certificate's SHA-1 fingerprint
+  , _msgEcdsaSignatureDepB_n_signature_bytes :: !Word8
+    -- ^ Number of bytes to use of the signature field.  The DER encoded
+    -- signature has a maximum size of 72 bytes but can vary between 70 and 72
+    -- bytes in length.
+  , _msgEcdsaSignatureDepB_signature       :: ![Word8]
+    -- ^ DER encoded ECDSA signature for the messages using SHA-256 as the
+    -- digest algorithm.
+  , _msgEcdsaSignatureDepB_signed_messages :: ![Word8]
+    -- ^ CRCs of the messages covered by this signature.  For Skylark, which
+    -- delivers SBP messages wrapped in Swift's proprietary RTCM message,
+    -- these are the 24-bit CRCs from the RTCM message framing. For SBP only
+    -- streams, this will be 16-bit CRCs from the SBP framing.  See the
+    -- `flags` field to determine the type of CRCs covered.
+  } deriving ( Show, Read, Eq )
+
+instance Binary MsgEcdsaSignatureDepB where
+  get = do
+    _msgEcdsaSignatureDepB_flags <- getWord8
+    _msgEcdsaSignatureDepB_stream_counter <- getWord8
+    _msgEcdsaSignatureDepB_on_demand_counter <- getWord8
+    _msgEcdsaSignatureDepB_certificate_id <- replicateM 4 getWord8
+    _msgEcdsaSignatureDepB_n_signature_bytes <- getWord8
+    _msgEcdsaSignatureDepB_signature <- replicateM 72 getWord8
+    _msgEcdsaSignatureDepB_signed_messages <- whileM (not <$> isEmpty) getWord8
+    pure MsgEcdsaSignatureDepB {..}
+
+  put MsgEcdsaSignatureDepB {..} = do
+    putWord8 _msgEcdsaSignatureDepB_flags
+    putWord8 _msgEcdsaSignatureDepB_stream_counter
+    putWord8 _msgEcdsaSignatureDepB_on_demand_counter
+    mapM_ putWord8 _msgEcdsaSignatureDepB_certificate_id
+    putWord8 _msgEcdsaSignatureDepB_n_signature_bytes
+    mapM_ putWord8 _msgEcdsaSignatureDepB_signature
+    mapM_ putWord8 _msgEcdsaSignatureDepB_signed_messages
+
+$(makeSBP 'msgEcdsaSignatureDepB ''MsgEcdsaSignatureDepB)
+$(makeJSON "_msgEcdsaSignatureDepB_" ''MsgEcdsaSignatureDepB)
+$(makeLenses ''MsgEcdsaSignatureDepB)
+
+msgEcdsaSignatureDepA :: Word16
+msgEcdsaSignatureDepA = 0x0C06
+
+-- | SBP class for message MSG_ECDSA_SIGNATURE_DEP_A (0x0C06).
+--
+-- An ECDSA-256 signature using SHA-256 as the message digest algorithm.
+data MsgEcdsaSignatureDepA = MsgEcdsaSignatureDepA
+  { _msgEcdsaSignatureDepA_flags           :: !Word8
+    -- ^ Describes the format of the `signed\_messages` field below.
+  , _msgEcdsaSignatureDepA_stream_counter  :: !Word8
+    -- ^ Signature message counter. Zero indexed and incremented with each
+    -- signature message.  The counter will not increment if this message was
+    -- in response to an on demand request.  The counter will roll over after
+    -- 256 messages. Upon connection, the value of the counter may not
+    -- initially be zero.
+  , _msgEcdsaSignatureDepA_on_demand_counter :: !Word8
+    -- ^ On demand message counter. Zero indexed and incremented with each
+    -- signature message sent in response to an on demand message. The counter
+    -- will roll over after 256 messages.  Upon connection, the value of the
+    -- counter may not initially be zero.
+  , _msgEcdsaSignatureDepA_certificate_id  :: ![Word8]
+    -- ^ The last 4 bytes of the certificate's SHA-1 fingerprint
+  , _msgEcdsaSignatureDepA_signature       :: ![Word8]
+    -- ^ ECDSA signature for the messages using SHA-256 as the digest algorithm.
+  , _msgEcdsaSignatureDepA_signed_messages :: ![Word8]
+    -- ^ CRCs of the messages covered by this signature.  For Skylark, which
+    -- delivers SBP messages wrapped in Swift's proprietary RTCM message,
+    -- these are the 24-bit CRCs from the RTCM message framing. For SBP only
+    -- streams, this will be 16-bit CRCs from the SBP framing.  See the
+    -- `flags` field to determine the type of CRCs covered.
+  } deriving ( Show, Read, Eq )
+
+instance Binary MsgEcdsaSignatureDepA where
+  get = do
+    _msgEcdsaSignatureDepA_flags <- getWord8
+    _msgEcdsaSignatureDepA_stream_counter <- getWord8
+    _msgEcdsaSignatureDepA_on_demand_counter <- getWord8
+    _msgEcdsaSignatureDepA_certificate_id <- replicateM 4 getWord8
+    _msgEcdsaSignatureDepA_signature <- replicateM 64 getWord8
+    _msgEcdsaSignatureDepA_signed_messages <- whileM (not <$> isEmpty) getWord8
+    pure MsgEcdsaSignatureDepA {..}
+
+  put MsgEcdsaSignatureDepA {..} = do
+    putWord8 _msgEcdsaSignatureDepA_flags
+    putWord8 _msgEcdsaSignatureDepA_stream_counter
+    putWord8 _msgEcdsaSignatureDepA_on_demand_counter
+    mapM_ putWord8 _msgEcdsaSignatureDepA_certificate_id
+    mapM_ putWord8 _msgEcdsaSignatureDepA_signature
+    mapM_ putWord8 _msgEcdsaSignatureDepA_signed_messages
+
+$(makeSBP 'msgEcdsaSignatureDepA ''MsgEcdsaSignatureDepA)
+$(makeJSON "_msgEcdsaSignatureDepA_" ''MsgEcdsaSignatureDepA)
+$(makeLenses ''MsgEcdsaSignatureDepA)
+
+msgEd25519CertificateDep :: Word16
+msgEd25519CertificateDep = 0x0C02
+
+data MsgEd25519CertificateDep = MsgEd25519CertificateDep
+  { _msgEd25519CertificateDep_n_msg           :: !Word8
     -- ^ Total number messages that make up the certificate. First nibble is the
     -- size of the sequence (n), second nibble is the zero-indexed counter
     -- (ith packet of n)
-  , _msgEd25519Certificate_fingerprint     :: ![Word8]
+  , _msgEd25519CertificateDep_fingerprint     :: ![Word8]
     -- ^ SHA-1 fingerprint of the associated certificate.
-  , _msgEd25519Certificate_certificate_bytes :: ![Word8]
+  , _msgEd25519CertificateDep_certificate_bytes :: ![Word8]
     -- ^ ED25519 certificate bytes.
   } deriving ( Show, Read, Eq )
 
-instance Binary MsgEd25519Certificate where
+instance Binary MsgEd25519CertificateDep where
   get = do
-    _msgEd25519Certificate_n_msg <- getWord8
-    _msgEd25519Certificate_fingerprint <- replicateM 20 getWord8
-    _msgEd25519Certificate_certificate_bytes <- whileM (not <$> isEmpty) getWord8
-    pure MsgEd25519Certificate {..}
+    _msgEd25519CertificateDep_n_msg <- getWord8
+    _msgEd25519CertificateDep_fingerprint <- replicateM 20 getWord8
+    _msgEd25519CertificateDep_certificate_bytes <- whileM (not <$> isEmpty) getWord8
+    pure MsgEd25519CertificateDep {..}
 
-  put MsgEd25519Certificate {..} = do
-    putWord8 _msgEd25519Certificate_n_msg
-    mapM_ putWord8 _msgEd25519Certificate_fingerprint
-    mapM_ putWord8 _msgEd25519Certificate_certificate_bytes
+  put MsgEd25519CertificateDep {..} = do
+    putWord8 _msgEd25519CertificateDep_n_msg
+    mapM_ putWord8 _msgEd25519CertificateDep_fingerprint
+    mapM_ putWord8 _msgEd25519CertificateDep_certificate_bytes
 
-$(makeSBP 'msgEd25519Certificate ''MsgEd25519Certificate)
-$(makeJSON "_msgEd25519Certificate_" ''MsgEd25519Certificate)
-$(makeLenses ''MsgEd25519Certificate)
+$(makeSBP 'msgEd25519CertificateDep ''MsgEd25519CertificateDep)
+$(makeJSON "_msgEd25519CertificateDep_" ''MsgEd25519CertificateDep)
+$(makeLenses ''MsgEd25519CertificateDep)
 
-msgEd25519Signature :: Word16
-msgEd25519Signature = 0x0C03
+msgEd25519SignatureDepA :: Word16
+msgEd25519SignatureDepA = 0x0C01
 
-data MsgEd25519Signature = MsgEd25519Signature
-  { _msgEd25519Signature_stream_counter  :: !Word8
+data MsgEd25519SignatureDepA = MsgEd25519SignatureDepA
+  { _msgEd25519SignatureDepA_signature     :: ![Word8]
+    -- ^ ED25519 signature for messages.
+  , _msgEd25519SignatureDepA_fingerprint   :: ![Word8]
+    -- ^ SHA-1 fingerprint of the associated certificate.
+  , _msgEd25519SignatureDepA_signed_messages :: ![Word32]
+    -- ^ CRCs of signed messages.
+  } deriving ( Show, Read, Eq )
+
+instance Binary MsgEd25519SignatureDepA where
+  get = do
+    _msgEd25519SignatureDepA_signature <- replicateM 64 getWord8
+    _msgEd25519SignatureDepA_fingerprint <- replicateM 20 getWord8
+    _msgEd25519SignatureDepA_signed_messages <- whileM (not <$> isEmpty) getWord32le
+    pure MsgEd25519SignatureDepA {..}
+
+  put MsgEd25519SignatureDepA {..} = do
+    mapM_ putWord8 _msgEd25519SignatureDepA_signature
+    mapM_ putWord8 _msgEd25519SignatureDepA_fingerprint
+    mapM_ putWord32le _msgEd25519SignatureDepA_signed_messages
+
+$(makeSBP 'msgEd25519SignatureDepA ''MsgEd25519SignatureDepA)
+$(makeJSON "_msgEd25519SignatureDepA_" ''MsgEd25519SignatureDepA)
+$(makeLenses ''MsgEd25519SignatureDepA)
+
+msgEd25519SignatureDepB :: Word16
+msgEd25519SignatureDepB = 0x0C03
+
+data MsgEd25519SignatureDepB = MsgEd25519SignatureDepB
+  { _msgEd25519SignatureDepB_stream_counter  :: !Word8
     -- ^ Signature message counter. Zero indexed and incremented with each
-    -- signature message. The counter will not increment if this message was
-    -- in response to an on demand request. The counter will roll over after
+    -- signature message.  The counter will not increment if this message was
+    -- in response to an on demand request.  The counter will roll over after
     -- 256 messages. Upon connection, the value of the counter may not
     -- initially be zero.
-  , _msgEd25519Signature_on_demand_counter :: !Word8
+  , _msgEd25519SignatureDepB_on_demand_counter :: !Word8
     -- ^ On demand message counter. Zero indexed and incremented with each
     -- signature message sent in response to an on demand message. The counter
-    -- will roll over after 256 messages. Upon connection, the value of the
+    -- will roll over after 256 messages.  Upon connection, the value of the
     -- counter may not initially be zero.
-  , _msgEd25519Signature_signature       :: ![Word8]
+  , _msgEd25519SignatureDepB_signature       :: ![Word8]
     -- ^ ED25519 signature for messages.
-  , _msgEd25519Signature_fingerprint     :: ![Word8]
+  , _msgEd25519SignatureDepB_fingerprint     :: ![Word8]
     -- ^ SHA-1 fingerprint of the associated certificate.
-  , _msgEd25519Signature_signed_messages :: ![Word32]
+  , _msgEd25519SignatureDepB_signed_messages :: ![Word32]
     -- ^ CRCs of signed messages.
   } deriving ( Show, Read, Eq )
 
-instance Binary MsgEd25519Signature where
+instance Binary MsgEd25519SignatureDepB where
   get = do
-    _msgEd25519Signature_stream_counter <- getWord8
-    _msgEd25519Signature_on_demand_counter <- getWord8
-    _msgEd25519Signature_signature <- replicateM 64 getWord8
-    _msgEd25519Signature_fingerprint <- replicateM 20 getWord8
-    _msgEd25519Signature_signed_messages <- whileM (not <$> isEmpty) getWord32le
-    pure MsgEd25519Signature {..}
+    _msgEd25519SignatureDepB_stream_counter <- getWord8
+    _msgEd25519SignatureDepB_on_demand_counter <- getWord8
+    _msgEd25519SignatureDepB_signature <- replicateM 64 getWord8
+    _msgEd25519SignatureDepB_fingerprint <- replicateM 20 getWord8
+    _msgEd25519SignatureDepB_signed_messages <- whileM (not <$> isEmpty) getWord32le
+    pure MsgEd25519SignatureDepB {..}
 
-  put MsgEd25519Signature {..} = do
-    putWord8 _msgEd25519Signature_stream_counter
-    putWord8 _msgEd25519Signature_on_demand_counter
-    mapM_ putWord8 _msgEd25519Signature_signature
-    mapM_ putWord8 _msgEd25519Signature_fingerprint
-    mapM_ putWord32le _msgEd25519Signature_signed_messages
+  put MsgEd25519SignatureDepB {..} = do
+    putWord8 _msgEd25519SignatureDepB_stream_counter
+    putWord8 _msgEd25519SignatureDepB_on_demand_counter
+    mapM_ putWord8 _msgEd25519SignatureDepB_signature
+    mapM_ putWord8 _msgEd25519SignatureDepB_fingerprint
+    mapM_ putWord32le _msgEd25519SignatureDepB_signed_messages
 
-$(makeSBP 'msgEd25519Signature ''MsgEd25519Signature)
-$(makeJSON "_msgEd25519Signature_" ''MsgEd25519Signature)
-$(makeLenses ''MsgEd25519Signature)
+$(makeSBP 'msgEd25519SignatureDepB ''MsgEd25519SignatureDepB)
+$(makeJSON "_msgEd25519SignatureDepB_" ''MsgEd25519SignatureDepB)
+$(makeLenses ''MsgEd25519SignatureDepB)
