/src/openthread/src/core/meshcop/secure_transport.cpp
Line | Count | Source (jump to first uncovered line) |
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 | | /** |
30 | | * @file |
31 | | * This file implements the necessary hooks for mbedTLS. |
32 | | */ |
33 | | |
34 | | #include "secure_transport.hpp" |
35 | | |
36 | | #include <mbedtls/debug.h> |
37 | | #ifdef MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED |
38 | | #include <mbedtls/pem.h> |
39 | | #endif |
40 | | |
41 | | #include "instance/instance.hpp" |
42 | | |
43 | | #if OPENTHREAD_CONFIG_SECURE_TRANSPORT_ENABLE |
44 | | |
45 | | namespace ot { |
46 | | namespace MeshCoP { |
47 | | |
48 | | RegisterLogModule("SecTransport"); |
49 | | |
50 | | //--------------------------------------------------------------------------------------------------------------------- |
51 | | // SecureSession |
52 | | |
53 | | SecureSession::SecureSession(SecureTransport &aTransport) |
54 | 42.6k | : mTransport(aTransport) |
55 | 42.6k | { |
56 | 42.6k | Init(); |
57 | 42.6k | } |
58 | | |
59 | | void SecureSession::Init(void) |
60 | 44.6k | { |
61 | 44.6k | mTimerSet = false; |
62 | 44.6k | mIsServer = false; |
63 | 44.6k | mState = kStateDisconnected; |
64 | 44.6k | mMessageSubType = Message::kSubTypeNone; |
65 | 44.6k | mConnectEvent = kDisconnectedError; |
66 | 44.6k | mReceiveMessage = nullptr; |
67 | 44.6k | mMessageInfo.Clear(); |
68 | | |
69 | 44.6k | MarkAsNotUsed(); |
70 | 44.6k | ClearAllBytes(mSsl); |
71 | 44.6k | ClearAllBytes(mConf); |
72 | 44.6k | #if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_COOKIE_C) |
73 | 44.6k | ClearAllBytes(mCookieCtx); |
74 | 44.6k | #endif |
75 | 44.6k | } |
76 | | |
77 | | void SecureSession::FreeMbedtls(void) |
78 | 1.96k | { |
79 | 1.96k | #if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_COOKIE_C) |
80 | 1.96k | if (mTransport.mDatagramTransport) |
81 | 1.96k | { |
82 | 1.96k | mbedtls_ssl_cookie_free(&mCookieCtx); |
83 | 1.96k | } |
84 | 1.96k | #endif |
85 | 1.96k | #if OPENTHREAD_CONFIG_TLS_API_ENABLE && defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) |
86 | 1.96k | if (mTransport.mExtension != nullptr) |
87 | 0 | { |
88 | 0 | mTransport.mExtension->mEcdheEcdsaInfo.Free(); |
89 | 0 | } |
90 | 1.96k | #endif |
91 | 1.96k | mbedtls_ssl_config_free(&mConf); |
92 | 1.96k | mbedtls_ssl_free(&mSsl); |
93 | 1.96k | } |
94 | | |
95 | | void SecureSession::SetState(State aState) |
96 | 5.94k | { |
97 | 5.94k | VerifyOrExit(mState != aState); |
98 | | |
99 | 4.23k | LogInfo("Session state: %s -> %s", StateToString(mState), StateToString(aState)); |
100 | 4.23k | mState = aState; |
101 | | |
102 | 5.94k | exit: |
103 | 5.94k | return; |
104 | 4.23k | } |
105 | | |
106 | | Error SecureSession::Connect(const Ip6::SockAddr &aSockAddr) |
107 | 0 | { |
108 | 0 | Error error; |
109 | |
|
110 | 0 | VerifyOrExit(mTransport.mIsOpen, error = kErrorInvalidState); |
111 | 0 | VerifyOrExit(!IsSessionInUse(), error = kErrorInvalidState); |
112 | | |
113 | 0 | Init(); |
114 | 0 | mMessageInfo.SetPeerAddr(aSockAddr.GetAddress()); |
115 | 0 | mMessageInfo.SetPeerPort(aSockAddr.mPort); |
116 | |
|
117 | 0 | SuccessOrExit(error = Setup()); |
118 | | |
119 | 0 | mTransport.mSessions.Push(*this); |
120 | |
|
121 | 0 | exit: |
122 | 0 | return error; |
123 | 0 | } |
124 | | |
125 | | void SecureSession::Accept(Message &aMessage, const Ip6::MessageInfo &aMessageInfo) |
126 | 1.97k | { |
127 | 1.97k | mMessageInfo.SetPeerAddr(aMessageInfo.GetPeerAddr()); |
128 | 1.97k | mMessageInfo.SetPeerPort(aMessageInfo.GetPeerPort()); |
129 | 1.97k | mMessageInfo.SetIsHostInterface(aMessageInfo.IsHostInterface()); |
130 | 1.97k | mMessageInfo.SetSockAddr(aMessageInfo.GetSockAddr()); |
131 | 1.97k | mMessageInfo.SetSockPort(aMessageInfo.GetSockPort()); |
132 | | |
133 | 1.97k | mIsServer = true; |
134 | | |
135 | 1.97k | if (Setup() == kErrorNone) |
136 | 221 | { |
137 | 221 | HandleTransportReceive(aMessage); |
138 | 221 | } |
139 | 1.97k | } |
140 | | |
141 | | void SecureSession::HandleTransportReceive(Message &aMessage) |
142 | 542 | { |
143 | 542 | VerifyOrExit(!IsDisconnected()); |
144 | | |
145 | 250 | #ifdef MBEDTLS_SSL_SRV_C |
146 | 250 | if (IsConnecting()) |
147 | 237 | { |
148 | 237 | mbedtls_ssl_set_client_transport_id(&mSsl, mMessageInfo.GetPeerAddr().GetBytes(), sizeof(Ip6::Address)); |
149 | 237 | } |
150 | 250 | #endif |
151 | | |
152 | 250 | mReceiveMessage = &aMessage; |
153 | 250 | Process(); |
154 | 250 | mReceiveMessage = nullptr; |
155 | | |
156 | 542 | exit: |
157 | 542 | return; |
158 | 250 | } |
159 | | |
160 | | Error SecureSession::Setup(void) |
161 | 1.97k | { |
162 | 1.97k | Error error = kErrorNone; |
163 | 1.97k | int rval = 0; |
164 | | |
165 | 1.97k | OT_ASSERT(mTransport.mCipherSuite != SecureTransport::kUnspecifiedCipherSuite); |
166 | | |
167 | 1.97k | SetState(kStateInitializing); |
168 | | |
169 | 1.97k | if (mTransport.HasNoRemainingConnectionAttempts()) |
170 | 0 | { |
171 | 0 | mConnectEvent = kDisconnectedMaxAttempts; |
172 | 0 | error = kErrorNoBufs; |
173 | 0 | ExitNow(); |
174 | 0 | } |
175 | | |
176 | 1.97k | mTransport.DecremenetRemainingConnectionAttempts(); |
177 | | |
178 | | //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
179 | | // Setup the mbedtls_ssl_config `mConf`. |
180 | | |
181 | 1.97k | mbedtls_ssl_config_init(&mConf); |
182 | | |
183 | 1.97k | rval = mbedtls_ssl_config_defaults(&mConf, mIsServer ? MBEDTLS_SSL_IS_SERVER : MBEDTLS_SSL_IS_CLIENT, |
184 | 1.97k | mTransport.mDatagramTransport ? MBEDTLS_SSL_TRANSPORT_DATAGRAM |
185 | 1.97k | : MBEDTLS_SSL_TRANSPORT_STREAM, |
186 | 1.97k | MBEDTLS_SSL_PRESET_DEFAULT); |
187 | 1.97k | VerifyOrExit(rval == 0); |
188 | | |
189 | 1.97k | #if OPENTHREAD_CONFIG_TLS_API_ENABLE && defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) |
190 | 1.97k | if (mTransport.mVerifyPeerCertificate && |
191 | 1.97k | (mTransport.mCipherSuite == SecureTransport::kEcdheEcdsaWithAes128Ccm8 || |
192 | 1.97k | mTransport.mCipherSuite == SecureTransport::kEcdheEcdsaWithAes128GcmSha256)) |
193 | 0 | { |
194 | 0 | mbedtls_ssl_conf_authmode(&mConf, MBEDTLS_SSL_VERIFY_REQUIRED); |
195 | 0 | } |
196 | 1.97k | else |
197 | 1.97k | { |
198 | 1.97k | mbedtls_ssl_conf_authmode(&mConf, MBEDTLS_SSL_VERIFY_NONE); |
199 | 1.97k | } |
200 | 1.97k | #endif |
201 | | |
202 | 1.97k | mbedtls_ssl_conf_rng(&mConf, Crypto::MbedTls::CryptoSecurePrng, nullptr); |
203 | 1.97k | #if (MBEDTLS_VERSION_NUMBER >= 0x03020000) |
204 | 1.97k | mbedtls_ssl_conf_min_tls_version(&mConf, MBEDTLS_SSL_VERSION_TLS1_2); |
205 | 1.97k | mbedtls_ssl_conf_max_tls_version(&mConf, MBEDTLS_SSL_VERSION_TLS1_2); |
206 | | #else |
207 | | mbedtls_ssl_conf_min_version(&mConf, MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3); |
208 | | mbedtls_ssl_conf_max_version(&mConf, MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3); |
209 | | #endif |
210 | | |
211 | 1.97k | { |
212 | | // We use `kCipherSuites[mCipherSuite]` to look up the cipher |
213 | | // suites array to pass to `mbedtls_ssl_conf_ciphersuites()` |
214 | | // associated with `mCipherSuite`. We validate that the `enum` |
215 | | // values are correct and match the order in the `kCipherSuites[]` |
216 | | // array. |
217 | | |
218 | 1.97k | struct EnumCheck |
219 | 1.97k | { |
220 | 1.97k | InitEnumValidatorCounter(); |
221 | 1.97k | ValidateNextEnum(SecureTransport::kEcjpakeWithAes128Ccm8); |
222 | 1.97k | #if OPENTHREAD_CONFIG_TLS_API_ENABLE && defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) |
223 | 1.97k | ValidateNextEnum(SecureTransport::kPskWithAes128Ccm8); |
224 | 1.97k | #endif |
225 | 1.97k | #if OPENTHREAD_CONFIG_TLS_API_ENABLE && defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) |
226 | 1.97k | ValidateNextEnum(SecureTransport::kEcdheEcdsaWithAes128Ccm8); |
227 | 1.97k | ValidateNextEnum(SecureTransport::kEcdheEcdsaWithAes128GcmSha256); |
228 | 1.97k | #endif |
229 | 1.97k | }; |
230 | | |
231 | 1.97k | mbedtls_ssl_conf_ciphersuites(&mConf, SecureTransport::kCipherSuites[mTransport.mCipherSuite]); |
232 | 1.97k | } |
233 | | |
234 | 1.97k | if (mTransport.mCipherSuite == SecureTransport::kEcjpakeWithAes128Ccm8) |
235 | 1.97k | { |
236 | 1.97k | #if (MBEDTLS_VERSION_NUMBER >= 0x03010000) |
237 | 1.97k | mbedtls_ssl_conf_groups(&mConf, SecureTransport::kGroups); |
238 | | #else |
239 | | mbedtls_ssl_conf_curves(&mConf, SecureTransport::kCurves); |
240 | | #endif |
241 | 1.97k | #if defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) || defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) |
242 | 1.97k | #if (MBEDTLS_VERSION_NUMBER >= 0x03020000) |
243 | 1.97k | mbedtls_ssl_conf_sig_algs(&mConf, SecureTransport::kSignatures); |
244 | | #else |
245 | | mbedtls_ssl_conf_sig_hashes(&mConf, SecureTransport::kHashes); |
246 | | #endif |
247 | 1.97k | #endif |
248 | 1.97k | } |
249 | | |
250 | | #if (MBEDTLS_VERSION_NUMBER < 0x03000000) |
251 | | mbedtls_ssl_conf_export_keys_cb(&mConf, SecureTransport::HandleMbedtlsExportKeys, &mTransport); |
252 | | #endif |
253 | | |
254 | 1.97k | mbedtls_ssl_conf_handshake_timeout(&mConf, 8000, 60000); |
255 | 1.97k | mbedtls_ssl_conf_dbg(&mConf, SecureTransport::HandleMbedtlsDebug, &mTransport); |
256 | | |
257 | | //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
258 | | // Setup the `Extension` components. |
259 | | |
260 | 1.97k | #if OPENTHREAD_CONFIG_TLS_API_ENABLE |
261 | 1.97k | if (mTransport.mExtension != nullptr) |
262 | 0 | { |
263 | 0 | #if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) |
264 | 0 | mTransport.mExtension->mEcdheEcdsaInfo.Init(); |
265 | 0 | #endif |
266 | 0 | rval = mTransport.mExtension->SetApplicationSecureKeys(mConf); |
267 | 0 | VerifyOrExit(rval == 0); |
268 | 0 | } |
269 | 1.97k | #endif |
270 | | |
271 | | //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
272 | | // Setup the mbedtls_ssl_cookie_ctx `mCookieCtx`. |
273 | | |
274 | 1.97k | #if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_COOKIE_C) |
275 | 1.97k | if (mTransport.mDatagramTransport) |
276 | 1.97k | { |
277 | 1.97k | mbedtls_ssl_cookie_init(&mCookieCtx); |
278 | | |
279 | 1.97k | if (mIsServer) |
280 | 1.97k | { |
281 | 1.97k | rval = mbedtls_ssl_cookie_setup(&mCookieCtx, Crypto::MbedTls::CryptoSecurePrng, nullptr); |
282 | 1.97k | VerifyOrExit(rval == 0); |
283 | | |
284 | 1.97k | mbedtls_ssl_conf_dtls_cookies(&mConf, mbedtls_ssl_cookie_write, mbedtls_ssl_cookie_check, &mCookieCtx); |
285 | 1.97k | } |
286 | 1.97k | } |
287 | 1.97k | #endif |
288 | | |
289 | | //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
290 | | // Setup the mbedtls_ssl_context `mSsl`. |
291 | | |
292 | 1.97k | mbedtls_ssl_init(&mSsl); |
293 | | |
294 | 1.97k | rval = mbedtls_ssl_setup(&mSsl, &mConf); |
295 | 1.97k | VerifyOrExit(rval == 0); |
296 | | |
297 | 221 | mbedtls_ssl_set_bio(&mSsl, this, HandleMbedtlsTransmit, HandleMbedtlsReceive, /* RecvTimeoutFn */ nullptr); |
298 | | |
299 | 221 | if (mTransport.mDatagramTransport) |
300 | 221 | { |
301 | 221 | mbedtls_ssl_set_timer_cb(&mSsl, this, HandleMbedtlsSetTimer, HandleMbedtlsGetTimer); |
302 | 221 | } |
303 | | |
304 | 221 | #if (MBEDTLS_VERSION_NUMBER >= 0x03000000) |
305 | 221 | mbedtls_ssl_set_export_keys_cb(&mSsl, SecureTransport::HandleMbedtlsExportKeys, &mTransport); |
306 | 221 | #endif |
307 | | |
308 | 221 | if (mTransport.mCipherSuite == SecureTransport::kEcjpakeWithAes128Ccm8) |
309 | 221 | { |
310 | 221 | rval = mbedtls_ssl_set_hs_ecjpake_password(&mSsl, mTransport.mPsk, mTransport.mPskLength); |
311 | 221 | VerifyOrExit(rval == 0); |
312 | 221 | } |
313 | | |
314 | 221 | #if defined(MBEDTLS_X509_CRT_PARSE_C) |
315 | 221 | if (!mIsServer) |
316 | 0 | { |
317 | 0 | mbedtls_ssl_set_hostname(&mSsl, nullptr); |
318 | 0 | } |
319 | 221 | #endif |
320 | | |
321 | 221 | mReceiveMessage = nullptr; |
322 | 221 | mMessageSubType = Message::kSubTypeNone; |
323 | | |
324 | 221 | SetState(kStateConnecting); |
325 | | |
326 | 221 | Process(); |
327 | | |
328 | 1.97k | exit: |
329 | 1.97k | if (IsInitializing()) |
330 | 1.75k | { |
331 | 1.75k | error = (error == kErrorNone) ? Crypto::MbedTls::MapError(rval) : error; |
332 | | |
333 | 1.75k | SetState(kStateDisconnected); |
334 | 1.75k | FreeMbedtls(); |
335 | 1.75k | mTransport.mUpdateTask.Post(); |
336 | 1.75k | } |
337 | | |
338 | 1.97k | return error; |
339 | 221 | } |
340 | | |
341 | | void SecureSession::Disconnect(ConnectEvent aEvent) |
342 | 1.99k | { |
343 | 1.99k | VerifyOrExit(mTransport.mIsOpen); |
344 | 1.99k | VerifyOrExit(IsConnectingOrConnected()); |
345 | | |
346 | 206 | mbedtls_ssl_close_notify(&mSsl); |
347 | 206 | SetState(kStateDisconnecting); |
348 | 206 | mConnectEvent = aEvent; |
349 | | |
350 | 206 | mTimerSet = false; |
351 | 206 | mTimerFinish = TimerMilli::GetNow() + kGuardTimeNewConnectionMilli; |
352 | 206 | mTransport.mTimer.FireAtIfEarlier(mTimerFinish); |
353 | | |
354 | 206 | FreeMbedtls(); |
355 | | |
356 | 1.99k | exit: |
357 | 1.99k | return; |
358 | 206 | } |
359 | | |
360 | | Error SecureSession::Send(Message &aMessage) |
361 | 0 | { |
362 | 0 | Error error = kErrorNone; |
363 | 0 | uint16_t length = aMessage.GetLength(); |
364 | 0 | uint8_t buffer[kApplicationDataMaxLength]; |
365 | |
|
366 | 0 | VerifyOrExit(length <= sizeof(buffer), error = kErrorNoBufs); |
367 | | |
368 | 0 | mMessageSubType = aMessage.GetSubType(); |
369 | 0 | aMessage.ReadBytes(0, buffer, length); |
370 | |
|
371 | 0 | SuccessOrExit(error = Crypto::MbedTls::MapError(mbedtls_ssl_write(&mSsl, buffer, length))); |
372 | | |
373 | 0 | aMessage.Free(); |
374 | |
|
375 | 0 | exit: |
376 | 0 | return error; |
377 | 0 | } |
378 | | |
379 | | bool SecureSession::IsMbedtlsHandshakeOver(mbedtls_ssl_context *aSslContext) |
380 | 663 | { |
381 | 663 | return |
382 | 663 | #if (MBEDTLS_VERSION_NUMBER >= 0x03000000) |
383 | 663 | mbedtls_ssl_is_handshake_over(aSslContext); |
384 | | #else |
385 | | (aSslContext->MBEDTLS_PRIVATE(state) == MBEDTLS_SSL_HANDSHAKE_OVER); |
386 | | #endif |
387 | 663 | } |
388 | | |
389 | | int SecureSession::HandleMbedtlsTransmit(void *aContext, const unsigned char *aBuf, size_t aLength) |
390 | 202 | { |
391 | 202 | return static_cast<SecureSession *>(aContext)->HandleMbedtlsTransmit(aBuf, aLength); |
392 | 202 | } |
393 | | |
394 | | int SecureSession::HandleMbedtlsTransmit(const unsigned char *aBuf, size_t aLength) |
395 | 202 | { |
396 | 202 | Message::SubType msgSubType = mMessageSubType; |
397 | | |
398 | 202 | mMessageSubType = Message::kSubTypeNone; |
399 | | |
400 | 202 | return mTransport.Transmit(aBuf, aLength, mMessageInfo, msgSubType); |
401 | 202 | } |
402 | | |
403 | | int SecureSession::HandleMbedtlsReceive(void *aContext, unsigned char *aBuf, size_t aLength) |
404 | 458 | { |
405 | 458 | return static_cast<SecureSession *>(aContext)->HandleMbedtlsReceive(aBuf, aLength); |
406 | 458 | } |
407 | | |
408 | | int SecureSession::HandleMbedtlsReceive(unsigned char *aBuf, size_t aLength) |
409 | 458 | { |
410 | 458 | int rval = MBEDTLS_ERR_SSL_WANT_READ; |
411 | 458 | uint16_t readLength; |
412 | | |
413 | 458 | VerifyOrExit(mReceiveMessage != nullptr); |
414 | | |
415 | 237 | readLength = mReceiveMessage->ReadBytes(mReceiveMessage->GetOffset(), aBuf, static_cast<uint16_t>(aLength)); |
416 | 237 | VerifyOrExit(readLength > 0); |
417 | | |
418 | 205 | mReceiveMessage->MoveOffset(readLength); |
419 | 205 | rval = static_cast<int>(readLength); |
420 | | |
421 | 458 | exit: |
422 | 458 | return rval; |
423 | 205 | } |
424 | | |
425 | | int SecureSession::HandleMbedtlsGetTimer(void *aContext) |
426 | 458 | { |
427 | 458 | return static_cast<SecureSession *>(aContext)->HandleMbedtlsGetTimer(); |
428 | 458 | } |
429 | | |
430 | | int SecureSession::HandleMbedtlsGetTimer(void) |
431 | 458 | { |
432 | 458 | int rval = 0; |
433 | | |
434 | | // `mbedtls_ssl_get_timer_t` return values: |
435 | | // -1 if cancelled |
436 | | // 0 if none of the delays have passed, |
437 | | // 1 if only the intermediate delay has passed, |
438 | | // 2 if the final delay has passed. |
439 | | |
440 | 458 | if (!mTimerSet) |
441 | 458 | { |
442 | 458 | rval = -1; |
443 | 458 | } |
444 | 0 | else |
445 | 0 | { |
446 | 0 | TimeMilli now = TimerMilli::GetNow(); |
447 | |
|
448 | 0 | if (now >= mTimerFinish) |
449 | 0 | { |
450 | 0 | rval = 2; |
451 | 0 | } |
452 | 0 | else if (now >= mTimerIntermediate) |
453 | 0 | { |
454 | 0 | rval = 1; |
455 | 0 | } |
456 | 0 | } |
457 | | |
458 | 458 | return rval; |
459 | 458 | } |
460 | | |
461 | | void SecureSession::HandleMbedtlsSetTimer(void *aContext, uint32_t aIntermediate, uint32_t aFinish) |
462 | 221 | { |
463 | 221 | static_cast<SecureSession *>(aContext)->HandleMbedtlsSetTimer(aIntermediate, aFinish); |
464 | 221 | } |
465 | | |
466 | | void SecureSession::HandleMbedtlsSetTimer(uint32_t aIntermediate, uint32_t aFinish) |
467 | 221 | { |
468 | 221 | if (aFinish == 0) |
469 | 221 | { |
470 | 221 | mTimerSet = false; |
471 | 221 | } |
472 | 0 | else |
473 | 0 | { |
474 | 0 | TimeMilli now = TimerMilli::GetNow(); |
475 | |
|
476 | 0 | mTimerSet = true; |
477 | 0 | mTimerIntermediate = now + aIntermediate; |
478 | 0 | mTimerFinish = now + aFinish; |
479 | |
|
480 | 0 | mTransport.mTimer.FireAtIfEarlier(mTimerFinish); |
481 | 0 | } |
482 | 221 | } |
483 | | |
484 | | void SecureSession::HandleTimer(TimeMilli aNow) |
485 | 0 | { |
486 | 0 | if (IsConnectingOrConnected()) |
487 | 0 | { |
488 | 0 | VerifyOrExit(mTimerSet); |
489 | | |
490 | 0 | if (aNow < mTimerFinish) |
491 | 0 | { |
492 | 0 | mTransport.mTimer.FireAtIfEarlier(mTimerFinish); |
493 | 0 | ExitNow(); |
494 | 0 | } |
495 | | |
496 | 0 | Process(); |
497 | 0 | ExitNow(); |
498 | 0 | } |
499 | | |
500 | 0 | if (IsDisconnecting()) |
501 | 0 | { |
502 | 0 | if (aNow < mTimerFinish) |
503 | 0 | { |
504 | 0 | mTransport.mTimer.FireAtIfEarlier(mTimerFinish); |
505 | 0 | ExitNow(); |
506 | 0 | } |
507 | | |
508 | 0 | SetState(kStateDisconnected); |
509 | 0 | mTransport.mUpdateTask.Post(); |
510 | 0 | } |
511 | | |
512 | 0 | exit: |
513 | 0 | return; |
514 | 0 | } |
515 | | |
516 | | void SecureSession::Process(void) |
517 | 471 | { |
518 | 471 | uint8_t buf[kMaxContentLen]; |
519 | 471 | int rval; |
520 | 471 | ConnectEvent disconnectEvent; |
521 | 471 | bool shouldReset; |
522 | | |
523 | 471 | while (IsConnectingOrConnected()) |
524 | 458 | { |
525 | 458 | if (IsConnecting()) |
526 | 458 | { |
527 | 458 | rval = mbedtls_ssl_handshake(&mSsl); |
528 | | |
529 | 458 | if (IsMbedtlsHandshakeOver(&mSsl)) |
530 | 0 | { |
531 | 0 | SetState(kStateConnected); |
532 | 0 | mConnectEvent = kConnected; |
533 | 0 | mConnectedCallback.InvokeIfSet(mConnectEvent); |
534 | 0 | } |
535 | 458 | } |
536 | 0 | else |
537 | 0 | { |
538 | 0 | rval = mbedtls_ssl_read(&mSsl, buf, sizeof(buf)); |
539 | |
|
540 | 0 | if (rval > 0) |
541 | 0 | { |
542 | 0 | mReceiveCallback.InvokeIfSet(buf, static_cast<uint16_t>(rval)); |
543 | 0 | continue; |
544 | 0 | } |
545 | 0 | } |
546 | | |
547 | | // Check `rval` to determine if the connection should be |
548 | | // disconnected, reset, or if we should wait. |
549 | | |
550 | 458 | disconnectEvent = kConnected; |
551 | 458 | shouldReset = true; |
552 | | |
553 | 458 | switch (rval) |
554 | 458 | { |
555 | 0 | case 0: |
556 | 253 | case MBEDTLS_ERR_SSL_WANT_READ: |
557 | 253 | case MBEDTLS_ERR_SSL_WANT_WRITE: |
558 | 253 | shouldReset = false; |
559 | 253 | break; |
560 | | |
561 | 0 | case MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY: |
562 | 0 | disconnectEvent = kDisconnectedPeerClosed; |
563 | 0 | break; |
564 | | |
565 | 0 | case MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED: |
566 | 0 | break; |
567 | | |
568 | 0 | case MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE: |
569 | 0 | disconnectEvent = kDisconnectedError; |
570 | 0 | break; |
571 | | |
572 | 0 | case MBEDTLS_ERR_SSL_INVALID_MAC: |
573 | 0 | if (!IsMbedtlsHandshakeOver(&mSsl)) |
574 | 0 | { |
575 | 0 | mbedtls_ssl_send_alert_message(&mSsl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, |
576 | 0 | MBEDTLS_SSL_ALERT_MSG_BAD_RECORD_MAC); |
577 | 0 | disconnectEvent = kDisconnectedError; |
578 | 0 | } |
579 | 0 | break; |
580 | | |
581 | 205 | default: |
582 | 205 | if (!IsMbedtlsHandshakeOver(&mSsl)) |
583 | 205 | { |
584 | 205 | mbedtls_ssl_send_alert_message(&mSsl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, |
585 | 205 | MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE); |
586 | 205 | disconnectEvent = kDisconnectedError; |
587 | 205 | } |
588 | | |
589 | 205 | break; |
590 | 458 | } |
591 | | |
592 | 458 | if (disconnectEvent != kConnected) |
593 | 205 | { |
594 | 205 | Disconnect(disconnectEvent); |
595 | 205 | } |
596 | 253 | else if (shouldReset) |
597 | 0 | { |
598 | 0 | mbedtls_ssl_session_reset(&mSsl); |
599 | |
|
600 | 0 | if (mTransport.mCipherSuite == SecureTransport::kEcjpakeWithAes128Ccm8) |
601 | 0 | { |
602 | 0 | mbedtls_ssl_set_hs_ecjpake_password(&mSsl, mTransport.mPsk, mTransport.mPskLength); |
603 | 0 | } |
604 | 0 | } |
605 | | |
606 | 458 | break; // from `while()` loop |
607 | 458 | } |
608 | 471 | } |
609 | | |
610 | | #if OT_SHOULD_LOG_AT(OT_LOG_LEVEL_INFO) |
611 | | |
612 | | const char *SecureSession::StateToString(State aState) |
613 | | { |
614 | | static const char *const kStateStrings[] = { |
615 | | "Disconnected", // (0) kStateDisconnected |
616 | | "Initializing", // (1) kStateInitializing |
617 | | "Connecting", // (2) kStateConnecting |
618 | | "Connected", // (3) kStateConnected |
619 | | "Disconnecting", // (4) kStateDisconnecting |
620 | | }; |
621 | | |
622 | | struct EnumCheck |
623 | | { |
624 | | InitEnumValidatorCounter(); |
625 | | ValidateNextEnum(kStateDisconnected); |
626 | | ValidateNextEnum(kStateInitializing); |
627 | | ValidateNextEnum(kStateConnecting); |
628 | | ValidateNextEnum(kStateConnected); |
629 | | ValidateNextEnum(kStateDisconnecting); |
630 | | }; |
631 | | |
632 | | return kStateStrings[aState]; |
633 | | } |
634 | | |
635 | | #endif |
636 | | |
637 | | //--------------------------------------------------------------------------------------------------------------------- |
638 | | // SecureTransport |
639 | | |
640 | | #if (MBEDTLS_VERSION_NUMBER >= 0x03010000) |
641 | | const uint16_t SecureTransport::kGroups[] = {MBEDTLS_SSL_IANA_TLS_GROUP_SECP256R1, MBEDTLS_SSL_IANA_TLS_GROUP_NONE}; |
642 | | #else |
643 | | const mbedtls_ecp_group_id SecureTransport::kCurves[] = {MBEDTLS_ECP_DP_SECP256R1, MBEDTLS_ECP_DP_NONE}; |
644 | | #endif |
645 | | |
646 | | #if defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) || defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) |
647 | | #if (MBEDTLS_VERSION_NUMBER >= 0x03020000) |
648 | | const uint16_t SecureTransport::kSignatures[] = {MBEDTLS_TLS1_3_SIG_ECDSA_SECP256R1_SHA256, MBEDTLS_TLS1_3_SIG_NONE}; |
649 | | #else |
650 | | const int SecureTransport::kHashes[] = {MBEDTLS_MD_SHA256, MBEDTLS_MD_NONE}; |
651 | | #endif |
652 | | #endif |
653 | | |
654 | | const int SecureTransport::kCipherSuites[][2] = { |
655 | | /* kEcjpakeWithAes128Ccm8 */ {MBEDTLS_TLS_ECJPAKE_WITH_AES_128_CCM_8, 0}, |
656 | | #if OPENTHREAD_CONFIG_TLS_API_ENABLE && defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) |
657 | | /* kPskWithAes128Ccm8 */ {MBEDTLS_TLS_PSK_WITH_AES_128_CCM_8, 0}, |
658 | | #endif |
659 | | #if OPENTHREAD_CONFIG_TLS_API_ENABLE && defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) |
660 | | /* kEcdheEcdsaWithAes128Ccm8 */ {MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8, 0}, |
661 | | /* kEcdheEcdsaWithAes128GcmSha256 */ {MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 0}, |
662 | | #endif |
663 | | }; |
664 | | |
665 | | SecureTransport::SecureTransport(Instance &aInstance, LinkSecurityMode aLayerTwoSecurity, bool aDatagramTransport) |
666 | 63.9k | : mLayerTwoSecurity(aLayerTwoSecurity) |
667 | 63.9k | , mDatagramTransport(aDatagramTransport) |
668 | 63.9k | , mIsOpen(false) |
669 | 63.9k | , mIsClosing(false) |
670 | 63.9k | , mVerifyPeerCertificate(true) |
671 | 63.9k | , mCipherSuite(kUnspecifiedCipherSuite) |
672 | 63.9k | , mPskLength(0) |
673 | 63.9k | , mMaxConnectionAttempts(0) |
674 | 63.9k | , mRemainingConnectionAttempts(0) |
675 | 63.9k | , mSocket(aInstance, *this) |
676 | 63.9k | , mTimer(aInstance, HandleTimer, this) |
677 | 63.9k | , mUpdateTask(aInstance, HandleUpdateTask, this) |
678 | | #if OPENTHREAD_CONFIG_TLS_API_ENABLE |
679 | 63.9k | , mExtension(nullptr) |
680 | | #endif |
681 | 63.9k | { |
682 | 63.9k | ClearAllBytes(mPsk); |
683 | 63.9k | OT_UNUSED_VARIABLE(mVerifyPeerCertificate); |
684 | 63.9k | } |
685 | | |
686 | | Error SecureTransport::Open(Ip6::NetifIdentifier aNetifIdentifier) |
687 | 6.15k | { |
688 | 6.15k | Error error; |
689 | | |
690 | 6.15k | VerifyOrExit(!mIsOpen, error = kErrorAlready); |
691 | | |
692 | 5.66k | SuccessOrExit(error = mSocket.Open(aNetifIdentifier)); |
693 | 5.66k | mIsOpen = true; |
694 | 5.66k | mRemainingConnectionAttempts = mMaxConnectionAttempts; |
695 | | |
696 | 6.15k | exit: |
697 | 6.15k | return error; |
698 | 5.66k | } |
699 | | |
700 | | Error SecureTransport::SetMaxConnectionAttempts(uint16_t aMaxAttempts, AutoCloseCallback aCallback, void *aContext) |
701 | 0 | { |
702 | 0 | Error error = kErrorNone; |
703 | |
|
704 | 0 | VerifyOrExit(!mIsOpen, error = kErrorInvalidState); |
705 | | |
706 | 0 | mMaxConnectionAttempts = aMaxAttempts; |
707 | 0 | mAutoCloseCallback.Set(aCallback, aContext); |
708 | |
|
709 | 0 | exit: |
710 | 0 | return error; |
711 | 0 | } |
712 | | |
713 | | void SecureTransport::HandleReceive(Message &aMessage, const Ip6::MessageInfo &aMessageInfo) |
714 | 2.74k | { |
715 | 2.74k | SecureSession *session; |
716 | | |
717 | 2.74k | VerifyOrExit(mIsOpen); |
718 | | |
719 | 2.74k | session = mSessions.FindMatching(aMessageInfo); |
720 | | |
721 | 2.74k | if (session != nullptr) |
722 | 321 | { |
723 | 321 | session->HandleTransportReceive(aMessage); |
724 | 321 | ExitNow(); |
725 | 321 | } |
726 | | |
727 | | // A new connection request |
728 | | |
729 | 2.41k | VerifyOrExit(mAcceptCallback.IsSet()); |
730 | | |
731 | 2.41k | session = mAcceptCallback.Invoke(aMessageInfo); |
732 | 2.41k | VerifyOrExit(session != nullptr); |
733 | | |
734 | 1.97k | session->Init(); |
735 | 1.97k | mSessions.Push(*session); |
736 | | |
737 | 1.97k | session->Accept(aMessage, aMessageInfo); |
738 | | |
739 | 2.74k | exit: |
740 | 2.74k | return; |
741 | 1.97k | } |
742 | | |
743 | | Error SecureTransport::Bind(uint16_t aPort) |
744 | 5.66k | { |
745 | 5.66k | Error error; |
746 | | |
747 | 5.66k | VerifyOrExit(mIsOpen, error = kErrorInvalidState); |
748 | 5.66k | VerifyOrExit(!mTransportCallback.IsSet(), error = kErrorAlready); |
749 | | |
750 | 5.66k | VerifyOrExit(mSessions.IsEmpty(), error = kErrorInvalidState); |
751 | | |
752 | 5.66k | error = mSocket.Bind(aPort); |
753 | | |
754 | 5.66k | exit: |
755 | 5.66k | return error; |
756 | 5.66k | } |
757 | | |
758 | | Error SecureTransport::Bind(TransportCallback aCallback, void *aContext) |
759 | 0 | { |
760 | 0 | Error error = kErrorNone; |
761 | |
|
762 | 0 | VerifyOrExit(mIsOpen, error = kErrorInvalidState); |
763 | 0 | VerifyOrExit(!mSocket.IsBound(), error = kErrorAlready); |
764 | 0 | VerifyOrExit(!mTransportCallback.IsSet(), error = kErrorAlready); |
765 | | |
766 | 0 | VerifyOrExit(mSessions.IsEmpty(), error = kErrorInvalidState); |
767 | | |
768 | 0 | mTransportCallback.Set(aCallback, aContext); |
769 | |
|
770 | 0 | exit: |
771 | 0 | return error; |
772 | 0 | } |
773 | | |
774 | | void SecureTransport::Close(void) |
775 | 6.48k | { |
776 | 6.48k | VerifyOrExit(mIsOpen); |
777 | 5.27k | VerifyOrExit(!mIsClosing); |
778 | | |
779 | | // `mIsClosing` is used to protect against multiple |
780 | | // calls to `Close()` and re-entry. As the transport is closed, |
781 | | // all existing sessions are disconnected, which can trigger |
782 | | // connect and remove callbacks to be invoked. These callbacks |
783 | | // may call `Close()` again. |
784 | | |
785 | 5.27k | mIsClosing = true; |
786 | | |
787 | 5.27k | for (SecureSession &session : mSessions) |
788 | 1.78k | { |
789 | 1.78k | session.Disconnect(SecureSession::kDisconnectedLocalClosed); |
790 | 1.78k | session.SetState(SecureSession::kStateDisconnected); |
791 | 1.78k | } |
792 | | |
793 | 5.27k | RemoveDisconnectedSessions(); |
794 | | |
795 | 5.27k | mIsOpen = false; |
796 | 5.27k | mIsClosing = false; |
797 | 5.27k | mTransportCallback.Clear(); |
798 | 5.27k | IgnoreError(mSocket.Close()); |
799 | 5.27k | mTimer.Stop(); |
800 | | |
801 | 6.48k | exit: |
802 | 6.48k | return; |
803 | 5.27k | } |
804 | | |
805 | | void SecureTransport::RemoveDisconnectedSessions(void) |
806 | 5.27k | { |
807 | 5.27k | LinkedList<SecureSession> disconnectedSessions; |
808 | 5.27k | SecureSession *session; |
809 | | |
810 | 5.27k | mSessions.RemoveAllMatching(disconnectedSessions, SecureSession::kStateDisconnected); |
811 | | |
812 | 7.05k | while ((session = disconnectedSessions.Pop()) != nullptr) |
813 | 1.78k | { |
814 | 1.78k | session->mConnectedCallback.InvokeIfSet(session->mConnectEvent); |
815 | 1.78k | session->MarkAsNotUsed(); |
816 | 1.78k | session->mMessageInfo.Clear(); |
817 | 1.78k | mRemoveSessionCallback.InvokeIfSet(*session); |
818 | 1.78k | } |
819 | 5.27k | } |
820 | | |
821 | | void SecureTransport::DecremenetRemainingConnectionAttempts(void) |
822 | 1.97k | { |
823 | 1.97k | if (mRemainingConnectionAttempts > 0) |
824 | 0 | { |
825 | 0 | mRemainingConnectionAttempts--; |
826 | 0 | } |
827 | 1.97k | } |
828 | | |
829 | | bool SecureTransport::HasNoRemainingConnectionAttempts(void) const |
830 | 1.97k | { |
831 | 1.97k | return (mMaxConnectionAttempts > 0) && (mRemainingConnectionAttempts == 0); |
832 | 1.97k | } |
833 | | |
834 | | Error SecureTransport::SetPsk(const uint8_t *aPsk, uint8_t aPskLength) |
835 | 5.66k | { |
836 | 5.66k | Error error = kErrorNone; |
837 | | |
838 | 5.66k | VerifyOrExit(aPskLength <= sizeof(mPsk), error = kErrorInvalidArgs); |
839 | | |
840 | 5.66k | memcpy(mPsk, aPsk, aPskLength); |
841 | 5.66k | mPskLength = aPskLength; |
842 | 5.66k | mCipherSuite = kEcjpakeWithAes128Ccm8; |
843 | | |
844 | 5.66k | exit: |
845 | 5.66k | return error; |
846 | 5.66k | } |
847 | | |
848 | | void SecureTransport::SetPsk(const JoinerPskd &aPskd) |
849 | 5.66k | { |
850 | 5.66k | static_assert(JoinerPskd::kMaxLength <= kPskMaxLength, "The max DTLS PSK length is smaller than joiner PSKd"); |
851 | | |
852 | 5.66k | IgnoreError(SetPsk(aPskd.GetBytes(), aPskd.GetLength())); |
853 | 5.66k | } |
854 | | |
855 | | int SecureTransport::Transmit(const unsigned char *aBuf, |
856 | | size_t aLength, |
857 | | const Ip6::MessageInfo &aMessageInfo, |
858 | | Message::SubType aMessageSubType) |
859 | 202 | { |
860 | 202 | Error error = kErrorNone; |
861 | 202 | Message *message = mSocket.NewMessage(); |
862 | 202 | int rval; |
863 | | |
864 | 202 | VerifyOrExit(message != nullptr, error = kErrorNoBufs); |
865 | 202 | message->SetSubType(aMessageSubType); |
866 | 202 | message->SetLinkSecurityEnabled(mLayerTwoSecurity); |
867 | | |
868 | 202 | SuccessOrExit(error = message->AppendBytes(aBuf, static_cast<uint16_t>(aLength))); |
869 | | |
870 | 202 | if (mTransportCallback.IsSet()) |
871 | 0 | { |
872 | 0 | error = mTransportCallback.Invoke(*message, aMessageInfo); |
873 | 0 | } |
874 | 202 | else |
875 | 202 | { |
876 | 202 | error = mSocket.SendTo(*message, aMessageInfo); |
877 | 202 | } |
878 | | |
879 | 202 | exit: |
880 | 202 | FreeMessageOnError(message, error); |
881 | | |
882 | 202 | switch (error) |
883 | 202 | { |
884 | 193 | case kErrorNone: |
885 | 193 | rval = static_cast<int>(aLength); |
886 | 193 | break; |
887 | | |
888 | 0 | case kErrorNoBufs: |
889 | 0 | rval = MBEDTLS_ERR_SSL_WANT_WRITE; |
890 | 0 | break; |
891 | | |
892 | 9 | default: |
893 | 9 | LogWarnOnError(error, "HandleMbedtlsTransmit"); |
894 | 9 | rval = MBEDTLS_ERR_NET_SEND_FAILED; |
895 | 9 | break; |
896 | 202 | } |
897 | | |
898 | 202 | return rval; |
899 | 202 | } |
900 | | |
901 | | #if (MBEDTLS_VERSION_NUMBER >= 0x03000000) |
902 | | |
903 | | void SecureTransport::HandleMbedtlsExportKeys(void *aContext, |
904 | | mbedtls_ssl_key_export_type aType, |
905 | | const unsigned char *aMasterSecret, |
906 | | size_t aMasterSecretLen, |
907 | | const unsigned char aClientRandom[32], |
908 | | const unsigned char aServerRandom[32], |
909 | | mbedtls_tls_prf_types aTlsPrfType) |
910 | 0 | { |
911 | 0 | static_cast<SecureTransport *>(aContext)->HandleMbedtlsExportKeys(aType, aMasterSecret, aMasterSecretLen, |
912 | 0 | aClientRandom, aServerRandom, aTlsPrfType); |
913 | 0 | } |
914 | | |
915 | | void SecureTransport::HandleMbedtlsExportKeys(mbedtls_ssl_key_export_type aType, |
916 | | const unsigned char *aMasterSecret, |
917 | | size_t aMasterSecretLen, |
918 | | const unsigned char aClientRandom[32], |
919 | | const unsigned char aServerRandom[32], |
920 | | mbedtls_tls_prf_types aTlsPrfType) |
921 | 0 | { |
922 | 0 | Crypto::Sha256::Hash kek; |
923 | 0 | Crypto::Sha256 sha256; |
924 | 0 | unsigned char keyBlock[kSecureTransportKeyBlockSize]; |
925 | 0 | unsigned char randBytes[2 * kSecureTransportRandomBufferSize]; |
926 | |
|
927 | 0 | VerifyOrExit(mCipherSuite == kEcjpakeWithAes128Ccm8); |
928 | 0 | VerifyOrExit(aType == MBEDTLS_SSL_KEY_EXPORT_TLS12_MASTER_SECRET); |
929 | | |
930 | 0 | memcpy(randBytes, aServerRandom, kSecureTransportRandomBufferSize); |
931 | 0 | memcpy(randBytes + kSecureTransportRandomBufferSize, aClientRandom, kSecureTransportRandomBufferSize); |
932 | | |
933 | | // Retrieve the Key block from Master secret |
934 | 0 | mbedtls_ssl_tls_prf(aTlsPrfType, aMasterSecret, aMasterSecretLen, "key expansion", randBytes, sizeof(randBytes), |
935 | 0 | keyBlock, sizeof(keyBlock)); |
936 | |
|
937 | 0 | sha256.Start(); |
938 | 0 | sha256.Update(keyBlock, kSecureTransportKeyBlockSize); |
939 | 0 | sha256.Finish(kek); |
940 | |
|
941 | 0 | mTimer.Get<KeyManager>().SetKek(kek.GetBytes()); |
942 | |
|
943 | 0 | exit: |
944 | 0 | return; |
945 | 0 | } |
946 | | |
947 | | #else |
948 | | |
949 | | int SecureTransport::HandleMbedtlsExportKeys(void *aContext, |
950 | | const unsigned char *aMasterSecret, |
951 | | const unsigned char *aKeyBlock, |
952 | | size_t aMacLength, |
953 | | size_t aKeyLength, |
954 | | size_t aIvLength) |
955 | | { |
956 | | return static_cast<SecureTransport *>(aContext)->HandleMbedtlsExportKeys(aMasterSecret, aKeyBlock, aMacLength, |
957 | | aKeyLength, aIvLength); |
958 | | } |
959 | | |
960 | | int SecureTransport::HandleMbedtlsExportKeys(const unsigned char *aMasterSecret, |
961 | | const unsigned char *aKeyBlock, |
962 | | size_t aMacLength, |
963 | | size_t aKeyLength, |
964 | | size_t aIvLength) |
965 | | { |
966 | | OT_UNUSED_VARIABLE(aMasterSecret); |
967 | | |
968 | | Crypto::Sha256::Hash kek; |
969 | | Crypto::Sha256 sha256; |
970 | | |
971 | | VerifyOrExit(mCipherSuite == kEcjpakeWithAes128Ccm8); |
972 | | |
973 | | sha256.Start(); |
974 | | sha256.Update(aKeyBlock, 2 * static_cast<uint16_t>(aMacLength + aKeyLength + aIvLength)); |
975 | | sha256.Finish(kek); |
976 | | |
977 | | mTimer.Get<KeyManager>().SetKek(kek.GetBytes()); |
978 | | |
979 | | exit: |
980 | | return 0; |
981 | | } |
982 | | |
983 | | #endif // (MBEDTLS_VERSION_NUMBER >= 0x03000000) |
984 | | |
985 | | void SecureTransport::HandleUpdateTask(Tasklet &aTasklet) |
986 | 0 | { |
987 | 0 | static_cast<SecureTransport *>(static_cast<TaskletContext &>(aTasklet).GetContext())->HandleUpdateTask(); |
988 | 0 | } |
989 | | |
990 | | void SecureTransport::HandleUpdateTask(void) |
991 | 0 | { |
992 | 0 | RemoveDisconnectedSessions(); |
993 | |
|
994 | 0 | if (mSessions.IsEmpty() && HasNoRemainingConnectionAttempts()) |
995 | 0 | { |
996 | 0 | Close(); |
997 | 0 | mAutoCloseCallback.InvokeIfSet(); |
998 | 0 | } |
999 | 0 | } |
1000 | | |
1001 | | void SecureTransport::HandleTimer(Timer &aTimer) |
1002 | 0 | { |
1003 | 0 | static_cast<SecureTransport *>(static_cast<TimerMilliContext &>(aTimer).GetContext())->HandleTimer(); |
1004 | 0 | } |
1005 | | |
1006 | | void SecureTransport::HandleTimer(void) |
1007 | 0 | { |
1008 | 0 | TimeMilli now = TimerMilli::GetNow(); |
1009 | |
|
1010 | 0 | VerifyOrExit(mIsOpen); |
1011 | | |
1012 | 0 | for (SecureSession &session : mSessions) |
1013 | 0 | { |
1014 | 0 | session.HandleTimer(now); |
1015 | 0 | } |
1016 | |
|
1017 | 0 | exit: |
1018 | 0 | return; |
1019 | 0 | } |
1020 | | |
1021 | | void SecureTransport::HandleMbedtlsDebug(void *aContext, int aLevel, const char *aFile, int aLine, const char *aStr) |
1022 | 0 | { |
1023 | 0 | static_cast<SecureTransport *>(aContext)->HandleMbedtlsDebug(aLevel, aFile, aLine, aStr); |
1024 | 0 | } |
1025 | | |
1026 | | void SecureTransport::HandleMbedtlsDebug(int aLevel, const char *aFile, int aLine, const char *aStr) |
1027 | 0 | { |
1028 | 0 | LogLevel logLevel = kLogLevelDebg; |
1029 | |
|
1030 | 0 | switch (aLevel) |
1031 | 0 | { |
1032 | 0 | case 1: |
1033 | 0 | logLevel = kLogLevelCrit; |
1034 | 0 | break; |
1035 | | |
1036 | 0 | case 2: |
1037 | 0 | logLevel = kLogLevelWarn; |
1038 | 0 | break; |
1039 | | |
1040 | 0 | case 3: |
1041 | 0 | logLevel = kLogLevelInfo; |
1042 | 0 | break; |
1043 | | |
1044 | 0 | case 4: |
1045 | 0 | default: |
1046 | 0 | break; |
1047 | 0 | } |
1048 | | |
1049 | 0 | LogAt(logLevel, "[%u] %s", mSocket.GetSockName().mPort, aStr); |
1050 | |
|
1051 | 0 | OT_UNUSED_VARIABLE(aStr); |
1052 | 0 | OT_UNUSED_VARIABLE(aFile); |
1053 | 0 | OT_UNUSED_VARIABLE(aLine); |
1054 | 0 | OT_UNUSED_VARIABLE(logLevel); |
1055 | 0 | } |
1056 | | |
1057 | | //--------------------------------------------------------------------------------------------------------------------- |
1058 | | // SecureTransport::Extension |
1059 | | |
1060 | | #if OPENTHREAD_CONFIG_TLS_API_ENABLE |
1061 | | |
1062 | | int SecureTransport::Extension::SetApplicationSecureKeys(mbedtls_ssl_config &aConfig) |
1063 | 0 | { |
1064 | 0 | int rval = 0; |
1065 | |
|
1066 | 0 | switch (mSecureTransport.mCipherSuite) |
1067 | 0 | { |
1068 | 0 | case kEcjpakeWithAes128Ccm8: |
1069 | | // PSK will be set on `mbedtls_ssl_context` when set up. |
1070 | 0 | break; |
1071 | | |
1072 | 0 | #ifdef MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED |
1073 | 0 | case kEcdheEcdsaWithAes128Ccm8: |
1074 | 0 | case kEcdheEcdsaWithAes128GcmSha256: |
1075 | 0 | rval = mEcdheEcdsaInfo.SetSecureKeys(aConfig); |
1076 | 0 | VerifyOrExit(rval == 0); |
1077 | 0 | break; |
1078 | 0 | #endif |
1079 | | |
1080 | 0 | #ifdef MBEDTLS_KEY_EXCHANGE_PSK_ENABLED |
1081 | 0 | case kPskWithAes128Ccm8: |
1082 | 0 | rval = mPskInfo.SetSecureKeys(aConfig); |
1083 | 0 | VerifyOrExit(rval == 0); |
1084 | 0 | break; |
1085 | 0 | #endif |
1086 | | |
1087 | 0 | default: |
1088 | 0 | LogCrit("Application Coap Secure: Not supported cipher."); |
1089 | 0 | rval = MBEDTLS_ERR_SSL_BAD_INPUT_DATA; |
1090 | 0 | ExitNow(); |
1091 | 0 | } |
1092 | | |
1093 | 0 | exit: |
1094 | 0 | return rval; |
1095 | 0 | } |
1096 | | |
1097 | | #ifdef MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED |
1098 | | |
1099 | | void SecureTransport::Extension::EcdheEcdsaInfo::Init(void) |
1100 | 0 | { |
1101 | 0 | mbedtls_x509_crt_init(&mCaChain); |
1102 | 0 | mbedtls_x509_crt_init(&mOwnCert); |
1103 | 0 | mbedtls_pk_init(&mPrivateKey); |
1104 | 0 | } |
1105 | | |
1106 | | void SecureTransport::Extension::EcdheEcdsaInfo::Free(void) |
1107 | 0 | { |
1108 | 0 | mbedtls_x509_crt_free(&mCaChain); |
1109 | 0 | mbedtls_x509_crt_free(&mOwnCert); |
1110 | 0 | mbedtls_pk_free(&mPrivateKey); |
1111 | 0 | } |
1112 | | |
1113 | | int SecureTransport::Extension::EcdheEcdsaInfo::SetSecureKeys(mbedtls_ssl_config &aConfig) |
1114 | 0 | { |
1115 | 0 | int rval = 0; |
1116 | |
|
1117 | 0 | if (mCaChainSrc != nullptr) |
1118 | 0 | { |
1119 | 0 | rval = mbedtls_x509_crt_parse(&mCaChain, static_cast<const unsigned char *>(mCaChainSrc), |
1120 | 0 | static_cast<size_t>(mCaChainLength)); |
1121 | 0 | VerifyOrExit(rval == 0); |
1122 | 0 | mbedtls_ssl_conf_ca_chain(&aConfig, &mCaChain, nullptr); |
1123 | 0 | } |
1124 | | |
1125 | 0 | if (mOwnCertSrc != nullptr && mPrivateKeySrc != nullptr) |
1126 | 0 | { |
1127 | 0 | rval = mbedtls_x509_crt_parse(&mOwnCert, static_cast<const unsigned char *>(mOwnCertSrc), |
1128 | 0 | static_cast<size_t>(mOwnCertLength)); |
1129 | 0 | VerifyOrExit(rval == 0); |
1130 | | |
1131 | 0 | #if (MBEDTLS_VERSION_NUMBER >= 0x03000000) |
1132 | 0 | rval = mbedtls_pk_parse_key(&mPrivateKey, static_cast<const unsigned char *>(mPrivateKeySrc), |
1133 | 0 | static_cast<size_t>(mPrivateKeyLength), nullptr, 0, |
1134 | 0 | Crypto::MbedTls::CryptoSecurePrng, nullptr); |
1135 | | #else |
1136 | | rval = mbedtls_pk_parse_key(&mPrivateKey, static_cast<const unsigned char *>(mPrivateKeySrc), |
1137 | | static_cast<size_t>(mPrivateKeyLength), nullptr, 0); |
1138 | | #endif |
1139 | 0 | VerifyOrExit(rval == 0); |
1140 | 0 | rval = mbedtls_ssl_conf_own_cert(&aConfig, &mOwnCert, &mPrivateKey); |
1141 | 0 | } |
1142 | | |
1143 | 0 | exit: |
1144 | 0 | return rval; |
1145 | 0 | } |
1146 | | |
1147 | | void SecureTransport::Extension::SetCertificate(const uint8_t *aX509Certificate, |
1148 | | uint32_t aX509CertLength, |
1149 | | const uint8_t *aPrivateKey, |
1150 | | uint32_t aPrivateKeyLength) |
1151 | 0 | { |
1152 | 0 | OT_ASSERT(aX509CertLength > 0); |
1153 | 0 | OT_ASSERT(aX509Certificate != nullptr); |
1154 | | |
1155 | 0 | OT_ASSERT(aPrivateKeyLength > 0); |
1156 | 0 | OT_ASSERT(aPrivateKey != nullptr); |
1157 | | |
1158 | 0 | mEcdheEcdsaInfo.mOwnCertSrc = aX509Certificate; |
1159 | 0 | mEcdheEcdsaInfo.mOwnCertLength = aX509CertLength; |
1160 | 0 | mEcdheEcdsaInfo.mPrivateKeySrc = aPrivateKey; |
1161 | 0 | mEcdheEcdsaInfo.mPrivateKeyLength = aPrivateKeyLength; |
1162 | |
|
1163 | 0 | mSecureTransport.mCipherSuite = |
1164 | 0 | mSecureTransport.mDatagramTransport ? kEcdheEcdsaWithAes128Ccm8 : kEcdheEcdsaWithAes128GcmSha256; |
1165 | 0 | } |
1166 | | |
1167 | | void SecureTransport::Extension::SetCaCertificateChain(const uint8_t *aX509CaCertificateChain, |
1168 | | uint32_t aX509CaCertChainLength) |
1169 | 0 | { |
1170 | 0 | OT_ASSERT(aX509CaCertChainLength > 0); |
1171 | 0 | OT_ASSERT(aX509CaCertificateChain != nullptr); |
1172 | | |
1173 | 0 | mEcdheEcdsaInfo.mCaChainSrc = aX509CaCertificateChain; |
1174 | 0 | mEcdheEcdsaInfo.mCaChainLength = aX509CaCertChainLength; |
1175 | 0 | } |
1176 | | |
1177 | | #endif // MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED |
1178 | | |
1179 | | #ifdef MBEDTLS_KEY_EXCHANGE_PSK_ENABLED |
1180 | | |
1181 | | int SecureTransport::Extension::PskInfo::SetSecureKeys(mbedtls_ssl_config &aConfig) const |
1182 | 0 | { |
1183 | 0 | return mbedtls_ssl_conf_psk(&aConfig, static_cast<const unsigned char *>(mPreSharedKey), mPreSharedKeyLength, |
1184 | 0 | static_cast<const unsigned char *>(mPreSharedKeyIdentity), mPreSharedKeyIdLength); |
1185 | 0 | } |
1186 | | |
1187 | | void SecureTransport::Extension::SetPreSharedKey(const uint8_t *aPsk, |
1188 | | uint16_t aPskLength, |
1189 | | const uint8_t *aPskIdentity, |
1190 | | uint16_t aPskIdLength) |
1191 | 0 | { |
1192 | 0 | OT_ASSERT(aPsk != nullptr); |
1193 | 0 | OT_ASSERT(aPskIdentity != nullptr); |
1194 | 0 | OT_ASSERT(aPskLength > 0); |
1195 | 0 | OT_ASSERT(aPskIdLength > 0); |
1196 | | |
1197 | 0 | mPskInfo.mPreSharedKey = aPsk; |
1198 | 0 | mPskInfo.mPreSharedKeyLength = aPskLength; |
1199 | 0 | mPskInfo.mPreSharedKeyIdentity = aPskIdentity; |
1200 | 0 | mPskInfo.mPreSharedKeyIdLength = aPskIdLength; |
1201 | |
|
1202 | 0 | mSecureTransport.mCipherSuite = kPskWithAes128Ccm8; |
1203 | 0 | } |
1204 | | |
1205 | | #endif // MBEDTLS_KEY_EXCHANGE_PSK_ENABLED |
1206 | | |
1207 | | #if defined(MBEDTLS_BASE64_C) && defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) |
1208 | | Error SecureTransport::Extension::GetPeerCertificateBase64(unsigned char *aPeerCert, |
1209 | | size_t *aCertLength, |
1210 | | size_t aCertBufferSize) |
1211 | | { |
1212 | | Error error = kErrorNone; |
1213 | | SecureSession *session = mSecureTransport.mSessions.GetHead(); |
1214 | | |
1215 | | VerifyOrExit(session != nullptr, error = kErrorInvalidState); |
1216 | | VerifyOrExit(session->IsConnected(), error = kErrorInvalidState); |
1217 | | |
1218 | | #if (MBEDTLS_VERSION_NUMBER >= 0x03010000) |
1219 | | VerifyOrExit(mbedtls_base64_encode(aPeerCert, aCertBufferSize, aCertLength, |
1220 | | session->mSsl.MBEDTLS_PRIVATE(session)->MBEDTLS_PRIVATE(peer_cert)->raw.p, |
1221 | | session->mSsl.MBEDTLS_PRIVATE(session)->MBEDTLS_PRIVATE(peer_cert)->raw.len) == |
1222 | | 0, |
1223 | | error = kErrorNoBufs); |
1224 | | #else |
1225 | | VerifyOrExit( |
1226 | | mbedtls_base64_encode( |
1227 | | aPeerCert, aCertBufferSize, aCertLength, |
1228 | | session->mSsl.MBEDTLS_PRIVATE(session)->MBEDTLS_PRIVATE(peer_cert)->MBEDTLS_PRIVATE(raw).MBEDTLS_PRIVATE(p), |
1229 | | session->mSsl.MBEDTLS_PRIVATE(session)->MBEDTLS_PRIVATE(peer_cert)->MBEDTLS_PRIVATE(raw).MBEDTLS_PRIVATE( |
1230 | | len)) == 0, |
1231 | | error = kErrorNoBufs); |
1232 | | #endif |
1233 | | |
1234 | | exit: |
1235 | | return error; |
1236 | | } |
1237 | | #endif // defined(MBEDTLS_BASE64_C) && defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) |
1238 | | |
1239 | | #if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) |
1240 | | Error SecureTransport::Extension::GetPeerCertificateDer(uint8_t *aPeerCert, size_t *aCertLength, size_t aCertBufferSize) |
1241 | | { |
1242 | | Error error = kErrorNone; |
1243 | | SecureSession *session = mSecureTransport.mSessions.GetHead(); |
1244 | | |
1245 | | VerifyOrExit(session->IsConnected(), error = kErrorInvalidState); |
1246 | | |
1247 | | #if (MBEDTLS_VERSION_NUMBER >= 0x03010000) |
1248 | | VerifyOrExit(session->mSsl.MBEDTLS_PRIVATE(session)->MBEDTLS_PRIVATE(peer_cert)->raw.len < aCertBufferSize, |
1249 | | error = kErrorNoBufs); |
1250 | | |
1251 | | *aCertLength = session->mSsl.MBEDTLS_PRIVATE(session)->MBEDTLS_PRIVATE(peer_cert)->raw.len; |
1252 | | memcpy(aPeerCert, session->mSsl.MBEDTLS_PRIVATE(session)->MBEDTLS_PRIVATE(peer_cert)->raw.p, *aCertLength); |
1253 | | |
1254 | | #else |
1255 | | VerifyOrExit( |
1256 | | session->mSsl.MBEDTLS_PRIVATE(session)->MBEDTLS_PRIVATE(peer_cert)->MBEDTLS_PRIVATE(raw).MBEDTLS_PRIVATE(len) < |
1257 | | aCertBufferSize, |
1258 | | error = kErrorNoBufs); |
1259 | | |
1260 | | *aCertLength = |
1261 | | session->mSsl.MBEDTLS_PRIVATE(session)->MBEDTLS_PRIVATE(peer_cert)->MBEDTLS_PRIVATE(raw).MBEDTLS_PRIVATE(len); |
1262 | | memcpy(aPeerCert, |
1263 | | session->mSsl.MBEDTLS_PRIVATE(session)->MBEDTLS_PRIVATE(peer_cert)->MBEDTLS_PRIVATE(raw).MBEDTLS_PRIVATE(p), |
1264 | | *aCertLength); |
1265 | | #endif |
1266 | | |
1267 | | exit: |
1268 | | return error; |
1269 | | } |
1270 | | |
1271 | | Error SecureTransport::Extension::GetPeerSubjectAttributeByOid(const char *aOid, |
1272 | | size_t aOidLength, |
1273 | | uint8_t *aAttributeBuffer, |
1274 | | size_t *aAttributeLength, |
1275 | | int *aAsn1Type) |
1276 | | { |
1277 | | Error error = kErrorNone; |
1278 | | const mbedtls_asn1_named_data *data; |
1279 | | size_t length; |
1280 | | size_t attributeBufferSize; |
1281 | | SecureSession *session; |
1282 | | mbedtls_x509_crt *peerCert; |
1283 | | |
1284 | | session = mSecureTransport.mSessions.GetHead(); |
1285 | | VerifyOrExit(session != nullptr, error = kErrorInvalidState); |
1286 | | |
1287 | | peerCert = const_cast<mbedtls_x509_crt *>(mbedtls_ssl_get_peer_cert(&session->mSsl)); |
1288 | | |
1289 | | VerifyOrExit(aAttributeLength != nullptr, error = kErrorInvalidArgs); |
1290 | | attributeBufferSize = *aAttributeLength; |
1291 | | *aAttributeLength = 0; |
1292 | | |
1293 | | VerifyOrExit(aAttributeBuffer != nullptr, error = kErrorNoBufs); |
1294 | | VerifyOrExit(peerCert != nullptr, error = kErrorInvalidState); |
1295 | | |
1296 | | data = mbedtls_asn1_find_named_data(&peerCert->subject, aOid, aOidLength); |
1297 | | VerifyOrExit(data != nullptr, error = kErrorNotFound); |
1298 | | |
1299 | | length = data->val.len; |
1300 | | VerifyOrExit(length <= attributeBufferSize, error = kErrorNoBufs); |
1301 | | *aAttributeLength = length; |
1302 | | |
1303 | | if (aAsn1Type != nullptr) |
1304 | | { |
1305 | | *aAsn1Type = data->val.tag; |
1306 | | } |
1307 | | |
1308 | | memcpy(aAttributeBuffer, data->val.p, length); |
1309 | | |
1310 | | exit: |
1311 | | return error; |
1312 | | } |
1313 | | |
1314 | | Error SecureTransport::Extension::GetThreadAttributeFromPeerCertificate(int aThreadOidDescriptor, |
1315 | | uint8_t *aAttributeBuffer, |
1316 | | size_t *aAttributeLength) |
1317 | | { |
1318 | | Error error; |
1319 | | SecureSession *session = mSecureTransport.mSessions.GetHead(); |
1320 | | const mbedtls_x509_crt *cert; |
1321 | | |
1322 | | VerifyOrExit(session != nullptr, error = kErrorInvalidState); |
1323 | | cert = mbedtls_ssl_get_peer_cert(&session->mSsl); |
1324 | | error = GetThreadAttributeFromCertificate(cert, aThreadOidDescriptor, aAttributeBuffer, aAttributeLength); |
1325 | | |
1326 | | exit: |
1327 | | return error; |
1328 | | } |
1329 | | |
1330 | | #endif // defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) |
1331 | | |
1332 | | Error SecureTransport::Extension::GetThreadAttributeFromOwnCertificate(int aThreadOidDescriptor, |
1333 | | uint8_t *aAttributeBuffer, |
1334 | | size_t *aAttributeLength) |
1335 | 0 | { |
1336 | 0 | const mbedtls_x509_crt *cert = &mEcdheEcdsaInfo.mOwnCert; |
1337 | |
|
1338 | 0 | return GetThreadAttributeFromCertificate(cert, aThreadOidDescriptor, aAttributeBuffer, aAttributeLength); |
1339 | 0 | } |
1340 | | |
1341 | | Error SecureTransport::Extension::GetThreadAttributeFromCertificate(const mbedtls_x509_crt *aCert, |
1342 | | int aThreadOidDescriptor, |
1343 | | uint8_t *aAttributeBuffer, |
1344 | | size_t *aAttributeLength) |
1345 | 0 | { |
1346 | 0 | Error error = kErrorNotFound; |
1347 | 0 | char oid[9] = {0x2B, 0x06, 0x01, 0x04, 0x01, static_cast<char>(0x82), static_cast<char>(0xDF), |
1348 | 0 | 0x2A, 0x00}; // 1.3.6.1.4.1.44970.0 |
1349 | 0 | mbedtls_x509_buf v3_ext; |
1350 | 0 | unsigned char *p, *end, *endExtData; |
1351 | 0 | size_t len; |
1352 | 0 | size_t attributeBufferSize; |
1353 | 0 | mbedtls_x509_buf extnOid; |
1354 | 0 | int ret, isCritical; |
1355 | |
|
1356 | 0 | VerifyOrExit(aAttributeLength != nullptr, error = kErrorInvalidArgs); |
1357 | 0 | attributeBufferSize = *aAttributeLength; |
1358 | 0 | *aAttributeLength = 0; |
1359 | |
|
1360 | 0 | VerifyOrExit(aCert != nullptr, error = kErrorInvalidState); |
1361 | 0 | v3_ext = aCert->v3_ext; |
1362 | 0 | p = v3_ext.p; |
1363 | 0 | VerifyOrExit(p != nullptr, error = kErrorInvalidState); |
1364 | 0 | end = p + v3_ext.len; |
1365 | 0 | VerifyOrExit(mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE) == 0, |
1366 | 0 | error = kErrorParse); |
1367 | 0 | VerifyOrExit(end == p + len, error = kErrorParse); |
1368 | | |
1369 | 0 | VerifyOrExit(aThreadOidDescriptor < 128, error = kErrorNotImplemented); |
1370 | 0 | oid[sizeof(oid) - 1] = static_cast<char>(aThreadOidDescriptor); |
1371 | |
|
1372 | 0 | while (p < end) |
1373 | 0 | { |
1374 | 0 | isCritical = 0; |
1375 | 0 | VerifyOrExit(mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE) == 0, |
1376 | 0 | error = kErrorParse); |
1377 | 0 | endExtData = p + len; |
1378 | | |
1379 | | // Get extension ID |
1380 | 0 | VerifyOrExit(mbedtls_asn1_get_tag(&p, endExtData, &extnOid.len, MBEDTLS_ASN1_OID) == 0, error = kErrorParse); |
1381 | 0 | extnOid.tag = MBEDTLS_ASN1_OID; |
1382 | 0 | extnOid.p = p; |
1383 | 0 | p += extnOid.len; |
1384 | | |
1385 | | // Get optional critical |
1386 | 0 | ret = mbedtls_asn1_get_bool(&p, endExtData, &isCritical); |
1387 | 0 | VerifyOrExit(ret == 0 || ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG, error = kErrorParse); |
1388 | | |
1389 | | // Data must be octet string type, see https://datatracker.ietf.org/doc/html/rfc5280#section-4.1 |
1390 | 0 | VerifyOrExit(mbedtls_asn1_get_tag(&p, endExtData, &len, MBEDTLS_ASN1_OCTET_STRING) == 0, error = kErrorParse); |
1391 | 0 | VerifyOrExit(endExtData == p + len, error = kErrorParse); |
1392 | | |
1393 | | // TODO: extensions with isCritical == 1 that are unknown should lead to rejection of the entire cert. |
1394 | 0 | if (extnOid.len == sizeof(oid) && memcmp(extnOid.p, oid, sizeof(oid)) == 0) |
1395 | 0 | { |
1396 | | // per RFC 5280, octet string must contain ASN.1 Type Length Value octets |
1397 | 0 | VerifyOrExit(len >= 2, error = kErrorParse); |
1398 | 0 | VerifyOrExit(*(p + 1) == len - 2, error = kErrorParse); // check TLV Length, not Type. |
1399 | 0 | *aAttributeLength = len - 2; // strip the ASN.1 Type Length bytes from embedded TLV |
1400 | |
|
1401 | 0 | if (aAttributeBuffer != nullptr) |
1402 | 0 | { |
1403 | 0 | VerifyOrExit(*aAttributeLength <= attributeBufferSize, error = kErrorNoBufs); |
1404 | 0 | memcpy(aAttributeBuffer, p + 2, *aAttributeLength); |
1405 | 0 | } |
1406 | | |
1407 | 0 | error = kErrorNone; |
1408 | 0 | break; |
1409 | 0 | } |
1410 | 0 | p += len; |
1411 | 0 | } |
1412 | | |
1413 | 0 | exit: |
1414 | 0 | return error; |
1415 | 0 | } |
1416 | | |
1417 | | #endif // OPENTHREAD_CONFIG_TLS_API_ENABLE |
1418 | | |
1419 | | #if OPENTHREAD_CONFIG_BLE_TCAT_ENABLE |
1420 | | |
1421 | | //--------------------------------------------------------------------------------------------------------------------- |
1422 | | // Tls |
1423 | | |
1424 | | SecureSession *Tls::HandleAccept(void *aContext, const Ip6::MessageInfo &aMessageInfo) |
1425 | | { |
1426 | | OT_UNUSED_VARIABLE(aMessageInfo); |
1427 | | |
1428 | | return static_cast<Tls *>(aContext)->HandleAccept(); |
1429 | | } |
1430 | | |
1431 | | SecureSession *Tls::HandleAccept(void) { return IsSessionInUse() ? nullptr : static_cast<SecureSession *>(this); } |
1432 | | |
1433 | | #endif |
1434 | | |
1435 | | } // namespace MeshCoP |
1436 | | } // namespace ot |
1437 | | |
1438 | | #endif // OPENTHREAD_CONFIG_SECURE_TRANSPORT_ENABLE |