• 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 /**
30  * @file
31  *   This file includes definitions for MeshCoP.
32  */
33 
34 #ifndef MESHCOP_HPP_
35 #define MESHCOP_HPP_
36 
37 #include "openthread-core-config.h"
38 
39 #include <openthread/commissioner.h>
40 #include <openthread/instance.h>
41 #include <openthread/joiner.h>
42 
43 #include "coap/coap.hpp"
44 #include "common/as_core_type.hpp"
45 #include "common/clearable.hpp"
46 #include "common/equatable.hpp"
47 #include "common/log.hpp"
48 #include "common/message.hpp"
49 #include "common/numeric_limits.hpp"
50 #include "common/string.hpp"
51 #include "mac/mac_types.hpp"
52 #include "meshcop/meshcop_tlvs.hpp"
53 
54 namespace ot {
55 
56 class ThreadNetif;
57 
58 namespace MeshCoP {
59 
60 /**
61  * Represents a Joiner PSKd.
62  */
63 class JoinerPskd : public otJoinerPskd, public Clearable<JoinerPskd>, public Unequatable<JoinerPskd>
64 {
65 public:
66     static constexpr uint8_t kMinLength = 6;                         ///< Min PSKd string length (excludes null char)
67     static constexpr uint8_t kMaxLength = OT_JOINER_MAX_PSKD_LENGTH; ///< Max PSKd string length (excludes null char)
68 
69     /**
70      * Indicates whether the PSKd if well-formed and valid.
71      *
72      * Per Thread specification, a Joining Device Credential is encoded as uppercase alphanumeric characters
73      * (base32-thread: 0-9, A-Z excluding I, O, Q, and Z for readability) with a minimum length of 6 such characters
74      * and a maximum length of 32 such characters.
75      *
76      * @returns TRUE if the PSKd is valid, FALSE otherwise.
77      */
IsValid(void) const78     bool IsValid(void) const { return IsPskdValid(m8); }
79 
80     /**
81      * Sets the joiner PSKd from a given C string.
82      *
83      * @param[in] aPskdString   A pointer to the PSKd C string array.
84      *
85      * @retval kErrorNone          The PSKd was updated successfully.
86      * @retval kErrorInvalidArgs   The given PSKd C string is not valid.
87      */
88     Error SetFrom(const char *aPskdString);
89 
90     /**
91      * Gets the PSKd as a null terminated C string.
92      *
93      * Must be used after the PSKd is validated, otherwise its behavior is undefined.
94      *
95      * @returns The PSKd as a C string.
96      */
GetAsCString(void) const97     const char *GetAsCString(void) const { return m8; }
98 
99     /**
100      * Gets the PSKd string length.
101      *
102      * Must be used after the PSKd is validated, otherwise its behavior is undefined.
103      *
104      * @returns The PSKd string length.
105      */
GetLength(void) const106     uint8_t GetLength(void) const { return static_cast<uint8_t>(StringLength(m8, kMaxLength + 1)); }
107 
108     /**
109      * Gets the PSKd as a byte array.
110      *
111      * @returns The PSKd as a byte array.
112      */
GetBytes(void) const113     const uint8_t *GetBytes(void) const { return reinterpret_cast<const uint8_t *>(m8); }
114 
115     /**
116      * Overloads operator `==` to evaluate whether or not two PSKds are equal.
117      *
118      * @param[in]  aOther  The other PSKd to compare with.
119      *
120      * @retval TRUE   If the two are equal.
121      * @retval FALSE  If the two are not equal.
122      */
123     bool operator==(const JoinerPskd &aOther) const;
124 
125     /**
126      * Indicates whether a given PSKd string if well-formed and valid.
127      *
128      * @param[in] aPskdString  A pointer to a PSKd string array.
129      *
130      * @sa IsValid()
131      *
132      * @returns TRUE if @p aPskdString is valid, FALSE otherwise.
133      */
134     static bool IsPskdValid(const char *aPskdString);
135 };
136 
137 /**
138  * Represents a Joiner Discerner.
139  */
140 class JoinerDiscerner : public otJoinerDiscerner, public Unequatable<JoinerDiscerner>
141 {
142     friend class SteeringData;
143 
144 public:
145     static constexpr uint8_t kMaxLength = OT_JOINER_MAX_DISCERNER_LENGTH; ///< Max length of a Discerner in bits.
146 
147     static constexpr uint16_t kInfoStringSize = 45; ///< Size of `InfoString` to use with `ToString()
148 
149     /**
150      * Defines the fixed-length `String` object returned from `ToString()`.
151      */
152     typedef String<kInfoStringSize> InfoString;
153 
154     /**
155      * Clears the Joiner Discerner.
156      */
Clear(void)157     void Clear(void) { mLength = 0; }
158 
159     /**
160      * Indicates whether the Joiner Discerner is empty (no value set).
161      *
162      * @returns TRUE if empty, FALSE otherwise.
163      */
IsEmpty(void) const164     bool IsEmpty(void) const { return mLength == 0; }
165 
166     /**
167      * Gets the Joiner Discerner's value.
168      *
169      * @returns The Joiner Discerner value.
170      */
GetValue(void) const171     uint64_t GetValue(void) const { return mValue; }
172 
173     /**
174      * Gets the Joiner Discerner's length (in bits).
175      *
176      * @return The Joiner Discerner length.
177      */
GetLength(void) const178     uint8_t GetLength(void) const { return mLength; }
179 
180     /**
181      * Indicates whether the Joiner Discerner is valid (i.e. it not empty and its length is within
182      * valid range).
183      *
184      * @returns TRUE if Joiner Discerner is valid, FALSE otherwise.
185      */
IsValid(void) const186     bool IsValid(void) const { return (0 < mLength) && (mLength <= kMaxLength); }
187 
188     /**
189      * Generates a Joiner ID from the Discerner.
190      *
191      * @param[out] aJoinerId   A reference to `Mac::ExtAddress` to output the generated Joiner ID.
192      */
193     void GenerateJoinerId(Mac::ExtAddress &aJoinerId) const;
194 
195     /**
196      * Indicates whether a given Joiner ID matches the Discerner.
197      *
198      * @param[in] aJoinerId  A Joiner ID to match with the Discerner.
199      *
200      * @returns TRUE if the Joiner ID matches the Discerner, FALSE otherwise.
201      */
202     bool Matches(const Mac::ExtAddress &aJoinerId) const;
203 
204     /**
205      * Overloads operator `==` to evaluate whether or not two Joiner Discerner instances are equal.
206      *
207      * @param[in]  aOther  The other Joiner Discerner to compare with.
208      *
209      * @retval TRUE   If the two are equal.
210      * @retval FALSE  If the two are not equal.
211      */
212     bool operator==(const JoinerDiscerner &aOther) const;
213 
214     /**
215      * Converts the Joiner Discerner to a string.
216      *
217      * @returns An `InfoString` representation of Joiner Discerner.
218      */
219     InfoString ToString(void) const;
220 
221 private:
GetMask(void) const222     uint64_t GetMask(void) const { return (static_cast<uint64_t>(1ULL) << mLength) - 1; }
223     void     CopyTo(Mac::ExtAddress &aExtAddress) const;
224 };
225 
226 /**
227  * Represents Steering Data (bloom filter).
228  */
229 class SteeringData : public otSteeringData
230 {
231 public:
232     static constexpr uint8_t kMaxLength = OT_STEERING_DATA_MAX_LENGTH; ///< Maximum Steering Data length (in bytes).
233 
234     /**
235      * Represents the hash bit index values for the bloom filter calculated from a Joiner ID.
236      *
237      * The first hash bit index is derived using CRC16-CCITT and second one using CRC16-ANSI.
238      */
239     struct HashBitIndexes
240     {
241         static constexpr uint8_t kNumIndexes = 2; ///< Number of hash bit indexes.
242 
243         uint16_t mIndex[kNumIndexes]; ///< The hash bit index array.
244     };
245 
246     /**
247      * Initializes the Steering Data and clears the bloom filter.
248      *
249      * @param[in]  aLength   The Steering Data length (in bytes) - MUST be smaller than or equal to `kMaxLength`.
250      */
251     void Init(uint8_t aLength = kMaxLength);
252 
253     /**
254      * Clears the bloom filter (all bits are cleared and no Joiner Id is accepted)..
255      *
256      * The Steering Data length (bloom filter length) is set to one byte with all bits cleared.
257      */
Clear(void)258     void Clear(void) { Init(1); }
259 
260     /**
261      * Sets the bloom filter to permit all Joiner IDs.
262      *
263      * To permit all Joiner IDs, The Steering Data length (bloom filter length) is set to one byte with all bits set.
264      */
265     void SetToPermitAllJoiners(void);
266 
267     /**
268      * Returns the Steering Data length (in bytes).
269      *
270      * @returns The Steering Data length (in bytes).
271      */
GetLength(void) const272     uint8_t GetLength(void) const { return mLength; }
273 
274     /**
275      * Gets the Steering Data buffer (bloom filter).
276      *
277      * @returns A pointer to the Steering Data buffer.
278      */
GetData(void) const279     const uint8_t *GetData(void) const { return m8; }
280 
281     /**
282      * Gets the Steering Data buffer (bloom filter).
283      *
284      * @returns A pointer to the Steering Data buffer.
285      */
GetData(void)286     uint8_t *GetData(void) { return m8; }
287 
288     /**
289      * Updates the bloom filter adding the given Joiner ID.
290      *
291      * @param[in]  aJoinerId  The Joiner ID to add to bloom filter.
292      */
293     void UpdateBloomFilter(const Mac::ExtAddress &aJoinerId);
294 
295     /**
296      * Updates the bloom filter adding a given Joiner Discerner.
297      *
298      * @param[in]  aDiscerner  The Joiner Discerner to add to bloom filter.
299      */
300     void UpdateBloomFilter(const JoinerDiscerner &aDiscerner);
301 
302     /**
303      * Indicates whether the bloom filter is empty (all the bits are cleared).
304      *
305      * @returns TRUE if the bloom filter is empty, FALSE otherwise.
306      */
IsEmpty(void) const307     bool IsEmpty(void) const { return DoesAllMatch(0); }
308 
309     /**
310      * Indicates whether the bloom filter permits all Joiner IDs (all the bits are set).
311      *
312      * @returns TRUE if the bloom filter permits all Joiners IDs, FALSE otherwise.
313      */
PermitsAllJoiners(void) const314     bool PermitsAllJoiners(void) const { return (mLength > 0) && DoesAllMatch(kPermitAll); }
315 
316     /**
317      * Indicates whether the bloom filter contains a given Joiner ID.
318      *
319      * @param[in] aJoinerId  A Joiner ID.
320      *
321      * @returns TRUE if the bloom filter contains @p aJoinerId, FALSE otherwise.
322      */
323     bool Contains(const Mac::ExtAddress &aJoinerId) const;
324 
325     /**
326      * Indicates whether the bloom filter contains a given Joiner Discerner.
327      *
328      * @param[in] aDiscerner   A Joiner Discerner.
329      *
330      * @returns TRUE if the bloom filter contains @p aDiscerner, FALSE otherwise.
331      */
332     bool Contains(const JoinerDiscerner &aDiscerner) const;
333 
334     /**
335      * Indicates whether the bloom filter contains the hash bit indexes (derived from a Joiner ID).
336      *
337      * @param[in]  aIndexes   A hash bit index structure (derived from a Joiner ID).
338      *
339      * @returns TRUE if the bloom filter contains the Joiner ID mapping to @p aIndexes, FALSE otherwise.
340      */
341     bool Contains(const HashBitIndexes &aIndexes) const;
342 
343     /**
344      * Calculates the bloom filter hash bit indexes from a given Joiner ID.
345      *
346      * The first hash bit index is derived using CRC16-CCITT and second one using CRC16-ANSI.
347      *
348      * @param[in]  aJoinerId  The Joiner ID to calculate the hash bit indexes.
349      * @param[out] aIndexes   A reference to a `HashBitIndexes` structure to output the calculated index values.
350      */
351     static void CalculateHashBitIndexes(const Mac::ExtAddress &aJoinerId, HashBitIndexes &aIndexes);
352 
353     /**
354      * Calculates the bloom filter hash bit indexes from a given Joiner Discerner.
355      *
356      * The first hash bit index is derived using CRC16-CCITT and second one using CRC16-ANSI.
357      *
358      * @param[in]  aDiscerner     The Joiner Discerner to calculate the hash bit indexes.
359      * @param[out] aIndexes       A reference to a `HashBitIndexes` structure to output the calculated index values.
360      */
361     static void CalculateHashBitIndexes(const JoinerDiscerner &aDiscerner, HashBitIndexes &aIndexes);
362 
363 private:
364     static constexpr uint8_t kPermitAll = 0xff;
365 
GetNumBits(void) const366     uint8_t GetNumBits(void) const { return (mLength * kBitsPerByte); }
367 
BitIndex(uint8_t aBit) const368     uint8_t BitIndex(uint8_t aBit) const { return (mLength - 1 - (aBit / kBitsPerByte)); }
BitFlag(uint8_t aBit) const369     uint8_t BitFlag(uint8_t aBit) const { return static_cast<uint8_t>(1U << (aBit % kBitsPerByte)); }
370 
GetBit(uint8_t aBit) const371     bool GetBit(uint8_t aBit) const { return (m8[BitIndex(aBit)] & BitFlag(aBit)) != 0; }
SetBit(uint8_t aBit)372     void SetBit(uint8_t aBit) { m8[BitIndex(aBit)] |= BitFlag(aBit); }
ClearBit(uint8_t aBit)373     void ClearBit(uint8_t aBit) { m8[BitIndex(aBit)] &= ~BitFlag(aBit); }
374 
375     bool DoesAllMatch(uint8_t aMatch) const;
376     void UpdateBloomFilter(const HashBitIndexes &aIndexes);
377 };
378 
379 /**
380  * Represents a Commissioning Dataset.
381  */
382 class CommissioningDataset : public otCommissioningDataset, public Clearable<CommissioningDataset>
383 {
384 public:
385     /**
386      * Indicates whether or not the Border Router RLOC16 Locator is set in the Dataset.
387      *
388      * @returns TRUE if Border Router RLOC16 Locator is set, FALSE otherwise.
389      */
IsLocatorSet(void) const390     bool IsLocatorSet(void) const { return mIsLocatorSet; }
391 
392     /**
393      * Gets the Border Router RLOC16 Locator in the Dataset.
394      *
395      * MUST be used when Locator is set in the Dataset, otherwise its behavior is undefined.
396      *
397      * @returns The Border Router RLOC16 Locator in the Dataset.
398      */
GetLocator(void) const399     uint16_t GetLocator(void) const { return mLocator; }
400 
401     /**
402      * Sets the Border Router RLOCG16 Locator in the Dataset.
403      *
404      * @param[in] aLocator  A Locator.
405      */
SetLocator(uint16_t aLocator)406     void SetLocator(uint16_t aLocator)
407     {
408         mIsLocatorSet = true;
409         mLocator      = aLocator;
410     }
411 
412     /**
413      * Indicates whether or not the Session ID is set in the Dataset.
414      *
415      * @returns TRUE if Session ID is set, FALSE otherwise.
416      */
IsSessionIdSet(void) const417     bool IsSessionIdSet(void) const { return mIsSessionIdSet; }
418 
419     /**
420      * Gets the Session ID in the Dataset.
421      *
422      * MUST be used when Session ID is set in the Dataset, otherwise its behavior is undefined.
423      *
424      * @returns The Session ID in the Dataset.
425      */
GetSessionId(void) const426     uint16_t GetSessionId(void) const { return mSessionId; }
427 
428     /**
429      * Sets the Session ID in the Dataset.
430      *
431      * @param[in] aSessionId  The Session ID.
432      */
SetSessionId(uint16_t aSessionId)433     void SetSessionId(uint16_t aSessionId)
434     {
435         mIsSessionIdSet = true;
436         mSessionId      = aSessionId;
437     }
438 
439     /**
440      * Indicates whether or not the Steering Data is set in the Dataset.
441      *
442      * @returns TRUE if Steering Data is set, FALSE otherwise.
443      */
IsSteeringDataSet(void) const444     bool IsSteeringDataSet(void) const { return mIsSteeringDataSet; }
445 
446     /**
447      * Gets the Steering Data in the Dataset.
448      *
449      * MUST be used when Steering Data is set in the Dataset, otherwise its behavior is undefined.
450      *
451      * @returns The Steering Data in the Dataset.
452      */
GetSteeringData(void) const453     const SteeringData &GetSteeringData(void) const { return static_cast<const SteeringData &>(mSteeringData); }
454 
455     /**
456      * Returns a reference to the Steering Data in the Dataset to be updated by caller.
457      *
458      * @returns A reference to the Steering Data in the Dataset.
459      */
UpdateSteeringData(void)460     SteeringData &UpdateSteeringData(void)
461     {
462         mIsSteeringDataSet = true;
463         return static_cast<SteeringData &>(mSteeringData);
464     }
465 
466     /**
467      * Indicates whether or not the Joiner UDP port is set in the Dataset.
468      *
469      * @returns TRUE if Joiner UDP port is set, FALSE otherwise.
470      */
IsJoinerUdpPortSet(void) const471     bool IsJoinerUdpPortSet(void) const { return mIsJoinerUdpPortSet; }
472 
473     /**
474      * Gets the Joiner UDP port in the Dataset.
475      *
476      * MUST be used when Joiner UDP port is set in the Dataset, otherwise its behavior is undefined.
477      *
478      * @returns The Joiner UDP port in the Dataset.
479      */
GetJoinerUdpPort(void) const480     uint16_t GetJoinerUdpPort(void) const { return mJoinerUdpPort; }
481 
482     /**
483      * Sets the Joiner UDP Port in the Dataset.
484      *
485      * @param[in] aJoinerUdpPort  The Joiner UDP Port.
486      */
SetJoinerUdpPort(uint16_t aJoinerUdpPort)487     void SetJoinerUdpPort(uint16_t aJoinerUdpPort)
488     {
489         mIsJoinerUdpPortSet = true;
490         mJoinerUdpPort      = aJoinerUdpPort;
491     }
492 };
493 
494 /**
495  * Generates PSKc.
496  *
497  * PSKc is used to establish the Commissioner Session.
498  *
499  * @param[in]  aPassPhrase   The commissioning passphrase.
500  * @param[in]  aNetworkName  The network name for PSKc computation.
501  * @param[in]  aExtPanId     The extended PAN ID for PSKc computation.
502  * @param[out] aPskc         A reference to a PSKc where the generated PSKc will be placed.
503  *
504  * @retval kErrorNone          Successfully generate PSKc.
505  * @retval kErrorInvalidArgs   If the length of passphrase is out of range.
506  */
507 Error GeneratePskc(const char          *aPassPhrase,
508                    const NetworkName   &aNetworkName,
509                    const ExtendedPanId &aExtPanId,
510                    Pskc                &aPskc);
511 
512 /**
513  * Computes the Joiner ID from a factory-assigned IEEE EUI-64.
514  *
515  * @param[in]   aEui64     The factory-assigned IEEE EUI-64.
516  * @param[out]  aJoinerId  The Joiner ID.
517  */
518 void ComputeJoinerId(const Mac::ExtAddress &aEui64, Mac::ExtAddress &aJoinerId);
519 
520 #if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
521 
522 /**
523  * Generates a message dump log for certification test.
524  *
525  * @param[in] aText     The title text to include in the log.
526  * @param[in] aMessage  The message to dump the content of.
527  */
528 void LogCertMessage(const char *aText, const Coap::Message &aMessage);
529 
530 #endif
531 
532 } // namespace MeshCoP
533 
534 DefineCoreType(otJoinerPskd, MeshCoP::JoinerPskd);
535 DefineCoreType(otJoinerDiscerner, MeshCoP::JoinerDiscerner);
536 DefineCoreType(otSteeringData, MeshCoP::SteeringData);
537 DefineCoreType(otCommissioningDataset, MeshCoP::CommissioningDataset);
538 
539 } // namespace ot
540 
541 #endif // MESHCOP_HPP_
542