1 /*
2 * Copyright (c) 2021, 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" AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28 /**
29 * @file
30 * This file implements the Crypto platform callbacks into OpenThread and default/weak Crypto platform APIs.
31 */
32
33 #include "openthread-core-config.h"
34
35 #include <mbedtls/aes.h>
36 #include <mbedtls/ctr_drbg.h>
37 #include <mbedtls/entropy.h>
38 #include <mbedtls/md.h>
39 #include <mbedtls/sha256.h>
40
41 #include <openthread/instance.h>
42 #include <openthread/platform/crypto.h>
43 #include <openthread/platform/entropy.h>
44 #include <openthread/platform/time.h>
45
46 #include "common/code_utils.hpp"
47 #include "common/debug.hpp"
48 #include "common/instance.hpp"
49 #include "common/new.hpp"
50 #include "config/crypto.h"
51 #include "crypto/hmac_sha256.hpp"
52 #include "crypto/storage.hpp"
53
54 using namespace ot;
55 using namespace Crypto;
56
57 #if OPENTHREAD_CONFIG_CRYPTO_LIB == OPENTHREAD_CONFIG_CRYPTO_LIB_MBEDTLS
58
59 //---------------------------------------------------------------------------------------------------------------------
60 // Default/weak implementation of crypto platform APIs
61
62 #if (!defined(MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES) && \
63 (!defined(MBEDTLS_NO_PLATFORM_ENTROPY) || defined(MBEDTLS_HAVEGE_C) || defined(MBEDTLS_ENTROPY_HARDWARE_ALT)))
64 #define OT_MBEDTLS_STRONG_DEFAULT_ENTROPY_PRESENT
65 #endif
66
67 #if !OPENTHREAD_RADIO
68 static mbedtls_ctr_drbg_context sCtrDrbgContext;
69 static mbedtls_entropy_context sEntropyContext;
70 #ifndef OT_MBEDTLS_STRONG_DEFAULT_ENTROPY_PRESENT
71 static constexpr uint16_t kEntropyMinThreshold = 16;
72 #endif
73 #endif
74
otPlatCryptoInit(void)75 OT_TOOL_WEAK void otPlatCryptoInit(void)
76 {
77 // Intentionally empty.
78 }
79
80 // AES Implementation
otPlatCryptoAesInit(otCryptoContext * aContext)81 OT_TOOL_WEAK otError otPlatCryptoAesInit(otCryptoContext *aContext)
82 {
83 Error error = kErrorNone;
84 mbedtls_aes_context *context;
85
86 VerifyOrExit(aContext != nullptr, error = kErrorInvalidArgs);
87 VerifyOrExit(aContext->mContextSize >= sizeof(mbedtls_aes_context), error = kErrorFailed);
88
89 context = static_cast<mbedtls_aes_context *>(aContext->mContext);
90 mbedtls_aes_init(context);
91
92 exit:
93 return error;
94 }
95
otPlatCryptoAesSetKey(otCryptoContext * aContext,const otCryptoKey * aKey)96 OT_TOOL_WEAK otError otPlatCryptoAesSetKey(otCryptoContext *aContext, const otCryptoKey *aKey)
97 {
98 Error error = kErrorNone;
99 mbedtls_aes_context *context;
100 const LiteralKey key(*static_cast<const Key *>(aKey));
101
102 VerifyOrExit(aContext != nullptr, error = kErrorInvalidArgs);
103 VerifyOrExit(aContext->mContextSize >= sizeof(mbedtls_aes_context), error = kErrorFailed);
104
105 context = static_cast<mbedtls_aes_context *>(aContext->mContext);
106 VerifyOrExit((mbedtls_aes_setkey_enc(context, key.GetBytes(), (key.GetLength() * CHAR_BIT)) == 0),
107 error = kErrorFailed);
108
109 exit:
110 return error;
111 }
112
otPlatCryptoAesEncrypt(otCryptoContext * aContext,const uint8_t * aInput,uint8_t * aOutput)113 OT_TOOL_WEAK otError otPlatCryptoAesEncrypt(otCryptoContext *aContext, const uint8_t *aInput, uint8_t *aOutput)
114 {
115 Error error = kErrorNone;
116 mbedtls_aes_context *context;
117
118 VerifyOrExit(aContext != nullptr, error = kErrorInvalidArgs);
119 VerifyOrExit(aContext->mContextSize >= sizeof(mbedtls_aes_context), error = kErrorFailed);
120
121 context = static_cast<mbedtls_aes_context *>(aContext->mContext);
122 VerifyOrExit((mbedtls_aes_crypt_ecb(context, MBEDTLS_AES_ENCRYPT, aInput, aOutput) == 0), error = kErrorFailed);
123
124 exit:
125 return error;
126 }
127
otPlatCryptoAesFree(otCryptoContext * aContext)128 OT_TOOL_WEAK otError otPlatCryptoAesFree(otCryptoContext *aContext)
129 {
130 Error error = kErrorNone;
131 mbedtls_aes_context *context;
132
133 VerifyOrExit(aContext != nullptr, error = kErrorInvalidArgs);
134 VerifyOrExit(aContext->mContextSize >= sizeof(mbedtls_aes_context), error = kErrorFailed);
135
136 context = static_cast<mbedtls_aes_context *>(aContext->mContext);
137 mbedtls_aes_free(context);
138
139 exit:
140 return error;
141 }
142
143 #if !OPENTHREAD_RADIO
144
145 // HMAC implementations
otPlatCryptoHmacSha256Init(otCryptoContext * aContext)146 OT_TOOL_WEAK otError otPlatCryptoHmacSha256Init(otCryptoContext *aContext)
147 {
148 Error error = kErrorNone;
149 const mbedtls_md_info_t *mdInfo = nullptr;
150 mbedtls_md_context_t * context;
151
152 VerifyOrExit(aContext != nullptr, error = kErrorInvalidArgs);
153 VerifyOrExit(aContext->mContextSize >= sizeof(mbedtls_md_context_t), error = kErrorFailed);
154
155 context = static_cast<mbedtls_md_context_t *>(aContext->mContext);
156 mbedtls_md_init(context);
157 mdInfo = mbedtls_md_info_from_type(MBEDTLS_MD_SHA256);
158 VerifyOrExit((mbedtls_md_setup(context, mdInfo, 1) == 0), error = kErrorFailed);
159
160 exit:
161 return error;
162 }
163
otPlatCryptoHmacSha256Deinit(otCryptoContext * aContext)164 OT_TOOL_WEAK otError otPlatCryptoHmacSha256Deinit(otCryptoContext *aContext)
165 {
166 Error error = kErrorNone;
167 mbedtls_md_context_t *context;
168
169 VerifyOrExit(aContext != nullptr, error = kErrorInvalidArgs);
170 VerifyOrExit(aContext->mContextSize >= sizeof(mbedtls_md_context_t), error = kErrorFailed);
171
172 context = static_cast<mbedtls_md_context_t *>(aContext->mContext);
173 mbedtls_md_free(context);
174
175 exit:
176 return error;
177 }
178
otPlatCryptoHmacSha256Start(otCryptoContext * aContext,const otCryptoKey * aKey)179 OT_TOOL_WEAK otError otPlatCryptoHmacSha256Start(otCryptoContext *aContext, const otCryptoKey *aKey)
180 {
181 Error error = kErrorNone;
182 const LiteralKey key(*static_cast<const Key *>(aKey));
183 mbedtls_md_context_t *context;
184
185 VerifyOrExit(aContext != nullptr, error = kErrorInvalidArgs);
186 VerifyOrExit(aContext->mContextSize >= sizeof(mbedtls_md_context_t), error = kErrorFailed);
187
188 context = static_cast<mbedtls_md_context_t *>(aContext->mContext);
189 VerifyOrExit((mbedtls_md_hmac_starts(context, key.GetBytes(), key.GetLength()) == 0), error = kErrorFailed);
190
191 exit:
192 return error;
193 }
194
otPlatCryptoHmacSha256Update(otCryptoContext * aContext,const void * aBuf,uint16_t aBufLength)195 OT_TOOL_WEAK otError otPlatCryptoHmacSha256Update(otCryptoContext *aContext, const void *aBuf, uint16_t aBufLength)
196 {
197 Error error = kErrorNone;
198 mbedtls_md_context_t *context;
199
200 VerifyOrExit(aContext != nullptr, error = kErrorInvalidArgs);
201 VerifyOrExit(aContext->mContextSize >= sizeof(mbedtls_md_context_t), error = kErrorFailed);
202
203 context = static_cast<mbedtls_md_context_t *>(aContext->mContext);
204 VerifyOrExit((mbedtls_md_hmac_update(context, reinterpret_cast<const uint8_t *>(aBuf), aBufLength) == 0),
205 error = kErrorFailed);
206
207 exit:
208 return error;
209 }
210
otPlatCryptoHmacSha256Finish(otCryptoContext * aContext,uint8_t * aBuf,size_t aBufLength)211 OT_TOOL_WEAK otError otPlatCryptoHmacSha256Finish(otCryptoContext *aContext, uint8_t *aBuf, size_t aBufLength)
212 {
213 OT_UNUSED_VARIABLE(aBufLength);
214
215 Error error = kErrorNone;
216 mbedtls_md_context_t *context;
217
218 VerifyOrExit(aContext != nullptr, error = kErrorInvalidArgs);
219 VerifyOrExit(aContext->mContextSize >= sizeof(mbedtls_md_context_t), error = kErrorFailed);
220
221 context = static_cast<mbedtls_md_context_t *>(aContext->mContext);
222 VerifyOrExit((mbedtls_md_hmac_finish(context, aBuf) == 0), error = kErrorFailed);
223
224 exit:
225 return error;
226 }
227
otPlatCryptoHkdfInit(otCryptoContext * aContext)228 otError otPlatCryptoHkdfInit(otCryptoContext *aContext)
229 {
230 Error error = kErrorNone;
231
232 VerifyOrExit(aContext != nullptr, error = kErrorInvalidArgs);
233 VerifyOrExit(aContext->mContextSize >= sizeof(HmacSha256::Hash), error = kErrorFailed);
234
235 new (aContext->mContext) HmacSha256::Hash();
236
237 exit:
238 return error;
239 }
240
otPlatCryptoHkdfExpand(otCryptoContext * aContext,const uint8_t * aInfo,uint16_t aInfoLength,uint8_t * aOutputKey,uint16_t aOutputKeyLength)241 OT_TOOL_WEAK otError otPlatCryptoHkdfExpand(otCryptoContext *aContext,
242 const uint8_t * aInfo,
243 uint16_t aInfoLength,
244 uint8_t * aOutputKey,
245 uint16_t aOutputKeyLength)
246 {
247 Error error = kErrorNone;
248 HmacSha256 hmac;
249 HmacSha256::Hash hash;
250 uint8_t iter = 0;
251 uint16_t copyLength;
252 HmacSha256::Hash *prk;
253
254 VerifyOrExit(aContext != nullptr, error = kErrorInvalidArgs);
255 VerifyOrExit(aContext->mContextSize >= sizeof(HmacSha256::Hash), error = kErrorFailed);
256
257 prk = static_cast<HmacSha256::Hash *>(aContext->mContext);
258
259 // The aOutputKey is calculated as follows [RFC5889]:
260 //
261 // N = ceil( aOutputKeyLength / HashSize)
262 // T = T(1) | T(2) | T(3) | ... | T(N)
263 // aOutputKey is first aOutputKeyLength of T
264 //
265 // Where:
266 // T(0) = empty string (zero length)
267 // T(1) = HMAC-Hash(PRK, T(0) | info | 0x01)
268 // T(2) = HMAC-Hash(PRK, T(1) | info | 0x02)
269 // T(3) = HMAC-Hash(PRK, T(2) | info | 0x03)
270 // ...
271
272 while (aOutputKeyLength > 0)
273 {
274 Key cryptoKey;
275
276 cryptoKey.Set(prk->GetBytes(), sizeof(HmacSha256::Hash));
277 hmac.Start(cryptoKey);
278
279 if (iter != 0)
280 {
281 hmac.Update(hash);
282 }
283
284 hmac.Update(aInfo, aInfoLength);
285
286 iter++;
287 hmac.Update(iter);
288 hmac.Finish(hash);
289
290 copyLength = (aOutputKeyLength > sizeof(hash)) ? sizeof(hash) : aOutputKeyLength;
291
292 memcpy(aOutputKey, hash.GetBytes(), copyLength);
293 aOutputKey += copyLength;
294 aOutputKeyLength -= copyLength;
295 }
296
297 exit:
298 return error;
299 }
300
otPlatCryptoHkdfExtract(otCryptoContext * aContext,const uint8_t * aSalt,uint16_t aSaltLength,const otCryptoKey * aInputKey)301 OT_TOOL_WEAK otError otPlatCryptoHkdfExtract(otCryptoContext * aContext,
302 const uint8_t * aSalt,
303 uint16_t aSaltLength,
304 const otCryptoKey *aInputKey)
305 {
306 Error error = kErrorNone;
307 HmacSha256 hmac;
308 Key cryptoKey;
309 HmacSha256::Hash *prk;
310 const LiteralKey inputKey(*static_cast<const Key *>(aInputKey));
311
312 VerifyOrExit(aContext != nullptr, error = kErrorInvalidArgs);
313 VerifyOrExit(aContext->mContextSize >= sizeof(HmacSha256::Hash), error = kErrorFailed);
314
315 prk = static_cast<HmacSha256::Hash *>(aContext->mContext);
316
317 cryptoKey.Set(aSalt, aSaltLength);
318 // PRK is calculated as HMAC-Hash(aSalt, aInputKey)
319 hmac.Start(cryptoKey);
320 hmac.Update(inputKey.GetBytes(), inputKey.GetLength());
321 hmac.Finish(*prk);
322
323 exit:
324 return error;
325 }
326
otPlatCryptoHkdfDeinit(otCryptoContext * aContext)327 otError otPlatCryptoHkdfDeinit(otCryptoContext *aContext)
328 {
329 Error error = kErrorNone;
330 HmacSha256::Hash *prk;
331
332 VerifyOrExit(aContext != nullptr, error = kErrorInvalidArgs);
333 VerifyOrExit(aContext->mContextSize >= sizeof(HmacSha256::Hash), error = kErrorFailed);
334
335 prk = static_cast<HmacSha256::Hash *>(aContext->mContext);
336 prk->~Hash();
337 aContext->mContext = nullptr;
338 aContext->mContextSize = 0;
339
340 exit:
341 return error;
342 }
343
344 // SHA256 platform implementations
otPlatCryptoSha256Init(otCryptoContext * aContext)345 OT_TOOL_WEAK otError otPlatCryptoSha256Init(otCryptoContext *aContext)
346 {
347 Error error = kErrorNone;
348 mbedtls_sha256_context *context;
349
350 VerifyOrExit(aContext != nullptr, error = kErrorInvalidArgs);
351
352 context = static_cast<mbedtls_sha256_context *>(aContext->mContext);
353 mbedtls_sha256_init(context);
354
355 exit:
356 return error;
357 }
358
otPlatCryptoSha256Deinit(otCryptoContext * aContext)359 OT_TOOL_WEAK otError otPlatCryptoSha256Deinit(otCryptoContext *aContext)
360 {
361 Error error = kErrorNone;
362 mbedtls_sha256_context *context;
363
364 VerifyOrExit(aContext != nullptr, error = kErrorInvalidArgs);
365 VerifyOrExit(aContext->mContextSize >= sizeof(mbedtls_sha256_context), error = kErrorFailed);
366
367 context = static_cast<mbedtls_sha256_context *>(aContext->mContext);
368 mbedtls_sha256_free(context);
369 aContext->mContext = nullptr;
370 aContext->mContextSize = 0;
371
372 exit:
373 return error;
374 }
375
otPlatCryptoSha256Start(otCryptoContext * aContext)376 OT_TOOL_WEAK otError otPlatCryptoSha256Start(otCryptoContext *aContext)
377 {
378 Error error = kErrorNone;
379 mbedtls_sha256_context *context;
380
381 VerifyOrExit(aContext != nullptr, error = kErrorInvalidArgs);
382 VerifyOrExit(aContext->mContextSize >= sizeof(mbedtls_sha256_context), error = kErrorFailed);
383
384 context = static_cast<mbedtls_sha256_context *>(aContext->mContext);
385
386 #if (MBEDTLS_VERSION_NUMBER >= 0x03000000)
387 VerifyOrExit((mbedtls_sha256_starts(context, 0) == 0), error = kErrorFailed);
388 #else
389 VerifyOrExit((mbedtls_sha256_starts_ret(context, 0) == 0), error = kErrorFailed);
390 #endif
391
392 exit:
393 return error;
394 }
395
otPlatCryptoSha256Update(otCryptoContext * aContext,const void * aBuf,uint16_t aBufLength)396 OT_TOOL_WEAK otError otPlatCryptoSha256Update(otCryptoContext *aContext, const void *aBuf, uint16_t aBufLength)
397 {
398 Error error = kErrorNone;
399 mbedtls_sha256_context *context;
400
401 VerifyOrExit(aContext != nullptr, error = kErrorInvalidArgs);
402 VerifyOrExit(aContext->mContextSize >= sizeof(mbedtls_sha256_context), error = kErrorFailed);
403
404 context = static_cast<mbedtls_sha256_context *>(aContext->mContext);
405
406 #if (MBEDTLS_VERSION_NUMBER >= 0x03000000)
407 VerifyOrExit((mbedtls_sha256_update(context, reinterpret_cast<const uint8_t *>(aBuf), aBufLength) == 0),
408 error = kErrorFailed);
409 #else
410 VerifyOrExit((mbedtls_sha256_update_ret(context, reinterpret_cast<const uint8_t *>(aBuf), aBufLength) == 0),
411 error = kErrorFailed);
412 #endif
413
414 exit:
415 return error;
416 }
417
otPlatCryptoSha256Finish(otCryptoContext * aContext,uint8_t * aHash,uint16_t aHashSize)418 OT_TOOL_WEAK otError otPlatCryptoSha256Finish(otCryptoContext *aContext, uint8_t *aHash, uint16_t aHashSize)
419 {
420 OT_UNUSED_VARIABLE(aHashSize);
421
422 Error error = kErrorNone;
423 mbedtls_sha256_context *context;
424
425 VerifyOrExit(aContext != nullptr, error = kErrorInvalidArgs);
426 VerifyOrExit(aContext->mContextSize >= sizeof(mbedtls_sha256_context), error = kErrorFailed);
427
428 context = static_cast<mbedtls_sha256_context *>(aContext->mContext);
429
430 #if (MBEDTLS_VERSION_NUMBER >= 0x03000000)
431 VerifyOrExit((mbedtls_sha256_finish(context, aHash) == 0), error = kErrorFailed);
432 #else
433 VerifyOrExit((mbedtls_sha256_finish_ret(context, aHash) == 0), error = kErrorFailed);
434 #endif
435
436 exit:
437 return error;
438 }
439
440 #ifndef OT_MBEDTLS_STRONG_DEFAULT_ENTROPY_PRESENT
441
handleMbedtlsEntropyPoll(void * aData,unsigned char * aOutput,size_t aInLen,size_t * aOutLen)442 static int handleMbedtlsEntropyPoll(void *aData, unsigned char *aOutput, size_t aInLen, size_t *aOutLen)
443 {
444 int rval = MBEDTLS_ERR_ENTROPY_SOURCE_FAILED;
445
446 SuccessOrExit(otPlatEntropyGet(reinterpret_cast<uint8_t *>(aOutput), static_cast<uint16_t>(aInLen)));
447 rval = 0;
448
449 VerifyOrExit(aOutLen != nullptr);
450 *aOutLen = aInLen;
451
452 exit:
453 OT_UNUSED_VARIABLE(aData);
454 return rval;
455 }
456
457 #endif // OT_MBEDTLS_STRONG_DEFAULT_ENTROPY_PRESENT
458
otPlatCryptoRandomInit(void)459 OT_TOOL_WEAK void otPlatCryptoRandomInit(void)
460 {
461 mbedtls_entropy_init(&sEntropyContext);
462
463 #ifndef OT_MBEDTLS_STRONG_DEFAULT_ENTROPY_PRESENT
464 mbedtls_entropy_add_source(&sEntropyContext, handleMbedtlsEntropyPoll, nullptr, kEntropyMinThreshold,
465 MBEDTLS_ENTROPY_SOURCE_STRONG);
466 #endif
467
468 mbedtls_ctr_drbg_init(&sCtrDrbgContext);
469
470 int rval = mbedtls_ctr_drbg_seed(&sCtrDrbgContext, mbedtls_entropy_func, &sEntropyContext, nullptr, 0);
471 OT_ASSERT(rval == 0);
472 OT_UNUSED_VARIABLE(rval);
473 }
474
otPlatCryptoRandomDeinit(void)475 OT_TOOL_WEAK void otPlatCryptoRandomDeinit(void)
476 {
477 mbedtls_entropy_free(&sEntropyContext);
478 mbedtls_ctr_drbg_free(&sCtrDrbgContext);
479 }
480
otPlatCryptoRandomGet(uint8_t * aBuffer,uint16_t aSize)481 OT_TOOL_WEAK otError otPlatCryptoRandomGet(uint8_t *aBuffer, uint16_t aSize)
482 {
483 return ot::Crypto::MbedTls::MapError(
484 mbedtls_ctr_drbg_random(&sCtrDrbgContext, static_cast<unsigned char *>(aBuffer), static_cast<size_t>(aSize)));
485 }
486
487 #endif // #if !OPENTHREAD_RADIO
488
489 #endif // #if OPENTHREAD_CONFIG_CRYPTO_LIB == OPENTHREAD_CONFIG_CRYPTO_LIB_MBEDTLS
490