1 /*
2 * Copyright (c) 2023, 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-core-config.h"
30
31 #include "cli/cli_utils.hpp"
32
33 #include "cli/cli_tcat.hpp"
34
35 #include <openthread/ble_secure.h>
36
37 #include <mbedtls/oid.h>
38 #include <openthread/tcat.h>
39 #include <openthread/platform/ble.h>
40
41 #if OPENTHREAD_CONFIG_BLE_TCAT_ENABLE && OPENTHREAD_CONFIG_CLI_BLE_SECURE_ENABLE
42
43 #define OT_CLI_TCAT_X509_CERT \
44 "-----BEGIN CERTIFICATE-----\r\n" \
45 "MIIBmDCCAT+gAwIBAgIEAQIDBDAKBggqhkjOPQQDAjBvMQswCQYDVQQGEwJYWDEQ\r\n" \
46 "MA4GA1UECBMHTXlTdGF0ZTEPMA0GA1UEBxMGTXlDaXR5MQ8wDQYDVQQLEwZNeVVu\r\n" \
47 "aXQxETAPBgNVBAoTCE15VmVuZG9yMRkwFwYDVQQDExB3d3cubXl2ZW5kb3IuY29t\r\n" \
48 "MB4XDTIzMTAxNjEwMzk1NFoXDTI0MTAxNjEwMzk1NFowIjEgMB4GA1UEAxMXbXl2\r\n" \
49 "ZW5kb3IuY29tL3RjYXQvbXlkZXYwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAQB\r\n" \
50 "aWwFDNj1bpQIdN+Kp2cHWw55U/+fa+OmZnoy1B4BOT+822jdwPBuyXWAQoBdYdQJ\r\n" \
51 "ff4RgmhczyV4PhArPIuAoxYwFDASBgkrBgEEAYLfKgMEBQABAQEBMAoGCCqGSM49\r\n" \
52 "BAMCA0cAMEQCIBEHxiEDij26y6V77Q311Gj4CZAuZuPGXZpnzL2BLk7bAiAlFk6G\r\n" \
53 "mYGzkcrYyssFI9HlPgrisWoMmgummaTtCuvrEw==\r\n" \
54 "-----END CERTIFICATE-----\r\n"
55
56 #define OT_CLI_TCAT_PRIV_KEY \
57 "-----BEGIN EC PRIVATE KEY-----\r\n" \
58 "MHcCAQEEIDeJ6lVQKiOIBxKwTZp6TkU5QVHt9pvXOR9CGpPBI3DhoAoGCCqGSM49\r\n" \
59 "AwEHoUQDQgAEAWlsBQzY9W6UCHTfiqdnB1sOeVP/n2vjpmZ6MtQeATk/vNto3cDw\r\n" \
60 "bsl1gEKAXWHUCX3+EYJoXM8leD4QKzyLgA==\r\n" \
61 "-----END EC PRIVATE KEY-----\r\n"
62
63 #define OT_CLI_TCAT_TRUSTED_ROOT_CERTIFICATE \
64 "-----BEGIN CERTIFICATE-----\r\n" \
65 "MIICCDCCAa2gAwIBAgIJAIKxygBXoH+5MAoGCCqGSM49BAMCMG8xCzAJBgNVBAYT\r\n" \
66 "AlhYMRAwDgYDVQQIEwdNeVN0YXRlMQ8wDQYDVQQHEwZNeUNpdHkxDzANBgNVBAsT\r\n" \
67 "Bk15VW5pdDERMA8GA1UEChMITXlWZW5kb3IxGTAXBgNVBAMTEHd3dy5teXZlbmRv\r\n" \
68 "ci5jb20wHhcNMjMxMDE2MTAzMzE1WhcNMjYxMDE2MTAzMzE1WjBvMQswCQYDVQQG\r\n" \
69 "EwJYWDEQMA4GA1UECBMHTXlTdGF0ZTEPMA0GA1UEBxMGTXlDaXR5MQ8wDQYDVQQL\r\n" \
70 "EwZNeVVuaXQxETAPBgNVBAoTCE15VmVuZG9yMRkwFwYDVQQDExB3d3cubXl2ZW5k\r\n" \
71 "b3IuY29tMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEWdyzPAXGKeZY94OhHAWX\r\n" \
72 "HzJfQIjGSyaOzlgL9OEFw2SoUDncLKPGwfPAUSfuMyEkzszNDM0HHkBsDLqu4n25\r\n" \
73 "/6MyMDAwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU4EynoSw9eDKZEVPkums2\r\n" \
74 "IWLAJCowCgYIKoZIzj0EAwIDSQAwRgIhAMYGGL9xShyE6P9wEU+MAYF6W3CzdrwV\r\n" \
75 "kuerX1encIH2AiEA5rq490NUobM1Au43roxJq1T6Z43LscPVbGZfULD1Jq0=\r\n" \
76 "-----END CERTIFICATE-----\r\n"
77
78 namespace ot {
79
80 namespace Cli {
81
82 const char kPskdVendor[] = "J01NM3";
83 const char kUrl[] = "dummy_url";
84
HandleBleSecureReceive(otInstance * aInstance,const otMessage * aMessage,int32_t aOffset,otTcatApplicationProtocol aTcatApplicationProtocol,const char * aServiceName,void * aContext)85 static void HandleBleSecureReceive(otInstance *aInstance,
86 const otMessage *aMessage,
87 int32_t aOffset,
88 otTcatApplicationProtocol aTcatApplicationProtocol,
89 const char *aServiceName,
90 void *aContext)
91 {
92 OT_UNUSED_VARIABLE(aContext);
93 OT_UNUSED_VARIABLE(aTcatApplicationProtocol);
94 OT_UNUSED_VARIABLE(aServiceName);
95
96 static constexpr int kTextMaxLen = 100;
97 static constexpr uint8_t kBufPrefixLen = 5;
98
99 uint16_t nLen;
100 uint8_t buf[kTextMaxLen];
101
102 nLen = otMessageRead(aMessage, (uint16_t)aOffset, buf + kBufPrefixLen, sizeof(buf) - kBufPrefixLen - 1);
103
104 memcpy(buf, "RECV:", kBufPrefixLen);
105
106 buf[nLen + kBufPrefixLen] = 0;
107
108 IgnoreReturnValue(otBleSecureSendApplicationTlv(aInstance, buf, (uint16_t)strlen((char *)buf)));
109 IgnoreReturnValue(otBleSecureFlush(aInstance));
110 }
111
Process(Arg aArgs[])112 template <> otError Tcat::Process<Cmd("start")>(Arg aArgs[])
113 {
114 OT_UNUSED_VARIABLE(aArgs);
115
116 otError error = OT_ERROR_NONE;
117
118 ClearAllBytes(mVendorInfo);
119 mVendorInfo.mPskdString = kPskdVendor;
120 mVendorInfo.mProvisioningUrl = kUrl;
121
122 otBleSecureSetCertificate(GetInstancePtr(), reinterpret_cast<const uint8_t *>(OT_CLI_TCAT_X509_CERT),
123 sizeof(OT_CLI_TCAT_X509_CERT), reinterpret_cast<const uint8_t *>(OT_CLI_TCAT_PRIV_KEY),
124 sizeof(OT_CLI_TCAT_PRIV_KEY));
125
126 otBleSecureSetCaCertificateChain(GetInstancePtr(),
127 reinterpret_cast<const uint8_t *>(OT_CLI_TCAT_TRUSTED_ROOT_CERTIFICATE),
128 sizeof(OT_CLI_TCAT_TRUSTED_ROOT_CERTIFICATE));
129
130 otBleSecureSetSslAuthMode(GetInstancePtr(), true);
131
132 SuccessOrExit(error = otBleSecureStart(GetInstancePtr(), nullptr, HandleBleSecureReceive, true, nullptr));
133 SuccessOrExit(error = otBleSecureTcatStart(GetInstancePtr(), &mVendorInfo, nullptr));
134
135 exit:
136 return error;
137 }
138
Process(Arg aArgs[])139 template <> otError Tcat::Process<Cmd("stop")>(Arg aArgs[])
140 {
141 OT_UNUSED_VARIABLE(aArgs);
142
143 otBleSecureStop(GetInstancePtr());
144
145 return OT_ERROR_NONE;
146 }
147
Process(Arg aArgs[])148 otError Tcat::Process(Arg aArgs[])
149 {
150 #define CmdEntry(aCommandString) \
151 { \
152 aCommandString, &Tcat::Process<Cmd(aCommandString)> \
153 }
154
155 static constexpr Command kCommands[] = {CmdEntry("start"), CmdEntry("stop")};
156
157 static_assert(BinarySearch::IsSorted(kCommands), "kCommands is not sorted");
158
159 otError error = OT_ERROR_NONE;
160 const Command *command;
161
162 if (aArgs[0].IsEmpty() || (aArgs[0] == "help"))
163 {
164 OutputCommandTable(kCommands);
165 ExitNow(error = aArgs[0].IsEmpty() ? error : OT_ERROR_NONE);
166 }
167
168 command = BinarySearch::Find(aArgs[0].GetCString(), kCommands);
169 VerifyOrExit(command != nullptr);
170
171 error = (this->*command->mHandler)(aArgs + 1);
172
173 exit:
174 return error;
175 }
176
177 } // namespace Cli
178 } // namespace ot
179 #endif // OPENTHREAD_CONFIG_BLE_TCAT_ENABLE && OPENTHREAD_CONFIG_CLI_BLE_SECURE_ENABLE
180