1 /* 2 * Copyright (c) 2018, 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 /** 30 * @file 31 * @brief 32 * This file defines the top-level functions for the OpenThread CoAP Secure implementation. 33 * 34 * @note 35 * The functions in this module require the build-time feature `OPENTHREAD_CONFIG_COAP_SECURE_API_ENABLE=1`. 36 * 37 * @note 38 * To enable cipher suite DTLS_PSK_WITH_AES_128_CCM_8, MBEDTLS_KEY_EXCHANGE_PSK_ENABLED 39 * must be enabled in mbedtls-config.h 40 * To enable cipher suite DTLS_ECDHE_ECDSA_WITH_AES_128_CCM_8, 41 * MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED must be enabled in mbedtls-config.h. 42 */ 43 44 #ifndef OPENTHREAD_COAP_SECURE_H_ 45 #define OPENTHREAD_COAP_SECURE_H_ 46 47 #include <stdint.h> 48 49 #include <openthread/coap.h> 50 51 #ifdef __cplusplus 52 extern "C" { 53 #endif 54 55 /** 56 * @addtogroup api-coap-secure 57 * 58 * @brief 59 * This module includes functions that control CoAP Secure (CoAP over DTLS) communication. 60 * 61 * The functions in this module are available when CoAP Secure API feature 62 * (`OPENTHREAD_CONFIG_COAP_SECURE_API_ENABLE`) is enabled. 63 * 64 * @{ 65 * 66 */ 67 68 #define OT_DEFAULT_COAP_SECURE_PORT 5684 ///< Default CoAP Secure port, as specified in RFC 7252 69 70 /** 71 * CoAP secure connection event types. 72 * 73 */ 74 typedef enum otCoapSecureConnectEvent 75 { 76 OT_COAP_SECURE_CONNECTED = 0, ///< Connection established 77 OT_COAP_SECURE_DISCONNECTED_PEER_CLOSED, ///< Disconnected by peer 78 OT_COAP_SECURE_DISCONNECTED_LOCAL_CLOSED, ///< Disconnected locally 79 OT_COAP_SECURE_DISCONNECTED_MAX_ATTEMPTS, ///< Disconnected due to reaching the max connection attempts 80 OT_COAP_SECURE_DISCONNECTED_ERROR, ///< Disconnected due to an error 81 } otCoapSecureConnectEvent; 82 83 /** 84 * Pointer is called when the DTLS connection state changes. 85 * 86 * @param[in] aEvent The connection event. 87 * @param[in] aContext A pointer to arbitrary context information. 88 * 89 */ 90 typedef void (*otHandleCoapSecureClientConnect)(otCoapSecureConnectEvent aEvent, void *aContext); 91 92 /** 93 * Callback function pointer to notify when the CoAP secure agent is automatically stopped due to reaching the maximum 94 * number of connection attempts. 95 * 96 * @param[in] aContext A pointer to arbitrary context information. 97 * 98 */ 99 typedef void (*otCoapSecureAutoStopCallback)(void *aContext); 100 101 /** 102 * Starts the CoAP Secure service. 103 * 104 * @param[in] aInstance A pointer to an OpenThread instance. 105 * @param[in] aPort The local UDP port to bind to. 106 * 107 * @retval OT_ERROR_NONE Successfully started the CoAP Secure server. 108 * 109 */ 110 otError otCoapSecureStart(otInstance *aInstance, uint16_t aPort); 111 112 /** 113 * Starts the CoAP secure service and sets the maximum number of allowed connection attempts before stopping the 114 * agent automatically. 115 * 116 * @param[in] aInstance A pointer to an OpenThread instance. 117 * @param[in] aPort The local UDP port to bind to. 118 * @param[in] aMaxAttempts Maximum number of allowed connection request attempts. Zero indicates no limit. 119 * @param[in] aCallback Callback to notify if max number of attempts has reached and agent is stopped. 120 * @param[in] aContext A pointer to arbitrary context to use with @p aCallback. 121 * 122 * @retval OT_ERROR_NONE Successfully started the CoAP agent. 123 * @retval OT_ERROR_ALREADY Already started. 124 * 125 */ 126 otError otCoapSecureStartWithMaxConnAttempts(otInstance *aInstance, 127 uint16_t aPort, 128 uint16_t aMaxAttempts, 129 otCoapSecureAutoStopCallback aCallback, 130 void *aContext); 131 132 /** 133 * Stops the CoAP Secure server. 134 * 135 * @param[in] aInstance A pointer to an OpenThread instance. 136 * 137 */ 138 void otCoapSecureStop(otInstance *aInstance); 139 140 /** 141 * Sets the Pre-Shared Key (PSK) and cipher suite 142 * DTLS_PSK_WITH_AES_128_CCM_8. 143 * 144 * @note This function requires the build-time feature `MBEDTLS_KEY_EXCHANGE_PSK_ENABLED` to be enabled. 145 * 146 * @param[in] aInstance A pointer to an OpenThread instance. 147 * @param[in] aPsk A pointer to the PSK. 148 * @param[in] aPskLength The PSK length. 149 * @param[in] aPskIdentity The Identity Name for the PSK. 150 * @param[in] aPskIdLength The PSK Identity Length. 151 * 152 */ 153 void otCoapSecureSetPsk(otInstance *aInstance, 154 const uint8_t *aPsk, 155 uint16_t aPskLength, 156 const uint8_t *aPskIdentity, 157 uint16_t aPskIdLength); 158 159 /** 160 * Returns the peer x509 certificate base64 encoded. 161 * 162 * @note This function requires the build-time features `MBEDTLS_BASE64_C` and 163 * `MBEDTLS_SSL_KEEP_PEER_CERTIFICATE` to be enabled. 164 * 165 * @param[in] aInstance A pointer to an OpenThread instance. 166 * @param[out] aPeerCert A pointer to the base64 encoded certificate buffer. 167 * @param[out] aCertLength The length of the base64 encoded peer certificate. 168 * @param[in] aCertBufferSize The buffer size of aPeerCert. 169 * 170 * @retval OT_ERROR_INVALID_STATE Not connected yet. 171 * @retval OT_ERROR_NONE Successfully get the peer certificate. 172 * @retval OT_ERROR_NO_BUFS Can't allocate memory for certificate. 173 * 174 */ 175 otError otCoapSecureGetPeerCertificateBase64(otInstance *aInstance, 176 unsigned char *aPeerCert, 177 size_t *aCertLength, 178 size_t aCertBufferSize); 179 180 /** 181 * Sets the authentication mode for the coap secure connection. 182 * 183 * Disable or enable the verification of peer certificate. 184 * Must be called before start. 185 * 186 * @param[in] aInstance A pointer to an OpenThread instance. 187 * @param[in] aVerifyPeerCertificate true, to verify the peer certificate. 188 * 189 */ 190 void otCoapSecureSetSslAuthMode(otInstance *aInstance, bool aVerifyPeerCertificate); 191 192 /** 193 * Sets the local device's X509 certificate with corresponding private key for 194 * DTLS session with DTLS_ECDHE_ECDSA_WITH_AES_128_CCM_8. 195 * 196 * @note This function requires `MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED=1`. 197 * 198 * @param[in] aInstance A pointer to an OpenThread instance. 199 * @param[in] aX509Cert A pointer to the PEM formatted X509 certificate. 200 * @param[in] aX509Length The length of certificate. 201 * @param[in] aPrivateKey A pointer to the PEM formatted private key. 202 * @param[in] aPrivateKeyLength The length of the private key. 203 * 204 */ 205 void otCoapSecureSetCertificate(otInstance *aInstance, 206 const uint8_t *aX509Cert, 207 uint32_t aX509Length, 208 const uint8_t *aPrivateKey, 209 uint32_t aPrivateKeyLength); 210 211 /** 212 * Sets the trusted top level CAs. It is needed for validating the 213 * certificate of the peer. 214 * 215 * DTLS mode "ECDHE ECDSA with AES 128 CCM 8" for Application CoAPS. 216 * 217 * @note This function requires `MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED=1`. 218 * 219 * @param[in] aInstance A pointer to an OpenThread instance. 220 * @param[in] aX509CaCertificateChain A pointer to the PEM formatted X509 CA chain. 221 * @param[in] aX509CaCertChainLength The length of chain. 222 * 223 */ 224 void otCoapSecureSetCaCertificateChain(otInstance *aInstance, 225 const uint8_t *aX509CaCertificateChain, 226 uint32_t aX509CaCertChainLength); 227 228 /** 229 * Initializes DTLS session with a peer. 230 * 231 * @param[in] aInstance A pointer to an OpenThread instance. 232 * @param[in] aSockAddr A pointer to the remote socket address. 233 * @param[in] aHandler A pointer to a function that will be called when the DTLS connection 234 * state changes. 235 * @param[in] aContext A pointer to arbitrary context information. 236 * 237 * @retval OT_ERROR_NONE Successfully started DTLS connection. 238 * 239 */ 240 otError otCoapSecureConnect(otInstance *aInstance, 241 const otSockAddr *aSockAddr, 242 otHandleCoapSecureClientConnect aHandler, 243 void *aContext); 244 245 /** 246 * Stops the DTLS connection. 247 * 248 * @param[in] aInstance A pointer to an OpenThread instance. 249 * 250 */ 251 void otCoapSecureDisconnect(otInstance *aInstance); 252 253 /** 254 * Indicates whether or not the DTLS session is connected. 255 * 256 * @param[in] aInstance A pointer to an OpenThread instance. 257 * 258 * @retval TRUE The DTLS session is connected. 259 * @retval FALSE The DTLS session is not connected. 260 * 261 */ 262 bool otCoapSecureIsConnected(otInstance *aInstance); 263 264 /** 265 * Indicates whether or not the DTLS session is active. 266 * 267 * @param[in] aInstance A pointer to an OpenThread instance. 268 * 269 * @retval TRUE If DTLS session is active. 270 * @retval FALSE If DTLS session is not active. 271 * 272 */ 273 bool otCoapSecureIsConnectionActive(otInstance *aInstance); 274 275 /** 276 * Indicates whether or not the DTLS session is closed. 277 * 278 * @param[in] aInstance A pointer to an OpenThread instance. 279 * 280 * @retval TRUE The DTLS session is closed. 281 * @retval FALSE The DTLS session is not closed. 282 * 283 */ 284 bool otCoapSecureIsClosed(otInstance *aInstance); 285 286 /** 287 * Sends a CoAP request block-wise over secure DTLS connection. 288 * 289 * Is available when OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE configuration 290 * is enabled. 291 * 292 * If a response for a request is expected, respective function and context information should be provided. 293 * If no response is expected, these arguments should be NULL pointers. 294 * If Message Id was not set in the header (equal to 0), this function will assign unique Message Id to the message. 295 * 296 * @param[in] aInstance A pointer to an OpenThread instance. 297 * @param[in] aMessage A reference to the message to send. 298 * @param[in] aHandler A function pointer that shall be called on response reception or time-out. 299 * @param[in] aContext A pointer to arbitrary context information. 300 * @param[in] aTransmitHook A function pointer that is called on Block1 response reception. 301 * @param[in] aReceiveHook A function pointer that is called on Block2 response reception. 302 * 303 * @retval OT_ERROR_NONE Successfully sent CoAP message. 304 * @retval OT_ERROR_NO_BUFS Failed to allocate retransmission data. 305 * @retval OT_ERROR_INVALID_STATE DTLS connection was not initialized. 306 * 307 */ 308 otError otCoapSecureSendRequestBlockWise(otInstance *aInstance, 309 otMessage *aMessage, 310 otCoapResponseHandler aHandler, 311 void *aContext, 312 otCoapBlockwiseTransmitHook aTransmitHook, 313 otCoapBlockwiseReceiveHook aReceiveHook); 314 315 /** 316 * Sends a CoAP request over secure DTLS connection. 317 * 318 * If a response for a request is expected, respective function and context information should be provided. 319 * If no response is expected, these arguments should be NULL pointers. 320 * If Message Id was not set in the header (equal to 0), this function will assign unique Message Id to the message. 321 * 322 * @param[in] aInstance A pointer to an OpenThread instance. 323 * @param[in] aMessage A reference to the message to send. 324 * @param[in] aHandler A function pointer that shall be called on response reception or time-out. 325 * @param[in] aContext A pointer to arbitrary context information. 326 * 327 * @retval OT_ERROR_NONE Successfully sent CoAP message. 328 * @retval OT_ERROR_NO_BUFS Failed to allocate retransmission data. 329 * @retval OT_ERROR_INVALID_STATE DTLS connection was not initialized. 330 * 331 */ 332 otError otCoapSecureSendRequest(otInstance *aInstance, 333 otMessage *aMessage, 334 otCoapResponseHandler aHandler, 335 void *aContext); 336 337 /** 338 * Adds a resource to the CoAP Secure server. 339 * 340 * @param[in] aInstance A pointer to an OpenThread instance. 341 * @param[in] aResource A pointer to the resource. 342 * 343 */ 344 void otCoapSecureAddResource(otInstance *aInstance, otCoapResource *aResource); 345 346 /** 347 * Removes a resource from the CoAP Secure server. 348 * 349 * @param[in] aInstance A pointer to an OpenThread instance. 350 * @param[in] aResource A pointer to the resource. 351 * 352 */ 353 void otCoapSecureRemoveResource(otInstance *aInstance, otCoapResource *aResource); 354 355 /** 356 * Adds a block-wise resource to the CoAP Secure server. 357 * 358 * @param[in] aInstance A pointer to an OpenThread instance. 359 * @param[in] aResource A pointer to the resource. 360 * 361 */ 362 void otCoapSecureAddBlockWiseResource(otInstance *aInstance, otCoapBlockwiseResource *aResource); 363 364 /** 365 * Removes a block-wise resource from the CoAP Secure server. 366 * 367 * @param[in] aInstance A pointer to an OpenThread instance. 368 * @param[in] aResource A pointer to the resource. 369 * 370 */ 371 void otCoapSecureRemoveBlockWiseResource(otInstance *aInstance, otCoapBlockwiseResource *aResource); 372 373 /** 374 * Sets the default handler for unhandled CoAP Secure requests. 375 * 376 * @param[in] aInstance A pointer to an OpenThread instance. 377 * @param[in] aHandler A function pointer that shall be called when an unhandled request arrives. 378 * @param[in] aContext A pointer to arbitrary context information. May be NULL if not used. 379 * 380 */ 381 void otCoapSecureSetDefaultHandler(otInstance *aInstance, otCoapRequestHandler aHandler, void *aContext); 382 383 /** 384 * Sets the connect event callback to indicate when 385 * a Client connection to the CoAP Secure server has changed. 386 * 387 * @param[in] aInstance A pointer to an OpenThread instance. 388 * @param[in] aHandler A pointer to a function that will be called once DTLS connection has changed. 389 * @param[in] aContext A pointer to arbitrary context information. May be NULL if not used. 390 * 391 */ 392 void otCoapSecureSetClientConnectEventCallback(otInstance *aInstance, 393 otHandleCoapSecureClientConnect aHandler, 394 void *aContext); 395 396 /** 397 * Sends a CoAP response block-wise from the CoAP Secure server. 398 * 399 * Is available when OPENTHREAD_CONFIG_COAP_BLOCKWISE_TRANSFER_ENABLE configuration 400 * is enabled. 401 * 402 * @param[in] aInstance A pointer to an OpenThread instance. 403 * @param[in] aMessage A pointer to the CoAP response to send. 404 * @param[in] aMessageInfo A pointer to the message info associated with @p aMessage. 405 * @param[in] aContext A pointer to arbitrary context information. May be NULL if not used. 406 * @param[in] aTransmitHook A function pointer that is called on Block1 request reception. 407 * 408 * @retval OT_ERROR_NONE Successfully enqueued the CoAP response message. 409 * @retval OT_ERROR_NO_BUFS Insufficient buffers available to send the CoAP response. 410 * 411 */ 412 otError otCoapSecureSendResponseBlockWise(otInstance *aInstance, 413 otMessage *aMessage, 414 const otMessageInfo *aMessageInfo, 415 void *aContext, 416 otCoapBlockwiseTransmitHook aTransmitHook); 417 418 /** 419 * Sends a CoAP response from the CoAP Secure server. 420 * 421 * @param[in] aInstance A pointer to an OpenThread instance. 422 * @param[in] aMessage A pointer to the CoAP response to send. 423 * @param[in] aMessageInfo A pointer to the message info associated with @p aMessage. 424 * 425 * @retval OT_ERROR_NONE Successfully enqueued the CoAP response message. 426 * @retval OT_ERROR_NO_BUFS Insufficient buffers available to send the CoAP response. 427 * 428 */ 429 otError otCoapSecureSendResponse(otInstance *aInstance, otMessage *aMessage, const otMessageInfo *aMessageInfo); 430 431 /** 432 * @} 433 * 434 */ 435 436 #ifdef __cplusplus 437 } // extern "C" 438 #endif 439 440 #endif /* OPENTHREAD_COAP_SECURE_H_ */ 441