diff --git a/c/include/libsbp/cpp/message_traits.h b/c/include/libsbp/cpp/message_traits.h index 5a2814638f..dbe88518b1 100644 --- a/c/include/libsbp/cpp/message_traits.h +++ b/c/include/libsbp/cpp/message_traits.h @@ -304,6 +304,43 @@ struct MessageTraits { } }; +template <> +struct MessageTraits { + static constexpr sbp_msg_type_t id = SbpMsgAesCmacSignature; + static constexpr const char *name = "MSG_AES_CMAC_SIGNATURE"; + static const sbp_msg_aes_cmac_signature_t &get(const sbp_msg_t &msg) { + return msg.aes_cmac_signature; + } + static sbp_msg_aes_cmac_signature_t &get(sbp_msg_t &msg) { + return msg.aes_cmac_signature; + } + static void to_sbp_msg(const sbp_msg_aes_cmac_signature_t &msg, + sbp_msg_t *sbp_msg) { + sbp_msg->aes_cmac_signature = msg; + } + static sbp_msg_t to_sbp_msg(const sbp_msg_aes_cmac_signature_t &msg) { + sbp_msg_t sbp_msg; + sbp_msg.aes_cmac_signature = msg; + return sbp_msg; + } + static s8 send(sbp_state_t *state, u16 sender_id, + const sbp_msg_aes_cmac_signature_t &msg, + sbp_write_fn_t write) { + return sbp_msg_aes_cmac_signature_send(state, sender_id, &msg, write); + } + static s8 encode(uint8_t *buf, uint8_t len, uint8_t *n_written, + const sbp_msg_aes_cmac_signature_t &msg) { + return sbp_msg_aes_cmac_signature_encode(buf, len, n_written, &msg); + } + static s8 decode(const uint8_t *buf, uint8_t len, uint8_t *n_read, + sbp_msg_aes_cmac_signature_t *msg) { + return sbp_msg_aes_cmac_signature_decode(buf, len, n_read, msg); + } + static size_t encoded_len(const sbp_msg_aes_cmac_signature_t &msg) { + return sbp_msg_aes_cmac_signature_encoded_len(&msg); + } +}; + template <> struct MessageTraits { static constexpr sbp_msg_type_t id = SbpMsgAgeCorrections; diff --git a/c/include/libsbp/sbp_msg.h b/c/include/libsbp/sbp_msg.h index 51c87a176b..c8c510256f 100644 --- a/c/include/libsbp/sbp_msg.h +++ b/c/include/libsbp/sbp_msg.h @@ -67,6 +67,7 @@ typedef union { sbp_msg_acq_result_t acq_result; sbp_msg_acq_sv_profile_dep_t acq_sv_profile_dep; sbp_msg_acq_sv_profile_t acq_sv_profile; + sbp_msg_aes_cmac_signature_t aes_cmac_signature; sbp_msg_age_corrections_t age_corrections; sbp_msg_almanac_glo_dep_t almanac_glo_dep; sbp_msg_almanac_glo_t almanac_glo; @@ -336,6 +337,9 @@ static inline s8 sbp_message_encode(uint8_t *buf, uint8_t len, case SbpMsgAcqSvProfile: return sbp_msg_acq_sv_profile_encode(buf, len, n_written, &msg->acq_sv_profile); + case SbpMsgAesCmacSignature: + return sbp_msg_aes_cmac_signature_encode(buf, len, n_written, + &msg->aes_cmac_signature); case SbpMsgAgeCorrections: return sbp_msg_age_corrections_encode(buf, len, n_written, &msg->age_corrections); @@ -1008,6 +1012,9 @@ static inline s8 sbp_message_decode(const uint8_t *buf, uint8_t len, case SbpMsgAcqSvProfile: return sbp_msg_acq_sv_profile_decode(buf, len, n_read, &msg->acq_sv_profile); + case SbpMsgAesCmacSignature: + return sbp_msg_aes_cmac_signature_decode(buf, len, n_read, + &msg->aes_cmac_signature); case SbpMsgAgeCorrections: return sbp_msg_age_corrections_decode(buf, len, n_read, &msg->age_corrections); @@ -1659,6 +1666,8 @@ static inline size_t sbp_message_encoded_len(sbp_msg_type_t msg_type, return sbp_msg_acq_sv_profile_dep_encoded_len(&msg->acq_sv_profile_dep); case SbpMsgAcqSvProfile: return sbp_msg_acq_sv_profile_encoded_len(&msg->acq_sv_profile); + case SbpMsgAesCmacSignature: + return sbp_msg_aes_cmac_signature_encoded_len(&msg->aes_cmac_signature); case SbpMsgAgeCorrections: return sbp_msg_age_corrections_encoded_len(&msg->age_corrections); case SbpMsgAlmanacGloDep: @@ -2215,6 +2224,9 @@ static inline int sbp_message_cmp(sbp_msg_type_t msg_type, const sbp_msg_t *a, &b->acq_sv_profile_dep); case SbpMsgAcqSvProfile: return sbp_msg_acq_sv_profile_cmp(&a->acq_sv_profile, &b->acq_sv_profile); + case SbpMsgAesCmacSignature: + return sbp_msg_aes_cmac_signature_cmp(&a->aes_cmac_signature, + &b->aes_cmac_signature); case SbpMsgAgeCorrections: return sbp_msg_age_corrections_cmp(&a->age_corrections, &b->age_corrections); diff --git a/c/include/libsbp/sbp_msg_type.h b/c/include/libsbp/sbp_msg_type.h index 529d1f7b1d..906bdce08c 100644 --- a/c/include/libsbp/sbp_msg_type.h +++ b/c/include/libsbp/sbp_msg_type.h @@ -58,6 +58,7 @@ typedef enum { SbpMsgAcqResult = 0x002F, SbpMsgAcqSvProfileDep = 0x001E, SbpMsgAcqSvProfile = 0x002E, + SbpMsgAesCmacSignature = 0x0C10, SbpMsgAgeCorrections = 0x0210, SbpMsgAlmanacGloDep = 0x0071, SbpMsgAlmanacGlo = 0x0073, @@ -308,6 +309,8 @@ static inline const char *sbp_msg_type_to_string(sbp_msg_type_t msg_type) { return "MSG_ACQ_SV_PROFILE_DEP"; case SbpMsgAcqSvProfile: return "MSG_ACQ_SV_PROFILE"; + case SbpMsgAesCmacSignature: + return "MSG_AES_CMAC_SIGNATURE"; case SbpMsgAgeCorrections: return "MSG_AGE_CORRECTIONS"; case SbpMsgAlmanacGloDep: diff --git a/c/include/libsbp/signing.h b/c/include/libsbp/signing.h index 444407b9a1..f6429a5dd8 100644 --- a/c/include/libsbp/signing.h +++ b/c/include/libsbp/signing.h @@ -18,6 +18,7 @@ #ifndef LIBSBP_SIGNING_MESSAGES_H #define LIBSBP_SIGNING_MESSAGES_H #include +#include #include #include #include diff --git a/c/include/libsbp/signing/MSG_AES_CMAC_SIGNATURE.h b/c/include/libsbp/signing/MSG_AES_CMAC_SIGNATURE.h new file mode 100644 index 0000000000..a3205c171c --- /dev/null +++ b/c/include/libsbp/signing/MSG_AES_CMAC_SIGNATURE.h @@ -0,0 +1,226 @@ +/* + * Copyright (C) 2015-2021 Swift Navigation Inc. + * Contact: https://support.swiftnav.com + * + * This source is subject to the license found in the file 'LICENSE' which must + * be distributed together with this source. All other rights reserved. + * + * THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, + * EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE. + */ + +/***************************************************************************** + * Automatically generated from yaml/swiftnav/sbp/signing.yaml + * with generate.py. Please do not hand edit! + *****************************************************************************/ + +#ifndef LIBSBP_SIGNING_MSG_AES_CMAC_SIGNATURE_H +#define LIBSBP_SIGNING_MSG_AES_CMAC_SIGNATURE_H + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/****************************************************************************** + * + * SBP_MSG_AES_CMAC_SIGNATURE + * + *****************************************************************************/ +/** AES-CMAC 128 digital signature + * + * Digital signature using AES-CMAC 128 algorithm used for data integrity. + */ +typedef struct { + /** + * 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. + */ + u8 stream_counter; + + /** + * 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. + */ + u8 on_demand_counter; + + /** + * The last 4 bytes of the certificate's SHA-1 fingerprint + */ + u8 certificate_id[SBP_MSG_AES_CMAC_SIGNATURE_CERTIFICATE_ID_MAX]; + + /** + * Signature + */ + u8 signature[SBP_MSG_AES_CMAC_SIGNATURE_SIGNATURE_MAX]; + + /** + * Describes the format of the 'signed messages' field below. + */ + u8 flags; + + /** + * 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. + */ + u8 signed_messages[SBP_MSG_AES_CMAC_SIGNATURE_SIGNED_MESSAGES_MAX]; + /** + * Number of elements in signed_messages + * + * When sending a message fill in this field with the number elements set in + * signed_messages before calling an appropriate libsbp send function + * + * When receiving a message query this field for the number of elements in + * signed_messages. The value of any elements beyond the index specified in + * this field is undefined + */ + u8 n_signed_messages; +} sbp_msg_aes_cmac_signature_t; + +/** + * Get encoded size of an instance of sbp_msg_aes_cmac_signature_t + * + * @param msg sbp_msg_aes_cmac_signature_t instance + * @return Length of on-wire representation + */ +static inline size_t sbp_msg_aes_cmac_signature_encoded_len( + const sbp_msg_aes_cmac_signature_t *msg) { + return SBP_MSG_AES_CMAC_SIGNATURE_ENCODED_OVERHEAD + + (msg->n_signed_messages * SBP_ENCODED_LEN_U8); +} + +/** + * Encode an instance of sbp_msg_aes_cmac_signature_t to wire representation + * + * This function encodes the given instance in to the user provided buffer. The + * buffer provided to this function must be large enough to store the encoded + * message otherwise it will return SBP_ENCODE_ERROR without writing anything to + * the buffer. + * + * Specify the length of the destination buffer in the \p len parameter. If + * non-null the number of bytes written to the buffer will be returned in \p + * n_written. + * + * @param buf Destination buffer + * @param len Length of \p buf + * @param n_written If not null, on success will be set to the number of bytes + * written to \p buf + * @param msg Instance of sbp_msg_aes_cmac_signature_t to encode + * @return SBP_OK on success, or other libsbp error code + */ +SBP_EXPORT s8 +sbp_msg_aes_cmac_signature_encode(uint8_t *buf, uint8_t len, uint8_t *n_written, + const sbp_msg_aes_cmac_signature_t *msg); + +/** + * Decode an instance of sbp_msg_aes_cmac_signature_t from wire representation + * + * This function decodes the wire representation of a + * sbp_msg_aes_cmac_signature_t message to the given instance. The caller must + * specify the length of the buffer in the \p len parameter. If non-null the + * number of bytes read from the buffer will be returned in \p n_read. + * + * @param buf Wire representation of the sbp_msg_aes_cmac_signature_t instance + * @param len Length of \p buf + * @param n_read If not null, on success will be set to the number of bytes read + * from \p buf + * @param msg Destination + * @return SBP_OK on success, or other libsbp error code + */ +SBP_EXPORT s8 sbp_msg_aes_cmac_signature_decode( + const uint8_t *buf, uint8_t len, uint8_t *n_read, + sbp_msg_aes_cmac_signature_t *msg); +/** + * Send an instance of sbp_msg_aes_cmac_signature_t with the given write + * function + * + * An equivalent of #sbp_message_send which operates specifically on + * sbp_msg_aes_cmac_signature_t + * + * The given message will be encoded to wire representation and passed in to the + * given write function callback. The write callback will be called several + * times for each invocation of this function. + * + * @param s SBP state + * @param sender_id SBP sender id + * @param msg Message to send + * @param write Write function + * @return SBP_OK on success, or other libsbp error code + */ +SBP_EXPORT s8 sbp_msg_aes_cmac_signature_send( + sbp_state_t *s, u16 sender_id, const sbp_msg_aes_cmac_signature_t *msg, + sbp_write_fn_t write); + +/** + * Compare two instances of sbp_msg_aes_cmac_signature_t + * + * The two instances will be compared and a value returned consistent with the + * return codes of comparison functions from the C standard library + * + * 0 will be returned if \p a and \p b are considered equal + * A value less than 0 will be returned if \p a is considered to be less than \p + * b A value greater than 0 will be returned if \p b is considered to be greater + * than \p b + * + * @param a sbp_msg_aes_cmac_signature_t instance + * @param b sbp_msg_aes_cmac_signature_t instance + * @return 0, <0, >0 + */ +SBP_EXPORT int sbp_msg_aes_cmac_signature_cmp( + const sbp_msg_aes_cmac_signature_t *a, + const sbp_msg_aes_cmac_signature_t *b); + +#ifdef __cplusplus +} + +static inline bool operator==(const sbp_msg_aes_cmac_signature_t &lhs, + const sbp_msg_aes_cmac_signature_t &rhs) { + return sbp_msg_aes_cmac_signature_cmp(&lhs, &rhs) == 0; +} + +static inline bool operator!=(const sbp_msg_aes_cmac_signature_t &lhs, + const sbp_msg_aes_cmac_signature_t &rhs) { + return sbp_msg_aes_cmac_signature_cmp(&lhs, &rhs) != 0; +} + +static inline bool operator<(const sbp_msg_aes_cmac_signature_t &lhs, + const sbp_msg_aes_cmac_signature_t &rhs) { + return sbp_msg_aes_cmac_signature_cmp(&lhs, &rhs) < 0; +} + +static inline bool operator<=(const sbp_msg_aes_cmac_signature_t &lhs, + const sbp_msg_aes_cmac_signature_t &rhs) { + return sbp_msg_aes_cmac_signature_cmp(&lhs, &rhs) <= 0; +} + +static inline bool operator>(const sbp_msg_aes_cmac_signature_t &lhs, + const sbp_msg_aes_cmac_signature_t &rhs) { + return sbp_msg_aes_cmac_signature_cmp(&lhs, &rhs) > 0; +} + +static inline bool operator>=(const sbp_msg_aes_cmac_signature_t &lhs, + const sbp_msg_aes_cmac_signature_t &rhs) { + return sbp_msg_aes_cmac_signature_cmp(&lhs, &rhs) >= 0; +} + +#endif // ifdef __cplusplus + +#endif /* LIBSBP_SIGNING_MSG_AES_CMAC_SIGNATURE_H */ diff --git a/c/include/libsbp/signing_macros.h b/c/include/libsbp/signing_macros.h index a25421e0b9..6adb3894f0 100644 --- a/c/include/libsbp/signing_macros.h +++ b/c/include/libsbp/signing_macros.h @@ -137,6 +137,55 @@ */ #define SBP_MSG_CERTIFICATE_CHAIN_DEP_ENCODED_LEN 135u +/** + * The maximum number of items that can be stored in + * sbp_msg_aes_cmac_signature_t::certificate_id before the maximum SBP message + * size is exceeded + */ +#define SBP_MSG_AES_CMAC_SIGNATURE_CERTIFICATE_ID_MAX 4u + +/** + * The maximum number of items that can be stored in + * sbp_msg_aes_cmac_signature_t::signature before the maximum SBP message size + * is exceeded + */ +#define SBP_MSG_AES_CMAC_SIGNATURE_SIGNATURE_MAX 16u + +#define SBP_AES_CMAC_SIGNATURE_CRC_TYPE_MASK (0x3u) +#define SBP_AES_CMAC_SIGNATURE_CRC_TYPE_SHIFT (0u) +#define SBP_AES_CMAC_SIGNATURE_CRC_TYPE_GET(flags) \ + ((u8)((u8)((flags) >> SBP_AES_CMAC_SIGNATURE_CRC_TYPE_SHIFT) & \ + SBP_AES_CMAC_SIGNATURE_CRC_TYPE_MASK)) +#define SBP_AES_CMAC_SIGNATURE_CRC_TYPE_SET(flags, val) \ + do { \ + (flags) = (u8)((flags & (~(SBP_AES_CMAC_SIGNATURE_CRC_TYPE_MASK \ + << SBP_AES_CMAC_SIGNATURE_CRC_TYPE_SHIFT))) | \ + (((val) & (SBP_AES_CMAC_SIGNATURE_CRC_TYPE_MASK)) \ + << (SBP_AES_CMAC_SIGNATURE_CRC_TYPE_SHIFT))); \ + } while (0) + +#define SBP_AES_CMAC_SIGNATURE_CRC_TYPE_24_BIT_CRCS_FROM_RTCM_FRAMING (0) +#define SBP_AES_CMAC_SIGNATURE_CRC_TYPE_16_BIT_CRCS_FROM_SBP_FRAMING (1) +/** + * The maximum number of items that can be stored in + * sbp_msg_aes_cmac_signature_t::signed_messages before the maximum SBP message + * size is exceeded + */ +#define SBP_MSG_AES_CMAC_SIGNATURE_SIGNED_MESSAGES_MAX 232u + +/** + * Encoded length of sbp_msg_aes_cmac_signature_t + * + * This type is not fixed size and an instance of this message may be longer + * than the value indicated by this symbol. Users call + * #sbp_msg_aes_cmac_signature_encoded_len to determine the actual size of an + * instance of this message. + * + * See the documentation for libsbp for more details regarding the message + * structure and its variable length component(s) + */ +#define SBP_MSG_AES_CMAC_SIGNATURE_ENCODED_OVERHEAD 23u + #define SBP_ECDSA_SIGNATURE_CRC_TYPE_MASK (0x3u) #define SBP_ECDSA_SIGNATURE_CRC_TYPE_SHIFT (0u) #define SBP_ECDSA_SIGNATURE_CRC_TYPE_GET(flags) \ diff --git a/c/src/include/libsbp/internal/signing.h b/c/src/include/libsbp/internal/signing.h index 353d725ce9..cca25fc52a 100644 --- a/c/src/include/libsbp/internal/signing.h +++ b/c/src/include/libsbp/internal/signing.h @@ -126,6 +126,26 @@ bool sbp_msg_certificate_chain_dep_encode_internal( bool sbp_msg_certificate_chain_dep_decode_internal( sbp_decode_ctx_t *ctx, sbp_msg_certificate_chain_dep_t *msg); +/** + * Internal function to encode an SBP type to a buffer + * + * @param ctx Encode context + * @param msg SBP type instance + * @return true on success, false otherwise + */ +bool sbp_msg_aes_cmac_signature_encode_internal( + sbp_encode_ctx_t *ctx, const sbp_msg_aes_cmac_signature_t *msg); + +/** + * Internal function to decode an SBP type from a buffer + * + * @param ctx Decode context + * @param msg SBP type instance + * @return true on success, false otherwise + */ +bool sbp_msg_aes_cmac_signature_decode_internal( + sbp_decode_ctx_t *ctx, sbp_msg_aes_cmac_signature_t *msg); + /** * Internal function to encode an SBP type to a buffer * diff --git a/c/src/signing.c b/c/src/signing.c index 5a08f1c2b6..2797863bd1 100644 --- a/c/src/signing.c +++ b/c/src/signing.c @@ -650,6 +650,167 @@ int sbp_msg_certificate_chain_dep_cmp( return ret; } +bool sbp_msg_aes_cmac_signature_encode_internal( + sbp_encode_ctx_t *ctx, const sbp_msg_aes_cmac_signature_t *msg) { + if (!sbp_u8_encode(ctx, &msg->stream_counter)) { + return false; + } + if (!sbp_u8_encode(ctx, &msg->on_demand_counter)) { + return false; + } + for (size_t i = 0; i < SBP_MSG_AES_CMAC_SIGNATURE_CERTIFICATE_ID_MAX; i++) { + if (!sbp_u8_encode(ctx, &msg->certificate_id[i])) { + return false; + } + } + for (size_t i = 0; i < SBP_MSG_AES_CMAC_SIGNATURE_SIGNATURE_MAX; i++) { + if (!sbp_u8_encode(ctx, &msg->signature[i])) { + return false; + } + } + if (!sbp_u8_encode(ctx, &msg->flags)) { + return false; + } + for (size_t i = 0; i < msg->n_signed_messages; i++) { + if (!sbp_u8_encode(ctx, &msg->signed_messages[i])) { + return false; + } + } + return true; +} + +s8 sbp_msg_aes_cmac_signature_encode(uint8_t *buf, uint8_t len, + uint8_t *n_written, + const sbp_msg_aes_cmac_signature_t *msg) { + sbp_encode_ctx_t ctx; + ctx.buf = buf; + ctx.buf_len = len; + ctx.offset = 0; + if (!sbp_msg_aes_cmac_signature_encode_internal(&ctx, msg)) { + return SBP_ENCODE_ERROR; + } + if (n_written != NULL) { + *n_written = (uint8_t)ctx.offset; + } + return SBP_OK; +} + +bool sbp_msg_aes_cmac_signature_decode_internal( + sbp_decode_ctx_t *ctx, sbp_msg_aes_cmac_signature_t *msg) { + if (!sbp_u8_decode(ctx, &msg->stream_counter)) { + return false; + } + if (!sbp_u8_decode(ctx, &msg->on_demand_counter)) { + return false; + } + for (uint8_t i = 0; i < SBP_MSG_AES_CMAC_SIGNATURE_CERTIFICATE_ID_MAX; i++) { + if (!sbp_u8_decode(ctx, &msg->certificate_id[i])) { + return false; + } + } + for (uint8_t i = 0; i < SBP_MSG_AES_CMAC_SIGNATURE_SIGNATURE_MAX; i++) { + if (!sbp_u8_decode(ctx, &msg->signature[i])) { + return false; + } + } + if (!sbp_u8_decode(ctx, &msg->flags)) { + return false; + } + if (((ctx->buf_len - ctx->offset) % SBP_ENCODED_LEN_U8) != 0) { + return false; + } + msg->n_signed_messages = + (uint8_t)((ctx->buf_len - ctx->offset) / SBP_ENCODED_LEN_U8); + for (uint8_t i = 0; i < msg->n_signed_messages; i++) { + if (!sbp_u8_decode(ctx, &msg->signed_messages[i])) { + return false; + } + } + return true; +} + +s8 sbp_msg_aes_cmac_signature_decode(const uint8_t *buf, uint8_t len, + uint8_t *n_read, + sbp_msg_aes_cmac_signature_t *msg) { + sbp_decode_ctx_t ctx; + ctx.buf = buf; + ctx.buf_len = len; + ctx.offset = 0; + if (!sbp_msg_aes_cmac_signature_decode_internal(&ctx, msg)) { + return SBP_DECODE_ERROR; + } + if (n_read != NULL) { + *n_read = (uint8_t)ctx.offset; + } + return SBP_OK; +} + +s8 sbp_msg_aes_cmac_signature_send(sbp_state_t *s, u16 sender_id, + const sbp_msg_aes_cmac_signature_t *msg, + sbp_write_fn_t write) { + uint8_t payload[SBP_MAX_PAYLOAD_LEN]; + uint8_t payload_len; + s8 ret = sbp_msg_aes_cmac_signature_encode(payload, sizeof(payload), + &payload_len, msg); + if (ret != SBP_OK) { + return ret; + } + return sbp_internal_forward_payload(s, SbpMsgAesCmacSignature, sender_id, + payload_len, payload, write); +} + +int sbp_msg_aes_cmac_signature_cmp(const sbp_msg_aes_cmac_signature_t *a, + const sbp_msg_aes_cmac_signature_t *b) { + int ret = 0; + + ret = sbp_u8_cmp(&a->stream_counter, &b->stream_counter); + if (ret != 0) { + return ret; + } + + ret = sbp_u8_cmp(&a->on_demand_counter, &b->on_demand_counter); + if (ret != 0) { + return ret; + } + + for (uint8_t i = 0; i < SBP_MSG_AES_CMAC_SIGNATURE_CERTIFICATE_ID_MAX; i++) { + ret = sbp_u8_cmp(&a->certificate_id[i], &b->certificate_id[i]); + if (ret != 0) { + return ret; + } + } + if (ret != 0) { + return ret; + } + + for (uint8_t i = 0; i < SBP_MSG_AES_CMAC_SIGNATURE_SIGNATURE_MAX; i++) { + ret = sbp_u8_cmp(&a->signature[i], &b->signature[i]); + if (ret != 0) { + return ret; + } + } + if (ret != 0) { + return ret; + } + + ret = sbp_u8_cmp(&a->flags, &b->flags); + if (ret != 0) { + return ret; + } + + ret = sbp_u8_cmp(&a->n_signed_messages, &b->n_signed_messages); + if (ret != 0) { + return ret; + } + for (uint8_t i = 0; i < a->n_signed_messages; i++) { + ret = sbp_u8_cmp(&a->signed_messages[i], &b->signed_messages[i]); + if (ret != 0) { + return ret; + } + } + return ret; +} + bool sbp_msg_ecdsa_signature_encode_internal( sbp_encode_ctx_t *ctx, const sbp_msg_ecdsa_signature_t *msg) { if (!sbp_u8_encode(ctx, &msg->flags)) { diff --git a/c/test/auto_check_sbp_signing_MsgAesCmacSignature.c b/c/test/auto_check_sbp_signing_MsgAesCmacSignature.c new file mode 100644 index 0000000000..51d12917e9 --- /dev/null +++ b/c/test/auto_check_sbp_signing_MsgAesCmacSignature.c @@ -0,0 +1,336 @@ +/* + * Copyright (C) 2015-2021 Swift Navigation Inc. + * Contact: https://support.swiftnav.com + * + * This source is subject to the license found in the file 'LICENSE' which must + * be distributed together with this source. All other rights reserved. + * + * THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, + * EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE. + */ + +// This file was auto-generated from +// spec/tests/yaml/swiftnav/sbp/signing/test_MsgAesCmacSignature.yaml by +// generate.py. Do not modify by hand! + +#include +#include +#include +#include // for debugging +#include // for malloc + +static struct { + u32 n_callbacks_logged; + u16 sender_id; + sbp_msg_type_t msg_type; + sbp_msg_t msg; + void *context; +} last_msg; + +static size_t dummy_wr = 0; +static size_t dummy_rd = 0; +static u8 dummy_buff[1024]; +static void *last_io_context; + +static void *DUMMY_MEMORY_FOR_CALLBACKS = (void *)0xdeadbeef; +static void *DUMMY_MEMORY_FOR_IO = (void *)0xdead0000; + +static void dummy_reset() { + dummy_rd = dummy_wr = 0; + memset(dummy_buff, 0, sizeof(dummy_buff)); +} + +static s32 dummy_write(u8 *buff, u32 n, void *context) { + last_io_context = context; + size_t real_n = n; //(dummy_n > n) ? n : dummy_n; + memcpy(dummy_buff + dummy_wr, buff, real_n); + dummy_wr += real_n; + return (s32)real_n; +} + +static s32 dummy_read(u8 *buff, u32 n, void *context) { + last_io_context = context; + size_t real_n = n; //(dummy_n > n) ? n : dummy_n; + memcpy(buff, dummy_buff + dummy_rd, real_n); + dummy_rd += real_n; + return (s32)real_n; +} + +static void logging_reset() { memset(&last_msg, 0, sizeof(last_msg)); } + +static void msg_callback(u16 sender_id, sbp_msg_type_t msg_type, + const sbp_msg_t *msg, void *context) { + last_msg.n_callbacks_logged++; + last_msg.sender_id = sender_id; + last_msg.msg_type = msg_type; + last_msg.msg = *msg; + last_msg.context = context; +} + +START_TEST(test_auto_check_sbp_signing_MsgAesCmacSignature) { + static sbp_msg_callbacks_node_t n; + + // State of the SBP message parser. + // Must be statically allocated. + sbp_state_t sbp_state; + + // + // Run tests: + // + // Test successful parsing of a message + { + // SBP parser state must be initialized before sbp_process is called. + // We re-initialize before every test so that callbacks for the same message + // types can be + // allocated multiple times across different tests. + sbp_state_init(&sbp_state); + + sbp_state_set_io_context(&sbp_state, &DUMMY_MEMORY_FOR_IO); + + logging_reset(); + + sbp_callback_register(&sbp_state, 0xC10, &msg_callback, + &DUMMY_MEMORY_FOR_CALLBACKS, &n); + + u8 encoded_frame[] = { + 85, 16, 12, 66, 0, 26, 1, 2, 1, 2, 3, 4, 0, 1, 2, 3, 4, + 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 11, 22, 33, 192, 21, + }; + + dummy_reset(); + + sbp_msg_t test_msg; + memset(&test_msg, 0, sizeof(test_msg)); + + test_msg.aes_cmac_signature.certificate_id[0] = 1; + + test_msg.aes_cmac_signature.certificate_id[1] = 2; + + test_msg.aes_cmac_signature.certificate_id[2] = 3; + + test_msg.aes_cmac_signature.certificate_id[3] = 4; + + test_msg.aes_cmac_signature.flags = 0; + + test_msg.aes_cmac_signature.n_signed_messages = 3; + + test_msg.aes_cmac_signature.on_demand_counter = 2; + + test_msg.aes_cmac_signature.signature[0] = 0; + + test_msg.aes_cmac_signature.signature[1] = 1; + + test_msg.aes_cmac_signature.signature[2] = 2; + + test_msg.aes_cmac_signature.signature[3] = 3; + + test_msg.aes_cmac_signature.signature[4] = 4; + + test_msg.aes_cmac_signature.signature[5] = 5; + + test_msg.aes_cmac_signature.signature[6] = 6; + + test_msg.aes_cmac_signature.signature[7] = 7; + + test_msg.aes_cmac_signature.signature[8] = 8; + + test_msg.aes_cmac_signature.signature[9] = 9; + + test_msg.aes_cmac_signature.signature[10] = 10; + + test_msg.aes_cmac_signature.signature[11] = 11; + + test_msg.aes_cmac_signature.signature[12] = 12; + + test_msg.aes_cmac_signature.signature[13] = 13; + + test_msg.aes_cmac_signature.signature[14] = 14; + + test_msg.aes_cmac_signature.signature[15] = 15; + + test_msg.aes_cmac_signature.signed_messages[0] = 11; + + test_msg.aes_cmac_signature.signed_messages[1] = 22; + + test_msg.aes_cmac_signature.signed_messages[2] = 33; + + test_msg.aes_cmac_signature.stream_counter = 1; + + sbp_message_send(&sbp_state, SbpMsgAesCmacSignature, 66, &test_msg, + &dummy_write); + + ck_assert_msg(dummy_wr == sizeof(encoded_frame), + "not enough data was written to dummy_buff (expected: %zu, " + "actual: %zu)", + sizeof(encoded_frame), dummy_wr); + ck_assert_msg(memcmp(dummy_buff, encoded_frame, sizeof(encoded_frame)) == 0, + "frame was not encoded properly"); + + while (dummy_rd < dummy_wr) { + ck_assert_msg(sbp_process(&sbp_state, &dummy_read) >= SBP_OK, + "sbp_process threw an error!"); + } + + ck_assert_msg(last_msg.n_callbacks_logged == 1, + "msg_callback: one callback should have been logged"); + ck_assert_msg(last_msg.sender_id == 66, + "msg_callback: sender_id decoded incorrectly"); + + ck_assert_msg( + sbp_message_cmp(SbpMsgAesCmacSignature, &last_msg.msg, &test_msg) == 0, + "Sent and received messages did not compare equal"); + + ck_assert_msg(last_msg.msg.aes_cmac_signature.certificate_id[0] == 1, + "incorrect value for " + "last_msg.msg.aes_cmac_signature.certificate_id[0], expected " + "1, is %" PRId64, + (int64_t)last_msg.msg.aes_cmac_signature.certificate_id[0]); + ck_assert_msg(last_msg.msg.aes_cmac_signature.certificate_id[1] == 2, + "incorrect value for " + "last_msg.msg.aes_cmac_signature.certificate_id[1], expected " + "2, is %" PRId64, + (int64_t)last_msg.msg.aes_cmac_signature.certificate_id[1]); + ck_assert_msg(last_msg.msg.aes_cmac_signature.certificate_id[2] == 3, + "incorrect value for " + "last_msg.msg.aes_cmac_signature.certificate_id[2], expected " + "3, is %" PRId64, + (int64_t)last_msg.msg.aes_cmac_signature.certificate_id[2]); + ck_assert_msg(last_msg.msg.aes_cmac_signature.certificate_id[3] == 4, + "incorrect value for " + "last_msg.msg.aes_cmac_signature.certificate_id[3], expected " + "4, is %" PRId64, + (int64_t)last_msg.msg.aes_cmac_signature.certificate_id[3]); + + ck_assert_msg(last_msg.msg.aes_cmac_signature.flags == 0, + "incorrect value for last_msg.msg.aes_cmac_signature.flags, " + "expected 0, is %" PRId64, + (int64_t)last_msg.msg.aes_cmac_signature.flags); + + ck_assert_msg(last_msg.msg.aes_cmac_signature.n_signed_messages == 3, + "incorrect value for " + "last_msg.msg.aes_cmac_signature.n_signed_messages, expected " + "3, is %" PRId64, + (int64_t)last_msg.msg.aes_cmac_signature.n_signed_messages); + + ck_assert_msg(last_msg.msg.aes_cmac_signature.on_demand_counter == 2, + "incorrect value for " + "last_msg.msg.aes_cmac_signature.on_demand_counter, expected " + "2, is %" PRId64, + (int64_t)last_msg.msg.aes_cmac_signature.on_demand_counter); + + ck_assert_msg( + last_msg.msg.aes_cmac_signature.signature[0] == 0, + "incorrect value for last_msg.msg.aes_cmac_signature.signature[0], " + "expected 0, is %" PRId64, + (int64_t)last_msg.msg.aes_cmac_signature.signature[0]); + ck_assert_msg( + last_msg.msg.aes_cmac_signature.signature[1] == 1, + "incorrect value for last_msg.msg.aes_cmac_signature.signature[1], " + "expected 1, is %" PRId64, + (int64_t)last_msg.msg.aes_cmac_signature.signature[1]); + ck_assert_msg( + last_msg.msg.aes_cmac_signature.signature[2] == 2, + "incorrect value for last_msg.msg.aes_cmac_signature.signature[2], " + "expected 2, is %" PRId64, + (int64_t)last_msg.msg.aes_cmac_signature.signature[2]); + ck_assert_msg( + last_msg.msg.aes_cmac_signature.signature[3] == 3, + "incorrect value for last_msg.msg.aes_cmac_signature.signature[3], " + "expected 3, is %" PRId64, + (int64_t)last_msg.msg.aes_cmac_signature.signature[3]); + ck_assert_msg( + last_msg.msg.aes_cmac_signature.signature[4] == 4, + "incorrect value for last_msg.msg.aes_cmac_signature.signature[4], " + "expected 4, is %" PRId64, + (int64_t)last_msg.msg.aes_cmac_signature.signature[4]); + ck_assert_msg( + last_msg.msg.aes_cmac_signature.signature[5] == 5, + "incorrect value for last_msg.msg.aes_cmac_signature.signature[5], " + "expected 5, is %" PRId64, + (int64_t)last_msg.msg.aes_cmac_signature.signature[5]); + ck_assert_msg( + last_msg.msg.aes_cmac_signature.signature[6] == 6, + "incorrect value for last_msg.msg.aes_cmac_signature.signature[6], " + "expected 6, is %" PRId64, + (int64_t)last_msg.msg.aes_cmac_signature.signature[6]); + ck_assert_msg( + last_msg.msg.aes_cmac_signature.signature[7] == 7, + "incorrect value for last_msg.msg.aes_cmac_signature.signature[7], " + "expected 7, is %" PRId64, + (int64_t)last_msg.msg.aes_cmac_signature.signature[7]); + ck_assert_msg( + last_msg.msg.aes_cmac_signature.signature[8] == 8, + "incorrect value for last_msg.msg.aes_cmac_signature.signature[8], " + "expected 8, is %" PRId64, + (int64_t)last_msg.msg.aes_cmac_signature.signature[8]); + ck_assert_msg( + last_msg.msg.aes_cmac_signature.signature[9] == 9, + "incorrect value for last_msg.msg.aes_cmac_signature.signature[9], " + "expected 9, is %" PRId64, + (int64_t)last_msg.msg.aes_cmac_signature.signature[9]); + ck_assert_msg( + last_msg.msg.aes_cmac_signature.signature[10] == 10, + "incorrect value for last_msg.msg.aes_cmac_signature.signature[10], " + "expected 10, is %" PRId64, + (int64_t)last_msg.msg.aes_cmac_signature.signature[10]); + ck_assert_msg( + last_msg.msg.aes_cmac_signature.signature[11] == 11, + "incorrect value for last_msg.msg.aes_cmac_signature.signature[11], " + "expected 11, is %" PRId64, + (int64_t)last_msg.msg.aes_cmac_signature.signature[11]); + ck_assert_msg( + last_msg.msg.aes_cmac_signature.signature[12] == 12, + "incorrect value for last_msg.msg.aes_cmac_signature.signature[12], " + "expected 12, is %" PRId64, + (int64_t)last_msg.msg.aes_cmac_signature.signature[12]); + ck_assert_msg( + last_msg.msg.aes_cmac_signature.signature[13] == 13, + "incorrect value for last_msg.msg.aes_cmac_signature.signature[13], " + "expected 13, is %" PRId64, + (int64_t)last_msg.msg.aes_cmac_signature.signature[13]); + ck_assert_msg( + last_msg.msg.aes_cmac_signature.signature[14] == 14, + "incorrect value for last_msg.msg.aes_cmac_signature.signature[14], " + "expected 14, is %" PRId64, + (int64_t)last_msg.msg.aes_cmac_signature.signature[14]); + ck_assert_msg( + last_msg.msg.aes_cmac_signature.signature[15] == 15, + "incorrect value for last_msg.msg.aes_cmac_signature.signature[15], " + "expected 15, is %" PRId64, + (int64_t)last_msg.msg.aes_cmac_signature.signature[15]); + + ck_assert_msg(last_msg.msg.aes_cmac_signature.signed_messages[0] == 11, + "incorrect value for " + "last_msg.msg.aes_cmac_signature.signed_messages[0], " + "expected 11, is %" PRId64, + (int64_t)last_msg.msg.aes_cmac_signature.signed_messages[0]); + ck_assert_msg(last_msg.msg.aes_cmac_signature.signed_messages[1] == 22, + "incorrect value for " + "last_msg.msg.aes_cmac_signature.signed_messages[1], " + "expected 22, is %" PRId64, + (int64_t)last_msg.msg.aes_cmac_signature.signed_messages[1]); + ck_assert_msg(last_msg.msg.aes_cmac_signature.signed_messages[2] == 33, + "incorrect value for " + "last_msg.msg.aes_cmac_signature.signed_messages[2], " + "expected 33, is %" PRId64, + (int64_t)last_msg.msg.aes_cmac_signature.signed_messages[2]); + + ck_assert_msg( + last_msg.msg.aes_cmac_signature.stream_counter == 1, + "incorrect value for last_msg.msg.aes_cmac_signature.stream_counter, " + "expected 1, is %" PRId64, + (int64_t)last_msg.msg.aes_cmac_signature.stream_counter); + } +} +END_TEST + +Suite *auto_check_sbp_signing_MsgAesCmacSignature_suite(void) { + Suite *s = suite_create( + "SBP generated test suite: auto_check_sbp_signing_MsgAesCmacSignature"); + TCase *tc_acq = tcase_create( + "Automated_Suite_auto_check_sbp_signing_MsgAesCmacSignature"); + tcase_add_test(tc_acq, test_auto_check_sbp_signing_MsgAesCmacSignature); + suite_add_tcase(s, tc_acq); + return s; +} \ No newline at end of file diff --git a/c/test/check_main.c b/c/test/check_main.c index 8359ba976b..a3a17a23e6 100644 --- a/c/test/check_main.c +++ b/c/test/check_main.c @@ -225,6 +225,7 @@ int main(void) { srunner_add_suite(sr, auto_check_sbp_settings_MsgSettingsSave_suite()); srunner_add_suite(sr, auto_check_sbp_settings_MsgSettingsWrite_suite()); srunner_add_suite(sr, auto_check_sbp_settings_MsgSettingsWriteResp_suite()); + srunner_add_suite(sr, auto_check_sbp_signing_MsgAesCmacSignature_suite()); srunner_add_suite(sr, auto_check_sbp_signing_MsgCertificateChain_suite()); srunner_add_suite(sr, auto_check_sbp_signing_MsgCertificateChainDep_suite()); srunner_add_suite(sr, auto_check_sbp_signing_MsgEcdsaCertificate_suite()); diff --git a/c/test/check_suites.h b/c/test/check_suites.h index 402d5738af..745a5b3b5e 100644 --- a/c/test/check_suites.h +++ b/c/test/check_suites.h @@ -196,6 +196,7 @@ Suite* auto_check_sbp_settings_MsgSettingsRegisterResp_suite(void); Suite* auto_check_sbp_settings_MsgSettingsSave_suite(void); Suite* auto_check_sbp_settings_MsgSettingsWrite_suite(void); Suite* auto_check_sbp_settings_MsgSettingsWriteResp_suite(void); +Suite* auto_check_sbp_signing_MsgAesCmacSignature_suite(void); Suite* auto_check_sbp_signing_MsgCertificateChain_suite(void); Suite* auto_check_sbp_signing_MsgCertificateChainDep_suite(void); Suite* auto_check_sbp_signing_MsgEcdsaCertificate_suite(void); diff --git a/c/test/cpp/auto_check_sbp_signing_MsgAesCmacSignature.cc b/c/test/cpp/auto_check_sbp_signing_MsgAesCmacSignature.cc new file mode 100644 index 0000000000..f3ef5ed3e6 --- /dev/null +++ b/c/test/cpp/auto_check_sbp_signing_MsgAesCmacSignature.cc @@ -0,0 +1,1030 @@ +/* + * Copyright (C) 2015-2021 Swift Navigation Inc. + * Contact: https://support.swiftnav.com + * + * This source is subject to the license found in the file 'LICENSE' which must + * be distributed together with this source. All other rights reserved. + * + * THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, + * EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE. + */ + +// This file was auto-generated from +// spec/tests/yaml/swiftnav/sbp/signing/test_MsgAesCmacSignature.yaml by +// generate.py. Do not modify by hand! + +#include +#include +#include +#include +#include + +namespace { + +template +void assign(T &dest, const U &source) { + dest = static_cast(source); +} +class Testauto_check_sbp_signing_MsgAesCmacSignature0 : public ::testing::Test { + public: + Testauto_check_sbp_signing_MsgAesCmacSignature0() { + assign(test_msg_.certificate_id[0], 1); + + assign(test_msg_.certificate_id[1], 2); + + assign(test_msg_.certificate_id[2], 3); + + assign(test_msg_.certificate_id[3], 4); + assign(test_msg_.flags, 0); + assign(test_msg_.n_signed_messages, 3); + assign(test_msg_.on_demand_counter, 2); + + assign(test_msg_.signature[0], 0); + + assign(test_msg_.signature[1], 1); + + assign(test_msg_.signature[2], 2); + + assign(test_msg_.signature[3], 3); + + assign(test_msg_.signature[4], 4); + + assign(test_msg_.signature[5], 5); + + assign(test_msg_.signature[6], 6); + + assign(test_msg_.signature[7], 7); + + assign(test_msg_.signature[8], 8); + + assign(test_msg_.signature[9], 9); + + assign(test_msg_.signature[10], 10); + + assign(test_msg_.signature[11], 11); + + assign(test_msg_.signature[12], 12); + + assign(test_msg_.signature[13], 13); + + assign(test_msg_.signature[14], 14); + + assign(test_msg_.signature[15], 15); + + assign(test_msg_.signed_messages[0], 11); + + assign(test_msg_.signed_messages[1], 22); + + assign(test_msg_.signed_messages[2], 33); + assign(test_msg_.stream_counter, 1); + } + + class SlowReader final : public sbp::IReader { + public: + SlowReader(const uint8_t *buf, uint32_t len) + : sbp::IReader(), buf_{buf}, len_{len} {} + + s32 read(uint8_t *buf, const uint32_t n) override { + if (n == 0) { + return 0; + } + if (remaining() == 0) { + return -1; + } + skip_next_read = !skip_next_read; + if (skip_next_read) { + return 0; + } + uint32_t real_n = std::min(n, 1u); + memcpy(buf, buf_ + offset_, real_n); + offset_ += real_n; + return static_cast(real_n); + } + + uint32_t remaining() const noexcept { return len_ - offset_; } + + static s32 read_static(uint8_t *buf, uint32_t len, void *ctx) { + return static_cast(ctx)->read(buf, len); + } + + private: + const uint8_t *buf_; + uint32_t len_; + uint32_t offset_{}; + bool skip_next_read{}; + }; + + class Reader final : public sbp::IReader { + public: + Reader(const uint8_t *buf, uint32_t len) + : sbp::IReader(), buf_{buf}, len_{len} {} + + s32 read(uint8_t *buf, const uint32_t n) override { + if (n == 0) { + return 0; + } + uint32_t real_n = std::min(n, remaining()); + if (real_n == 0) { + return -1; + } + memcpy(buf, buf_ + offset_, real_n); + offset_ += real_n; + return static_cast(real_n); + } + + uint32_t remaining() const noexcept { return len_ - offset_; } + + static s32 read_static(uint8_t *buf, uint32_t len, void *ctx) { + return static_cast(ctx)->read(buf, len); + } + + private: + const uint8_t *buf_; + uint32_t len_; + uint32_t offset_{}; + }; + + class SlowWriter final : public sbp::IWriter { + public: + explicit SlowWriter(uint32_t max_len = cMaxLen) + : IWriter(), max_len_{max_len} {} + static constexpr uint32_t cMaxLen = SBP_MAX_FRAME_LEN; + + s32 write(const uint8_t *buf, uint32_t n) override { + if (n == 0) { + return 0; + } + uint32_t real_n = std::min(n, 1u); + if (real_n == 0) { + return -1; + } + memcpy(buf_ + offset_, buf, real_n); + offset_ += real_n; + return static_cast(real_n); + } + + uint32_t remaining() const noexcept { return max_len_ - offset_; } + + const uint8_t *data() const noexcept { return buf_; } + + uint32_t len() const noexcept { return offset_; } + + static s32 write_static(const uint8_t *buf, uint32_t len, void *ctx) { + return static_cast(ctx)->write(buf, len); + } + + static s32 write_c(uint8_t *buf, uint32_t len, void *ctx) { + return static_cast(ctx)->write(buf, len); + } + + private: + uint8_t buf_[cMaxLen]; + uint32_t max_len_; + uint32_t offset_{}; + }; + + class Writer final : public sbp::IWriter { + public: + explicit Writer(uint32_t max_len = cMaxLen) + : IWriter(), max_len_{max_len} {} + static constexpr uint32_t cMaxLen = SBP_MAX_FRAME_LEN; + + s32 write(const uint8_t *buf, uint32_t n) override { + if (n == 0) { + return 0; + } + uint32_t real_n = std::min(n, remaining()); + if (real_n == 0) { + return -1; + } + memcpy(buf_ + offset_, buf, real_n); + offset_ += real_n; + return static_cast(real_n); + } + + uint32_t remaining() const noexcept { return max_len_ - offset_; } + + const uint8_t *data() const noexcept { return buf_; } + + uint32_t len() const noexcept { return offset_; } + + static s32 write_static(const uint8_t *buf, uint32_t len, void *ctx) { + return static_cast(ctx)->write(buf, len); + } + + static s32 write_c(uint8_t *buf, uint32_t len, void *ctx) { + return static_cast(ctx)->write(buf, len); + } + + private: + uint8_t buf_[cMaxLen]; + uint32_t max_len_; + uint32_t offset_{}; + }; + + struct CppHandler final + : public sbp::MessageHandler { + using sbp::MessageHandler::MessageHandler; + + struct Output final { + uint16_t sender_id; + sbp_msg_aes_cmac_signature_t msg; + }; + + std::vector outputs{}; + + protected: + void handle_sbp_msg(uint16_t sender_id, + const sbp_msg_aes_cmac_signature_t &msg) override { + outputs.emplace_back(); + outputs.back().sender_id = sender_id; + memcpy(&outputs.back().msg, &msg, sizeof(msg)); + } + }; + + struct CHandler final { + explicit CHandler(sbp_state_t *state) : state_{state} { + sbp_callback_register(state, SbpMsgAesCmacSignature, + &CHandler::callback_static, this, &node_); + } + + ~CHandler() { sbp_remove_callback(state_, &node_); } + + struct Output final { + uint16_t sender_id; + sbp_msg_aes_cmac_signature_t msg; + }; + + std::vector outputs{}; + + private: + void callback(uint16_t sender_id, sbp_msg_type_t msg_type, + const sbp_msg_t *msg) { + ASSERT_EQ(msg_type, SbpMsgAesCmacSignature); + outputs.emplace_back(); + outputs.back().sender_id = sender_id; + memcpy(&outputs.back().msg, &msg->aes_cmac_signature, + sizeof(msg->aes_cmac_signature)); + } + + static void callback_static(uint16_t sender_id, sbp_msg_type_t msg_type, + const sbp_msg_t *msg, void *ctx) { + static_cast(ctx)->callback(sender_id, msg_type, msg); + } + + sbp_msg_callbacks_node_t node_{}; + sbp_state_t *state_; + }; + + struct TestMsgInfo { + sbp_msg_aes_cmac_signature_t test_msg; + sbp_msg_t test_msg_wrapped; + sbp_msg_type_t msg_type; + uint16_t sender_id; + uint8_t preamble; + uint16_t crc; + const uint8_t *encoded_frame; + uint32_t frame_len; + const uint8_t *encoded_payload; + uint8_t payload_len; + + Reader get_frame_reader() const noexcept { + return Reader{encoded_frame, frame_len}; + } + + Reader get_frame_reader(uint32_t max) const noexcept { + assert(max <= frame_len); + return Reader{encoded_frame, max}; + } + + SlowReader get_slow_frame_reader() const noexcept { + return SlowReader{encoded_frame, frame_len}; + } + + Writer get_frame_writer() const noexcept { return Writer{frame_len}; } + + Writer get_frame_writer(uint32_t max) const noexcept { return Writer{max}; } + + SlowWriter get_slow_frame_writer() const noexcept { + return SlowWriter{frame_len}; + } + }; + + TestMsgInfo get_test_msg_info() const noexcept { + TestMsgInfo info; + memcpy(&info.test_msg, &test_msg_, sizeof(test_msg_)); + memcpy(&info.test_msg_wrapped.aes_cmac_signature, &test_msg_, + sizeof(test_msg_)); + info.msg_type = static_cast(SbpMsgAesCmacSignature); + info.sender_id = 66; + info.preamble = 0x55; + info.crc = 0x15C0; + info.encoded_frame = encoded_frame_; + info.frame_len = sizeof(encoded_frame_); + info.encoded_payload = encoded_payload_; + info.payload_len = 26; + + return info; + } + + protected: + void comparison_tests(const sbp_msg_aes_cmac_signature_t &lesser, + const sbp_msg_aes_cmac_signature_t &greater) { + sbp_msg_t wrapped_lesser = + sbp::MessageTraits::to_sbp_msg(lesser); + sbp_msg_t wrapped_greater = + sbp::MessageTraits::to_sbp_msg(greater); + + EXPECT_EQ(sbp_msg_aes_cmac_signature_cmp(&lesser, &lesser), 0); + EXPECT_EQ(sbp_msg_aes_cmac_signature_cmp(&greater, &greater), 0); + EXPECT_LE(sbp_msg_aes_cmac_signature_cmp(&lesser, &greater), 0); + EXPECT_GT(sbp_msg_aes_cmac_signature_cmp(&greater, &lesser), 0); + + EXPECT_EQ(sbp_message_cmp(SbpMsgAesCmacSignature, &wrapped_lesser, + &wrapped_lesser), + 0); + EXPECT_EQ(sbp_message_cmp(SbpMsgAesCmacSignature, &wrapped_greater, + &wrapped_greater), + 0); + EXPECT_LE(sbp_message_cmp(SbpMsgAesCmacSignature, &wrapped_lesser, + &wrapped_greater), + 0); + EXPECT_GT(sbp_message_cmp(SbpMsgAesCmacSignature, &wrapped_greater, + &wrapped_lesser), + 0); + + // lesser vs lesser + EXPECT_TRUE(lesser == lesser); + EXPECT_FALSE(lesser != lesser); + EXPECT_FALSE(lesser < lesser); + EXPECT_TRUE(lesser <= lesser); + EXPECT_FALSE(lesser > lesser); + EXPECT_TRUE(lesser >= lesser); + + // greater vs greater + EXPECT_TRUE(greater == greater); + EXPECT_FALSE(greater != greater); + EXPECT_FALSE(greater < greater); + EXPECT_TRUE(greater <= greater); + EXPECT_FALSE(greater > greater); + EXPECT_TRUE(greater >= greater); + + // lesser vs greater + EXPECT_FALSE(lesser == greater); + EXPECT_TRUE(lesser != greater); + EXPECT_TRUE(lesser < greater); + EXPECT_TRUE(lesser <= greater); + EXPECT_FALSE(lesser > greater); + EXPECT_FALSE(lesser >= greater); + + // greater vs lesser + EXPECT_FALSE(greater == lesser); + EXPECT_TRUE(greater != lesser); + EXPECT_FALSE(greater < lesser); + EXPECT_FALSE(greater <= lesser); + EXPECT_TRUE(greater > lesser); + EXPECT_TRUE(greater >= lesser); + } + + template ::value, bool> = true> + void make_lesser_greater(T &lesser, T &greater) { + if (lesser > std::numeric_limits::min()) { + lesser--; + } else { + greater++; + } + } + + template ::value, bool> = true> + void make_lesser_greater(T &lesser, T &greater) { + (void)lesser; + greater += static_cast(1.0); + } + + void make_lesser_greater(sbp_string_t &lesser, sbp_string_t &greater) { + if (greater.data[0] == 'z') { + lesser.data[0]--; + } else { + greater.data[0]++; + } + } + + template + void make_lesser_greater(char (&lesser)[N], char (&greater)[N]) { + if (lesser[0] == 'z') { + lesser[0]--; + } else { + greater[0]++; + } + } + + private: + sbp_msg_aes_cmac_signature_t test_msg_{}; + uint8_t encoded_frame_[26 + 8] = { + 85, 16, 12, 66, 0, 26, 1, 2, 1, 2, 3, 4, 0, 1, 2, 3, 4, + 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 11, 22, 33, 192, 21, + }; + uint8_t encoded_payload_[26] = { + 1, 2, 1, 2, 3, 4, 0, 1, 2, 3, 4, 5, 6, + 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 11, 22, 33, + }; +}; + +TEST_F(Testauto_check_sbp_signing_MsgAesCmacSignature0, EncodedLen) { + auto info = get_test_msg_info(); + EXPECT_EQ(sbp_msg_aes_cmac_signature_encoded_len(&info.test_msg), + info.payload_len); + + EXPECT_EQ( + sbp_message_encoded_len(SbpMsgAesCmacSignature, &info.test_msg_wrapped), + info.payload_len); +} + +TEST_F(Testauto_check_sbp_signing_MsgAesCmacSignature0, EncodeToBuf) { + auto info = get_test_msg_info(); + uint8_t buf[26]; + uint8_t n_written; + + EXPECT_EQ(sbp_msg_aes_cmac_signature_encode(&buf[0], sizeof(buf), &n_written, + &info.test_msg), + SBP_OK); + EXPECT_EQ(n_written, 26); + EXPECT_EQ(memcmp(&buf[0], info.encoded_payload, 26), 0); + + memset(&buf[0], 0, sizeof(buf)); + EXPECT_EQ(sbp_message_encode(&buf[0], sizeof(buf), &n_written, + SbpMsgAesCmacSignature, &info.test_msg_wrapped), + SBP_OK); + EXPECT_EQ(n_written, 26); + EXPECT_EQ(memcmp(&buf[0], info.encoded_payload, 26), 0); +} + +TEST_F(Testauto_check_sbp_signing_MsgAesCmacSignature0, + EncodeToBufWithoutNwritten) { + auto info = get_test_msg_info(); + uint8_t buf[26]; + + EXPECT_EQ(sbp_msg_aes_cmac_signature_encode(&buf[0], sizeof(buf), nullptr, + &info.test_msg), + SBP_OK); + EXPECT_EQ(memcmp(&buf[0], info.encoded_payload, 26), 0); +} +TEST_F(Testauto_check_sbp_signing_MsgAesCmacSignature0, EncodedToBufUnderflow) { + auto info = get_test_msg_info(); + uint8_t buf[26]; + + for (uint8_t i = 0; i < 26; i++) { + EXPECT_EQ( + sbp_msg_aes_cmac_signature_encode(&buf[0], i, nullptr, &info.test_msg), + SBP_ENCODE_ERROR); + } +} + +TEST_F(Testauto_check_sbp_signing_MsgAesCmacSignature0, DecodeFromBuf) { + auto info = get_test_msg_info(); + sbp_msg_aes_cmac_signature_t msg{}; + uint8_t n_read; + + EXPECT_EQ(sbp_msg_aes_cmac_signature_decode(&info.encoded_payload[0], + info.payload_len, &n_read, &msg), + SBP_OK); + EXPECT_EQ(n_read, 26); + EXPECT_EQ(msg, info.test_msg); + + sbp_msg_t wrapped_msg{}; + EXPECT_EQ(sbp_message_decode(&info.encoded_payload[0], info.payload_len, + &n_read, SbpMsgAesCmacSignature, &wrapped_msg), + SBP_OK); + EXPECT_EQ(n_read, 26); + EXPECT_EQ(msg, info.test_msg); +} + +TEST_F(Testauto_check_sbp_signing_MsgAesCmacSignature0, + DecodeFromBufWithoutNread) { + auto info = get_test_msg_info(); + sbp_msg_aes_cmac_signature_t msg{}; + + EXPECT_EQ(sbp_msg_aes_cmac_signature_decode(&info.encoded_payload[0], + info.payload_len, nullptr, &msg), + SBP_OK); + EXPECT_EQ(msg, info.test_msg); +} +TEST_F(Testauto_check_sbp_signing_MsgAesCmacSignature0, + DecodeFromBufUnderflow) { + auto info = get_test_msg_info(); + sbp_msg_aes_cmac_signature_t msg{}; + + for (uint8_t i = 0; i < info.payload_len; i++) { + int expected_return = SBP_DECODE_ERROR; + size_t overhead = []() -> size_t { + sbp_msg_aes_cmac_signature_t t{}; + return sbp_msg_aes_cmac_signature_encoded_len(&t); + }(); + size_t elem_size = []() -> size_t { + sbp_msg_aes_cmac_signature_t t{}; + t.n_signed_messages = 1; + return sbp_msg_aes_cmac_signature_encoded_len(&t); + }() - overhead; + + if (i >= overhead) { + if (((i - overhead) % elem_size) == 0) { + expected_return = SBP_OK; + } + } + + EXPECT_EQ(sbp_msg_aes_cmac_signature_decode(&info.encoded_payload[0], i, + nullptr, &msg), + expected_return); + } +} + +TEST_F(Testauto_check_sbp_signing_MsgAesCmacSignature0, + ReceiveThroughSbpState) { + auto info = get_test_msg_info(); + sbp_state_t state; + sbp_state_init(&state); + + auto reader = info.get_frame_reader(); + sbp_state_set_io_context(&state, &reader); + + CHandler handler{&state}; + + while (reader.remaining() > 0) { + EXPECT_GE(sbp_process(&state, &Reader::read_static), SBP_OK); + } + + EXPECT_EQ(handler.outputs.size(), 1); + EXPECT_EQ(handler.outputs[0].sender_id, info.sender_id); + EXPECT_EQ(handler.outputs[0].msg, info.test_msg); +} + +TEST_F(Testauto_check_sbp_signing_MsgAesCmacSignature0, + ReceiveThroughSbpStateUnderflow) { + auto info = get_test_msg_info(); + + for (uint32_t i = 0; i < info.frame_len; i++) { + sbp_state_t state; + sbp_state_init(&state); + + auto reader = info.get_frame_reader(i); + sbp_state_set_io_context(&state, &reader); + + CHandler handler(&state); + + int most_recent_return = sbp_process(&state, &Reader::read_static); + while (most_recent_return == SBP_OK || reader.remaining() > 0) { + most_recent_return = sbp_process(&state, &Reader::read_static); + } + + EXPECT_NE(most_recent_return, SBP_OK); + EXPECT_EQ(reader.remaining(), 0); + + EXPECT_EQ(handler.outputs.size(), 0); + } +} + +TEST_F(Testauto_check_sbp_signing_MsgAesCmacSignature0, SlowRead) { + auto info = get_test_msg_info(); + sbp_state_t state; + sbp_state_init(&state); + + auto reader = info.get_slow_frame_reader(); + sbp_state_set_io_context(&state, &reader); + + CHandler handler{&state}; + + while (reader.remaining() > 0) { + EXPECT_GE(sbp_process(&state, &SlowReader::read_static), SBP_OK); + } + + EXPECT_EQ(handler.outputs.size(), 1); + EXPECT_EQ(handler.outputs[0].sender_id, info.sender_id); + EXPECT_EQ(handler.outputs[0].msg, info.test_msg); +} + +TEST_F(Testauto_check_sbp_signing_MsgAesCmacSignature0, BadCRC) { + auto info = get_test_msg_info(); + uint8_t buf[SBP_MAX_FRAME_LEN]; + memcpy(&buf[0], info.encoded_frame, info.frame_len); + + // Introduce a CRC error which should cause an error return and no callback + buf[info.frame_len - 1]++; + + sbp_state_t state; + sbp_state_init(&state); + + Reader reader{buf, info.frame_len}; + sbp_state_set_io_context(&state, &reader); + + CHandler handler{&state}; + + while (reader.remaining() > 0) { + int res = sbp_process(&state, &Reader::read_static); + EXPECT_EQ(res, reader.remaining() == 0 ? SBP_CRC_ERROR : SBP_OK); + } + + EXPECT_EQ(handler.outputs.size(), 0); +} + +TEST_F(Testauto_check_sbp_signing_MsgAesCmacSignature0, SendThroughSbpState) { + auto info = get_test_msg_info(); + sbp_state_t state; + sbp_state_init(&state); + + auto writer = info.get_frame_writer(); + sbp_state_set_io_context(&state, &writer); + + EXPECT_EQ(sbp_msg_aes_cmac_signature_send(&state, info.sender_id, + &info.test_msg, &Writer::write_c), + SBP_OK); + EXPECT_EQ(writer.len(), info.frame_len); + EXPECT_EQ(memcmp(writer.data(), &info.encoded_frame[0], writer.len()), 0); +} + +TEST_F(Testauto_check_sbp_signing_MsgAesCmacSignature0, + SendWrappedThroughSbpState) { + auto info = get_test_msg_info(); + sbp_state_t state; + sbp_state_init(&state); + + auto writer = info.get_frame_writer(); + sbp_state_set_io_context(&state, &writer); + + EXPECT_EQ(sbp_message_send(&state, SbpMsgAesCmacSignature, info.sender_id, + &info.test_msg_wrapped, &Writer::write_c), + SBP_OK); + EXPECT_EQ(writer.len(), info.frame_len); + EXPECT_EQ(memcmp(writer.data(), info.encoded_frame, info.frame_len), 0); +} + +TEST_F(Testauto_check_sbp_signing_MsgAesCmacSignature0, + SendThroughSbpStateUnderflow) { + auto info = get_test_msg_info(); + + for (uint32_t i = 0; i < info.frame_len; i++) { + sbp_state_t state; + sbp_state_init(&state); + + auto writer = info.get_frame_writer(i); + sbp_state_set_io_context(&state, &writer); + + EXPECT_NE(sbp_message_send(&state, SbpMsgAesCmacSignature, info.sender_id, + &info.test_msg_wrapped, &Writer::write_c), + SBP_OK); + EXPECT_EQ(writer.len(), i); + EXPECT_EQ(memcmp(writer.data(), info.encoded_frame, i), 0); + } +} + +TEST_F(Testauto_check_sbp_signing_MsgAesCmacSignature0, DISABLED_SlowWrite) { + auto info = get_test_msg_info(); + sbp_state_t state; + sbp_state_init(&state); + + auto writer = info.get_slow_frame_writer(); + sbp_state_set_io_context(&state, &writer); + + EXPECT_EQ(sbp_message_send(&state, SbpMsgAesCmacSignature, info.sender_id, + &info.test_msg_wrapped, &SlowWriter::write_c), + SBP_OK); + EXPECT_EQ(writer.len(), info.frame_len); + EXPECT_EQ(memcmp(writer.data(), info.encoded_frame, info.frame_len), 0); +} + +TEST_F(Testauto_check_sbp_signing_MsgAesCmacSignature0, Comparison) { + auto info = get_test_msg_info(); + + { + sbp_msg_aes_cmac_signature_t lesser = info.test_msg; + sbp_msg_aes_cmac_signature_t greater = info.test_msg; + make_lesser_greater(lesser.certificate_id[0], greater.certificate_id[0]); + comparison_tests(lesser, greater); + } + + { + sbp_msg_aes_cmac_signature_t lesser = info.test_msg; + sbp_msg_aes_cmac_signature_t greater = info.test_msg; + make_lesser_greater(lesser.certificate_id[1], greater.certificate_id[1]); + comparison_tests(lesser, greater); + } + + { + sbp_msg_aes_cmac_signature_t lesser = info.test_msg; + sbp_msg_aes_cmac_signature_t greater = info.test_msg; + make_lesser_greater(lesser.certificate_id[2], greater.certificate_id[2]); + comparison_tests(lesser, greater); + } + + { + sbp_msg_aes_cmac_signature_t lesser = info.test_msg; + sbp_msg_aes_cmac_signature_t greater = info.test_msg; + make_lesser_greater(lesser.certificate_id[3], greater.certificate_id[3]); + comparison_tests(lesser, greater); + } + { + sbp_msg_aes_cmac_signature_t lesser = info.test_msg; + sbp_msg_aes_cmac_signature_t greater = info.test_msg; + make_lesser_greater(lesser.flags, greater.flags); + comparison_tests(lesser, greater); + } + { + sbp_msg_aes_cmac_signature_t lesser = info.test_msg; + sbp_msg_aes_cmac_signature_t greater = info.test_msg; + make_lesser_greater(lesser.n_signed_messages, greater.n_signed_messages); + comparison_tests(lesser, greater); + } + { + sbp_msg_aes_cmac_signature_t lesser = info.test_msg; + sbp_msg_aes_cmac_signature_t greater = info.test_msg; + make_lesser_greater(lesser.on_demand_counter, greater.on_demand_counter); + comparison_tests(lesser, greater); + } + + { + sbp_msg_aes_cmac_signature_t lesser = info.test_msg; + sbp_msg_aes_cmac_signature_t greater = info.test_msg; + make_lesser_greater(lesser.signature[0], greater.signature[0]); + comparison_tests(lesser, greater); + } + + { + sbp_msg_aes_cmac_signature_t lesser = info.test_msg; + sbp_msg_aes_cmac_signature_t greater = info.test_msg; + make_lesser_greater(lesser.signature[1], greater.signature[1]); + comparison_tests(lesser, greater); + } + + { + sbp_msg_aes_cmac_signature_t lesser = info.test_msg; + sbp_msg_aes_cmac_signature_t greater = info.test_msg; + make_lesser_greater(lesser.signature[2], greater.signature[2]); + comparison_tests(lesser, greater); + } + + { + sbp_msg_aes_cmac_signature_t lesser = info.test_msg; + sbp_msg_aes_cmac_signature_t greater = info.test_msg; + make_lesser_greater(lesser.signature[3], greater.signature[3]); + comparison_tests(lesser, greater); + } + + { + sbp_msg_aes_cmac_signature_t lesser = info.test_msg; + sbp_msg_aes_cmac_signature_t greater = info.test_msg; + make_lesser_greater(lesser.signature[4], greater.signature[4]); + comparison_tests(lesser, greater); + } + + { + sbp_msg_aes_cmac_signature_t lesser = info.test_msg; + sbp_msg_aes_cmac_signature_t greater = info.test_msg; + make_lesser_greater(lesser.signature[5], greater.signature[5]); + comparison_tests(lesser, greater); + } + + { + sbp_msg_aes_cmac_signature_t lesser = info.test_msg; + sbp_msg_aes_cmac_signature_t greater = info.test_msg; + make_lesser_greater(lesser.signature[6], greater.signature[6]); + comparison_tests(lesser, greater); + } + + { + sbp_msg_aes_cmac_signature_t lesser = info.test_msg; + sbp_msg_aes_cmac_signature_t greater = info.test_msg; + make_lesser_greater(lesser.signature[7], greater.signature[7]); + comparison_tests(lesser, greater); + } + + { + sbp_msg_aes_cmac_signature_t lesser = info.test_msg; + sbp_msg_aes_cmac_signature_t greater = info.test_msg; + make_lesser_greater(lesser.signature[8], greater.signature[8]); + comparison_tests(lesser, greater); + } + + { + sbp_msg_aes_cmac_signature_t lesser = info.test_msg; + sbp_msg_aes_cmac_signature_t greater = info.test_msg; + make_lesser_greater(lesser.signature[9], greater.signature[9]); + comparison_tests(lesser, greater); + } + + { + sbp_msg_aes_cmac_signature_t lesser = info.test_msg; + sbp_msg_aes_cmac_signature_t greater = info.test_msg; + make_lesser_greater(lesser.signature[10], greater.signature[10]); + comparison_tests(lesser, greater); + } + + { + sbp_msg_aes_cmac_signature_t lesser = info.test_msg; + sbp_msg_aes_cmac_signature_t greater = info.test_msg; + make_lesser_greater(lesser.signature[11], greater.signature[11]); + comparison_tests(lesser, greater); + } + + { + sbp_msg_aes_cmac_signature_t lesser = info.test_msg; + sbp_msg_aes_cmac_signature_t greater = info.test_msg; + make_lesser_greater(lesser.signature[12], greater.signature[12]); + comparison_tests(lesser, greater); + } + + { + sbp_msg_aes_cmac_signature_t lesser = info.test_msg; + sbp_msg_aes_cmac_signature_t greater = info.test_msg; + make_lesser_greater(lesser.signature[13], greater.signature[13]); + comparison_tests(lesser, greater); + } + + { + sbp_msg_aes_cmac_signature_t lesser = info.test_msg; + sbp_msg_aes_cmac_signature_t greater = info.test_msg; + make_lesser_greater(lesser.signature[14], greater.signature[14]); + comparison_tests(lesser, greater); + } + + { + sbp_msg_aes_cmac_signature_t lesser = info.test_msg; + sbp_msg_aes_cmac_signature_t greater = info.test_msg; + make_lesser_greater(lesser.signature[15], greater.signature[15]); + comparison_tests(lesser, greater); + } + + { + sbp_msg_aes_cmac_signature_t lesser = info.test_msg; + sbp_msg_aes_cmac_signature_t greater = info.test_msg; + make_lesser_greater(lesser.signed_messages[0], greater.signed_messages[0]); + comparison_tests(lesser, greater); + } + + { + sbp_msg_aes_cmac_signature_t lesser = info.test_msg; + sbp_msg_aes_cmac_signature_t greater = info.test_msg; + make_lesser_greater(lesser.signed_messages[1], greater.signed_messages[1]); + comparison_tests(lesser, greater); + } + + { + sbp_msg_aes_cmac_signature_t lesser = info.test_msg; + sbp_msg_aes_cmac_signature_t greater = info.test_msg; + make_lesser_greater(lesser.signed_messages[2], greater.signed_messages[2]); + comparison_tests(lesser, greater); + } + { + sbp_msg_aes_cmac_signature_t lesser = info.test_msg; + sbp_msg_aes_cmac_signature_t greater = info.test_msg; + make_lesser_greater(lesser.stream_counter, greater.stream_counter); + comparison_tests(lesser, greater); + } +} + +TEST_F(Testauto_check_sbp_signing_MsgAesCmacSignature0, CppTraitsProperties) { + // EXPECT_EQ(sbp::MessageTraits::id, + // SbpMsgAesCmacSignature); + EXPECT_STREQ(sbp::MessageTraits::name, + "MSG_AES_CMAC_SIGNATURE"); +} + +TEST_F(Testauto_check_sbp_signing_MsgAesCmacSignature0, CppTraitsFromSbpMsgT) { + auto info = get_test_msg_info(); + + const sbp_msg_t &const_sbp_msg_t = info.test_msg_wrapped; + sbp_msg_t &non_const_sbp_msg_t = info.test_msg_wrapped; + + const sbp_msg_aes_cmac_signature_t &const_unwrapped = + sbp::MessageTraits::get(const_sbp_msg_t); + sbp_msg_aes_cmac_signature_t &non_const_unwrapped = + sbp::MessageTraits::get( + non_const_sbp_msg_t); + + EXPECT_EQ((const void *)&const_sbp_msg_t, (const void *)&const_unwrapped); + EXPECT_EQ((void *)&non_const_sbp_msg_t, (void *)&non_const_unwrapped); +} + +TEST_F(Testauto_check_sbp_signing_MsgAesCmacSignature0, CppTraitsToSbpMsgT) { + auto info = get_test_msg_info(); + + sbp_msg_t msg1 = sbp::MessageTraits::to_sbp_msg( + info.test_msg); + EXPECT_EQ(msg1.aes_cmac_signature, info.test_msg); + + sbp_msg_t msg2; + sbp::MessageTraits::to_sbp_msg(info.test_msg, + &msg2); + EXPECT_EQ(msg2.aes_cmac_signature, info.test_msg); +} + +TEST_F(Testauto_check_sbp_signing_MsgAesCmacSignature0, CppTraitsEncodedLen) { + auto info = get_test_msg_info(); + EXPECT_EQ(sbp::MessageTraits::encoded_len( + info.test_msg), + info.payload_len); +} + +TEST_F(Testauto_check_sbp_signing_MsgAesCmacSignature0, + CppTraitsSendThroughSbpState) { + auto info = get_test_msg_info(); + sbp_state_t state; + sbp_state_init(&state); + + auto writer = info.get_frame_writer(); + sbp_state_set_io_context(&state, &writer); + + EXPECT_EQ(sbp::MessageTraits::send( + &state, info.sender_id, info.test_msg, &Writer::write_c), + SBP_OK); + EXPECT_EQ(writer.len(), info.frame_len); + EXPECT_EQ(memcmp(writer.data(), &info.encoded_frame[0], writer.len()), 0); +} + +TEST_F(Testauto_check_sbp_signing_MsgAesCmacSignature0, CppTraitsEncodeToBuf) { + auto info = get_test_msg_info(); + uint8_t buf[26]; + uint8_t n_written; + + EXPECT_EQ(sbp::MessageTraits::encode( + &buf[0], sizeof(buf), &n_written, info.test_msg), + SBP_OK); + EXPECT_EQ(n_written, 26); + EXPECT_EQ(memcmp(&buf[0], info.encoded_payload, 26), 0); +} + +TEST_F(Testauto_check_sbp_signing_MsgAesCmacSignature0, + CppTraitsDecodeFromBuf) { + auto info = get_test_msg_info(); + sbp_msg_aes_cmac_signature_t msg{}; + uint8_t n_read; + + EXPECT_EQ(sbp::MessageTraits::decode( + &info.encoded_payload[0], info.payload_len, &n_read, &msg), + SBP_OK); + EXPECT_EQ(n_read, 26); + EXPECT_EQ(msg, info.test_msg); +} + +TEST_F(Testauto_check_sbp_signing_MsgAesCmacSignature0, + ReceiveThroughMessageHandler) { + auto info = get_test_msg_info(); + auto reader = info.get_frame_reader(); + + sbp::State state{}; + state.set_reader(&reader); + + CppHandler handler{&state}; + + while (reader.remaining() > 0) { + EXPECT_GE(state.process(), SBP_OK); + } + + EXPECT_EQ(handler.outputs.size(), 1); + EXPECT_EQ(handler.outputs[0].sender_id, info.sender_id); + EXPECT_EQ(handler.outputs[0].msg, info.test_msg); +} + +TEST_F(Testauto_check_sbp_signing_MsgAesCmacSignature0, + ProcessSbpMsgTThroughMessageHandler) { + auto info = get_test_msg_info(); + sbp::State state{}; + CppHandler handler(&state); + + state.process_message(info.sender_id, SbpMsgAesCmacSignature, + &info.test_msg_wrapped); + + EXPECT_EQ(handler.outputs.size(), 1); + EXPECT_EQ(handler.outputs[0].sender_id, info.sender_id); + EXPECT_EQ(handler.outputs[0].msg, info.test_msg); +} + +TEST_F(Testauto_check_sbp_signing_MsgAesCmacSignature0, SendThroughCppState) { + auto info = get_test_msg_info(); + auto writer = info.get_frame_writer(); + + sbp::State state{}; + state.set_writer(&writer); + + EXPECT_EQ(state.send_message(info.sender_id, info.test_msg), SBP_OK); + EXPECT_EQ(writer.len(), info.frame_len); + EXPECT_EQ(memcmp(writer.data(), info.encoded_frame, info.frame_len), 0); +} + +TEST_F(Testauto_check_sbp_signing_MsgAesCmacSignature0, + SendWrappedSbpMsgTThroughCppState) { + auto info = get_test_msg_info(); + auto writer = info.get_frame_writer(); + + sbp::State state{}; + state.set_writer(&writer); + + EXPECT_EQ(state.send_message(info.sender_id, SbpMsgAesCmacSignature, + info.test_msg_wrapped), + SBP_OK); + EXPECT_EQ(writer.len(), info.frame_len); + EXPECT_EQ(memcmp(writer.data(), info.encoded_frame, info.frame_len), 0); +} + +} // namespace \ No newline at end of file diff --git a/docs/sbp.pdf b/docs/sbp.pdf index e09f1129ce..7b49d5a08d 100644 Binary files a/docs/sbp.pdf and b/docs/sbp.pdf differ diff --git a/haskell/src/SwiftNav/SBP/Msg.hs b/haskell/src/SwiftNav/SBP/Msg.hs index 3e46239095..0cbaebe6d4 100644 --- a/haskell/src/SwiftNav/SBP/Msg.hs +++ b/haskell/src/SwiftNav/SBP/Msg.hs @@ -66,6 +66,7 @@ data SBPMsg = | SBPMsgAcqResultDepC MsgAcqResultDepC Msg | SBPMsgAcqSvProfile MsgAcqSvProfile Msg | SBPMsgAcqSvProfileDep MsgAcqSvProfileDep Msg + | SBPMsgAesCmacSignature MsgAesCmacSignature Msg | SBPMsgAgeCorrections MsgAgeCorrections Msg | SBPMsgAlmanac MsgAlmanac Msg | SBPMsgAlmanacGlo MsgAlmanacGlo Msg @@ -316,6 +317,7 @@ instance Binary SBPMsg where | _msgSBPType == msgAcqResultDepC = SBPMsgAcqResultDepC (decode (fromStrict (unBytes _msgSBPPayload))) m | _msgSBPType == msgAcqSvProfile = SBPMsgAcqSvProfile (decode (fromStrict (unBytes _msgSBPPayload))) m | _msgSBPType == msgAcqSvProfileDep = SBPMsgAcqSvProfileDep (decode (fromStrict (unBytes _msgSBPPayload))) m + | _msgSBPType == msgAesCmacSignature = SBPMsgAesCmacSignature (decode (fromStrict (unBytes _msgSBPPayload))) m | _msgSBPType == msgAgeCorrections = SBPMsgAgeCorrections (decode (fromStrict (unBytes _msgSBPPayload))) m | _msgSBPType == msgAlmanac = SBPMsgAlmanac (decode (fromStrict (unBytes _msgSBPPayload))) m | _msgSBPType == msgAlmanacGlo = SBPMsgAlmanacGlo (decode (fromStrict (unBytes _msgSBPPayload))) m @@ -558,6 +560,7 @@ instance Binary SBPMsg where encoder (SBPMsgAcqResultDepC _ m) = put m encoder (SBPMsgAcqSvProfile _ m) = put m encoder (SBPMsgAcqSvProfileDep _ m) = put m + encoder (SBPMsgAesCmacSignature _ m) = put m encoder (SBPMsgAgeCorrections _ m) = put m encoder (SBPMsgAlmanac _ m) = put m encoder (SBPMsgAlmanacGlo _ m) = put m @@ -804,6 +807,7 @@ instance FromJSON SBPMsg where | msgType == msgAcqResultDepC = SBPMsgAcqResultDepC <$> pure (decode (fromStrict (unBytes payload))) <*> parseJSON obj | msgType == msgAcqSvProfile = SBPMsgAcqSvProfile <$> pure (decode (fromStrict (unBytes payload))) <*> parseJSON obj | msgType == msgAcqSvProfileDep = SBPMsgAcqSvProfileDep <$> pure (decode (fromStrict (unBytes payload))) <*> parseJSON obj + | msgType == msgAesCmacSignature = SBPMsgAesCmacSignature <$> pure (decode (fromStrict (unBytes payload))) <*> parseJSON obj | msgType == msgAgeCorrections = SBPMsgAgeCorrections <$> pure (decode (fromStrict (unBytes payload))) <*> parseJSON obj | msgType == msgAlmanac = SBPMsgAlmanac <$> pure (decode (fromStrict (unBytes payload))) <*> parseJSON obj | msgType == msgAlmanacGlo = SBPMsgAlmanacGlo <$> pure (decode (fromStrict (unBytes payload))) <*> parseJSON obj @@ -1051,6 +1055,7 @@ instance ToJSON SBPMsg where toJSON (SBPMsgAcqResultDepC n m) = toJSON n <<>> toJSON m toJSON (SBPMsgAcqSvProfile n m) = toJSON n <<>> toJSON m toJSON (SBPMsgAcqSvProfileDep n m) = toJSON n <<>> toJSON m + toJSON (SBPMsgAesCmacSignature n m) = toJSON n <<>> toJSON m toJSON (SBPMsgAgeCorrections n m) = toJSON n <<>> toJSON m toJSON (SBPMsgAlmanac _ m) = toJSON m toJSON (SBPMsgAlmanacGlo n m) = toJSON n <<>> toJSON m @@ -1292,6 +1297,7 @@ instance HasMsg SBPMsg where msg f (SBPMsgAcqResultDepC n m) = SBPMsgAcqResultDepC n <$> f m msg f (SBPMsgAcqSvProfile n m) = SBPMsgAcqSvProfile n <$> f m msg f (SBPMsgAcqSvProfileDep n m) = SBPMsgAcqSvProfileDep n <$> f m + msg f (SBPMsgAesCmacSignature n m) = SBPMsgAesCmacSignature n <$> f m msg f (SBPMsgAgeCorrections n m) = SBPMsgAgeCorrections n <$> f m msg f (SBPMsgAlmanac n m) = SBPMsgAlmanac n <$> f m msg f (SBPMsgAlmanacGlo n m) = SBPMsgAlmanacGlo n <$> f m diff --git a/haskell/src/SwiftNav/SBP/Signing.hs b/haskell/src/SwiftNav/SBP/Signing.hs index 258117e11b..abaea2555a 100644 --- a/haskell/src/SwiftNav/SBP/Signing.hs +++ b/haskell/src/SwiftNav/SBP/Signing.hs @@ -224,6 +224,60 @@ $(makeSBP 'msgCertificateChainDep ''MsgCertificateChainDep) $(makeJSON "_msgCertificateChainDep_" ''MsgCertificateChainDep) $(makeLenses ''MsgCertificateChainDep) +msgAesCmacSignature :: Word16 +msgAesCmacSignature = 0x0C10 + +-- | SBP class for message MSG_AES_CMAC_SIGNATURE (0x0C10). +-- +-- Digital signature using AES-CMAC 128 algorithm used for data integrity. +data MsgAesCmacSignature = MsgAesCmacSignature + { _msgAesCmacSignature_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. + , _msgAesCmacSignature_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. + , _msgAesCmacSignature_certificate_id :: ![Word8] + -- ^ The last 4 bytes of the certificate's SHA-1 fingerprint + , _msgAesCmacSignature_signature :: ![Word8] + -- ^ Signature + , _msgAesCmacSignature_flags :: !Word8 + -- ^ Describes the format of the 'signed messages' field below. + , _msgAesCmacSignature_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 MsgAesCmacSignature where + get = do + _msgAesCmacSignature_stream_counter <- getWord8 + _msgAesCmacSignature_on_demand_counter <- getWord8 + _msgAesCmacSignature_certificate_id <- replicateM 4 getWord8 + _msgAesCmacSignature_signature <- replicateM 16 getWord8 + _msgAesCmacSignature_flags <- getWord8 + _msgAesCmacSignature_signed_messages <- whileM (not <$> isEmpty) getWord8 + pure MsgAesCmacSignature {..} + + put MsgAesCmacSignature {..} = do + putWord8 _msgAesCmacSignature_stream_counter + putWord8 _msgAesCmacSignature_on_demand_counter + mapM_ putWord8 _msgAesCmacSignature_certificate_id + mapM_ putWord8 _msgAesCmacSignature_signature + putWord8 _msgAesCmacSignature_flags + mapM_ putWord8 _msgAesCmacSignature_signed_messages + +$(makeSBP 'msgAesCmacSignature ''MsgAesCmacSignature) +$(makeJSON "_msgAesCmacSignature_" ''MsgAesCmacSignature) +$(makeLenses ''MsgAesCmacSignature) + msgEcdsaSignature :: Word16 msgEcdsaSignature = 0x0C08 diff --git a/java/src/com/swiftnav/sbp/client/MessageTable.java b/java/src/com/swiftnav/sbp/client/MessageTable.java index f73abf745e..048adecf9f 100644 --- a/java/src/com/swiftnav/sbp/client/MessageTable.java +++ b/java/src/com/swiftnav/sbp/client/MessageTable.java @@ -193,6 +193,7 @@ import com.swiftnav.sbp.settings.MsgSettingsSave; import com.swiftnav.sbp.settings.MsgSettingsWrite; import com.swiftnav.sbp.settings.MsgSettingsWriteResp; +import com.swiftnav.sbp.signing.MsgAesCmacSignature; import com.swiftnav.sbp.signing.MsgCertificateChain; import com.swiftnav.sbp.signing.MsgCertificateChainDep; import com.swiftnav.sbp.signing.MsgEcdsaCertificate; @@ -620,6 +621,8 @@ static SBPMessage dispatch(SBPMessage msg) throws SBPBinaryException { return new MsgCertificateChain(msg); case MsgCertificateChainDep.TYPE: return new MsgCertificateChainDep(msg); + case MsgAesCmacSignature.TYPE: + return new MsgAesCmacSignature(msg); case MsgEcdsaSignature.TYPE: return new MsgEcdsaSignature(msg); case MsgEcdsaSignatureDepB.TYPE: diff --git a/java/src/com/swiftnav/sbp/signing/MsgAesCmacSignature.java b/java/src/com/swiftnav/sbp/signing/MsgAesCmacSignature.java new file mode 100644 index 0000000000..675b601b4b --- /dev/null +++ b/java/src/com/swiftnav/sbp/signing/MsgAesCmacSignature.java @@ -0,0 +1,117 @@ +/* Copyright (C) 2015-2022 Swift Navigation Inc. + * Contact: https://support.swiftnav.com + * + * This source is subject to the license found in the file 'LICENSE' which must + * be distributed together with this source. All other rights reserved. + * + * THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, + * EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE. + */ +package com.swiftnav.sbp.signing; + +// This file was auto-generated from yaml/swiftnav/sbp/signing.yaml by generate.py. +// Do not modify by hand! + + +import com.swiftnav.sbp.SBPBinaryException; +import com.swiftnav.sbp.SBPMessage; +import org.json.JSONArray; +import org.json.JSONObject; + +/** + * SBP class for message MSG_AES_CMAC_SIGNATURE (0x0C10). + * + *

You can have MSG_AES_CMAC_SIGNATURE inherent its fields directly from an inherited SBP object, + * or construct it inline using a dict of its fields. + * + *

Digital signature using AES-CMAC 128 algorithm used for data integrity. + */ +public class MsgAesCmacSignature extends SBPMessage { + public static final int TYPE = 0x0C10; + + /** + * 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. + */ + public int stream_counter; + + /** + * 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. + */ + public int on_demand_counter; + + /** The last 4 bytes of the certificate's SHA-1 fingerprint */ + public int[] certificate_id; + + /** Signature */ + public int[] signature; + + /** Describes the format of the 'signed messages' field below. */ + public int flags; + + /** + * 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. + */ + public int[] signed_messages; + + public MsgAesCmacSignature(int sender) { + super(sender, TYPE); + } + + public MsgAesCmacSignature() { + super(TYPE); + } + + public MsgAesCmacSignature(SBPMessage msg) throws SBPBinaryException { + super(msg); + if (msg.type != TYPE) + throw new SBPBinaryException( + "Type mismatch for MsgAesCmacSignature, expected 3088, actual " + msg.type); + } + + @Override + protected void parse(Parser parser) throws SBPBinaryException { + /* Parse fields from binary */ + stream_counter = parser.getU8(); + on_demand_counter = parser.getU8(); + certificate_id = parser.getArrayofU8(4); + signature = parser.getArrayofU8(16); + flags = parser.getU8(); + signed_messages = parser.getArrayofU8(); + } + + @Override + protected void build(Builder builder) { + builder.putU8(stream_counter); + builder.putU8(on_demand_counter); + builder.putArrayofU8(certificate_id, 4); + builder.putArrayofU8(signature, 16); + builder.putU8(flags); + builder.putArrayofU8(signed_messages); + } + + @Override + public JSONObject toJSON() { + JSONObject obj = super.toJSON(); + obj.put("stream_counter", stream_counter); + obj.put("on_demand_counter", on_demand_counter); + obj.put("certificate_id", new JSONArray(certificate_id)); + obj.put("signature", new JSONArray(signature)); + obj.put("flags", flags); + obj.put("signed_messages", new JSONArray(signed_messages)); + return obj; + } + + @Override + public String getFriendlyName() { + return "AES CMAC SIGNATURE"; + } +} diff --git a/java/test/auto_check_sbp_signing_MsgAesCmacSignatureTest.java b/java/test/auto_check_sbp_signing_MsgAesCmacSignatureTest.java new file mode 100644 index 0000000000..36ca1657f6 --- /dev/null +++ b/java/test/auto_check_sbp_signing_MsgAesCmacSignatureTest.java @@ -0,0 +1,307 @@ +/* Copyright (C) 2015-2022 Swift Navigation Inc. + * Contact: https://support.swiftnav.com + * + * This source is subject to the license found in the file 'LICENSE' which must + * be distributed together with this source. All other rights reserved. + * + * THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, + * EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE. + */ +package com.swiftnav.sbp.test; + +// This file was auto-generated from +// spec/tests/yaml/swiftnav/sbp/signing/test_MsgAesCmacSignature.yaml by generate.py. Do not modify +// by hand! + + +import com.swiftnav.sbp.SBPMessage; +import com.swiftnav.sbp.signing.MsgAesCmacSignature; +import java.math.BigInteger; +import org.json.JSONObject; +import org.junit.Test; + +public class auto_check_sbp_signing_MsgAesCmacSignatureTest { + + public static boolean debug = false; + private static final double DELTA = 1e-15; + + @Test + public void test1() throws Throwable { + if (debug) + System.out.format("%n%s%n", "auto_check_sbp_signing_MsgAesCmacSignatureTest.test1"); + byte[] payload = + new byte[] { + (byte) 1, (byte) 2, (byte) 1, (byte) 2, (byte) 3, (byte) 4, (byte) 0, (byte) 1, + (byte) 2, (byte) 3, (byte) 4, (byte) 5, (byte) 6, (byte) 7, (byte) 8, (byte) 9, + (byte) 10, (byte) 11, (byte) 12, (byte) 13, (byte) 14, (byte) 15, (byte) 0, + (byte) 11, (byte) 22, (byte) 33, + }; + SBPMessage sbp = new SBPMessage(0x42, 0xC10, payload); + MsgAesCmacSignature msg = new MsgAesCmacSignature(sbp); + JSONObject json = msg.toJSON(); + Number value; + Number expected; + value = msg.certificate_id[0]; + if (value instanceof BigInteger) { + org.junit.Assert.assertTrue( + "'" + msg.certificate_id[0] + "' != '" + 1 + "'", + value.equals(BigInteger.valueOf(1L))); + } else { + value = value.longValue(); + expected = 1L; + org.junit.Assert.assertEquals(value, expected); + } + value = msg.certificate_id[1]; + if (value instanceof BigInteger) { + org.junit.Assert.assertTrue( + "'" + msg.certificate_id[1] + "' != '" + 2 + "'", + value.equals(BigInteger.valueOf(2L))); + } else { + value = value.longValue(); + expected = 2L; + org.junit.Assert.assertEquals(value, expected); + } + value = msg.certificate_id[2]; + if (value instanceof BigInteger) { + org.junit.Assert.assertTrue( + "'" + msg.certificate_id[2] + "' != '" + 3 + "'", + value.equals(BigInteger.valueOf(3L))); + } else { + value = value.longValue(); + expected = 3L; + org.junit.Assert.assertEquals(value, expected); + } + value = msg.certificate_id[3]; + if (value instanceof BigInteger) { + org.junit.Assert.assertTrue( + "'" + msg.certificate_id[3] + "' != '" + 4 + "'", + value.equals(BigInteger.valueOf(4L))); + } else { + value = value.longValue(); + expected = 4L; + org.junit.Assert.assertEquals(value, expected); + } + value = msg.flags; + if (value instanceof BigInteger) { + org.junit.Assert.assertTrue( + "'" + msg.flags + "' != '" + 0 + "'", value.equals(BigInteger.valueOf(0L))); + } else { + value = value.longValue(); + expected = 0L; + org.junit.Assert.assertEquals(value, expected); + } + value = msg.on_demand_counter; + if (value instanceof BigInteger) { + org.junit.Assert.assertTrue( + "'" + msg.on_demand_counter + "' != '" + 2 + "'", + value.equals(BigInteger.valueOf(2L))); + } else { + value = value.longValue(); + expected = 2L; + org.junit.Assert.assertEquals(value, expected); + } + value = msg.signature[0]; + if (value instanceof BigInteger) { + org.junit.Assert.assertTrue( + "'" + msg.signature[0] + "' != '" + 0 + "'", + value.equals(BigInteger.valueOf(0L))); + } else { + value = value.longValue(); + expected = 0L; + org.junit.Assert.assertEquals(value, expected); + } + value = msg.signature[1]; + if (value instanceof BigInteger) { + org.junit.Assert.assertTrue( + "'" + msg.signature[1] + "' != '" + 1 + "'", + value.equals(BigInteger.valueOf(1L))); + } else { + value = value.longValue(); + expected = 1L; + org.junit.Assert.assertEquals(value, expected); + } + value = msg.signature[2]; + if (value instanceof BigInteger) { + org.junit.Assert.assertTrue( + "'" + msg.signature[2] + "' != '" + 2 + "'", + value.equals(BigInteger.valueOf(2L))); + } else { + value = value.longValue(); + expected = 2L; + org.junit.Assert.assertEquals(value, expected); + } + value = msg.signature[3]; + if (value instanceof BigInteger) { + org.junit.Assert.assertTrue( + "'" + msg.signature[3] + "' != '" + 3 + "'", + value.equals(BigInteger.valueOf(3L))); + } else { + value = value.longValue(); + expected = 3L; + org.junit.Assert.assertEquals(value, expected); + } + value = msg.signature[4]; + if (value instanceof BigInteger) { + org.junit.Assert.assertTrue( + "'" + msg.signature[4] + "' != '" + 4 + "'", + value.equals(BigInteger.valueOf(4L))); + } else { + value = value.longValue(); + expected = 4L; + org.junit.Assert.assertEquals(value, expected); + } + value = msg.signature[5]; + if (value instanceof BigInteger) { + org.junit.Assert.assertTrue( + "'" + msg.signature[5] + "' != '" + 5 + "'", + value.equals(BigInteger.valueOf(5L))); + } else { + value = value.longValue(); + expected = 5L; + org.junit.Assert.assertEquals(value, expected); + } + value = msg.signature[6]; + if (value instanceof BigInteger) { + org.junit.Assert.assertTrue( + "'" + msg.signature[6] + "' != '" + 6 + "'", + value.equals(BigInteger.valueOf(6L))); + } else { + value = value.longValue(); + expected = 6L; + org.junit.Assert.assertEquals(value, expected); + } + value = msg.signature[7]; + if (value instanceof BigInteger) { + org.junit.Assert.assertTrue( + "'" + msg.signature[7] + "' != '" + 7 + "'", + value.equals(BigInteger.valueOf(7L))); + } else { + value = value.longValue(); + expected = 7L; + org.junit.Assert.assertEquals(value, expected); + } + value = msg.signature[8]; + if (value instanceof BigInteger) { + org.junit.Assert.assertTrue( + "'" + msg.signature[8] + "' != '" + 8 + "'", + value.equals(BigInteger.valueOf(8L))); + } else { + value = value.longValue(); + expected = 8L; + org.junit.Assert.assertEquals(value, expected); + } + value = msg.signature[9]; + if (value instanceof BigInteger) { + org.junit.Assert.assertTrue( + "'" + msg.signature[9] + "' != '" + 9 + "'", + value.equals(BigInteger.valueOf(9L))); + } else { + value = value.longValue(); + expected = 9L; + org.junit.Assert.assertEquals(value, expected); + } + value = msg.signature[10]; + if (value instanceof BigInteger) { + org.junit.Assert.assertTrue( + "'" + msg.signature[10] + "' != '" + 10 + "'", + value.equals(BigInteger.valueOf(10L))); + } else { + value = value.longValue(); + expected = 10L; + org.junit.Assert.assertEquals(value, expected); + } + value = msg.signature[11]; + if (value instanceof BigInteger) { + org.junit.Assert.assertTrue( + "'" + msg.signature[11] + "' != '" + 11 + "'", + value.equals(BigInteger.valueOf(11L))); + } else { + value = value.longValue(); + expected = 11L; + org.junit.Assert.assertEquals(value, expected); + } + value = msg.signature[12]; + if (value instanceof BigInteger) { + org.junit.Assert.assertTrue( + "'" + msg.signature[12] + "' != '" + 12 + "'", + value.equals(BigInteger.valueOf(12L))); + } else { + value = value.longValue(); + expected = 12L; + org.junit.Assert.assertEquals(value, expected); + } + value = msg.signature[13]; + if (value instanceof BigInteger) { + org.junit.Assert.assertTrue( + "'" + msg.signature[13] + "' != '" + 13 + "'", + value.equals(BigInteger.valueOf(13L))); + } else { + value = value.longValue(); + expected = 13L; + org.junit.Assert.assertEquals(value, expected); + } + value = msg.signature[14]; + if (value instanceof BigInteger) { + org.junit.Assert.assertTrue( + "'" + msg.signature[14] + "' != '" + 14 + "'", + value.equals(BigInteger.valueOf(14L))); + } else { + value = value.longValue(); + expected = 14L; + org.junit.Assert.assertEquals(value, expected); + } + value = msg.signature[15]; + if (value instanceof BigInteger) { + org.junit.Assert.assertTrue( + "'" + msg.signature[15] + "' != '" + 15 + "'", + value.equals(BigInteger.valueOf(15L))); + } else { + value = value.longValue(); + expected = 15L; + org.junit.Assert.assertEquals(value, expected); + } + value = msg.signed_messages[0]; + if (value instanceof BigInteger) { + org.junit.Assert.assertTrue( + "'" + msg.signed_messages[0] + "' != '" + 11 + "'", + value.equals(BigInteger.valueOf(11L))); + } else { + value = value.longValue(); + expected = 11L; + org.junit.Assert.assertEquals(value, expected); + } + value = msg.signed_messages[1]; + if (value instanceof BigInteger) { + org.junit.Assert.assertTrue( + "'" + msg.signed_messages[1] + "' != '" + 22 + "'", + value.equals(BigInteger.valueOf(22L))); + } else { + value = value.longValue(); + expected = 22L; + org.junit.Assert.assertEquals(value, expected); + } + value = msg.signed_messages[2]; + if (value instanceof BigInteger) { + org.junit.Assert.assertTrue( + "'" + msg.signed_messages[2] + "' != '" + 33 + "'", + value.equals(BigInteger.valueOf(33L))); + } else { + value = value.longValue(); + expected = 33L; + org.junit.Assert.assertEquals(value, expected); + } + value = msg.stream_counter; + if (value instanceof BigInteger) { + org.junit.Assert.assertTrue( + "'" + msg.stream_counter + "' != '" + 1 + "'", + value.equals(BigInteger.valueOf(1L))); + } else { + value = value.longValue(); + expected = 1L; + org.junit.Assert.assertEquals(value, expected); + } + + org.junit.Assert.assertNotEquals("", msg.getFriendlyName()); + } +} diff --git a/javascript/sbp/signing.js b/javascript/sbp/signing.js index 7448e39d6c..6d06a8c745 100644 --- a/javascript/sbp/signing.js +++ b/javascript/sbp/signing.js @@ -223,6 +223,58 @@ MsgCertificateChainDep.prototype.fieldSpec.push(['corrections_certificate', 'arr MsgCertificateChainDep.prototype.fieldSpec.push(['expiration', UtcTime.prototype.fieldSpec]); MsgCertificateChainDep.prototype.fieldSpec.push(['signature', 'array', 'writeUInt8', function () { return 1; }, 64]); +/** + * SBP class for message MSG_AES_CMAC_SIGNATURE (0x0C10). + * + * Digital signature using AES-CMAC 128 algorithm used for data integrity. + * + * Fields in the SBP payload (`sbp.payload`): + * @field stream_counter number (unsigned 8-bit int, 1 byte) 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. + * @field on_demand_counter number (unsigned 8-bit int, 1 byte) 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. + * @field certificate_id array The last 4 bytes of the certificate's SHA-1 fingerprint + * @field signature array Signature + * @field flags number (unsigned 8-bit int, 1 byte) Describes the format of the 'signed messages' field below. + * @field signed_messages array 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. + * + * @param sbp An SBP object with a payload to be decoded. + */ +let MsgAesCmacSignature = function (sbp, fields) { + SBP.call(this, sbp); + this.messageType = "MSG_AES_CMAC_SIGNATURE"; + this.fields = (fields || this.parser.parse(sbp.payload)); + + return this; +}; +MsgAesCmacSignature.prototype = Object.create(SBP.prototype); +MsgAesCmacSignature.prototype.messageType = "MSG_AES_CMAC_SIGNATURE"; +MsgAesCmacSignature.prototype.msg_type = 0x0C10; +MsgAesCmacSignature.prototype.constructor = MsgAesCmacSignature; +MsgAesCmacSignature.prototype.parser = new Parser() + .endianess('little') + .uint8('stream_counter') + .uint8('on_demand_counter') + .array('certificate_id', { length: 4, type: 'uint8' }) + .array('signature', { length: 16, type: 'uint8' }) + .uint8('flags') + .array('signed_messages', { type: 'uint8', readUntil: 'eof' }); +MsgAesCmacSignature.prototype.fieldSpec = []; +MsgAesCmacSignature.prototype.fieldSpec.push(['stream_counter', 'writeUInt8', 1]); +MsgAesCmacSignature.prototype.fieldSpec.push(['on_demand_counter', 'writeUInt8', 1]); +MsgAesCmacSignature.prototype.fieldSpec.push(['certificate_id', 'array', 'writeUInt8', function () { return 1; }, 4]); +MsgAesCmacSignature.prototype.fieldSpec.push(['signature', 'array', 'writeUInt8', function () { return 1; }, 16]); +MsgAesCmacSignature.prototype.fieldSpec.push(['flags', 'writeUInt8', 1]); +MsgAesCmacSignature.prototype.fieldSpec.push(['signed_messages', 'array', 'writeUInt8', function () { return 1; }, null]); + /** * SBP class for message MSG_ECDSA_SIGNATURE (0x0C08). * @@ -505,6 +557,8 @@ module.exports = { MsgCertificateChain: MsgCertificateChain, 0x0C05: MsgCertificateChainDep, MsgCertificateChainDep: MsgCertificateChainDep, + 0x0C10: MsgAesCmacSignature, + MsgAesCmacSignature: MsgAesCmacSignature, 0x0C08: MsgEcdsaSignature, MsgEcdsaSignature: MsgEcdsaSignature, 0x0C07: MsgEcdsaSignatureDepB, diff --git a/jsonschema/MsgAesCmacSignature.json b/jsonschema/MsgAesCmacSignature.json new file mode 100644 index 0000000000..b4d17b1c31 --- /dev/null +++ b/jsonschema/MsgAesCmacSignature.json @@ -0,0 +1,34 @@ +{ + "copyright": [ + "Copyright (C) 2019-2021 Swift Navigation Inc.", + "Contact: https://support.swiftnav.com", + "", + "This source is subject to the license found in the file 'LICENSE' which must", + "be distributed together with this source. All other rights reserved.", + "", + "THIS CODE AND INFORMATION IS PROVIDED 'AS IS' WITHOUT WARRANTY OF ANY KIND,", + "EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED", + "WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE." + ], + "$schema": "http://json-schema.org/draft-06/schema#", + "$id": "#MsgAesCmacSignature", + "title":"MsgAesCmacSignature", + "description":"Digital signature using AES-CMAC 128 algorithm used for data integrity.\n", + "type": "object", + "properties": { + "stream_counter": {"type": "integer"}, + "on_demand_counter": {"type": "integer"}, + "certificate_id": {"type": "array", "items": {"type": "integer"}}, + "signature": {"type": "array", "items": {"type": "integer"}}, + "flags": {"type": "integer"}, + "signed_messages": {"type": "array", "items": {"type": "integer"}} + }, + "required": [ + "stream_counter", + "on_demand_counter", + "certificate_id", + "signature", + "flags", + "signed_messages" + ] +} \ No newline at end of file diff --git a/kaitai/ksy/sbp.ksy b/kaitai/ksy/sbp.ksy index 41c28783dc..f60844e304 100644 --- a/kaitai/ksy/sbp.ksy +++ b/kaitai/ksy/sbp.ksy @@ -257,6 +257,7 @@ enums: 3076: msg_ecdsa_certificate 3081: msg_certificate_chain 3077: msg_certificate_chain_dep + 3088: msg_aes_cmac_signature 3080: msg_ecdsa_signature 3079: msg_ecdsa_signature_dep_b 3078: msg_ecdsa_signature_dep_a @@ -539,6 +540,7 @@ types: 3076: signing::msg_ecdsa_certificate 3081: signing::msg_certificate_chain 3077: signing::msg_certificate_chain_dep + 3088: signing::msg_aes_cmac_signature 3080: signing::msg_ecdsa_signature 3079: signing::msg_ecdsa_signature_dep_b 3078: signing::msg_ecdsa_signature_dep_a diff --git a/kaitai/ksy/signing.ksy b/kaitai/ksy/signing.ksy index 4f8c5cf68c..e7b3bf0b15 100644 --- a/kaitai/ksy/signing.ksy +++ b/kaitai/ksy/signing.ksy @@ -168,6 +168,51 @@ types: repeat: expr repeat-expr: 64 + msg_aes_cmac_signature: + doc: | + Digital signature using AES-CMAC 128 algorithm used for data integrity. + seq: + - id: stream_counter + doc: | + 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. + type: u1 + - id: on_demand_counter + doc: | + 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. + type: u1 + - id: certificate_id + doc: | + The last 4 bytes of the certificate's SHA-1 fingerprint + type: u1 + repeat: expr + repeat-expr: 4 + - id: signature + doc: | + Signature + type: u1 + repeat: expr + repeat-expr: 16 + - id: flags + doc: | + Describes the format of the 'signed messages' field below. + type: u1 + - id: signed_messages + doc: | + 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. + type: u1 + repeat: eos + msg_ecdsa_signature: doc: | An ECDSA-256 signature using SHA-256 as the message digest algorithm. diff --git a/kaitai/perl/KaitaiSbp/Sbp.pm b/kaitai/perl/KaitaiSbp/Sbp.pm index d15db3734f..444adedc19 100644 --- a/kaitai/perl/KaitaiSbp/Sbp.pm +++ b/kaitai/perl/KaitaiSbp/Sbp.pm @@ -249,6 +249,7 @@ our $MSG_IDS_MSG_ECDSA_SIGNATURE_DEP_A = 3078; our $MSG_IDS_MSG_ECDSA_SIGNATURE_DEP_B = 3079; our $MSG_IDS_MSG_ECDSA_SIGNATURE = 3080; our $MSG_IDS_MSG_CERTIFICATE_CHAIN = 3081; +our $MSG_IDS_MSG_AES_CMAC_SIGNATURE = 3088; our $MSG_IDS_MSG_FILEIO_CONFIG_REQ = 4097; our $MSG_IDS_MSG_FILEIO_CONFIG_RESP = 4098; our $MSG_IDS_MSG_SBAS_RAW = 30583; @@ -975,6 +976,11 @@ sub _read { my $io__raw_payload = IO::KaitaiStruct::Stream->new($self->{_raw_payload}); $self->{payload} = Settings::MsgSettingsReadByIndexDone->new($io__raw_payload, $self, $self->{_root}); } + elsif ($_on == 3088) { + $self->{_raw_payload} = $self->{_io}->read_bytes($self->length()); + my $io__raw_payload = IO::KaitaiStruct::Stream->new($self->{_raw_payload}); + $self->{payload} = Signing::MsgAesCmacSignature->new($io__raw_payload, $self, $self->{_root}); + } elsif ($_on == 114) { $self->{_raw_payload} = $self->{_io}->read_bytes($self->length()); my $io__raw_payload = IO::KaitaiStruct::Stream->new($self->{_raw_payload}); diff --git a/kaitai/perl/KaitaiSbp/Signing.pm b/kaitai/perl/KaitaiSbp/Signing.pm index 5720d3f6eb..ac433e98c4 100644 --- a/kaitai/perl/KaitaiSbp/Signing.pm +++ b/kaitai/perl/KaitaiSbp/Signing.pm @@ -244,6 +244,85 @@ sub certificate_bytes { return $self->{certificate_bytes}; } +######################################################################## +package Signing::MsgAesCmacSignature; + +our @ISA = 'IO::KaitaiStruct::Struct'; + +sub from_file { + my ($class, $filename) = @_; + my $fd; + + open($fd, '<', $filename) or return undef; + binmode($fd); + return new($class, IO::KaitaiStruct::Stream->new($fd)); +} + +sub new { + my ($class, $_io, $_parent, $_root) = @_; + my $self = IO::KaitaiStruct::Struct->new($_io); + + bless $self, $class; + $self->{_parent} = $_parent; + $self->{_root} = $_root || $self;; + + $self->_read(); + + return $self; +} + +sub _read { + my ($self) = @_; + + $self->{stream_counter} = $self->{_io}->read_u1(); + $self->{on_demand_counter} = $self->{_io}->read_u1(); + $self->{certificate_id} = []; + my $n_certificate_id = 4; + for (my $i = 0; $i < $n_certificate_id; $i++) { + push @{$self->{certificate_id}}, $self->{_io}->read_u1(); + } + $self->{signature} = []; + my $n_signature = 16; + for (my $i = 0; $i < $n_signature; $i++) { + push @{$self->{signature}}, $self->{_io}->read_u1(); + } + $self->{flags} = $self->{_io}->read_u1(); + $self->{signed_messages} = []; + while (!$self->{_io}->is_eof()) { + push @{$self->{signed_messages}}, $self->{_io}->read_u1(); + } +} + +sub stream_counter { + my ($self) = @_; + return $self->{stream_counter}; +} + +sub on_demand_counter { + my ($self) = @_; + return $self->{on_demand_counter}; +} + +sub certificate_id { + my ($self) = @_; + return $self->{certificate_id}; +} + +sub signature { + my ($self) = @_; + return $self->{signature}; +} + +sub flags { + my ($self) = @_; + return $self->{flags}; +} + +sub signed_messages { + my ($self) = @_; + return $self->{signed_messages}; +} + ######################################################################## package Signing::UtcTime; diff --git a/kaitai/perl/KaitaiSbp/Table.pm b/kaitai/perl/KaitaiSbp/Table.pm index 47ed33a104..b4cb0d3916 100644 --- a/kaitai/perl/KaitaiSbp/Table.pm +++ b/kaitai/perl/KaitaiSbp/Table.pm @@ -251,6 +251,7 @@ our %TABLE = ( 3076 => sub{Signing::MsgEcdsaCertificate->new(@_)}, 3081 => sub{Signing::MsgCertificateChain->new(@_)}, 3077 => sub{Signing::MsgCertificateChainDep->new(@_)}, + 3088 => sub{Signing::MsgAesCmacSignature->new(@_)}, 3080 => sub{Signing::MsgEcdsaSignature->new(@_)}, 3079 => sub{Signing::MsgEcdsaSignatureDepB->new(@_)}, 3078 => sub{Signing::MsgEcdsaSignatureDepA->new(@_)}, diff --git a/kaitai/perl/KaitaiSbp/t/auto_check_sbp_signing_MsgAesCmacSignature.t b/kaitai/perl/KaitaiSbp/t/auto_check_sbp_signing_MsgAesCmacSignature.t new file mode 100644 index 0000000000..6ffb81c549 --- /dev/null +++ b/kaitai/perl/KaitaiSbp/t/auto_check_sbp_signing_MsgAesCmacSignature.t @@ -0,0 +1,66 @@ +#!/usr/bin/perl -w +# +# Copyright (C) 2015-2023 Swift Navigation Inc. +# Contact: https://support.swiftnav.com +# +# This source is subject to the license found in the file 'LICENSE' which must +# be distributed together with this source. All other rights reserved. +# +# THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, +# EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE. +# +# Test cases automatically generated from spec/tests/yaml/swiftnav/sbp/signing/test_MsgAesCmacSignature.yaml +# with generate.py. Do not modify by hand! + +use strict; + +BEGIN { + # add grandparent directory to include path + use Cwd qw(realpath); + use File::Basename; + unshift @INC, realpath(dirname($0))."/../../"; +} + +use KaitaiSbp::Sbp; +use KaitaiSbp::ParseUtils; +use IO::KaitaiStruct; +use Test::More; +use JSON::PP; +use MIME::Base64; +sub test_auto_check_sbp_signing_msg_aes_cmac_signature_1() { + my $buf = decode_base64("VRAMQgAaAQIBAgMEAAECAwQFBgcICQoLDA0ODwALFiHAFQ=="); + my $stream = IO::KaitaiStruct::Stream->new($buf); + my $msg = ParseUtils::get_flattened_msg(Sbp::SbpMessage->new($stream)); + + is($msg->{'crc'}, 0x15C0, "crc"); + + is($msg->{'length'}, 26, "length"); + + is($msg->{'msg_type'}, 0xC10, "msg_type"); + + is($msg->{'payload'}, "AQIBAgMEAAECAwQFBgcICQoLDA0ODwALFiE=", "payload"); + + is($msg->{'preamble'}, 0x55, "preamble"); + + is($msg->{'sender'}, 0x42, "sender"); + + my $json = JSON::PP->new->convert_blessed->canonical; + + is($json->encode($msg->certificate_id()), $json->encode($json->decode(q{[1,2,3,4]})), "certificate_id"); + + is($msg->flags(), 0, "flags"); + + is($msg->on_demand_counter(), 2, "on_demand_counter"); + + is($json->encode($msg->signature()), $json->encode($json->decode(q{[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]})), "signature"); + + is($json->encode($msg->signed_messages()), $json->encode($json->decode(q{[11,22,33]})), "signed_messages"); + + is($msg->stream_counter(), 1, "stream_counter"); + + is($json->encode($msg), $json->encode($json->decode(q{{"certificate_id":[1,2,3,4],"crc":5568,"flags":0,"length":26,"msg_type":3088,"on_demand_counter":2,"payload":"AQIBAgMEAAECAwQFBgcICQoLDA0ODwALFiE=","preamble":85,"sender":66,"signature":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15],"signed_messages":[11,22,33],"stream_counter":1}})), "raw_json"); +} +test_auto_check_sbp_signing_msg_aes_cmac_signature_1(); + +done_testing(); \ No newline at end of file diff --git a/kaitai/python/kaitai_sbp/sbp.py b/kaitai/python/kaitai_sbp/sbp.py index a1ad08f349..3a0adf2b4e 100644 --- a/kaitai/python/kaitai_sbp/sbp.py +++ b/kaitai/python/kaitai_sbp/sbp.py @@ -242,6 +242,7 @@ class MsgIds(Enum): msg_ecdsa_signature_dep_b = 3079 msg_ecdsa_signature = 3080 msg_certificate_chain = 3081 + msg_aes_cmac_signature = 3088 msg_fileio_config_req = 4097 msg_fileio_config_resp = 4098 msg_sbas_raw = 30583 @@ -808,6 +809,10 @@ def _read(self): self._raw_payload = self._io.read_bytes(self.length) _io__raw_payload = KaitaiStream(BytesIO(self._raw_payload)) self.payload = Settings.MsgSettingsReadByIndexDone(_io__raw_payload, self, self._root) + elif _on == 3088: + self._raw_payload = self._io.read_bytes(self.length) + _io__raw_payload = KaitaiStream(BytesIO(self._raw_payload)) + self.payload = Signing.MsgAesCmacSignature(_io__raw_payload, self, self._root) elif _on == 114: self._raw_payload = self._io.read_bytes(self.length) _io__raw_payload = KaitaiStream(BytesIO(self._raw_payload)) diff --git a/kaitai/python/kaitai_sbp/signing.py b/kaitai/python/kaitai_sbp/signing.py index 354dfb32c7..a5283a78e4 100644 --- a/kaitai/python/kaitai_sbp/signing.py +++ b/kaitai/python/kaitai_sbp/signing.py @@ -97,6 +97,35 @@ def _read(self): + class MsgAesCmacSignature(KaitaiStruct): + """Digital signature using AES-CMAC 128 algorithm used for data integrity. + """ + def __init__(self, _io, _parent=None, _root=None): + self._io = _io + self._parent = _parent + self._root = _root if _root else self + self._read() + + def _read(self): + self.stream_counter = self._io.read_u1() + self.on_demand_counter = self._io.read_u1() + self.certificate_id = [] + for i in range(4): + self.certificate_id.append(self._io.read_u1()) + + self.signature = [] + for i in range(16): + self.signature.append(self._io.read_u1()) + + self.flags = self._io.read_u1() + self.signed_messages = [] + i = 0 + while not self._io.is_eof(): + self.signed_messages.append(self._io.read_u1()) + i += 1 + + + class UtcTime(KaitaiStruct): def __init__(self, _io, _parent=None, _root=None): self._io = _io diff --git a/kaitai/python/kaitai_sbp/table.py b/kaitai/python/kaitai_sbp/table.py index 678927382e..d6fff9e27e 100644 --- a/kaitai/python/kaitai_sbp/table.py +++ b/kaitai/python/kaitai_sbp/table.py @@ -245,6 +245,7 @@ 3076: Signing.MsgEcdsaCertificate, 3081: Signing.MsgCertificateChain, 3077: Signing.MsgCertificateChainDep, + 3088: Signing.MsgAesCmacSignature, 3080: Signing.MsgEcdsaSignature, 3079: Signing.MsgEcdsaSignatureDepB, 3078: Signing.MsgEcdsaSignatureDepA, diff --git a/kaitai/python/kaitai_sbp/tests/test_auto_check_sbp_signing_MsgAesCmacSignature.py b/kaitai/python/kaitai_sbp/tests/test_auto_check_sbp_signing_MsgAesCmacSignature.py new file mode 100644 index 0000000000..8257200313 --- /dev/null +++ b/kaitai/python/kaitai_sbp/tests/test_auto_check_sbp_signing_MsgAesCmacSignature.py @@ -0,0 +1,51 @@ +# Copyright (C) 2015-2023 Swift Navigation Inc. +# Contact: https://support.swiftnav.com +# +# This source is subject to the license found in the file 'LICENSE' which must +# be distributed together with this source. All other rights reserved. +# +# THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, +# EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE. +# +# Test cases automatically generated from spec/tests/yaml/swiftnav/sbp/signing/test_MsgAesCmacSignature.yaml +# with generate.py. Do not modify by hand! + +import kaitai_sbp.sbp as sbp +from kaitai_sbp.parse_utils import get_flattened_msg +from kaitai_sbp.tests.utils import dictify +from kaitaistruct import KaitaiStream +import io +import base64 + +def test_auto_check_sbp_signing_msg_aes_cmac_signature_1(): + buf = base64.standard_b64decode("VRAMQgAaAQIBAgMEAAECAwQFBgcICQoLDA0ODwALFiHAFQ==") + + stream = KaitaiStream(io.BytesIO(buf)) + msg = get_flattened_msg(sbp.Sbp.SbpMessage(stream)) + + assert msg.crc == 0x15C0 + + assert msg.length == 26 + + assert msg.msg_type == 0xC10 + + assert msg.payload == "AQIBAgMEAAECAwQFBgcICQoLDA0ODwALFiE=" + + assert msg.preamble == 0x55 + + assert msg.sender == 0x42 + + assert dictify(msg.certificate_id) == [1, 2, 3, 4] + + assert dictify(msg.flags) == 0 + + assert dictify(msg.on_demand_counter) == 2 + + assert dictify(msg.signature) == [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15] + + assert dictify(msg.signed_messages) == [11, 22, 33] + + assert dictify(msg.stream_counter) == 1 + + assert dictify(msg) == {'crc': 5568, 'length': 26, 'msg_type': 3088, 'payload': 'AQIBAgMEAAECAwQFBgcICQoLDA0ODwALFiE=', 'preamble': 85, 'sender': 66, 'stream_counter': 1, 'on_demand_counter': 2, 'certificate_id': [1, 2, 3, 4], 'signature': [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15], 'flags': 0, 'signed_messages': [11, 22, 33]} \ No newline at end of file diff --git a/proto/signing.proto b/proto/signing.proto index fd5c591b15..4078ebe8de 100644 --- a/proto/signing.proto +++ b/proto/signing.proto @@ -66,6 +66,19 @@ message MsgCertificateChain { ECDSASignature signature = 5; } +/** AES-CMAC 128 digital signature + * + * Digital signature using AES-CMAC 128 algorithm used for data integrity. + */ +message MsgAesCmacSignature { + uint32 stream_counter = 1; + uint32 on_demand_counter = 2; + repeated uint32 certificate_id = 3; + repeated uint32 signature = 4; + uint32 flags = 5; + repeated uint32 signed_messages = 6; +} + /** An ECDSA signature * * An ECDSA-256 signature using SHA-256 as the message digest algorithm. diff --git a/python/sbp/signing.py b/python/sbp/signing.py index 492603998a..1c8f49e8c2 100644 --- a/python/sbp/signing.py +++ b/python/sbp/signing.py @@ -476,6 +476,137 @@ def to_json_dict(self): d.update(j) return d +SBP_MSG_AES_CMAC_SIGNATURE = 0x0C10 +class MsgAesCmacSignature(SBP): + """SBP class for message MSG_AES_CMAC_SIGNATURE (0x0C10). + + You can have MSG_AES_CMAC_SIGNATURE inherit its fields directly + from an inherited SBP object, or construct it inline using a dict + of its fields. + + + Digital signature using AES-CMAC 128 algorithm used for data integrity. + + Parameters + ---------- + sbp : SBP + SBP parent object to inherit from. + stream_counter : int + 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. + on_demand_counter : int + 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. + certificate_id : array + The last 4 bytes of the certificate's SHA-1 fingerprint + signature : array + Signature + flags : int + Describes the format of the 'signed messages' field below. + signed_messages : array + 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. + sender : int + Optional sender ID, defaults to SENDER_ID (see sbp/msg.py). + + """ + _parser = construct.Struct( + 'stream_counter' / construct.Int8ul, + 'on_demand_counter' / construct.Int8ul, + 'certificate_id' / construct.Array(4, construct.Int8ul), + 'signature' / construct.Array(16, construct.Int8ul), + 'flags' / construct.Int8ul, + 'signed_messages' / construct.GreedyRange(construct.Int8ul),) + __slots__ = [ + 'stream_counter', + 'on_demand_counter', + 'certificate_id', + 'signature', + 'flags', + 'signed_messages', + ] + + def __init__(self, sbp=None, **kwargs): + if sbp: + super( MsgAesCmacSignature, + self).__init__(sbp.msg_type, sbp.sender, sbp.length, + sbp.payload, sbp.crc) + self.from_binary(sbp.payload) + else: + super( MsgAesCmacSignature, self).__init__() + self.msg_type = SBP_MSG_AES_CMAC_SIGNATURE + self.sender = kwargs.pop('sender', SENDER_ID) + self.stream_counter = kwargs.pop('stream_counter') + self.on_demand_counter = kwargs.pop('on_demand_counter') + self.certificate_id = kwargs.pop('certificate_id') + self.signature = kwargs.pop('signature') + self.flags = kwargs.pop('flags') + self.signed_messages = kwargs.pop('signed_messages') + + def __repr__(self): + return fmt_repr(self) + + @staticmethod + def from_json(s): + """Given a JSON-encoded string s, build a message object. + + """ + d = json.loads(s) + return MsgAesCmacSignature.from_json_dict(d) + + @staticmethod + def from_json_dict(d): + sbp = SBP.from_json_dict(d) + return MsgAesCmacSignature(sbp, **d) + + + def from_binary(self, d): + """Given a binary payload d, update the appropriate payload fields of + the message. + + """ + p = MsgAesCmacSignature._parser.parse(d) + for n in self.__class__.__slots__: + setattr(self, n, getattr(p, n)) + + def to_binary(self): + """Produce a framed/packed SBP message. + + """ + c = containerize(exclude_fields(self)) + self.payload = MsgAesCmacSignature._parser.build(c) + return self.pack() + + def friendly_name(self): + """Produces friendly human-readable name for this message + + """ + return "AES CMAC SIGNATURE" + + def into_buffer(self, buf, offset): + """Produce a framed/packed SBP message into the provided buffer and offset. + + """ + self.payload = containerize(exclude_fields(self)) + self.parser = MsgAesCmacSignature._parser + self.stream_payload.reset(buf, offset) + return self.pack_into(buf, offset, self._build_payload) + + def to_json_dict(self): + self.to_binary() + d = super( MsgAesCmacSignature, self).to_json_dict() + j = walk_json_dict(exclude_fields(self)) + d.update(j) + return d + SBP_MSG_ECDSA_SIGNATURE = 0x0C08 class MsgEcdsaSignature(SBP): """SBP class for message MSG_ECDSA_SIGNATURE (0x0C08). @@ -1216,6 +1347,7 @@ def to_json_dict(self): 0x0C04: MsgEcdsaCertificate, 0x0C09: MsgCertificateChain, 0x0C05: MsgCertificateChainDep, + 0x0C10: MsgAesCmacSignature, 0x0C08: MsgEcdsaSignature, 0x0C07: MsgEcdsaSignatureDepB, 0x0C06: MsgEcdsaSignatureDepA, diff --git a/rust/sbp/src/messages/mod.rs b/rust/sbp/src/messages/mod.rs index 468b9b07ae..bad1920949 100644 --- a/rust/sbp/src/messages/mod.rs +++ b/rust/sbp/src/messages/mod.rs @@ -225,6 +225,7 @@ use self::settings::msg_settings_register_resp::MsgSettingsRegisterResp; use self::settings::msg_settings_save::MsgSettingsSave; use self::settings::msg_settings_write::MsgSettingsWrite; use self::settings::msg_settings_write_resp::MsgSettingsWriteResp; +use self::signing::msg_aes_cmac_signature::MsgAesCmacSignature; use self::signing::msg_certificate_chain::MsgCertificateChain; use self::signing::msg_certificate_chain_dep::MsgCertificateChainDep; use self::signing::msg_ecdsa_certificate::MsgEcdsaCertificate; @@ -797,6 +798,8 @@ pub enum Sbp { MsgEcdsaSignature(MsgEcdsaSignature), /// The certificate chain MsgCertificateChain(MsgCertificateChain), + /// AES-CMAC 128 digital signature + MsgAesCmacSignature(MsgAesCmacSignature), /// Request advice on the optimal configuration for FileIO MsgFileioConfigReq(MsgFileioConfigReq), /// Response with advice on the optimal configuration for FileIO. @@ -1526,6 +1529,9 @@ impl<'de> serde::Deserialize<'de> for Sbp { Some(MsgCertificateChain::MESSAGE_TYPE) => { serde_json::from_value::(value).map(Sbp::MsgCertificateChain) } + Some(MsgAesCmacSignature::MESSAGE_TYPE) => { + serde_json::from_value::(value).map(Sbp::MsgAesCmacSignature) + } Some(MsgFileioConfigReq::MESSAGE_TYPE) => { serde_json::from_value::(value).map(Sbp::MsgFileioConfigReq) } @@ -2230,6 +2236,9 @@ impl Sbp { MsgCertificateChain::MESSAGE_TYPE => { MsgCertificateChain::parse(&mut payload).map(Sbp::MsgCertificateChain) } + MsgAesCmacSignature::MESSAGE_TYPE => { + MsgAesCmacSignature::parse(&mut payload).map(Sbp::MsgAesCmacSignature) + } MsgFileioConfigReq::MESSAGE_TYPE => { MsgFileioConfigReq::parse(&mut payload).map(Sbp::MsgFileioConfigReq) } @@ -2550,6 +2559,7 @@ impl SbpMessage for Sbp { Sbp::MsgEcdsaSignatureDepB(msg) => msg.message_name(), Sbp::MsgEcdsaSignature(msg) => msg.message_name(), Sbp::MsgCertificateChain(msg) => msg.message_name(), + Sbp::MsgAesCmacSignature(msg) => msg.message_name(), Sbp::MsgFileioConfigReq(msg) => msg.message_name(), Sbp::MsgFileioConfigResp(msg) => msg.message_name(), Sbp::MsgSbasRaw(msg) => msg.message_name(), @@ -2794,6 +2804,7 @@ impl SbpMessage for Sbp { Sbp::MsgEcdsaSignatureDepB(msg) => msg.message_type(), Sbp::MsgEcdsaSignature(msg) => msg.message_type(), Sbp::MsgCertificateChain(msg) => msg.message_type(), + Sbp::MsgAesCmacSignature(msg) => msg.message_type(), Sbp::MsgFileioConfigReq(msg) => msg.message_type(), Sbp::MsgFileioConfigResp(msg) => msg.message_type(), Sbp::MsgSbasRaw(msg) => msg.message_type(), @@ -3038,6 +3049,7 @@ impl SbpMessage for Sbp { Sbp::MsgEcdsaSignatureDepB(msg) => msg.sender_id(), Sbp::MsgEcdsaSignature(msg) => msg.sender_id(), Sbp::MsgCertificateChain(msg) => msg.sender_id(), + Sbp::MsgAesCmacSignature(msg) => msg.sender_id(), Sbp::MsgFileioConfigReq(msg) => msg.sender_id(), Sbp::MsgFileioConfigResp(msg) => msg.sender_id(), Sbp::MsgSbasRaw(msg) => msg.sender_id(), @@ -3282,6 +3294,7 @@ impl SbpMessage for Sbp { Sbp::MsgEcdsaSignatureDepB(msg) => msg.set_sender_id(new_id), Sbp::MsgEcdsaSignature(msg) => msg.set_sender_id(new_id), Sbp::MsgCertificateChain(msg) => msg.set_sender_id(new_id), + Sbp::MsgAesCmacSignature(msg) => msg.set_sender_id(new_id), Sbp::MsgFileioConfigReq(msg) => msg.set_sender_id(new_id), Sbp::MsgFileioConfigResp(msg) => msg.set_sender_id(new_id), Sbp::MsgSbasRaw(msg) => msg.set_sender_id(new_id), @@ -3526,6 +3539,7 @@ impl SbpMessage for Sbp { Sbp::MsgEcdsaSignatureDepB(msg) => msg.encoded_len(), Sbp::MsgEcdsaSignature(msg) => msg.encoded_len(), Sbp::MsgCertificateChain(msg) => msg.encoded_len(), + Sbp::MsgAesCmacSignature(msg) => msg.encoded_len(), Sbp::MsgFileioConfigReq(msg) => msg.encoded_len(), Sbp::MsgFileioConfigResp(msg) => msg.encoded_len(), Sbp::MsgSbasRaw(msg) => msg.encoded_len(), @@ -3773,6 +3787,7 @@ impl SbpMessage for Sbp { Sbp::MsgEcdsaSignatureDepB(msg) => msg.gps_time(), Sbp::MsgEcdsaSignature(msg) => msg.gps_time(), Sbp::MsgCertificateChain(msg) => msg.gps_time(), + Sbp::MsgAesCmacSignature(msg) => msg.gps_time(), Sbp::MsgFileioConfigReq(msg) => msg.gps_time(), Sbp::MsgFileioConfigResp(msg) => msg.gps_time(), Sbp::MsgSbasRaw(msg) => msg.gps_time(), @@ -4017,6 +4032,7 @@ impl SbpMessage for Sbp { Sbp::MsgEcdsaSignatureDepB(msg) => msg.friendly_name(), Sbp::MsgEcdsaSignature(msg) => msg.friendly_name(), Sbp::MsgCertificateChain(msg) => msg.friendly_name(), + Sbp::MsgAesCmacSignature(msg) => msg.friendly_name(), Sbp::MsgFileioConfigReq(msg) => msg.friendly_name(), Sbp::MsgFileioConfigResp(msg) => msg.friendly_name(), Sbp::MsgSbasRaw(msg) => msg.friendly_name(), @@ -4261,6 +4277,7 @@ impl SbpMessage for Sbp { Sbp::MsgEcdsaSignatureDepB(msg) => msg.is_valid(), Sbp::MsgEcdsaSignature(msg) => msg.is_valid(), Sbp::MsgCertificateChain(msg) => msg.is_valid(), + Sbp::MsgAesCmacSignature(msg) => msg.is_valid(), Sbp::MsgFileioConfigReq(msg) => msg.is_valid(), Sbp::MsgFileioConfigResp(msg) => msg.is_valid(), Sbp::MsgSbasRaw(msg) => msg.is_valid(), @@ -4586,6 +4603,7 @@ impl SbpMessage for Sbp { } Sbp::MsgEcdsaSignature(msg) => Ok(Sbp::MsgEcdsaSignature(msg.into_valid_msg()?)), Sbp::MsgCertificateChain(msg) => Ok(Sbp::MsgCertificateChain(msg.into_valid_msg()?)), + Sbp::MsgAesCmacSignature(msg) => Ok(Sbp::MsgAesCmacSignature(msg.into_valid_msg()?)), Sbp::MsgFileioConfigReq(msg) => Ok(Sbp::MsgFileioConfigReq(msg.into_valid_msg()?)), Sbp::MsgFileioConfigResp(msg) => Ok(Sbp::MsgFileioConfigResp(msg.into_valid_msg()?)), Sbp::MsgSbasRaw(msg) => Ok(Sbp::MsgSbasRaw(msg.into_valid_msg()?)), @@ -4859,6 +4877,7 @@ impl WireFormat for Sbp { Sbp::MsgEcdsaSignatureDepB(msg) => WireFormat::write(msg, buf), Sbp::MsgEcdsaSignature(msg) => WireFormat::write(msg, buf), Sbp::MsgCertificateChain(msg) => WireFormat::write(msg, buf), + Sbp::MsgAesCmacSignature(msg) => WireFormat::write(msg, buf), Sbp::MsgFileioConfigReq(msg) => WireFormat::write(msg, buf), Sbp::MsgFileioConfigResp(msg) => WireFormat::write(msg, buf), Sbp::MsgSbasRaw(msg) => WireFormat::write(msg, buf), @@ -5103,6 +5122,7 @@ impl WireFormat for Sbp { Sbp::MsgEcdsaSignatureDepB(msg) => WireFormat::len(msg), Sbp::MsgEcdsaSignature(msg) => WireFormat::len(msg), Sbp::MsgCertificateChain(msg) => WireFormat::len(msg), + Sbp::MsgAesCmacSignature(msg) => WireFormat::len(msg), Sbp::MsgFileioConfigReq(msg) => WireFormat::len(msg), Sbp::MsgFileioConfigResp(msg) => WireFormat::len(msg), Sbp::MsgSbasRaw(msg) => WireFormat::len(msg), @@ -6366,6 +6386,12 @@ impl From for Sbp { } } +impl From for Sbp { + fn from(msg: MsgAesCmacSignature) -> Self { + Sbp::MsgAesCmacSignature(msg) + } +} + impl From for Sbp { fn from(msg: MsgFileioConfigReq) -> Self { Sbp::MsgFileioConfigReq(msg) diff --git a/rust/sbp/src/messages/signing.rs b/rust/sbp/src/messages/signing.rs index 283496122d..2719888808 100644 --- a/rust/sbp/src/messages/signing.rs +++ b/rust/sbp/src/messages/signing.rs @@ -14,6 +14,7 @@ //****************************************************************************/ //! Messages relating to signatures pub use ecdsa_signature::ECDSASignature; +pub use msg_aes_cmac_signature::MsgAesCmacSignature; pub use msg_certificate_chain::MsgCertificateChain; pub use msg_certificate_chain_dep::MsgCertificateChainDep; pub use msg_ecdsa_certificate::MsgEcdsaCertificate; @@ -64,6 +65,182 @@ pub mod ecdsa_signature { } } +pub mod msg_aes_cmac_signature { + #![allow(unused_imports)] + + use super::*; + use crate::messages::lib::*; + + /// AES-CMAC 128 digital signature + /// + /// Digital signature using AES-CMAC 128 algorithm used for data integrity. + /// + #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] + #[allow(clippy::derive_partial_eq_without_eq)] + #[derive(Debug, PartialEq, Clone)] + pub struct MsgAesCmacSignature { + /// The message sender_id + #[cfg_attr(feature = "serde", serde(skip_serializing, alias = "sender"))] + pub sender_id: Option, + /// 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. + #[cfg_attr(feature = "serde", serde(rename = "stream_counter"))] + pub stream_counter: u8, + /// 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. + #[cfg_attr(feature = "serde", serde(rename = "on_demand_counter"))] + pub on_demand_counter: u8, + /// The last 4 bytes of the certificate's SHA-1 fingerprint + #[cfg_attr(feature = "serde", serde(rename = "certificate_id"))] + pub certificate_id: [u8; 4], + /// Signature + #[cfg_attr(feature = "serde", serde(rename = "signature"))] + pub signature: [u8; 16], + /// Describes the format of the 'signed messages' field below. + #[cfg_attr(feature = "serde", serde(rename = "flags"))] + pub flags: u8, + /// 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. + #[cfg_attr(feature = "serde", serde(rename = "signed_messages"))] + pub signed_messages: Vec, + } + + impl MsgAesCmacSignature { + /// Gets the [CrcType][self::CrcType] stored in the `flags` bitfield. + /// + /// Returns `Ok` if the bitrange contains a known `CrcType` variant. + /// Otherwise the value of the bitrange is returned as an `Err(u8)`. This may be because of a malformed message, + /// or because new variants of `CrcType` were added. + pub fn crc_type(&self) -> Result { + get_bit_range!(self.flags, u8, u8, 1, 0).try_into() + } + + /// Set the bitrange corresponding to the [CrcType][CrcType] of the `flags` bitfield. + pub fn set_crc_type(&mut self, crc_type: CrcType) { + set_bit_range!(&mut self.flags, crc_type, u8, u8, 1, 0); + } + } + + impl ConcreteMessage for MsgAesCmacSignature { + const MESSAGE_TYPE: u16 = 3088; + const MESSAGE_NAME: &'static str = "MSG_AES_CMAC_SIGNATURE"; + } + + impl SbpMessage for MsgAesCmacSignature { + fn message_name(&self) -> &'static str { + ::MESSAGE_NAME + } + fn message_type(&self) -> Option { + Some(::MESSAGE_TYPE) + } + fn sender_id(&self) -> Option { + self.sender_id + } + fn set_sender_id(&mut self, new_id: u16) { + self.sender_id = Some(new_id); + } + fn encoded_len(&self) -> usize { + WireFormat::len(self) + crate::HEADER_LEN + crate::CRC_LEN + } + fn is_valid(&self) -> bool { + true + } + fn into_valid_msg(self) -> Result { + Ok(self) + } + } + + impl FriendlyName for MsgAesCmacSignature { + fn friendly_name() -> &'static str { + "AES CMAC SIGNATURE" + } + } + + impl TryFrom for MsgAesCmacSignature { + type Error = TryFromSbpError; + fn try_from(msg: Sbp) -> Result { + match msg { + Sbp::MsgAesCmacSignature(m) => Ok(m), + _ => Err(TryFromSbpError(msg)), + } + } + } + + impl WireFormat for MsgAesCmacSignature { + const MIN_LEN: usize = ::MIN_LEN + + ::MIN_LEN + + <[u8; 4] as WireFormat>::MIN_LEN + + <[u8; 16] as WireFormat>::MIN_LEN + + ::MIN_LEN + + as WireFormat>::MIN_LEN; + fn len(&self) -> usize { + WireFormat::len(&self.stream_counter) + + WireFormat::len(&self.on_demand_counter) + + WireFormat::len(&self.certificate_id) + + WireFormat::len(&self.signature) + + WireFormat::len(&self.flags) + + WireFormat::len(&self.signed_messages) + } + fn write(&self, buf: &mut B) { + WireFormat::write(&self.stream_counter, buf); + WireFormat::write(&self.on_demand_counter, buf); + WireFormat::write(&self.certificate_id, buf); + WireFormat::write(&self.signature, buf); + WireFormat::write(&self.flags, buf); + WireFormat::write(&self.signed_messages, buf); + } + fn parse_unchecked(buf: &mut B) -> Self { + MsgAesCmacSignature { + sender_id: None, + stream_counter: WireFormat::parse_unchecked(buf), + on_demand_counter: WireFormat::parse_unchecked(buf), + certificate_id: WireFormat::parse_unchecked(buf), + signature: WireFormat::parse_unchecked(buf), + flags: WireFormat::parse_unchecked(buf), + signed_messages: WireFormat::parse_unchecked(buf), + } + } + } + + /// CRC type + #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] + pub enum CrcType { + /// 24-bit CRCs from RTCM framing + _24BitCrcsFromRtcmFraming = 0, + + /// 16-bit CRCs from SBP framing + _16BitCrcsFromSbpFraming = 1, + } + + impl std::fmt::Display for CrcType { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + CrcType::_24BitCrcsFromRtcmFraming => f.write_str("24-bit CRCs from RTCM framing"), + CrcType::_16BitCrcsFromSbpFraming => f.write_str("16-bit CRCs from SBP framing"), + } + } + } + + impl TryFrom for CrcType { + type Error = u8; + fn try_from(i: u8) -> Result { + match i { + 0 => Ok(CrcType::_24BitCrcsFromRtcmFraming), + 1 => Ok(CrcType::_16BitCrcsFromSbpFraming), + i => Err(i), + } + } + } +} + pub mod msg_certificate_chain { #![allow(unused_imports)] diff --git a/rust/sbp/tests/integration/auto_check_sbp_signing_msg_aes_cmac_signature.rs b/rust/sbp/tests/integration/auto_check_sbp_signing_msg_aes_cmac_signature.rs new file mode 100644 index 0000000000..04d79e29f0 --- /dev/null +++ b/rust/sbp/tests/integration/auto_check_sbp_signing_msg_aes_cmac_signature.rs @@ -0,0 +1,559 @@ +// +// Copyright (C) 2019-2021 Swift Navigation Inc. +// Contact: https://support.swiftnav.com +// +// This source is subject to the license found in the file 'LICENSE' which must +// be distributed together with this source. All other rights reserved. +// +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, +// EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED +// WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE. + +// This file was auto-generated from spec/tests/yaml/swiftnav/sbp/signing/test_MsgAesCmacSignature.yaml by generate.py. Do not modify by hand! + +use crate::*; + +/// Tests [`sbp::iter_messages`], from payload into SBP messages +/// +/// Asserts: +/// - SBP fields equates to that of the field +/// - Payload is identical +#[test] +fn test_auto_check_sbp_signing_msg_aes_cmac_signature() { + { + let mut payload = Cursor::new(vec![ + 85, 16, 12, 66, 0, 26, 1, 2, 1, 2, 3, 4, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, + 14, 15, 0, 11, 22, 33, 192, 21, + ]); + + // Test the round trip payload parsing + let sbp_msg = { + let mut msgs = iter_messages(&mut payload); + msgs.next() + .expect("no message found") + .expect("failed to parse message") + }; + match &sbp_msg { + sbp::messages::Sbp::MsgAesCmacSignature(msg) => { + let msg_type = msg.message_type().unwrap(); + assert_eq!( + msg_type, 0xC10, + "Incorrect message type, expected 0xC10, is {}", + msg_type + ); + let sender_id = msg.sender_id().unwrap(); + assert_eq!( + sender_id, 0x42, + "incorrect sender id, expected 0x42, is {sender_id}" + ); + assert_eq!( + msg.certificate_id[0], 1, + "incorrect value for certificate_id[0], expected 1, is {}", + msg.certificate_id[0] + ); + assert_eq!( + msg.certificate_id[1], 2, + "incorrect value for certificate_id[1], expected 2, is {}", + msg.certificate_id[1] + ); + assert_eq!( + msg.certificate_id[2], 3, + "incorrect value for certificate_id[2], expected 3, is {}", + msg.certificate_id[2] + ); + assert_eq!( + msg.certificate_id[3], 4, + "incorrect value for certificate_id[3], expected 4, is {}", + msg.certificate_id[3] + ); + assert_eq!( + msg.flags, 0, + "incorrect value for flags, expected 0, is {}", + msg.flags + ); + assert_eq!( + msg.on_demand_counter, 2, + "incorrect value for on_demand_counter, expected 2, is {}", + msg.on_demand_counter + ); + assert_eq!( + msg.signature[0], 0, + "incorrect value for signature[0], expected 0, is {}", + msg.signature[0] + ); + assert_eq!( + msg.signature[1], 1, + "incorrect value for signature[1], expected 1, is {}", + msg.signature[1] + ); + assert_eq!( + msg.signature[2], 2, + "incorrect value for signature[2], expected 2, is {}", + msg.signature[2] + ); + assert_eq!( + msg.signature[3], 3, + "incorrect value for signature[3], expected 3, is {}", + msg.signature[3] + ); + assert_eq!( + msg.signature[4], 4, + "incorrect value for signature[4], expected 4, is {}", + msg.signature[4] + ); + assert_eq!( + msg.signature[5], 5, + "incorrect value for signature[5], expected 5, is {}", + msg.signature[5] + ); + assert_eq!( + msg.signature[6], 6, + "incorrect value for signature[6], expected 6, is {}", + msg.signature[6] + ); + assert_eq!( + msg.signature[7], 7, + "incorrect value for signature[7], expected 7, is {}", + msg.signature[7] + ); + assert_eq!( + msg.signature[8], 8, + "incorrect value for signature[8], expected 8, is {}", + msg.signature[8] + ); + assert_eq!( + msg.signature[9], 9, + "incorrect value for signature[9], expected 9, is {}", + msg.signature[9] + ); + assert_eq!( + msg.signature[10], 10, + "incorrect value for signature[10], expected 10, is {}", + msg.signature[10] + ); + assert_eq!( + msg.signature[11], 11, + "incorrect value for signature[11], expected 11, is {}", + msg.signature[11] + ); + assert_eq!( + msg.signature[12], 12, + "incorrect value for signature[12], expected 12, is {}", + msg.signature[12] + ); + assert_eq!( + msg.signature[13], 13, + "incorrect value for signature[13], expected 13, is {}", + msg.signature[13] + ); + assert_eq!( + msg.signature[14], 14, + "incorrect value for signature[14], expected 14, is {}", + msg.signature[14] + ); + assert_eq!( + msg.signature[15], 15, + "incorrect value for signature[15], expected 15, is {}", + msg.signature[15] + ); + assert_eq!( + msg.signed_messages[0], 11, + "incorrect value for signed_messages[0], expected 11, is {}", + msg.signed_messages[0] + ); + assert_eq!( + msg.signed_messages[1], 22, + "incorrect value for signed_messages[1], expected 22, is {}", + msg.signed_messages[1] + ); + assert_eq!( + msg.signed_messages[2], 33, + "incorrect value for signed_messages[2], expected 33, is {}", + msg.signed_messages[2] + ); + assert_eq!( + msg.stream_counter, 1, + "incorrect value for stream_counter, expected 1, is {}", + msg.stream_counter + ); + } + _ => panic!("Invalid message type! Expected a MsgAesCmacSignature"), + }; + let frame = sbp::to_vec(&sbp_msg).unwrap(); + assert_eq!(frame, payload.into_inner()); + } +} + +/// Tests [`sbp::json::iter_messages`] for JSON payload -> SBP message +/// and [`sbp::json::iter_messages_from_fields`] for JSON fields -> SBP message. +/// +/// Asserts: +/// - SBP message constructed via payload is identical to from fields +/// - SBP fields equates to that of the field +/// - Payload is identical +#[test] +#[cfg(feature = "json")] +fn test_json2sbp_auto_check_sbp_signing_msg_aes_cmac_signature() { + { + let json_input = r#"{"crc":5568,"length":26,"msg_type":3088,"payload":"AQIBAgMEAAECAwQFBgcICQoLDA0ODwALFiE=","preamble":85,"sender":66,"stream_counter":1,"on_demand_counter":2,"certificate_id":[1,2,3,4],"signature":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15],"flags":0,"signed_messages":[11,22,33]}"#.as_bytes(); + + let sbp_msg = { + // JSON to SBP message from payload + let mut iter = json2sbp_iter_msg(json_input); + let from_payload = iter + .next() + .expect("no message found") + .expect("failed to parse message"); + + // JSON to SBP message from fields + let mut iter = iter_messages_from_fields(json_input); + let from_fields = iter + .next() + .expect("no message found") + .expect("failed to parse message"); + + assert_eq!(from_fields, from_payload); + from_fields + }; + match &sbp_msg { + sbp::messages::Sbp::MsgAesCmacSignature(msg) => { + let msg_type = msg.message_type().unwrap(); + assert_eq!( + msg_type, 0xC10, + "Incorrect message type, expected 0xC10, is {}", + msg_type + ); + let sender_id = msg.sender_id().unwrap(); + assert_eq!( + sender_id, 0x42, + "incorrect sender id, expected 0x42, is {sender_id}" + ); + assert_eq!( + msg.certificate_id[0], 1, + "incorrect value for certificate_id[0], expected 1, is {}", + msg.certificate_id[0] + ); + assert_eq!( + msg.certificate_id[1], 2, + "incorrect value for certificate_id[1], expected 2, is {}", + msg.certificate_id[1] + ); + assert_eq!( + msg.certificate_id[2], 3, + "incorrect value for certificate_id[2], expected 3, is {}", + msg.certificate_id[2] + ); + assert_eq!( + msg.certificate_id[3], 4, + "incorrect value for certificate_id[3], expected 4, is {}", + msg.certificate_id[3] + ); + assert_eq!( + msg.flags, 0, + "incorrect value for flags, expected 0, is {}", + msg.flags + ); + assert_eq!( + msg.on_demand_counter, 2, + "incorrect value for on_demand_counter, expected 2, is {}", + msg.on_demand_counter + ); + assert_eq!( + msg.signature[0], 0, + "incorrect value for signature[0], expected 0, is {}", + msg.signature[0] + ); + assert_eq!( + msg.signature[1], 1, + "incorrect value for signature[1], expected 1, is {}", + msg.signature[1] + ); + assert_eq!( + msg.signature[2], 2, + "incorrect value for signature[2], expected 2, is {}", + msg.signature[2] + ); + assert_eq!( + msg.signature[3], 3, + "incorrect value for signature[3], expected 3, is {}", + msg.signature[3] + ); + assert_eq!( + msg.signature[4], 4, + "incorrect value for signature[4], expected 4, is {}", + msg.signature[4] + ); + assert_eq!( + msg.signature[5], 5, + "incorrect value for signature[5], expected 5, is {}", + msg.signature[5] + ); + assert_eq!( + msg.signature[6], 6, + "incorrect value for signature[6], expected 6, is {}", + msg.signature[6] + ); + assert_eq!( + msg.signature[7], 7, + "incorrect value for signature[7], expected 7, is {}", + msg.signature[7] + ); + assert_eq!( + msg.signature[8], 8, + "incorrect value for signature[8], expected 8, is {}", + msg.signature[8] + ); + assert_eq!( + msg.signature[9], 9, + "incorrect value for signature[9], expected 9, is {}", + msg.signature[9] + ); + assert_eq!( + msg.signature[10], 10, + "incorrect value for signature[10], expected 10, is {}", + msg.signature[10] + ); + assert_eq!( + msg.signature[11], 11, + "incorrect value for signature[11], expected 11, is {}", + msg.signature[11] + ); + assert_eq!( + msg.signature[12], 12, + "incorrect value for signature[12], expected 12, is {}", + msg.signature[12] + ); + assert_eq!( + msg.signature[13], 13, + "incorrect value for signature[13], expected 13, is {}", + msg.signature[13] + ); + assert_eq!( + msg.signature[14], 14, + "incorrect value for signature[14], expected 14, is {}", + msg.signature[14] + ); + assert_eq!( + msg.signature[15], 15, + "incorrect value for signature[15], expected 15, is {}", + msg.signature[15] + ); + assert_eq!( + msg.signed_messages[0], 11, + "incorrect value for signed_messages[0], expected 11, is {}", + msg.signed_messages[0] + ); + assert_eq!( + msg.signed_messages[1], 22, + "incorrect value for signed_messages[1], expected 22, is {}", + msg.signed_messages[1] + ); + assert_eq!( + msg.signed_messages[2], 33, + "incorrect value for signed_messages[2], expected 33, is {}", + msg.signed_messages[2] + ); + assert_eq!( + msg.stream_counter, 1, + "incorrect value for stream_counter, expected 1, is {}", + msg.stream_counter + ); + } + _ => panic!("Invalid message type! Expected a MsgAesCmacSignature"), + }; + } +} + +/// Tests [`sbp::json::JsonEncoder`] for roundtrip SBP message -> JSON +/// +/// Assumes: +/// - [`self::test_auto_check_sbp_signing_msg_aes_cmac_signature`] passes +/// +/// Asserts: +/// - SBP fields equates to that of the field +/// - Payload is identical +#[test] +#[cfg(feature = "json")] +fn test_sbp2json_auto_check_sbp_signing_msg_aes_cmac_signature() { + { + let mut payload = Cursor::new(vec![ + 85, 16, 12, 66, 0, 26, 1, 2, 1, 2, 3, 4, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, + 14, 15, 0, 11, 22, 33, 192, 21, + ]); + + // Construct sbp message + let sbp_msg = { + let mut msgs = iter_messages(&mut payload); + msgs.next() + .expect("no message found") + .expect("failed to parse message") + }; + + let mut json_buffer = vec![]; + // Populate json buffer, CompactFormatter + sbp::json::JsonEncoder::new(&mut json_buffer, sbp::json::CompactFormatter {}) + .send(&sbp_msg) + .unwrap(); + + // Reconstruct Sbp message from json fields, roundtrip + let sbp_msg = sbp::messages::Sbp::MsgAesCmacSignature( + serde_json::from_str( + std::str::from_utf8(json_buffer.as_slice()) + .unwrap() + .to_string() + .as_str(), + ) + .unwrap(), + ); + match &sbp_msg { + sbp::messages::Sbp::MsgAesCmacSignature(msg) => { + let msg_type = msg.message_type().unwrap(); + assert_eq!( + msg_type, 0xC10, + "Incorrect message type, expected 0xC10, is {}", + msg_type + ); + let sender_id = msg.sender_id().unwrap(); + assert_eq!( + sender_id, 0x42, + "incorrect sender id, expected 0x42, is {sender_id}" + ); + assert_eq!( + msg.certificate_id[0], 1, + "incorrect value for certificate_id[0], expected 1, is {}", + msg.certificate_id[0] + ); + assert_eq!( + msg.certificate_id[1], 2, + "incorrect value for certificate_id[1], expected 2, is {}", + msg.certificate_id[1] + ); + assert_eq!( + msg.certificate_id[2], 3, + "incorrect value for certificate_id[2], expected 3, is {}", + msg.certificate_id[2] + ); + assert_eq!( + msg.certificate_id[3], 4, + "incorrect value for certificate_id[3], expected 4, is {}", + msg.certificate_id[3] + ); + assert_eq!( + msg.flags, 0, + "incorrect value for flags, expected 0, is {}", + msg.flags + ); + assert_eq!( + msg.on_demand_counter, 2, + "incorrect value for on_demand_counter, expected 2, is {}", + msg.on_demand_counter + ); + assert_eq!( + msg.signature[0], 0, + "incorrect value for signature[0], expected 0, is {}", + msg.signature[0] + ); + assert_eq!( + msg.signature[1], 1, + "incorrect value for signature[1], expected 1, is {}", + msg.signature[1] + ); + assert_eq!( + msg.signature[2], 2, + "incorrect value for signature[2], expected 2, is {}", + msg.signature[2] + ); + assert_eq!( + msg.signature[3], 3, + "incorrect value for signature[3], expected 3, is {}", + msg.signature[3] + ); + assert_eq!( + msg.signature[4], 4, + "incorrect value for signature[4], expected 4, is {}", + msg.signature[4] + ); + assert_eq!( + msg.signature[5], 5, + "incorrect value for signature[5], expected 5, is {}", + msg.signature[5] + ); + assert_eq!( + msg.signature[6], 6, + "incorrect value for signature[6], expected 6, is {}", + msg.signature[6] + ); + assert_eq!( + msg.signature[7], 7, + "incorrect value for signature[7], expected 7, is {}", + msg.signature[7] + ); + assert_eq!( + msg.signature[8], 8, + "incorrect value for signature[8], expected 8, is {}", + msg.signature[8] + ); + assert_eq!( + msg.signature[9], 9, + "incorrect value for signature[9], expected 9, is {}", + msg.signature[9] + ); + assert_eq!( + msg.signature[10], 10, + "incorrect value for signature[10], expected 10, is {}", + msg.signature[10] + ); + assert_eq!( + msg.signature[11], 11, + "incorrect value for signature[11], expected 11, is {}", + msg.signature[11] + ); + assert_eq!( + msg.signature[12], 12, + "incorrect value for signature[12], expected 12, is {}", + msg.signature[12] + ); + assert_eq!( + msg.signature[13], 13, + "incorrect value for signature[13], expected 13, is {}", + msg.signature[13] + ); + assert_eq!( + msg.signature[14], 14, + "incorrect value for signature[14], expected 14, is {}", + msg.signature[14] + ); + assert_eq!( + msg.signature[15], 15, + "incorrect value for signature[15], expected 15, is {}", + msg.signature[15] + ); + assert_eq!( + msg.signed_messages[0], 11, + "incorrect value for signed_messages[0], expected 11, is {}", + msg.signed_messages[0] + ); + assert_eq!( + msg.signed_messages[1], 22, + "incorrect value for signed_messages[1], expected 22, is {}", + msg.signed_messages[1] + ); + assert_eq!( + msg.signed_messages[2], 33, + "incorrect value for signed_messages[2], expected 33, is {}", + msg.signed_messages[2] + ); + assert_eq!( + msg.stream_counter, 1, + "incorrect value for stream_counter, expected 1, is {}", + msg.stream_counter + ); + } + _ => panic!("Invalid message type! Expected a MsgAesCmacSignature"), + }; + + // Check payload is still identical + let frame = sbp::to_vec(&sbp_msg).unwrap(); + assert_eq!(frame, payload.into_inner()); + } +} diff --git a/rust/sbp/tests/integration/main.rs b/rust/sbp/tests/integration/main.rs index 7392ebb4a5..cfc224e26f 100644 --- a/rust/sbp/tests/integration/main.rs +++ b/rust/sbp/tests/integration/main.rs @@ -191,6 +191,7 @@ mod auto_check_sbp_settings_msg_settings_register_resp; mod auto_check_sbp_settings_msg_settings_save; mod auto_check_sbp_settings_msg_settings_write; mod auto_check_sbp_settings_msg_settings_write_resp; +mod auto_check_sbp_signing_msg_aes_cmac_signature; mod auto_check_sbp_signing_msg_certificate_chain; mod auto_check_sbp_signing_msg_certificate_chain_dep; mod auto_check_sbp_signing_msg_ecdsa_certificate; diff --git a/sbpjson/elm/SbpJson.elm b/sbpjson/elm/SbpJson.elm index 7738cd5b61..bcee891a1a 100644 --- a/sbpjson/elm/SbpJson.elm +++ b/sbpjson/elm/SbpJson.elm @@ -5,7 +5,7 @@ -- add these imports -- -- import Json.Decode exposing (decodeString)`); --- import SbpJson exposing (acqSvProfile, almanacCommonContent, boundsHeader, carrierPhase, codeBiasesContent, codePhaseBiasesSatSig, doppler, ecdsaSignature, ephemerisCommonContent, estimatedHorizontalErrorEllipse, gnssInputType, gnssCapb, gnssSignal, gpsTime, gpsTimeSEC, gridElement, gridElementNoStd, griddedCorrectionHeader, imuInputType, integritySSRHeader, latency, measurementState, msgAcknowledge, msgAcqResult, msgAcqSvProfile, msgAgeCorrections, msgAlmanac, msgAlmanacGPS, msgAlmanacGlo, msgAngularRate, msgBasePosECEF, msgBasePosLLH, msgBaselineECEF, msgBaselineHeading, msgBaselineNED, msgBootloaderHandshakeReq, msgBootloaderHandshakeResp, msgBootloaderJumpToApp, msgCellModemStatus, msgCertificateChain, msgCommandOutput, msgCommandReq, msgCommandResp, msgCsacTelemetry, msgCsacTelemetryLabels, msgCwResults, msgCwStart, msgDeviceMonitor, msgDgnssStatus, msgDops, msgEcdsaCertificate, msgEcdsaSignature, msgEphemerisBds, msgEphemerisGPS, msgEphemerisGal, msgEphemerisGlo, msgEphemerisQzss, msgEphemerisSbas, msgEXTEvent, msgFileioConfigReq, msgFileioConfigResp, msgFileioReadDirReq, msgFileioReadDirResp, msgFileioReadReq, msgFileioReadResp, msgFileioRemove, msgFileioWriteReq, msgFileioWriteResp, msgFlashDone, msgFlashErase, msgFlashProgram, msgFlashReadReq, msgFlashReadResp, msgFrontEndGain, msgFwd, msgGPSTime, msgGPSTimeGnss, msgGloBiases, msgGnssCapb, msgGnssTimeOffset, msgGroupDelay, msgGroupMeta, msgHeartbeat, msgIarState, msgImuAux, msgImuRaw, msgInsStatus, msgInsUpdates, msgIono, msgLinuxCPUState, msgLinuxMemState, msgLinuxProcessFdCount, msgLinuxProcessFdSummary, msgLinuxProcessSocketCounts, msgLinuxProcessSocketQueues, msgLinuxSocketUsage, msgLinuxSysState, msgLog, msgM25FlashWriteStatus, msgMagRaw, msgMaskSatellite, msgMeasurementPoint, msgMeasurementState, msgNapDeviceDnaReq, msgNapDeviceDnaResp, msgNdbEvent, msgNetworkBandwidthUsage, msgNetworkStateReq, msgNetworkStateResp, msgObs, msgOdometry, msgOrientEuler, msgOrientQuat, msgOsr, msgPosECEF, msgPosECEFCov, msgPosECEFCovGnss, msgPosECEFGnss, msgPosLLH, msgPosLLHAcc, msgPosLLHCov, msgPosLLHCovGnss, msgPosLLHGnss, msgPoseRelative, msgPpsTime, msgProfilingResourceCounter, msgProfilingSystemInfo, msgProfilingThreadInfo, msgProtectionLevel, msgReferenceFrameParam, msgReset, msgResetFilters, msgSbasRaw, msgSensorAidEvent, msgSetTime, msgSettingsReadByIndexDone, msgSettingsReadByIndexReq, msgSettingsReadByIndexResp, msgSettingsReadReq, msgSettingsReadResp, msgSettingsRegister, msgSettingsRegisterResp, msgSettingsSave, msgSettingsWrite, msgSettingsWriteResp, msgSolnMeta, msgSpecan, msgSsrCodeBiases, msgSsrCodePhaseBiasesBounds, msgSsrFlagHighLevel, msgSsrFlagIonoGridPointSatLos, msgSsrFlagIonoGridPoints, msgSsrFlagIonoTileSatLos, msgSsrFlagSatellites, msgSsrFlagTropoGridPoints, msgSsrGriddedCorrection, msgSsrGriddedCorrectionBounds, msgSsrOrbitClock, msgSsrOrbitClockBounds, msgSsrOrbitClockBoundsDegradation, msgSsrPhaseBiases, msgSsrSatelliteApc, msgSsrStecCorrection, msgSsrTileDefinition, msgStartup, msgStatusJournal, msgStatusReport, msgStmFlashLockSector, msgStmFlashUnlockSector, msgStmUniqueIDReq, msgStmUniqueIDResp, msgSvAzEl, msgTelSv, msgThreadState, msgTrackingIq, msgTrackingState, msgUARTState, msgUserData, msgUTCLeapSecond, msgUTCTime, msgUTCTimeGnss, msgVelBody, msgVelCog, msgVelECEF, msgVelECEFCov, msgVelECEFCovGnss, msgVelECEFGnss, msgVelNED, msgVelNEDCov, msgVelNEDCovGnss, msgVelNEDGnss, msgWheeltick, networkUsage, observationHeader, odoInputType, orbitClockBound, orbitClockBoundDegradation, packedObsContent, packedOsrContent, period, phaseBiasesContent, resourceBucket, stecHeader, stecResidual, stecResidualNoStd, stecSatElement, stecSatElementIntegrity, satelliteAPC, solutionInputType, statusJournalItem, subSystemReport, svAzEl, svID, telemetrySV, trackingChannelCorrelation, trackingChannelState, troposphericDelayCorrection, troposphericDelayCorrectionNoStd, uartChannel, utcTime) +-- import SbpJson exposing (acqSvProfile, almanacCommonContent, boundsHeader, carrierPhase, codeBiasesContent, codePhaseBiasesSatSig, doppler, ecdsaSignature, ephemerisCommonContent, estimatedHorizontalErrorEllipse, gnssInputType, gnssCapb, gnssSignal, gpsTime, gpsTimeSEC, gridElement, gridElementNoStd, griddedCorrectionHeader, imuInputType, integritySSRHeader, latency, measurementState, msgAcknowledge, msgAcqResult, msgAcqSvProfile, msgAESCmacSignature, msgAgeCorrections, msgAlmanac, msgAlmanacGPS, msgAlmanacGlo, msgAngularRate, msgBasePosECEF, msgBasePosLLH, msgBaselineECEF, msgBaselineHeading, msgBaselineNED, msgBootloaderHandshakeReq, msgBootloaderHandshakeResp, msgBootloaderJumpToApp, msgCellModemStatus, msgCertificateChain, msgCommandOutput, msgCommandReq, msgCommandResp, msgCsacTelemetry, msgCsacTelemetryLabels, msgCwResults, msgCwStart, msgDeviceMonitor, msgDgnssStatus, msgDops, msgEcdsaCertificate, msgEcdsaSignature, msgEphemerisBds, msgEphemerisGPS, msgEphemerisGal, msgEphemerisGlo, msgEphemerisQzss, msgEphemerisSbas, msgEXTEvent, msgFileioConfigReq, msgFileioConfigResp, msgFileioReadDirReq, msgFileioReadDirResp, msgFileioReadReq, msgFileioReadResp, msgFileioRemove, msgFileioWriteReq, msgFileioWriteResp, msgFlashDone, msgFlashErase, msgFlashProgram, msgFlashReadReq, msgFlashReadResp, msgFrontEndGain, msgFwd, msgGPSTime, msgGPSTimeGnss, msgGloBiases, msgGnssCapb, msgGnssTimeOffset, msgGroupDelay, msgGroupMeta, msgHeartbeat, msgIarState, msgImuAux, msgImuRaw, msgInsStatus, msgInsUpdates, msgIono, msgLinuxCPUState, msgLinuxMemState, msgLinuxProcessFdCount, msgLinuxProcessFdSummary, msgLinuxProcessSocketCounts, msgLinuxProcessSocketQueues, msgLinuxSocketUsage, msgLinuxSysState, msgLog, msgM25FlashWriteStatus, msgMagRaw, msgMaskSatellite, msgMeasurementPoint, msgMeasurementState, msgNapDeviceDnaReq, msgNapDeviceDnaResp, msgNdbEvent, msgNetworkBandwidthUsage, msgNetworkStateReq, msgNetworkStateResp, msgObs, msgOdometry, msgOrientEuler, msgOrientQuat, msgOsr, msgPosECEF, msgPosECEFCov, msgPosECEFCovGnss, msgPosECEFGnss, msgPosLLH, msgPosLLHAcc, msgPosLLHCov, msgPosLLHCovGnss, msgPosLLHGnss, msgPoseRelative, msgPpsTime, msgProfilingResourceCounter, msgProfilingSystemInfo, msgProfilingThreadInfo, msgProtectionLevel, msgReferenceFrameParam, msgReset, msgResetFilters, msgSbasRaw, msgSensorAidEvent, msgSetTime, msgSettingsReadByIndexDone, msgSettingsReadByIndexReq, msgSettingsReadByIndexResp, msgSettingsReadReq, msgSettingsReadResp, msgSettingsRegister, msgSettingsRegisterResp, msgSettingsSave, msgSettingsWrite, msgSettingsWriteResp, msgSolnMeta, msgSpecan, msgSsrCodeBiases, msgSsrCodePhaseBiasesBounds, msgSsrFlagHighLevel, msgSsrFlagIonoGridPointSatLos, msgSsrFlagIonoGridPoints, msgSsrFlagIonoTileSatLos, msgSsrFlagSatellites, msgSsrFlagTropoGridPoints, msgSsrGriddedCorrection, msgSsrGriddedCorrectionBounds, msgSsrOrbitClock, msgSsrOrbitClockBounds, msgSsrOrbitClockBoundsDegradation, msgSsrPhaseBiases, msgSsrSatelliteApc, msgSsrStecCorrection, msgSsrTileDefinition, msgStartup, msgStatusJournal, msgStatusReport, msgStmFlashLockSector, msgStmFlashUnlockSector, msgStmUniqueIDReq, msgStmUniqueIDResp, msgSvAzEl, msgTelSv, msgThreadState, msgTrackingIq, msgTrackingState, msgUARTState, msgUserData, msgUTCLeapSecond, msgUTCTime, msgUTCTimeGnss, msgVelBody, msgVelCog, msgVelECEF, msgVelECEFCov, msgVelECEFCovGnss, msgVelECEFGnss, msgVelNED, msgVelNEDCov, msgVelNEDCovGnss, msgVelNEDGnss, msgWheeltick, networkUsage, observationHeader, odoInputType, orbitClockBound, orbitClockBoundDegradation, packedObsContent, packedOsrContent, period, phaseBiasesContent, resourceBucket, stecHeader, stecResidual, stecResidualNoStd, stecSatElement, stecSatElementIntegrity, satelliteAPC, solutionInputType, statusJournalItem, subSystemReport, svAzEl, svID, telemetrySV, trackingChannelCorrelation, trackingChannelState, troposphericDelayCorrection, troposphericDelayCorrectionNoStd, uartChannel, utcTime) -- -- and you're off to the races with -- @@ -34,6 +34,7 @@ -- decodeString msgAcknowledge myJsonString -- decodeString msgAcqResult myJsonString -- decodeString msgAcqSvProfile myJsonString +-- decodeString msgAESCmacSignature myJsonString -- decodeString msgAgeCorrections myJsonString -- decodeString msgAlmanac myJsonString -- decodeString msgAlmanacGPS myJsonString @@ -306,6 +307,9 @@ module SbpJson exposing , MsgAcqSvProfile , msgAcqSvProfileToString , msgAcqSvProfile + , MsgAESCmacSignature + , msgAESCmacSignatureToString + , msgAESCmacSignature , MsgAgeCorrections , msgAgeCorrectionsToString , msgAgeCorrections @@ -1032,6 +1036,16 @@ type alias AcqSvProfile = , timestamp : Int } +{-| Digital signature using AES-CMAC 128 algorithm used for data integrity. -} +type alias MsgAESCmacSignature = + { certificateID : Array Int + , flags : Int + , onDemandCounter : Int + , signature : Array Int + , signedMessages : Array Int + , streamCounter : Int + } + {-| This message reports the Age of the corrections used for the current Differential solution. -} @@ -3642,6 +3656,9 @@ msgAcqResultToString r = Jenc.encode 0 (encodeMsgAcqResult r) msgAcqSvProfileToString : MsgAcqSvProfile -> String msgAcqSvProfileToString r = Jenc.encode 0 (encodeMsgAcqSvProfile r) +msgAESCmacSignatureToString : MsgAESCmacSignature -> String +msgAESCmacSignatureToString r = Jenc.encode 0 (encodeMsgAESCmacSignature r) + msgAgeCorrectionsToString : MsgAgeCorrections -> String msgAgeCorrectionsToString r = Jenc.encode 0 (encodeMsgAgeCorrections r) @@ -4473,6 +4490,27 @@ encodeAcqSvProfile x = , ("timestamp", Jenc.int x.timestamp) ] +msgAESCmacSignature : Jdec.Decoder MsgAESCmacSignature +msgAESCmacSignature = + Jpipe.decode MsgAESCmacSignature + |> Jpipe.required "certificate_id" (Jdec.array Jdec.int) + |> Jpipe.required "flags" Jdec.int + |> Jpipe.required "on_demand_counter" Jdec.int + |> Jpipe.required "signature" (Jdec.array Jdec.int) + |> Jpipe.required "signed_messages" (Jdec.array Jdec.int) + |> Jpipe.required "stream_counter" Jdec.int + +encodeMsgAESCmacSignature : MsgAESCmacSignature -> Jenc.Value +encodeMsgAESCmacSignature x = + Jenc.object + [ ("certificate_id", makeArrayEncoder Jenc.int x.certificateID) + , ("flags", Jenc.int x.flags) + , ("on_demand_counter", Jenc.int x.onDemandCounter) + , ("signature", makeArrayEncoder Jenc.int x.signature) + , ("signed_messages", makeArrayEncoder Jenc.int x.signedMessages) + , ("stream_counter", Jenc.int x.streamCounter) + ] + msgAgeCorrections : Jdec.Decoder MsgAgeCorrections msgAgeCorrections = Jpipe.decode MsgAgeCorrections diff --git a/sbpjson/typescript/SbpJson.ts b/sbpjson/typescript/SbpJson.ts index 7278e6380c..1915dcdbe8 100644 --- a/sbpjson/typescript/SbpJson.ts +++ b/sbpjson/typescript/SbpJson.ts @@ -1,6 +1,6 @@ // To parse this data: // -// import { Convert, AcqSvProfile, AlmanacCommonContent, BoundsHeader, CarrierPhase, CodeBiasesContent, CodePhaseBiasesSatSig, Doppler, ECDSASignature, EphemerisCommonContent, EstimatedHorizontalErrorEllipse, GNSSInputType, GnssCapb, GnssSignal, GpsTime, GpsTimeSEC, GridElement, GridElementNoStd, GriddedCorrectionHeader, IMUInputType, IntegritySSRHeader, Latency, MeasurementState, MsgAcknowledge, MsgAcqResult, MsgAcqSvProfile, MsgAgeCorrections, MsgAlmanacGPS, MsgAlmanacGlo, MsgAngularRate, MsgBasePosECEF, MsgBasePosLLH, MsgBaselineECEF, MsgBaselineHeading, MsgBaselineNED, MsgBootloaderHandshakeResp, MsgBootloaderJumpToApp, MsgCellModemStatus, MsgCertificateChain, MsgCommandOutput, MsgCommandReq, MsgCommandResp, MsgCsacTelemetry, MsgCsacTelemetryLabels, MsgDeviceMonitor, MsgDgnssStatus, MsgDops, MsgEcdsaCertificate, MsgEcdsaSignature, MsgEphemerisBds, MsgEphemerisGPS, MsgEphemerisGal, MsgEphemerisGlo, MsgEphemerisQzss, MsgEphemerisSbas, MsgEXTEvent, MsgFileioConfigReq, MsgFileioConfigResp, MsgFileioReadDirReq, MsgFileioReadDirResp, MsgFileioReadReq, MsgFileioReadResp, MsgFileioRemove, MsgFileioWriteReq, MsgFileioWriteResp, MsgFlashDone, MsgFlashErase, MsgFlashProgram, MsgFlashReadReq, MsgFlashReadResp, MsgFrontEndGain, MsgFwd, MsgGPSTime, MsgGPSTimeGnss, MsgGloBiases, MsgGnssCapb, MsgGnssTimeOffset, MsgGroupDelay, MsgGroupMeta, MsgHeartbeat, MsgIarState, MsgImuAux, MsgImuRaw, MsgInsStatus, MsgInsUpdates, MsgIono, MsgLinuxCPUState, MsgLinuxMemState, MsgLinuxProcessFdCount, MsgLinuxProcessFdSummary, MsgLinuxProcessSocketCounts, MsgLinuxProcessSocketQueues, MsgLinuxSocketUsage, MsgLinuxSysState, MsgLog, MsgM25FlashWriteStatus, MsgMagRaw, MsgMaskSatellite, MsgMeasurementPoint, MsgMeasurementState, MsgNapDeviceDnaResp, MsgNdbEvent, MsgNetworkBandwidthUsage, MsgNetworkStateResp, MsgObs, MsgOdometry, MsgOrientEuler, MsgOrientQuat, MsgOsr, MsgPosECEF, MsgPosECEFCov, MsgPosECEFCovGnss, MsgPosECEFGnss, MsgPosLLH, MsgPosLLHAcc, MsgPosLLHCov, MsgPosLLHCovGnss, MsgPosLLHGnss, MsgPoseRelative, MsgPpsTime, MsgProfilingResourceCounter, MsgProfilingSystemInfo, MsgProfilingThreadInfo, MsgProtectionLevel, MsgReferenceFrameParam, MsgReset, MsgResetFilters, MsgSbasRaw, MsgSensorAidEvent, MsgSettingsReadByIndexReq, MsgSettingsReadByIndexResp, MsgSettingsReadReq, MsgSettingsReadResp, MsgSettingsRegister, MsgSettingsRegisterResp, MsgSettingsWrite, MsgSettingsWriteResp, MsgSolnMeta, MsgSpecan, MsgSsrCodeBiases, MsgSsrCodePhaseBiasesBounds, MsgSsrFlagHighLevel, MsgSsrFlagIonoGridPointSatLos, MsgSsrFlagIonoGridPoints, MsgSsrFlagIonoTileSatLos, MsgSsrFlagSatellites, MsgSsrFlagTropoGridPoints, MsgSsrGriddedCorrection, MsgSsrGriddedCorrectionBounds, MsgSsrOrbitClock, MsgSsrOrbitClockBounds, MsgSsrOrbitClockBoundsDegradation, MsgSsrPhaseBiases, MsgSsrSatelliteApc, MsgSsrStecCorrection, MsgSsrTileDefinition, MsgStartup, MsgStatusJournal, MsgStatusReport, MsgStmFlashLockSector, MsgStmFlashUnlockSector, MsgStmUniqueIDResp, MsgSvAzEl, MsgTelSv, MsgThreadState, MsgTrackingIq, MsgTrackingState, MsgUARTState, MsgUserData, MsgUTCLeapSecond, MsgUTCTime, MsgUTCTimeGnss, MsgVelBody, MsgVelCog, MsgVelECEF, MsgVelECEFCov, MsgVelECEFCovGnss, MsgVelECEFGnss, MsgVelNED, MsgVelNEDCov, MsgVelNEDCovGnss, MsgVelNEDGnss, MsgWheeltick, NetworkUsage, ObservationHeader, OdoInputType, OrbitClockBound, OrbitClockBoundDegradation, PackedObsContent, PackedOsrContent, Period, PhaseBiasesContent, ResourceBucket, STECHeader, STECResidual, STECResidualNoStd, STECSatElement, STECSatElementIntegrity, SatelliteAPC, SolutionInputType, StatusJournalItem, SubSystemReport, SvAzEl, SvID, TelemetrySV, TrackingChannelCorrelation, TrackingChannelState, TroposphericDelayCorrection, TroposphericDelayCorrectionNoStd, UARTChannel, UTCTime } from "./file"; +// import { Convert, AcqSvProfile, AlmanacCommonContent, BoundsHeader, CarrierPhase, CodeBiasesContent, CodePhaseBiasesSatSig, Doppler, ECDSASignature, EphemerisCommonContent, EstimatedHorizontalErrorEllipse, GNSSInputType, GnssCapb, GnssSignal, GpsTime, GpsTimeSEC, GridElement, GridElementNoStd, GriddedCorrectionHeader, IMUInputType, IntegritySSRHeader, Latency, MeasurementState, MsgAcknowledge, MsgAcqResult, MsgAcqSvProfile, MsgAESCmacSignature, MsgAgeCorrections, MsgAlmanacGPS, MsgAlmanacGlo, MsgAngularRate, MsgBasePosECEF, MsgBasePosLLH, MsgBaselineECEF, MsgBaselineHeading, MsgBaselineNED, MsgBootloaderHandshakeResp, MsgBootloaderJumpToApp, MsgCellModemStatus, MsgCertificateChain, MsgCommandOutput, MsgCommandReq, MsgCommandResp, MsgCsacTelemetry, MsgCsacTelemetryLabels, MsgDeviceMonitor, MsgDgnssStatus, MsgDops, MsgEcdsaCertificate, MsgEcdsaSignature, MsgEphemerisBds, MsgEphemerisGPS, MsgEphemerisGal, MsgEphemerisGlo, MsgEphemerisQzss, MsgEphemerisSbas, MsgEXTEvent, MsgFileioConfigReq, MsgFileioConfigResp, MsgFileioReadDirReq, MsgFileioReadDirResp, MsgFileioReadReq, MsgFileioReadResp, MsgFileioRemove, MsgFileioWriteReq, MsgFileioWriteResp, MsgFlashDone, MsgFlashErase, MsgFlashProgram, MsgFlashReadReq, MsgFlashReadResp, MsgFrontEndGain, MsgFwd, MsgGPSTime, MsgGPSTimeGnss, MsgGloBiases, MsgGnssCapb, MsgGnssTimeOffset, MsgGroupDelay, MsgGroupMeta, MsgHeartbeat, MsgIarState, MsgImuAux, MsgImuRaw, MsgInsStatus, MsgInsUpdates, MsgIono, MsgLinuxCPUState, MsgLinuxMemState, MsgLinuxProcessFdCount, MsgLinuxProcessFdSummary, MsgLinuxProcessSocketCounts, MsgLinuxProcessSocketQueues, MsgLinuxSocketUsage, MsgLinuxSysState, MsgLog, MsgM25FlashWriteStatus, MsgMagRaw, MsgMaskSatellite, MsgMeasurementPoint, MsgMeasurementState, MsgNapDeviceDnaResp, MsgNdbEvent, MsgNetworkBandwidthUsage, MsgNetworkStateResp, MsgObs, MsgOdometry, MsgOrientEuler, MsgOrientQuat, MsgOsr, MsgPosECEF, MsgPosECEFCov, MsgPosECEFCovGnss, MsgPosECEFGnss, MsgPosLLH, MsgPosLLHAcc, MsgPosLLHCov, MsgPosLLHCovGnss, MsgPosLLHGnss, MsgPoseRelative, MsgPpsTime, MsgProfilingResourceCounter, MsgProfilingSystemInfo, MsgProfilingThreadInfo, MsgProtectionLevel, MsgReferenceFrameParam, MsgReset, MsgResetFilters, MsgSbasRaw, MsgSensorAidEvent, MsgSettingsReadByIndexReq, MsgSettingsReadByIndexResp, MsgSettingsReadReq, MsgSettingsReadResp, MsgSettingsRegister, MsgSettingsRegisterResp, MsgSettingsWrite, MsgSettingsWriteResp, MsgSolnMeta, MsgSpecan, MsgSsrCodeBiases, MsgSsrCodePhaseBiasesBounds, MsgSsrFlagHighLevel, MsgSsrFlagIonoGridPointSatLos, MsgSsrFlagIonoGridPoints, MsgSsrFlagIonoTileSatLos, MsgSsrFlagSatellites, MsgSsrFlagTropoGridPoints, MsgSsrGriddedCorrection, MsgSsrGriddedCorrectionBounds, MsgSsrOrbitClock, MsgSsrOrbitClockBounds, MsgSsrOrbitClockBoundsDegradation, MsgSsrPhaseBiases, MsgSsrSatelliteApc, MsgSsrStecCorrection, MsgSsrTileDefinition, MsgStartup, MsgStatusJournal, MsgStatusReport, MsgStmFlashLockSector, MsgStmFlashUnlockSector, MsgStmUniqueIDResp, MsgSvAzEl, MsgTelSv, MsgThreadState, MsgTrackingIq, MsgTrackingState, MsgUARTState, MsgUserData, MsgUTCLeapSecond, MsgUTCTime, MsgUTCTimeGnss, MsgVelBody, MsgVelCog, MsgVelECEF, MsgVelECEFCov, MsgVelECEFCovGnss, MsgVelECEFGnss, MsgVelNED, MsgVelNEDCov, MsgVelNEDCovGnss, MsgVelNEDGnss, MsgWheeltick, NetworkUsage, ObservationHeader, OdoInputType, OrbitClockBound, OrbitClockBoundDegradation, PackedObsContent, PackedOsrContent, Period, PhaseBiasesContent, ResourceBucket, STECHeader, STECResidual, STECResidualNoStd, STECSatElement, STECSatElementIntegrity, SatelliteAPC, SolutionInputType, StatusJournalItem, SubSystemReport, SvAzEl, SvID, TelemetrySV, TrackingChannelCorrelation, TrackingChannelState, TroposphericDelayCorrection, TroposphericDelayCorrectionNoStd, UARTChannel, UTCTime } from "./file"; // // const acqSvProfile = Convert.toAcqSvProfile(json); // const almanacCommonContent = Convert.toAlmanacCommonContent(json); @@ -27,6 +27,7 @@ // const msgAcknowledge = Convert.toMsgAcknowledge(json); // const msgAcqResult = Convert.toMsgAcqResult(json); // const msgAcqSvProfile = Convert.toMsgAcqSvProfile(json); +// const msgAESCmacSignature = Convert.toMsgAESCmacSignature(json); // const msgAgeCorrections = Convert.toMsgAgeCorrections(json); // const msgAlmanac = Convert.toMsgAlmanac(json); // const msgAlmanacGPS = Convert.toMsgAlmanacGPS(json); @@ -373,6 +374,19 @@ export interface AcqSvProfile { [property: string]: any; } +/** + * Digital signature using AES-CMAC 128 algorithm used for data integrity. + */ +export interface MsgAESCmacSignature { + certificate_id: number[]; + flags: number; + on_demand_counter: number; + signature: number[]; + signed_messages: number[]; + stream_counter: number; + [property: string]: any; +} + /** * This message reports the Age of the corrections used for the current Differential * solution. @@ -3506,6 +3520,14 @@ export class Convert { return JSON.stringify(uncast(value, r("MsgAcqSvProfile")), null, 2); } + public static toMsgAESCmacSignature(json: string): MsgAESCmacSignature { + return cast(JSON.parse(json), r("MsgAESCmacSignature")); + } + + public static msgAESCmacSignatureToJson(value: MsgAESCmacSignature): string { + return JSON.stringify(uncast(value, r("MsgAESCmacSignature")), null, 2); + } + public static toMsgAgeCorrections(json: string): MsgAgeCorrections { return cast(JSON.parse(json), r("MsgAgeCorrections")); } @@ -5293,6 +5315,14 @@ const typeMap: any = { { json: "time_spent", js: "time_spent", typ: 0 }, { json: "timestamp", js: "timestamp", typ: 0 }, ], "any"), + "MsgAESCmacSignature": o([ + { json: "certificate_id", js: "certificate_id", typ: a(0) }, + { json: "flags", js: "flags", typ: 0 }, + { json: "on_demand_counter", js: "on_demand_counter", typ: 0 }, + { json: "signature", js: "signature", typ: a(0) }, + { json: "signed_messages", js: "signed_messages", typ: a(0) }, + { json: "stream_counter", js: "stream_counter", typ: 0 }, + ], "any"), "MsgAgeCorrections": o([ { json: "age", js: "age", typ: 0 }, { json: "tow", js: "tow", typ: 0 },