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 performing AES-CCM computations.
32  */
33 
34 #ifndef AES_CCM_HPP_
35 #define AES_CCM_HPP_
36 
37 #include "openthread-core-config.h"
38 
39 #include <stdint.h>
40 
41 #include <openthread/platform/crypto.h>
42 #include "common/error.hpp"
43 #include "common/message.hpp"
44 #include "common/type_traits.hpp"
45 #include "crypto/aes_ecb.hpp"
46 #include "crypto/storage.hpp"
47 #include "mac/mac_types.hpp"
48 
49 namespace ot {
50 namespace Crypto {
51 
52 /**
53  * @addtogroup core-security
54  *
55  * @{
56  *
57  */
58 
59 /**
60  * Implements AES CCM computation.
61  *
62  */
63 class AesCcm
64 {
65 public:
66     static constexpr uint8_t kMinTagLength = 4;                  ///< Minimum tag length (in bytes).
67     static constexpr uint8_t kMaxTagLength = AesEcb::kBlockSize; ///< Maximum tag length (in bytes).
68     static constexpr uint8_t kNonceSize    = 13;                 ///< Size of IEEE 802.15.4 Nonce (in bytes).
69 
70     /**
71      * Type represent the encryption vs decryption mode.
72      *
73      */
74     enum Mode : uint8_t
75     {
76         kEncrypt, // Encryption mode.
77         kDecrypt, // Decryption mode.
78     };
79 
80     /**
81      * Sets the key.
82      *
83      * @param[in]  aKey    Crypto Key used in AES operation
84      *
85      */
SetKey(const Key & aKey)86     void SetKey(const Key &aKey) { mEcb.SetKey(aKey); }
87 
88     /**
89      * Sets the key.
90      *
91      * @param[in]  aKey        A pointer to the key.
92      * @param[in]  aKeyLength  Length of the key in bytes.
93      *
94      */
95     void SetKey(const uint8_t *aKey, uint16_t aKeyLength);
96 
97     /**
98      * Sets the key.
99      *
100      * @param[in]  aMacKey        Key Material for AES operation.
101      *
102      */
103     void SetKey(const Mac::KeyMaterial &aMacKey);
104 
105     /**
106      * Initializes the AES CCM computation.
107      *
108      * @param[in]  aHeaderLength     Length of header in bytes.
109      * @param[in]  aPlainTextLength  Length of plaintext in bytes.
110      * @param[in]  aTagLength        Length of tag in bytes (must be even and in `[kMinTagLength, kMaxTagLength]`).
111      * @param[in]  aNonce            A pointer to the nonce.
112      * @param[in]  aNonceLength      Length of nonce in bytes.
113      *
114      */
115     void Init(uint32_t    aHeaderLength,
116               uint32_t    aPlainTextLength,
117               uint8_t     aTagLength,
118               const void *aNonce,
119               uint8_t     aNonceLength);
120 
121     /**
122      * Processes the header.
123      *
124      * @param[in]  aHeader        A pointer to the header.
125      * @param[in]  aHeaderLength  Length of header in bytes.
126      *
127      */
128     void Header(const void *aHeader, uint32_t aHeaderLength);
129 
130     /**
131      * Processes the header.
132      *
133      * @tparam    ObjectType   The object type.
134      *
135      * @param[in] aObject      A reference to the object to add to header.
136      *
137      */
Header(const ObjectType & aObject)138     template <typename ObjectType> void Header(const ObjectType &aObject)
139     {
140         static_assert(!TypeTraits::IsPointer<ObjectType>::kValue, "ObjectType must not be a pointer");
141 
142         Header(&aObject, sizeof(ObjectType));
143     }
144 
145     /**
146      * Processes the payload.
147      *
148      * @param[in,out]  aPlainText   A pointer to the plaintext.
149      * @param[in,out]  aCipherText  A pointer to the ciphertext.
150      * @param[in]      aLength      Payload length in bytes.
151      * @param[in]      aMode        Mode to indicate whether to encrypt (`kEncrypt`) or decrypt (`kDecrypt`).
152      *
153      */
154     void Payload(void *aPlainText, void *aCipherText, uint32_t aLength, Mode aMode);
155 
156 #if !OPENTHREAD_RADIO
157     /**
158      * Processes the payload within a given message.
159      *
160      * Encrypts/decrypts the payload content in place within the @p aMessage.
161      *
162      * @param[in,out]  aMessage     The message to read from and update.
163      * @param[in]      aOffset      The offset in @p aMessage to start of payload.
164      * @param[in]      aLength      Payload length in bytes.
165      * @param[in]      aMode        Mode to indicate whether to encrypt (`kEncrypt`) or decrypt (`kDecrypt`).
166      *
167      */
168     void Payload(Message &aMessage, uint16_t aOffset, uint16_t aLength, Mode aMode);
169 #endif
170 
171     /**
172      * Returns the tag length in bytes.
173      *
174      * @returns The tag length in bytes.
175      *
176      */
GetTagLength(void) const177     uint8_t GetTagLength(void) const { return mTagLength; }
178 
179     /**
180      * Generates the tag.
181      *
182      * @param[out]  aTag        A pointer to the tag (must have `GetTagLength()` bytes).
183      *
184      */
185     void Finalize(void *aTag);
186 
187     /**
188      * Generates IEEE 802.15.4 nonce byte sequence.
189      *
190      * @param[in]  aAddress        An extended address.
191      * @param[in]  aFrameCounter   A frame counter.
192      * @param[in]  aSecurityLevel  A security level.
193      * @param[out] aNonce          A buffer (with `kNonceSize` bytes) to place the generated nonce.
194      *
195      */
196     static void GenerateNonce(const Mac::ExtAddress &aAddress,
197                               uint32_t               aFrameCounter,
198                               uint8_t                aSecurityLevel,
199                               uint8_t               *aNonce);
200 
201 private:
202     AesEcb   mEcb;
203     uint8_t  mBlock[AesEcb::kBlockSize];
204     uint8_t  mCtr[AesEcb::kBlockSize];
205     uint8_t  mCtrPad[AesEcb::kBlockSize];
206     uint32_t mHeaderLength;
207     uint32_t mHeaderCur;
208     uint32_t mPlainTextLength;
209     uint32_t mPlainTextCur;
210     uint16_t mBlockLength;
211     uint16_t mCtrLength;
212     uint8_t  mNonceLength;
213     uint8_t  mTagLength;
214 };
215 
216 /**
217  * @}
218  *
219  */
220 
221 } // namespace Crypto
222 } // namespace ot
223 
224 #endif // AES_CCM_HPP_
225