blob: 0a1b368980b262df5d78fdd73bca8d821e3bebcc [file] [log] [blame]
/*
* Copyright (c) 2019 Google LLC
* Copyright (c) 2013-2017 Nest Labs, Inc.
* All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @file
* This file defines message descriptions for the messages in
* the software update profile.
*
* The profile has a client and server role. the basic protocol
* can be diagrammed as follows:
*
*
* | Server | | Client |
* ----------------------------------------
* ImageAnnounce--------------->
* <----------------------ImageQuery
* ImageQueryResponse---------->
* (Client downloads firmware image)
* <----------------------DownloadNotify
* NotifyResponse--------------->
* (Client updates its firmware)
* <----------------------UpdateNotify
* NotifyResponse--------------->
*
* where the image announce message is optional.
*
*/
#ifndef _SW_UPDATE_PROFILE_H
#define _SW_UPDATE_PROFILE_H
#include <Weave/Support/NLDLLUtil.h>
/**
* @namespace nl::Weave::Profiles::SoftwareUpdate
*
* @brief
* This namespace includes all interfaces within Weave for the
* Weave Software Update profile, which includes the
* corresponding, protocol of the same name.
*/
namespace nl {
namespace Weave {
namespace Profiles {
namespace SoftwareUpdate {
/**
* SoftwareUpdate Message types.
*/
// clang-format off
enum
{
kMsgType_ImageAnnounce = 0, /**< An optional unsolicited messsage, used by the server to announce availability of a software update. The message carries no payload. */
kMsgType_ImageQuery = 1, /**< A query message sent by the client to the server. Its format is defined with the ImageQuery class. */
kMsgType_ImageQueryResponse = 2, /**< A message generated in response to a successful image query message. Its format is defined by the ImageQueryResponse class. */
kMsgType_DownloadNotify = 3, /**< An optional message from the client to the server used to notify the server about the download status. Its payload is a nl::Weave::Profiles::StatusReporting::StatusReport with the additional status info drawn from @ref SoftwareUpdateStatusCodes.*/
kMsgType_NotifyResponse = 4, /**< A message generated in response to the download notify message. Its payload is a nl::Weave::Profiles::StatusReporting::StatusReport with the additional status info drawn from @ref SoftwareUpdateStatusCodes. */
kMsgType_UpdateNotify = 5, /**< An optional message from the client to the server used to communicate the final status of the update. Its payload is a nl::Weave::Profiles::StatusReporting::StatusReport with the additional status info drawn from @ref SoftwareUpdateStatusCodes. As the message is expected to be generated post actual update, it is sent on a new ExchangeContext and is treated as an unsolicited message on the server. */
kMsgType_ImageQueryStatus = 6, /**< A message generated in response to a failed image query message. Its payload is a nl::Weave::Profiles::StatusReporting::StatusReport with the additional status info drawn from @ref SoftwareUpdateStatusCodes. */
};
// clang-format on
/**
* @anchor SoftwareUpdateStatusCodes
* SoftwareUpdate profile-specific status codes.
*/
// clang-format off
enum
{
kStatus_NoUpdateAvailable = 0x0001, /**< server => client, indicates that an image query has been received and understood and that the server has no update for the client at this time. */
kStatus_UpdateFailed = 0x0010, /**< client => server, indicates that an attempt to install an image specified by the server has failed. */
kStatus_InvalidInstructions = 0x0050, /**< client => server, indicates that the client was unable to download an image because the download instructions contained in the ImageQueryResponse, i.e. URI, update scheme, update condition, were poorly formed or inconsistent. */
kStatus_DownloadFailed = 0x0051, /**< client => server, indicates that an attempted download failed.*/
kStatus_IntegrityCheckFailed = 0x0052, /**< client => server, indicates that an image was downloaded but it failed the subsequent integrity check.*/
kStatus_Abort = 0x0053, /**< server => client, indicates that the client should give up since the server is out of options. */
kStatus_Retry = 0x0091, /**< server => client, indicates that the client should submit another image query and restart/continue the update */
};
// clang-format on
/**
* Control flags for the control field of the ImageQuery frame
*/
enum
{
kFlag_PackageSpecPresent = 1, /**< Package specification is present in the ImageQuery. */
kFlag_LocaleSpecPresent = 2, /**< Locale specification is present in the ImageQuery. */
kFlag_TargetNodeIdPresent = 4, /**< Target node ID is present in the ImageQuery. */
};
/**
* Bitmasks for the optional update options field of the ImageQueryResponse.
*/
enum
{
kMask_UpdatePriority = 0x03, // 0b00000011
kMask_UpdateCondition = 0x1C, // 0b00011100
kMask_ReportStatus = 0x20, // 0b00100000
};
/**
* Shift offsets for the optional update options field of the ImageQueryResponse.
*/
enum
{
kOffset_UpdatePriority = 0,
kOffset_UpdateCondition = 2,
kOffset_ReportStatus = 5,
};
/**
* @anchor IntegrityTypes
* Integrity types supported by the SoftwareUpdate profile.
*
* The image query frame contains information about which integrity checking
* the client supports and the image query response contains an integrity type
* and value for the image that the client is being instructed to download and
* install. The supported types are:
*/
enum
{
kIntegrityType_SHA160 = 0, /**< 160-bit Secure Hash, (SHA-1), required. */
kIntegrityType_SHA256 = 1, /**< 256-bit Secure Hash (SHA-2). */
kIntegrityType_SHA512 = 2, /**< 512-bit, Secure Hash (SHA-2). */
kIntegrityType_Last = 3, /**< Number of valid elements in the enumeration */
};
/**
* Lengths, in bytes, for the integrity specification byte-strings.
*/
enum
{
kLength_SHA160 = 20,
kLength_SHA256 = 32,
kLength_SHA512 = 64,
};
/**
* @anchor UpdateSchemes
* Update schemes supported by the SofwareUpdate profile.
*
* Similarly to the supported integrity types, the image query contains
* information about which update schemes, i.e. download protocols, the client
* supports, and the response contains a value for indicating the update scheme
* to use in downloading the images. The supported schemes are:
*/
enum
{
kUpdateScheme_HTTP = 0, /**< HTTP shall be used as the download protocol. */
kUpdateScheme_HTTPS = 1, /**< HTTPS shall be used as the download protocol. */
kUpdateScheme_SFTP = 2, /**< SFTP shall be used as the download protocol. */
kUpdateScheme_BDX = 3, /**< Weave Bulk data transfer shall be used as the download protocol. */
kUpdateScheme_Last = 4, /**< Number of valid elements in the enumeration */
};
/**
* Data Element Tags for the SoftwareUpdate Profile
*/
enum
{
// ---- Top-level Tags ----
// Tag Type Element Type Disposition
// ----------------------------------------------
kTag_InstalledLocales = 0x00, // Fully-Qualified Array of strings Required
kTag_CertBodyId = 0x01, // Fully-Qualified Integer Required
kTag_WirelessRegDom = 0x02, // Fully-Qualified Integer Optional
kTag_SufficientBatterySWU = 0x03 // Fully-Qualified Bool Required
};
/**
* Class describing the ImageAnnounce message.
*
* Over the wire and on the air, the message consists of a bare Weave
* application header with profile ID 0x0000000C and message type 1. The
* structure provided here is not really used except as a placeholder.
*/
class ImageAnnounce
{
};
/**
* An auxiliary class to hold a list of integrity types as a part of the image query.
*
* A simple wrapper, sized to hold any subset of possible integrity types. In
* order to accomplish this task, its size is equal to the number of elements in
* the @ref IntegrityTypes. It is used to generate the list of supported
* integrity types in the ImageQuery message.
*/
class NL_DLL_EXPORT IntegrityTypeList
{
public:
// constructor
IntegrityTypeList();
// initializer
WEAVE_ERROR init(uint8_t, uint8_t *);
// packing and parsing
WEAVE_ERROR pack(MessageIterator &);
static WEAVE_ERROR parse(MessageIterator &, IntegrityTypeList &);
// comparison
bool operator ==(const IntegrityTypeList &) const;
uint8_t theLength; /**< Length of the supported element list. Length of 0 indicates an empty list */
uint8_t theList[kIntegrityType_Last]; /**< Container holding supported integrity types. It is sized equal to the number of elements in @ref
IntegrityTypes */
};
/**
* An auxiliary class to hold a list of update schemes as a part of the image query.
*
* A simple wrapper, sized to hold any subset of possible update schemes. In
* order to accomplish this task, its size is equal to the number of elements in
* the @ref UpdateSchemes is used to generate the list of supported
* update schemes in the ImageQuery message.
*/
class NL_DLL_EXPORT UpdateSchemeList
{
public:
// constructor
UpdateSchemeList();
// initializer
WEAVE_ERROR init(uint8_t, uint8_t *);
// packing and parsing
WEAVE_ERROR pack(MessageIterator &);
static WEAVE_ERROR parse(MessageIterator &, UpdateSchemeList &);
// comparison
bool operator ==(const UpdateSchemeList &) const;
uint8_t theLength; /**< Length of the supported element list. Length of 0 indicates an empty list */
uint8_t theList[kUpdateScheme_Last]; /**< Container holding supported update schemes. It is sized equal to the number of elements in @ref
UpdateSchemes */
};
/**
* An auxiliary class that representing a product specification.
*/
class NL_DLL_EXPORT ProductSpec
{
public:
// constructors
ProductSpec(uint16_t aVendor, uint16_t aProduct, uint16_t aRevision);
ProductSpec();
// comparison
bool operator ==(const ProductSpec &) const;
// data members
uint16_t vendorId; /**< Weave Vendor ID drawn from the Weave Vendor Identifier Registry. */
uint16_t productId; /**< A 16-bit product ID drawn from a vendor-managed namespace. */
uint16_t productRev; /**< A 16-bit product revision drawn from a vendor managed namespace. */
};
/**
* A class to support creation and decoding of image query messages.
*
* The image query frame has the following form over the wire
*
*
* Length | Field Name
* -------|------------
* 1 byte | frame control
* 6 bytes| product specification
* variable | version specification
* 2..4 bytes | integrity type list
* 2..5 bytes | update scheme list
* variable | locale specification (optional)
* 8 bytes | target node ID
* variable | vendor specific data (optional)
*
* where the frame control field has bit-fields as follows:
*
* Bit | Meaning
* ----|--------
* 0 | 1 - vendor-specific data present, 0 - not present
* 1 | 1 - locale specification present, 0 - not present
* 2 | 1 - target node id present, 0 - not present
* 3..7 | Reserved
*
* The ImageQuery, as a structure reads slightly differently from the in-flight
* representation. In particular, the version and locale are null-terminated
* c-strings (as opposed to (length, characters) tuples) and both of the optional
* items are represented as nullable pointers so there isn't a separate boolean
* to check.
*/
class NL_DLL_EXPORT ImageQuery
{
public:
// constructor
ImageQuery();
// initializer
WEAVE_ERROR init(ProductSpec & aProductSpec,
ReferencedString & aVersion, // 1 byte length
IntegrityTypeList & aTypeList, UpdateSchemeList & aSchemeList,
ReferencedString * aPackage = NULL, // 1 byte length
ReferencedString * aLocale = NULL, uint64_t aTargetNodeId = 0,
ReferencedTLVData * aMetaData = NULL); // 2 byte length
WEAVE_ERROR pack(PacketBuffer *);
static WEAVE_ERROR parse(PacketBuffer *, ImageQuery &);
// comparison
bool operator ==(const ImageQuery &) const;
// utility
void print(void);
// data members
ProductSpec productSpec; /**< Product specification describing the device that is making the image query. */
ReferencedString version; /**< A variable length UTF-8 string containing the vendor-specified software version of the device for
which the query is being made. Must be of length 32 or smaller. */
IntegrityTypeList integrityTypes; /**< Integrity types supported by the device. */
UpdateSchemeList updateSchemes; /**< Update schemes (download protocols) supported by the device. */
uint64_t targetNodeId; /**< An optional node id of the device for which the query is being made. The target node id field is
optional. If absent, the target node id for the query is implicitly the node that was the source of the image query message.
The target node id field is typically used in instances where the node that is the source of the IMAGE QUERY message is serving as a
software update proxy for another node. */
ReferencedString packageSpec; /**< A variable length UTF-8 string containing a vendor-specific package specification string. The
contents of the field describe the desired container type for the software image, such as ‘rpm’, ‘deb’,
‘tgz’, ‘elf’, etc. (NOTE: This field is unused in Nest implementations of the protocol) */
ReferencedString localeSpec; /**< A variable length UTF-8 string containing the POSIX locale in effect on the device for which
the image query is being made. The contents of the string must conform to the POSIX locale
identifier format, as specified in ISO/IEC 15897, e.g. en_AU.UTF-8 for Australian English.*/
ReferencedTLVData theMetaData; /**< The vendor-specific data field is variable in length and occupies the remainder of the Weave
message payload, beyond the fields described above. The field encodes vendor-specific
information about the device for which the query is being made. The vendor-specific data field
is optional. If present, the field has a form of anonymous TLV-encoded structure. The tags
presented within this structure shall be fully-qualified profile-specific tags. */
};
/**
* Update priorities
*/
enum UpdatePriority
{
Normal, /**< Update may be execute at clients discretion. */
Critical, /**< Update must be executed immediately. */
};
/**
* Conditions governing update policy
*/
enum UpdateCondition
{
IfUnmatched, /**< Download and install the image if the version specification in the response frame doesn't match the software
version currently installed. */
IfLater, /**< Download and install the image if the version specification in the response frame is later than the software
version currently installed. */
Unconditionally, /**< Download and install the image regardless of the currently running software version. */
OnOptIn /**< download and install the image on some trigger provided by an on-site user. */
};
/**
* An auxiliary class holding the integrity type and the actual hash of the software update image.
*
* The object holds the @ref IntegrityTypes field specifying the type of the
* hash, and the actual hash of the software update image. The length of the hash is
* fixed based on the type of the hash. The object is sized to hold the largest
* of the supported hashes.
*/
class NL_DLL_EXPORT IntegritySpec
{
public:
// constructor
IntegritySpec();
// initializer
WEAVE_ERROR init(uint8_t, uint8_t *);
// packing and parsing
WEAVE_ERROR pack(MessageIterator &);
static WEAVE_ERROR parse(MessageIterator &, IntegritySpec &);
// comparison
bool operator ==(const IntegritySpec &) const;
// data members
uint8_t type; /**< Type of the hash, value to be drawn from @ref IntegrityTypes */
uint8_t
value[64]; /**< A variable length sequence of bytes containing the integrity value for the software image identified by the
URI field. The integrity value is computed by applying the integrity function specified by the integrity type
to the contents of the software update image accessed at the URI specified above.  The integrity specification
allows the client to confirm that the image downloaded matches the image specified in this response.*/
};
/**
* A class to support creation and decoding of the image query response messages.
*
* The image query response message has the form:
*
* Length | Field Name
* -------| ----------
* variable | URI
* variable | Version specification
* variable | Integrity specification
* 1 byte | Update scheme
* 1 byte | Update options
*
* The format of the (optional) update options field is as follows:
*
* Bit | Meaning
* ----|--------
* 0..2 | Update priority
* 3..4 | Update condition
* 5 | Report status. When set, the client is requested to generate the optional DownloadNotify and UpdateNotify messages.
* 5..7 | Reserved
*
* The image query response is only sent in the case where the image query is
* processed successfully and produces an image to download. The message
* constitutes download instructions for the node the submitted the query. Note
* that in cases where the server fails to process the image query, it shall
* generate an image query status.
*/
class NL_DLL_EXPORT ImageQueryResponse
{
public:
// constructor
ImageQueryResponse();
// initializers
WEAVE_ERROR init(ReferencedString &, ReferencedString &, IntegritySpec &, uint8_t, UpdatePriority, UpdateCondition, bool);
// packing and parsing
WEAVE_ERROR pack(PacketBuffer *);
static WEAVE_ERROR parse(PacketBuffer *, ImageQueryResponse &);
// comparison
bool operator ==(const ImageQueryResponse &) const;
// utility
void print(void);
// data members
ReferencedString uri; /**< A variable length UTF-8 string containing the location of the software image. The contents of this
string must conform to the RFC 3986 specification.  For update schemes corresponding to a well defined
Internet Protocol (HTTP, HTTPS, SFTP), the scheme element of the URI MUST conform to the canonical URL
encoding for that protocol scheme. The string length must not exceed 65565 and the the string must fit
within a single Weave message, which may be subject to MTU limitations. */
ReferencedString versionSpec; /**< A variable length UTF-8 string containing a vendor-specific a software version
identification. The string length must not exceed 256 bytes. */
IntegritySpec integritySpec; /**< A field containing the integrity information (integrity type and a hash) for the software
update image. */
uint8_t updateScheme; /**< The update scheme to be used to download the software update image. Its value is drawn from @ref
UpdateSchemes. */
UpdatePriority updatePriority; /**< Instructions directing the device when to perform the software update. */
UpdateCondition updateCondition; /**< Instructions as to the conditions under which to proceed with software update. */
bool reportStatus; /**< Request to inform the server about the progress of software update via the optional DownloadNotify and
UpdateNotify messages. */
};
} // namespace SoftwareUpdate
} // namespace Profiles
} // namespace Weave
} // namespace nl
#endif // _SW_UPDATE_PROFILE_H