• 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 #include <openthread/config.h>
30 
31 #include "common/debug.hpp"
32 #include "crypto/aes_ccm.hpp"
33 
34 #include "test_platform.h"
35 #include "test_util.hpp"
36 
37 namespace ot {
38 
39 /**
40  * Verifies test vectors from IEEE 802.15.4-2006 Annex C Section C.2.1
41  */
TestMacBeaconFrame(void)42 void TestMacBeaconFrame(void)
43 {
44     uint8_t key[] = {
45         0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
46     };
47 
48     uint8_t test[] = {0x08, 0xD0, 0x84, 0x21, 0x43, 0x01, 0x00, 0x00, 0x00, 0x00, 0x48, 0xDE,
49                       0xAC, 0x02, 0x05, 0x00, 0x00, 0x00, 0x55, 0xCF, 0x00, 0x00, 0x51, 0x52,
50                       0x53, 0x54, 0x22, 0x3B, 0xC1, 0xEC, 0x84, 0x1A, 0xB5, 0x53};
51 
52     uint8_t encrypted[] = {0x08, 0xD0, 0x84, 0x21, 0x43, 0x01, 0x00, 0x00, 0x00, 0x00, 0x48, 0xDE,
53                            0xAC, 0x02, 0x05, 0x00, 0x00, 0x00, 0x55, 0xCF, 0x00, 0x00, 0x51, 0x52,
54                            0x53, 0x54, 0x22, 0x3B, 0xC1, 0xEC, 0x84, 0x1A, 0xB5, 0x53};
55 
56     uint8_t decrypted[] = {0x08, 0xD0, 0x84, 0x21, 0x43, 0x01, 0x00, 0x00, 0x00, 0x00, 0x48, 0xDE,
57                            0xAC, 0x02, 0x05, 0x00, 0x00, 0x00, 0x55, 0xCF, 0x00, 0x00, 0x51, 0x52,
58                            0x53, 0x54, 0x22, 0x3B, 0xC1, 0xEC, 0x84, 0x1A, 0xB5, 0x53};
59 
60     otInstance    *instance = testInitInstance();
61     Crypto::AesCcm aesCcm;
62     uint32_t       headerLength  = sizeof(test) - 8;
63     uint32_t       payloadLength = 0;
64     uint8_t        tagLength     = 8;
65 
66     uint8_t nonce[] = {
67         0xAC, 0xDE, 0x48, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x02,
68     };
69 
70     VerifyOrQuit(instance != nullptr);
71 
72     aesCcm.SetKey(key, sizeof(key));
73     aesCcm.Init(headerLength, payloadLength, tagLength, nonce, sizeof(nonce));
74     aesCcm.Header(test, headerLength);
75     VerifyOrQuit(aesCcm.GetTagLength() == tagLength);
76     aesCcm.Finalize(test + headerLength);
77 
78     VerifyOrQuit(memcmp(test, encrypted, sizeof(encrypted)) == 0);
79 
80     aesCcm.Init(headerLength, payloadLength, tagLength, nonce, sizeof(nonce));
81     aesCcm.Header(test, headerLength);
82     VerifyOrQuit(aesCcm.GetTagLength() == tagLength);
83     aesCcm.Finalize(test + headerLength);
84 
85     VerifyOrQuit(memcmp(test, decrypted, sizeof(decrypted)) == 0);
86 
87     testFreeInstance(instance);
88 }
89 
90 /**
91  * Verifies test vectors from IEEE 802.15.4-2006 Annex C Section C.2.3
92  */
TestMacCommandFrame(void)93 void TestMacCommandFrame(void)
94 {
95     uint8_t key[] = {
96         0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
97     };
98 
99     uint8_t test[] = {
100         0x2B, 0xDC, 0x84, 0x21, 0x43, 0x02, 0x00, 0x00, 0x00, 0x00, 0x48, 0xDE, 0xAC,
101         0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x48, 0xDE, 0xAC, 0x06, 0x05, 0x00,
102         0x00, 0x00, 0x01, 0xCE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
103     };
104 
105     static constexpr uint32_t kHeaderLength  = 29;
106     static constexpr uint32_t kPayloadLength = 1;
107     static constexpr uint8_t  kTagLength     = 8;
108 
109     uint8_t encrypted[] = {
110         0x2B, 0xDC, 0x84, 0x21, 0x43, 0x02, 0x00, 0x00, 0x00, 0x00, 0x48, 0xDE, 0xAC,
111         0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x48, 0xDE, 0xAC, 0x06, 0x05, 0x00,
112         0x00, 0x00, 0x01, 0xD8, 0x4F, 0xDE, 0x52, 0x90, 0x61, 0xF9, 0xC6, 0xF1,
113     };
114 
115     uint8_t decrypted[] = {
116         0x2B, 0xDC, 0x84, 0x21, 0x43, 0x02, 0x00, 0x00, 0x00, 0x00, 0x48, 0xDE, 0xAC,
117         0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x48, 0xDE, 0xAC, 0x06, 0x05, 0x00,
118         0x00, 0x00, 0x01, 0xCE, 0x4F, 0xDE, 0x52, 0x90, 0x61, 0xF9, 0xC6, 0xF1,
119     };
120 
121     uint8_t nonce[] = {
122         0xAC, 0xDE, 0x48, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x06,
123     };
124 
125     uint8_t tag[kTagLength];
126 
127     Instance      *instance = testInitInstance();
128     Message       *message;
129     Crypto::AesCcm aesCcm;
130 
131     VerifyOrQuit(instance != nullptr);
132 
133     aesCcm.SetKey(key, sizeof(key));
134     aesCcm.Init(kHeaderLength, kPayloadLength, kTagLength, nonce, sizeof(nonce));
135     aesCcm.Header(test, kHeaderLength);
136     aesCcm.Payload(test + kHeaderLength, test + kHeaderLength, kPayloadLength, Crypto::AesCcm::kEncrypt);
137     VerifyOrQuit(aesCcm.GetTagLength() == kTagLength);
138     aesCcm.Finalize(test + kHeaderLength + kPayloadLength);
139     VerifyOrQuit(memcmp(test, encrypted, sizeof(encrypted)) == 0);
140 
141     aesCcm.Init(kHeaderLength, kPayloadLength, kTagLength, nonce, sizeof(nonce));
142     aesCcm.Header(test, kHeaderLength);
143     aesCcm.Payload(test + kHeaderLength, test + kHeaderLength, kPayloadLength, Crypto::AesCcm::kDecrypt);
144     VerifyOrQuit(aesCcm.GetTagLength() == kTagLength);
145     aesCcm.Finalize(test + kHeaderLength + kPayloadLength);
146 
147     VerifyOrQuit(memcmp(test, decrypted, sizeof(decrypted)) == 0);
148 
149     // Verify encryption/decryption in place within a message.
150 
151     message = instance->Get<MessagePool>().Allocate(Message::kTypeIp6);
152     VerifyOrQuit(message != nullptr);
153 
154     SuccessOrQuit(message->AppendBytes(test, kHeaderLength + kPayloadLength));
155 
156     aesCcm.Init(kHeaderLength, kPayloadLength, kTagLength, nonce, sizeof(nonce));
157     aesCcm.Header(test, kHeaderLength);
158 
159     aesCcm.Payload(*message, kHeaderLength, kPayloadLength, Crypto::AesCcm::kEncrypt);
160     VerifyOrQuit(aesCcm.GetTagLength() == kTagLength);
161     aesCcm.Finalize(tag);
162     SuccessOrQuit(message->Append(tag));
163     VerifyOrQuit(message->GetLength() == sizeof(encrypted));
164     VerifyOrQuit(message->Compare(0, encrypted));
165 
166     aesCcm.Init(kHeaderLength, kPayloadLength, kTagLength, nonce, sizeof(nonce));
167     aesCcm.Header(test, kHeaderLength);
168     aesCcm.Payload(*message, kHeaderLength, kPayloadLength, Crypto::AesCcm::kDecrypt);
169 
170     VerifyOrQuit(message->GetLength() == sizeof(encrypted));
171     VerifyOrQuit(message->Compare(0, decrypted));
172 
173     message->Free();
174     testFreeInstance(instance);
175 }
176 
177 /**
178  * Verifies in-place encryption/decryption.
179  */
TestInPlaceAesCcmProcessing(void)180 void TestInPlaceAesCcmProcessing(void)
181 {
182     static constexpr uint16_t kTagLength    = 4;
183     static constexpr uint32_t kHeaderLength = 19;
184 
185     static const uint8_t kKey[] = {
186         0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
187     };
188 
189     static const uint8_t kNonce[] = {
190         0xac, 0xde, 0x48, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x06,
191     };
192 
193     static uint16_t kMessageLengths[] = {30, 400, 800};
194 
195     uint8_t tag[kTagLength];
196     uint8_t header[kHeaderLength];
197 
198     Crypto::AesCcm aesCcm;
199     Instance      *instance = testInitInstance();
200     Message       *message;
201     Message       *messageClone;
202 
203     VerifyOrQuit(instance != nullptr);
204 
205     message = instance->Get<MessagePool>().Allocate(Message::kTypeIp6);
206     VerifyOrQuit(message != nullptr);
207 
208     aesCcm.SetKey(kKey, sizeof(kKey));
209 
210     for (uint16_t msgLength : kMessageLengths)
211     {
212         printf("msgLength %d\n", msgLength);
213 
214         SuccessOrQuit(message->SetLength(0));
215 
216         for (uint16_t i = msgLength; i != 0; i--)
217         {
218             SuccessOrQuit(message->Append<uint8_t>(i & 0xff));
219         }
220 
221         messageClone = message->Clone();
222         VerifyOrQuit(messageClone != nullptr);
223         VerifyOrQuit(messageClone->GetLength() == msgLength);
224 
225         SuccessOrQuit(message->Read(0, header));
226 
227         // Encrypt in place
228         aesCcm.Init(kHeaderLength, msgLength - kHeaderLength, kTagLength, kNonce, sizeof(kNonce));
229         aesCcm.Header(header);
230         aesCcm.Payload(*message, kHeaderLength, msgLength - kHeaderLength, Crypto::AesCcm::kEncrypt);
231 
232         // Append the tag
233         aesCcm.Finalize(tag);
234         SuccessOrQuit(message->Append(tag));
235 
236         VerifyOrQuit(message->GetLength() == msgLength + kTagLength);
237 
238         // Decrypt in place
239         aesCcm.Init(kHeaderLength, msgLength - kHeaderLength, kTagLength, kNonce, sizeof(kNonce));
240         aesCcm.Header(header);
241         aesCcm.Payload(*message, kHeaderLength, msgLength - kHeaderLength, Crypto::AesCcm::kDecrypt);
242 
243         // Check the tag against what is the message
244         aesCcm.Finalize(tag);
245         VerifyOrQuit(message->Compare(msgLength, tag));
246 
247         // Check that decrypted message is the same as original (cloned) message
248         VerifyOrQuit(message->CompareBytes(0, *messageClone, 0, msgLength));
249 
250         messageClone->Free();
251     }
252 
253     message->Free();
254     testFreeInstance(instance);
255 }
256 
257 } // namespace ot
258 
main(void)259 int main(void)
260 {
261     ot::TestMacBeaconFrame();
262     ot::TestMacCommandFrame();
263     ot::TestInPlaceAesCcmProcessing();
264     printf("All tests passed\n");
265     return 0;
266 }
267