blob: c1e5465a8cc4aa50c311f8249ee9e7961c8ef4d5 [file] [log] [blame]
/*
*
* Copyright (c) 2019 Google LLC.
* 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 the Certificate Provisioning Protocol, used to
* get new Weave operational device certificate from the CA service.
*
*/
#ifndef WEAVECERTPROVISIONING_H_
#define WEAVECERTPROVISIONING_H_
#include <Weave/Core/WeaveCore.h>
/**
* @namespace nl::Weave::Profiles::Security::CertProvisioning
*
* @brief
* This namespace includes all interfaces within Weave for the
* Weave Certificate Provisioning protocol within the Weave
* security profile.
*/
namespace nl {
namespace Weave {
namespace Profiles {
namespace Security {
namespace CertProvisioning {
/**
* Abstract interface to which platform specific actions are delegated during
* Weave node operational authentication.
*/
class WeaveNodeOpAuthDelegate
{
public:
// ===== Abstract Interface methods
/**
* Encode Weave operational certificate for the local node.
*
* When invoked, the implementation should write a local node operational certificate.
* The operational certificate should then be written in the form of a WeaveCertificate
* structure to the supplied TLV writer using the specified tag.
*/
virtual WEAVE_ERROR EncodeOpCert(TLVWriter & writer, uint64_t tag) = 0;
/**
* Encode array of certificates related to the node operational certificate.
*
* When invoked, the implementation should write certificates related to local node
* operational certificate. The related certificates should then be written in the form
* of an array of WeaveCertificate structures to the supplied TLV writer using the specified tag.
*/
virtual WEAVE_ERROR EncodeOpRelatedCerts(TLVWriter & writer, uint64_t tag) = 0;
/**
* Generate and encode operational signature using local node's operational private key.
*
* When invoked, implementations must compute a signature on the given hash value
* using the node's operational private key. The generated signature should then
* be written in the form of a ECDSASignature structure to the supplied TLV writer
* using the specified tag.
*
* Note: in cases where the node's corresponding Elliptic Curve private key is held
* in a local buffer, the GenerateAndEncodeWeaveECDSASignature() utility function
* can be useful for implementing this method.
*/
virtual WEAVE_ERROR GenerateAndEncodeOpSig(const uint8_t * hash, uint8_t hashLen, TLVWriter & writer, uint64_t tag) = 0;
};
/**
* Abstract interface to which platform specific actions are delegated during
* Weave node manufacturer attestation.
*/
class WeaveNodeManufAttestDelegate
{
public:
// ===== Abstract Interface methods
/**
* Encode Weave manufacturer attestation information for the local node.
*
* When invoked, the implementation should write a structure containing information
* used for node's manufacturer attestation. The manufacturer attestation information
* should be written in the form of a TLV structure to the supplied TLV writer using
* the Security Profile specific tag.
*/
virtual WEAVE_ERROR EncodeMAInfo(TLVWriter & writer) = 0;
/**
* Generate and encode manufacturer attestation signature using local node's
* manufacturer attestation private key.
*
* When invoked, implementations must compute a signature on the given hash value
* using the node's manufacturer attestation private key.
*
* First, the enumerated value identifying the manufacturer attestation signature
* algorithm should be written in the form of unsiged integer to the supplied TLV
* writer using the following tag:
* -- kTag_GetCertReqMsg_ManufAttestSigAlgo
* Legal enumerated values are taken from the kOID_SigAlgo_* constant namespace.
*
* The generated signature should then be written in the form of a ECDSASignature,
* RSASignature, HMACSignature, or custom structure to the supplied TLV writer
* using one of the following tags:
* -- kTag_GetCertReqMsg_ManufAttestSig_ECDSA
* -- kTag_GetCertReqMsg_ManufAttestSig_RSA
* -- kTag_GetCertReqMsg_ManufAttestSig_HMAC
* -- custom security profile specific tag
*
* Note: in cases where the node's corresponding Elliptic Curve private key is held
* in a local buffer, the GenerateAndEncodeWeaveECDSASignature() utility function
* can be useful for implementing this method.
*/
virtual WEAVE_ERROR GenerateAndEncodeMASig(const uint8_t * data, uint16_t dataLen, TLVWriter & writer) = 0;
};
/**
* Implements the core logic of the Weave Certificate Provisioning protocol object.
*/
class NL_DLL_EXPORT WeaveCertProvEngine
{
public:
struct InEventParam;
struct OutEventParam;
enum State
{
kState_NotInitialized = 0, /**< The engine object is not initialized. */
kState_Idle = 1, /**< The engine object is idle. */
kState_PreparingBinding = 2, /**< The engine object is waiting for the binding to become ready. */
kState_RequestInProgress = 3, /**< A GetCertificateRequest message has been sent and the engine object is awaiting a response. */
};
enum EventType
{
kEvent_PrepareAuthorizeInfo = 1, /**< The application is requested to prepare the payload for the GetCertificateRequest. */
kEvent_ResponseReceived = 2, /**< A GetCertificateResponse message was received from the peer. */
kEvent_CommunicationError = 3, /**< A communication error occurred while sending a GetCertificateRequest or waiting for a response. */
};
enum
{
kReqType_NotSpecified = 0, /**< The Get Certificate request type is not specified. */
kReqType_GetInitialOpDeviceCert = 1, /**< The Get Certificate request type is to obtain initial operational certificatete. */
kReqType_RotateOpDeviceCert = 2, /**< The Get Certificate request type is to rotate the current operational certificatete. */
};
/**
* This function is the application callback that is invoked on Certificate Provisioning Engine API events.
*
* @param[in] appState A pointer to application-defined state information associated with the engine object.
* @param[in] eventType Event ID passed by the event callback.
* @param[in] inParam Reference of input event parameters passed by the event callback.
* @param[in] outParam Reference of output event parameters passed by the event callback.
*/
typedef void (* EventCallback)(void * appState, EventType eventType, const InEventParam & inParam, OutEventParam & outParam);
void * AppState; /**< A pointer to application-specific data. */
WeaveCertProvEngine(void);
WEAVE_ERROR Init(Binding * binding, WeaveNodeOpAuthDelegate * opAuthDelegate, WeaveNodeManufAttestDelegate * manufAttestDelegate, EventCallback eventCallback, void * appState = NULL);
void Shutdown(void);
WEAVE_ERROR StartCertificateProvisioning(uint8_t reqType, bool doManufAttest);
void AbortCertificateProvisioning(void);
State GetState(void) const;
uint8_t GetReqType(void) const;
Binding * GetBinding(void) const;
void SetBinding(Binding * binding);
WeaveNodeOpAuthDelegate * GetOpAuthDelegate(void) const;
void SetOpAuthDelegate(WeaveNodeOpAuthDelegate * opAuthDelegate);
WeaveNodeManufAttestDelegate * GetManufAttestDelegate(void) const;
void SetManufAttestDelegate(WeaveNodeManufAttestDelegate * manufAttestDelegate);
EventCallback GetEventCallback(void) const;
void SetEventCallback(EventCallback eventCallback);
WEAVE_ERROR GenerateGetCertificateRequest(PacketBuffer * msgBuf, uint8_t reqType, bool doManufAttest);
WEAVE_ERROR ProcessGetCertificateResponse(PacketBuffer * msgBuf);
private:
uint8_t mReqType;
bool mDoManufAttest;
Binding * mBinding;
WeaveNodeOpAuthDelegate *mOpAuthDelegate;
WeaveNodeManufAttestDelegate *mManufAttestDelegate;
EventCallback mEventCallback;
ExchangeContext * mEC;
State mState;
WEAVE_ERROR SendGetCertificateRequest(void);
void HandleRequestDone(void);
void DeliverCommunicationError(WEAVE_ERROR err);
static void HandleBindingEvent(void * const appState, const Binding::EventType eventType, const Binding::InEventParam & inParam,
Binding::OutEventParam & outParam);
static void HandleResponse(ExchangeContext * ec, const IPPacketInfo * pktInfo, const WeaveMessageInfo * msgInfo,
uint32_t profileId, uint8_t msgType, PacketBuffer * payload);
static void HandleResponseTimeout(ExchangeContext * ec);
#if WEAVE_CONFIG_ENABLE_RELIABLE_MESSAGING
static void HandleAckRcvd(ExchangeContext * ec, void * msgCtxt);
#endif // WEAVE_CONFIG_ENABLE_RELIABLE_MESSAGING
static void HandleSendError(ExchangeContext * ec, WEAVE_ERROR sendErr, void * msgCtxt);
static void HandleKeyError(ExchangeContext * ec, WEAVE_ERROR keyErr);
static void HandleConnectionClosed(ExchangeContext *ec, WeaveConnection *con, WEAVE_ERROR conErr);
};
/**
* Input parameters to Weave Certificate Provisioning API event.
*/
struct WeaveCertProvEngine::InEventParam
{
WeaveCertProvEngine * Source; /**< The WeaveCertProvEngine from which the API event originated. */
union
{
struct
{
TLVWriter * Writer; /**< A pointer to the TLV Writer object, where get certificate authorization
information should be encoded. */
} PrepareAuthorizeInfo;
struct
{
WEAVE_ERROR Reason; /**< The error code associated with the communication failure. */
StatusReport * RcvdStatusReport; /**< A pointer to the StatusReport object. Relevant if status report message received from the peer. */
} CommunicationError;
struct
{
bool ReplaceCert; /**< Boolean indicator of whether operational device certificate should be replaced. */
const uint8_t * Cert; /**< A pointer to the TLV encoded Weave operational certificate assigned by CA Service. */
uint16_t CertLen; /**< Length of the certificate received in the GetCertificateResponse message. */
const uint8_t * RelatedCerts; /**< A pointer to the TLV encoded list of certificate related to the operational certificate. */
uint16_t RelatedCertsLen; /**< Length of the related certificate list received in the GetCertificateResponse message. */
} ResponseReceived;
};
void Clear() { memset(this, 0, sizeof(*this)); }
};
/**
* Output parameters to Weave Certificate Provisioning API event.
*/
struct WeaveCertProvEngine::OutEventParam
{
union
{
struct
{
WEAVE_ERROR Error; /**< An error set by the application indicating that
an authorization info couldn't be prepared. */
} PrepareAuthorizeInfo;
struct
{
WEAVE_ERROR Error; /**< An error set by the application indicating that
response data couldn't be processed. */
} ResponseReceived;
};
void Clear() { memset(this, 0, sizeof(*this)); }
};
/*
* Inline Functions
*
* Documentation for these functions can be found at the end of the .cpp file.
*/
inline WeaveCertProvEngine::WeaveCertProvEngine(void)
{
}
inline void WeaveCertProvEngine::AbortCertificateProvisioning(void)
{
return HandleRequestDone();
}
inline WeaveCertProvEngine::State WeaveCertProvEngine::GetState(void) const
{
return mState;
}
inline uint8_t WeaveCertProvEngine::GetReqType(void) const
{
return mReqType;
}
inline Binding *WeaveCertProvEngine::GetBinding(void) const
{
return mBinding;
}
inline void WeaveCertProvEngine::SetBinding(Binding * binding)
{
mBinding = binding;
}
inline WeaveNodeOpAuthDelegate * WeaveCertProvEngine::GetOpAuthDelegate(void) const
{
return mOpAuthDelegate;
}
inline void WeaveCertProvEngine::SetOpAuthDelegate(WeaveNodeOpAuthDelegate * opAuthDelegate)
{
mOpAuthDelegate = opAuthDelegate;
}
inline WeaveNodeManufAttestDelegate * WeaveCertProvEngine::GetManufAttestDelegate(void) const
{
return mManufAttestDelegate;
}
inline void WeaveCertProvEngine::SetManufAttestDelegate(WeaveNodeManufAttestDelegate * manufAttestDelegate)
{
mManufAttestDelegate = manufAttestDelegate;
}
inline WeaveCertProvEngine::EventCallback WeaveCertProvEngine::GetEventCallback(void) const
{
return mEventCallback;
}
inline void WeaveCertProvEngine::SetEventCallback(WeaveCertProvEngine::EventCallback eventCallback)
{
mEventCallback = eventCallback;
}
} // namespace CertProvisioning
} // namespace Security
} // namespace Profiles
} // namespace Weave
} // namespace nl
#endif /* WEAVECERTPROVISIONING_H_ */