• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *  Copyright (c) 2016, The OpenThread Authors.
3  *  All rights reserved.
4  *
5  *  Redistribution and use in source and binary forms, with or without
6  *  modification, are permitted provided that the following conditions are met:
7  *  1. Redistributions of source code must retain the above copyright
8  *     notice, this list of conditions and the following disclaimer.
9  *  2. Redistributions in binary form must reproduce the above copyright
10  *     notice, this list of conditions and the following disclaimer in the
11  *     documentation and/or other materials provided with the distribution.
12  *  3. Neither the name of the copyright holder nor the
13  *     names of its contributors may be used to endorse or promote products
14  *     derived from this software without specific prior written permission.
15  *
16  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17  *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20  *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21  *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22  *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23  *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24  *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25  *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26  *  POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 #include "coap_secure.hpp"
30 
31 #if OPENTHREAD_CONFIG_SECURE_TRANSPORT_ENABLE
32 
33 #include "instance/instance.hpp"
34 
35 /**
36  * @file
37  *   This file implements the secure CoAP session.
38  */
39 
40 namespace ot {
41 namespace Coap {
42 
43 RegisterLogModule("CoapSecure");
44 
SecureSession(Instance & aInstance,Dtls::Transport & aDtlsTransport)45 SecureSession::SecureSession(Instance &aInstance, Dtls::Transport &aDtlsTransport)
46     : CoapBase(aInstance, Transmit)
47     , Dtls::Session(aDtlsTransport)
48     , mTransmitTask(aInstance, HandleTransmitTask, this)
49 {
50     Dtls::Session::SetConnectCallback(HandleDtlsConnectEvent, this);
51     Dtls::Session::SetReceiveCallback(HandleDtlsReceive, this);
52 }
53 
Cleanup(void)54 void SecureSession::Cleanup(void)
55 {
56     ClearAllRequestsAndResponses();
57     mTransmitQueue.DequeueAndFreeAll();
58     mTransmitTask.Unpost();
59 }
60 
61 #if OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
62 
SendMessage(Message & aMessage,ResponseHandler aHandler,void * aContext,otCoapBlockwiseTransmitHook aTransmitHook,otCoapBlockwiseReceiveHook aReceiveHook)63 Error SecureSession::SendMessage(Message                    &aMessage,
64                                  ResponseHandler             aHandler,
65                                  void                       *aContext,
66                                  otCoapBlockwiseTransmitHook aTransmitHook,
67                                  otCoapBlockwiseReceiveHook  aReceiveHook)
68 {
69     return IsConnected() ? CoapBase::SendMessage(aMessage, GetMessageInfo(), TxParameters::GetDefault(), aHandler,
70                                                  aContext, aTransmitHook, aReceiveHook)
71                          : kErrorInvalidState;
72 }
73 
74 #else
75 
SendMessage(Message & aMessage,ResponseHandler aHandler,void * aContext)76 Error SecureSession::SendMessage(Message &aMessage, ResponseHandler aHandler, void *aContext)
77 {
78     return IsConnected() ? CoapBase::SendMessage(aMessage, GetMessageInfo(), aHandler, aContext) : kErrorInvalidState;
79 }
80 
81 #endif // OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE
82 
Transmit(CoapBase & aCoapBase,ot::Message & aMessage,const Ip6::MessageInfo & aMessageInfo)83 Error SecureSession::Transmit(CoapBase &aCoapBase, ot::Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
84 {
85     return static_cast<SecureSession &>(aCoapBase).Transmit(aMessage, aMessageInfo);
86 }
87 
Transmit(ot::Message & aMessage,const Ip6::MessageInfo & aMessageInfo)88 Error SecureSession::Transmit(ot::Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
89 {
90     OT_UNUSED_VARIABLE(aMessageInfo);
91 
92     Error error = kErrorNone;
93 
94     VerifyOrExit(!GetTransport().IsClosed(), error = kErrorInvalidState);
95 
96     mTransmitQueue.Enqueue(aMessage);
97     mTransmitTask.Post();
98 
99 exit:
100     return error;
101 }
102 
HandleDtlsConnectEvent(ConnectEvent aEvent,void * aContext)103 void SecureSession::HandleDtlsConnectEvent(ConnectEvent aEvent, void *aContext)
104 {
105     static_cast<SecureSession *>(aContext)->HandleDtlsConnectEvent(aEvent);
106 }
107 
HandleDtlsConnectEvent(ConnectEvent aEvent)108 void SecureSession::HandleDtlsConnectEvent(ConnectEvent aEvent)
109 {
110     if (aEvent != kConnected)
111     {
112         mTransmitQueue.DequeueAndFreeAll();
113         ClearAllRequestsAndResponses();
114     }
115 
116     mConnectCallback.InvokeIfSet(aEvent);
117 }
118 
HandleDtlsReceive(void * aContext,uint8_t * aBuf,uint16_t aLength)119 void SecureSession::HandleDtlsReceive(void *aContext, uint8_t *aBuf, uint16_t aLength)
120 {
121     static_cast<SecureSession *>(aContext)->HandleDtlsReceive(aBuf, aLength);
122 }
123 
HandleDtlsReceive(uint8_t * aBuf,uint16_t aLength)124 void SecureSession::HandleDtlsReceive(uint8_t *aBuf, uint16_t aLength)
125 {
126     ot::Message *message = nullptr;
127 
128     VerifyOrExit((message = Get<MessagePool>().Allocate(Message::kTypeIp6, Message::GetHelpDataReserved())) != nullptr);
129     SuccessOrExit(message->AppendBytes(aBuf, aLength));
130 
131     CoapBase::Receive(*message, GetMessageInfo());
132 
133 exit:
134     FreeMessage(message);
135 }
136 
HandleTransmitTask(Tasklet & aTasklet)137 void SecureSession::HandleTransmitTask(Tasklet &aTasklet)
138 {
139     static_cast<SecureSession *>(static_cast<TaskletContext &>(aTasklet).GetContext())->HandleTransmitTask();
140 }
141 
HandleTransmitTask(void)142 void SecureSession::HandleTransmitTask(void)
143 {
144     Error        error   = kErrorNone;
145     ot::Message *message = mTransmitQueue.GetHead();
146 
147     VerifyOrExit(message != nullptr);
148     mTransmitQueue.Dequeue(*message);
149 
150     if (mTransmitQueue.GetHead() != nullptr)
151     {
152         mTransmitTask.Post();
153     }
154 
155     error = Dtls::Session::Send(*message);
156 
157 exit:
158     FreeMessageOnError(message, error);
159 }
160 
161 #if OPENTHREAD_CONFIG_COAP_SECURE_API_ENABLE
162 
HandleDtlsAccept(void * aContext,const Ip6::MessageInfo & aMessageInfo)163 MeshCoP::SecureSession *ApplicationCoapSecure::HandleDtlsAccept(void *aContext, const Ip6::MessageInfo &aMessageInfo)
164 {
165     OT_UNUSED_VARIABLE(aMessageInfo);
166 
167     return static_cast<ApplicationCoapSecure *>(aContext)->HandleDtlsAccept();
168 }
169 
HandleDtlsAccept(void)170 SecureSession *ApplicationCoapSecure::HandleDtlsAccept(void)
171 {
172     return IsSessionInUse() ? nullptr : static_cast<SecureSession *>(this);
173 }
174 
175 #endif
176 
177 } // namespace Coap
178 } // namespace ot
179 
180 #endif // OPENTHREAD_CONFIG_SECURE_TRANSPORT_ENABLE
181