1 /*
2 * SPDX-FileCopyrightText: 2019-2021 Espressif Systems (Shanghai) CO LTD
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6 #include <stdio.h>
7 #include <string.h>
8 #include <stdlib.h>
9 #include <unistd.h>
10
11 #include <sys/types.h>
12 #include <sys/socket.h>
13 #include <netdb.h>
14
15 #include <http_parser.h>
16 #include "esp_tls_mbedtls.h"
17 #include "esp_tls_error_capture_internal.h"
18 #include <errno.h>
19 #include "esp_log.h"
20
21 #ifdef CONFIG_MBEDTLS_CERTIFICATE_BUNDLE
22 #include "esp_crt_bundle.h"
23 #endif
24
25 #ifdef CONFIG_ESP_TLS_USE_SECURE_ELEMENT
26
27 #define ATECC608A_TNG_SLAVE_ADDR 0x6A
28 #define ATECC608A_TFLEX_SLAVE_ADDR 0x6C
29 #define ATECC608A_TCUSTOM_SLAVE_ADDR 0xC0
30 /* cryptoauthlib includes */
31 #include "mbedtls/atca_mbedtls_wrap.h"
32 #include "tng_atca.h"
33 #include "cryptoauthlib.h"
34 static const atcacert_def_t *cert_def = NULL;
35 /* Prototypes for functions */
36 static esp_err_t esp_set_atecc608a_pki_context(esp_tls_t *tls, esp_tls_cfg_t *cfg);
37 #endif /* CONFIG_ESP_TLS_USE_SECURE_ELEMENT */
38
39 #if defined(CONFIG_ESP_TLS_USE_DS_PERIPHERAL)
40 #include "rsa_sign_alt.h"
41 static esp_err_t esp_mbedtls_init_pk_ctx_for_ds(const void *pki);
42 #endif /* CONFIG_ESP_TLS_USE_DS_PERIPHERAL */
43
44 static const char *TAG = "esp-tls-mbedtls";
45 static mbedtls_x509_crt *global_cacert = NULL;
46
47 /* This function shall return the error message when appropriate log level has been set, otherwise this function shall do nothing */
mbedtls_print_error_msg(int error)48 static void mbedtls_print_error_msg(int error)
49 {
50 #if (CONFIG_LOG_DEFAULT_LEVEL_DEBUG || CONFIG_LOG_DEFAULT_LEVEL_VERBOSE)
51 static char error_buf[100];
52 mbedtls_strerror(error, error_buf, sizeof(error_buf));
53 ESP_LOGI(TAG, "(%04X): %s", error, error_buf);
54 #endif
55 }
56
57 typedef struct esp_tls_pki_t {
58 mbedtls_x509_crt *public_cert;
59 mbedtls_pk_context *pk_key;
60 const unsigned char *publiccert_pem_buf;
61 unsigned int publiccert_pem_bytes;
62 const unsigned char *privkey_pem_buf;
63 unsigned int privkey_pem_bytes;
64 const unsigned char *privkey_password;
65 unsigned int privkey_password_len;
66 #ifdef CONFIG_ESP_TLS_USE_DS_PERIPHERAL
67 void *esp_ds_data;
68 #endif
69 } esp_tls_pki_t;
70
esp_create_mbedtls_handle(const char * hostname,size_t hostlen,const void * cfg,esp_tls_t * tls)71 esp_err_t esp_create_mbedtls_handle(const char *hostname, size_t hostlen, const void *cfg, esp_tls_t *tls)
72 {
73 assert(cfg != NULL);
74 assert(tls != NULL);
75 int ret;
76 esp_err_t esp_ret = ESP_FAIL;
77 tls->server_fd.fd = tls->sockfd;
78 mbedtls_ssl_init(&tls->ssl);
79 mbedtls_ctr_drbg_init(&tls->ctr_drbg);
80 mbedtls_ssl_config_init(&tls->conf);
81 mbedtls_entropy_init(&tls->entropy);
82
83 if (tls->role == ESP_TLS_CLIENT) {
84 esp_ret = set_client_config(hostname, hostlen, (esp_tls_cfg_t *)cfg, tls);
85 if (esp_ret != ESP_OK) {
86 ESP_LOGE(TAG, "Failed to set client configurations, returned [0x%04X] (%s)", esp_ret, esp_err_to_name(esp_ret));
87 goto exit;
88 }
89 } else if (tls->role == ESP_TLS_SERVER) {
90 #ifdef CONFIG_ESP_TLS_SERVER
91 esp_ret = set_server_config((esp_tls_cfg_server_t *) cfg, tls);
92 if (esp_ret != 0) {
93 ESP_LOGE(TAG, "Failed to set server configurations, returned [0x%04X] (%s)", esp_ret, esp_err_to_name(esp_ret));
94 goto exit;
95 }
96 #else
97 ESP_LOGE(TAG, "ESP_TLS_SERVER Not enabled in Kconfig");
98 goto exit;
99 #endif
100 }
101
102 if ((ret = mbedtls_ctr_drbg_seed(&tls->ctr_drbg,
103 mbedtls_entropy_func, &tls->entropy, NULL, 0)) != 0) {
104 ESP_LOGE(TAG, "mbedtls_ctr_drbg_seed returned -0x%04X", -ret);
105 mbedtls_print_error_msg(ret);
106 ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ESP_TLS_ERR_TYPE_MBEDTLS, -ret);
107 esp_ret = ESP_ERR_MBEDTLS_CTR_DRBG_SEED_FAILED;
108 goto exit;
109 }
110
111 mbedtls_ssl_conf_rng(&tls->conf, mbedtls_ctr_drbg_random, &tls->ctr_drbg);
112
113 #ifdef CONFIG_MBEDTLS_DEBUG
114 mbedtls_esp_enable_debug_log(&tls->conf, CONFIG_MBEDTLS_DEBUG_LEVEL);
115 #endif
116
117 if ((ret = mbedtls_ssl_setup(&tls->ssl, &tls->conf)) != 0) {
118 ESP_LOGE(TAG, "mbedtls_ssl_setup returned -0x%04X", -ret);
119 mbedtls_print_error_msg(ret);
120 ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ESP_TLS_ERR_TYPE_MBEDTLS, -ret);
121 esp_ret = ESP_ERR_MBEDTLS_SSL_SETUP_FAILED;
122 goto exit;
123 }
124 mbedtls_ssl_set_bio(&tls->ssl, &tls->server_fd, mbedtls_net_send, mbedtls_net_recv, NULL);
125
126 return ESP_OK;
127
128 exit:
129 esp_mbedtls_cleanup(tls);
130 return esp_ret;
131
132 }
133
134 #ifdef CONFIG_ESP_TLS_CLIENT_SESSION_TICKETS
esp_mbedtls_get_client_session(esp_tls_t * tls)135 esp_tls_client_session_t *esp_mbedtls_get_client_session(esp_tls_t *tls)
136 {
137 if (tls == NULL) {
138 ESP_LOGE(TAG, "esp_tls session context cannot be NULL");
139 return NULL;
140 }
141
142 esp_tls_client_session_t *client_session = (esp_tls_client_session_t*)calloc(1, sizeof(esp_tls_client_session_t));
143 if (client_session == NULL) {
144 ESP_LOGE(TAG, "Failed to allocate memory for client session ctx");
145 return NULL;
146 }
147
148 int ret = mbedtls_ssl_get_session(&tls->ssl, &(client_session->saved_session));
149 if (ret != 0) {
150 ESP_LOGE(TAG, "Error in obtaining the client ssl session");
151 mbedtls_print_error_msg(ret);
152 free(client_session);
153 return NULL;
154 }
155
156 return client_session;
157 }
158 #endif /* CONFIG_ESP_TLS_CLIENT_SESSION_TICKETS */
159
esp_mbedtls_handshake(esp_tls_t * tls,const esp_tls_cfg_t * cfg)160 int esp_mbedtls_handshake(esp_tls_t *tls, const esp_tls_cfg_t *cfg)
161 {
162 int ret;
163 #ifdef CONFIG_ESP_TLS_CLIENT_SESSION_TICKETS
164 if (cfg->client_session != NULL) {
165 ESP_LOGD(TAG, "Reusing the already saved client session context");
166 if ((ret = mbedtls_ssl_set_session(&tls->ssl, &(cfg->client_session->saved_session))) != 0 ) {
167 ESP_LOGE(TAG, " mbedtls_ssl_conf_session returned -0x%04X", -ret);
168 return -1;
169 }
170 }
171 #endif
172 ret = mbedtls_ssl_handshake(&tls->ssl);
173 if (ret == 0) {
174 tls->conn_state = ESP_TLS_DONE;
175
176 #ifdef CONFIG_ESP_TLS_USE_DS_PERIPHERAL
177 esp_ds_release_ds_lock();
178 #endif
179 return 1;
180 } else {
181 if (ret != ESP_TLS_ERR_SSL_WANT_READ && ret != ESP_TLS_ERR_SSL_WANT_WRITE) {
182 ESP_LOGE(TAG, "mbedtls_ssl_handshake returned -0x%04X", -ret);
183 mbedtls_print_error_msg(ret);
184 ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ESP_TLS_ERR_TYPE_MBEDTLS, -ret);
185 ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ESP_TLS_ERR_TYPE_ESP, ESP_ERR_MBEDTLS_SSL_HANDSHAKE_FAILED);
186 if (cfg->cacert_buf != NULL || cfg->use_global_ca_store == true) {
187 /* This is to check whether handshake failed due to invalid certificate*/
188 esp_mbedtls_verify_certificate(tls);
189 }
190 tls->conn_state = ESP_TLS_FAIL;
191 return -1;
192 }
193 /* Irrespective of blocking or non-blocking I/O, we return on getting ESP_TLS_ERR_SSL_WANT_READ
194 or ESP_TLS_ERR_SSL_WANT_WRITE during handshake */
195 return 0;
196 }
197 }
198
esp_mbedtls_read(esp_tls_t * tls,char * data,size_t datalen)199 ssize_t esp_mbedtls_read(esp_tls_t *tls, char *data, size_t datalen)
200 {
201
202 ssize_t ret = mbedtls_ssl_read(&tls->ssl, (unsigned char *)data, datalen);
203 if (ret < 0) {
204 if (ret == MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY) {
205 return 0;
206 }
207 if (ret != ESP_TLS_ERR_SSL_WANT_READ && ret != ESP_TLS_ERR_SSL_WANT_WRITE) {
208 ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ESP_TLS_ERR_TYPE_MBEDTLS, -ret);
209 ESP_LOGE(TAG, "read error :-0x%04X:", -ret);
210 mbedtls_print_error_msg(ret);
211 }
212 }
213 return ret;
214 }
215
esp_mbedtls_write(esp_tls_t * tls,const char * data,size_t datalen)216 ssize_t esp_mbedtls_write(esp_tls_t *tls, const char *data, size_t datalen)
217 {
218 size_t written = 0;
219 size_t write_len = datalen;
220 while (written < datalen) {
221 if (write_len > MBEDTLS_SSL_OUT_CONTENT_LEN) {
222 write_len = MBEDTLS_SSL_OUT_CONTENT_LEN;
223 }
224 if (datalen > MBEDTLS_SSL_OUT_CONTENT_LEN) {
225 ESP_LOGD(TAG, "Fragmenting data of excessive size :%d, offset: %d, size %d", datalen, written, write_len);
226 }
227 ssize_t ret = mbedtls_ssl_write(&tls->ssl, (unsigned char*) data + written, write_len);
228 if (ret <= 0) {
229 if (ret != ESP_TLS_ERR_SSL_WANT_READ && ret != ESP_TLS_ERR_SSL_WANT_WRITE && ret != 0) {
230 ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ESP_TLS_ERR_TYPE_MBEDTLS, -ret);
231 ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ESP_TLS_ERR_TYPE_ESP, ESP_ERR_MBEDTLS_SSL_WRITE_FAILED);
232 ESP_LOGE(TAG, "write error :-0x%04X:", -ret);
233 mbedtls_print_error_msg(ret);
234 return ret;
235 } else {
236 // Exiting the tls-write process as less than desired datalen are writable
237 ESP_LOGD(TAG, "mbedtls_ssl_write() returned -0x%04X, already written %d, exitting...", -ret, written);
238 mbedtls_print_error_msg(ret);
239 return (written > 0) ? written : ret;
240 }
241 }
242 written += ret;
243 write_len = datalen - written;
244 }
245 return written;
246 }
247
esp_mbedtls_conn_delete(esp_tls_t * tls)248 void esp_mbedtls_conn_delete(esp_tls_t *tls)
249 {
250 if (tls != NULL) {
251 esp_mbedtls_cleanup(tls);
252 if (tls->is_tls) {
253 mbedtls_net_free(&tls->server_fd);
254 tls->sockfd = tls->server_fd.fd;
255 }
256 }
257 }
258
esp_mbedtls_verify_certificate(esp_tls_t * tls)259 void esp_mbedtls_verify_certificate(esp_tls_t *tls)
260 {
261 int flags;
262
263 if ((flags = mbedtls_ssl_get_verify_result(&tls->ssl)) != 0) {
264 ESP_LOGI(TAG, "Failed to verify peer certificate!");
265 ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ESP_TLS_ERR_TYPE_MBEDTLS_CERT_FLAGS, flags);
266 #if (CONFIG_LOG_DEFAULT_LEVEL > CONFIG_LOG_DEFAULT_LEVEL_DEBUG)
267 char buf[100];
268 bzero(buf, sizeof(buf));
269 mbedtls_x509_crt_verify_info(buf, sizeof(buf), " ! ", flags);
270 ESP_LOGD(TAG, "verification info: %s", buf);
271 #endif
272 } else {
273 ESP_LOGI(TAG, "Certificate verified.");
274 }
275 }
276
esp_mbedtls_get_bytes_avail(esp_tls_t * tls)277 ssize_t esp_mbedtls_get_bytes_avail(esp_tls_t *tls)
278 {
279 if (!tls) {
280 ESP_LOGE(TAG, "empty arg passed to esp_tls_get_bytes_avail()");
281 return ESP_FAIL;
282 }
283 return mbedtls_ssl_get_bytes_avail(&tls->ssl);
284 }
285
esp_mbedtls_cleanup(esp_tls_t * tls)286 void esp_mbedtls_cleanup(esp_tls_t *tls)
287 {
288 if (!tls) {
289 return;
290 }
291 if (tls->cacert_ptr != global_cacert) {
292 mbedtls_x509_crt_free(tls->cacert_ptr);
293 }
294 tls->cacert_ptr = NULL;
295 #ifdef CONFIG_ESP_TLS_SERVER
296 mbedtls_x509_crt_free(&tls->servercert);
297 mbedtls_pk_free(&tls->serverkey);
298 #endif
299 mbedtls_x509_crt_free(&tls->cacert);
300 mbedtls_x509_crt_free(&tls->clientcert);
301 mbedtls_pk_free(&tls->clientkey);
302 mbedtls_entropy_free(&tls->entropy);
303 mbedtls_ssl_config_free(&tls->conf);
304 mbedtls_ctr_drbg_free(&tls->ctr_drbg);
305 mbedtls_ssl_free(&tls->ssl);
306 #ifdef CONFIG_ESP_TLS_USE_SECURE_ELEMENT
307 atcab_release();
308 #endif
309 #ifdef CONFIG_ESP_TLS_USE_DS_PERIPHERAL
310 esp_ds_release_ds_lock();
311 #endif
312 }
313
set_ca_cert(esp_tls_t * tls,const unsigned char * cacert,size_t cacert_len)314 static esp_err_t set_ca_cert(esp_tls_t *tls, const unsigned char *cacert, size_t cacert_len)
315 {
316 assert(tls);
317 tls->cacert_ptr = &tls->cacert;
318 mbedtls_x509_crt_init(tls->cacert_ptr);
319 int ret = mbedtls_x509_crt_parse(tls->cacert_ptr, cacert, cacert_len);
320 if (ret < 0) {
321 ESP_LOGE(TAG, "mbedtls_x509_crt_parse returned -0x%04X", -ret);
322 mbedtls_print_error_msg(ret);
323 ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ESP_TLS_ERR_TYPE_MBEDTLS, -ret);
324 return ESP_ERR_MBEDTLS_X509_CRT_PARSE_FAILED;
325 }
326 if (ret > 0) {
327 /* This will happen if the CA chain contains one or more invalid certs, going ahead as the hadshake
328 * may still succeed if the other certificates in the CA chain are enough for the authentication */
329 ESP_LOGW(TAG, "mbedtls_x509_crt_parse was partly successful. No. of failed certificates: %d", ret);
330 }
331 mbedtls_ssl_conf_authmode(&tls->conf, MBEDTLS_SSL_VERIFY_REQUIRED);
332 mbedtls_ssl_conf_ca_chain(&tls->conf, tls->cacert_ptr, NULL);
333 return ESP_OK;
334 }
335
set_pki_context(esp_tls_t * tls,const esp_tls_pki_t * pki)336 static esp_err_t set_pki_context(esp_tls_t *tls, const esp_tls_pki_t *pki)
337 {
338 assert(tls);
339 assert(pki);
340 int ret;
341
342 if (pki->publiccert_pem_buf != NULL &&
343 pki->public_cert != NULL &&
344 pki->pk_key != NULL) {
345
346 mbedtls_x509_crt_init(pki->public_cert);
347 mbedtls_pk_init(pki->pk_key);
348
349 ret = mbedtls_x509_crt_parse(pki->public_cert, pki->publiccert_pem_buf, pki->publiccert_pem_bytes);
350 if (ret < 0) {
351 ESP_LOGE(TAG, "mbedtls_x509_crt_parse returned -0x%04X", -ret);
352 mbedtls_print_error_msg(ret);
353 ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ESP_TLS_ERR_TYPE_MBEDTLS, -ret);
354 return ESP_ERR_MBEDTLS_X509_CRT_PARSE_FAILED;
355 }
356
357 #ifdef CONFIG_ESP_TLS_USE_DS_PERIPHERAL
358 if (pki->esp_ds_data != NULL) {
359 ret = esp_mbedtls_init_pk_ctx_for_ds(pki);
360 if (ret != ESP_OK) {
361 ESP_LOGE(TAG, "Failed to initialize pk context for esp_ds");
362 return ret;
363 }
364 } else
365 #endif
366 if (pki->privkey_pem_buf != NULL) {
367 ret = mbedtls_pk_parse_key(pki->pk_key, pki->privkey_pem_buf, pki->privkey_pem_bytes,
368 pki->privkey_password, pki->privkey_password_len);
369 } else {
370 return ESP_ERR_INVALID_ARG;
371 }
372
373 if (ret < 0) {
374 ESP_LOGE(TAG, "mbedtls_pk_parse_keyfile returned -0x%04X", -ret);
375 mbedtls_print_error_msg(ret);
376 ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ESP_TLS_ERR_TYPE_MBEDTLS, -ret);
377 return ESP_ERR_MBEDTLS_PK_PARSE_KEY_FAILED;
378 }
379
380 ret = mbedtls_ssl_conf_own_cert(&tls->conf, pki->public_cert, pki->pk_key);
381 if (ret < 0) {
382 ESP_LOGE(TAG, "mbedtls_ssl_conf_own_cert returned -0x%04X", -ret);
383 mbedtls_print_error_msg(ret);
384 ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ESP_TLS_ERR_TYPE_MBEDTLS, -ret);
385 return ESP_ERR_MBEDTLS_SSL_CONF_OWN_CERT_FAILED;
386 }
387 } else {
388 return ESP_ERR_INVALID_ARG;
389 }
390 return ESP_OK;
391 }
392
set_global_ca_store(esp_tls_t * tls)393 static esp_err_t set_global_ca_store(esp_tls_t *tls)
394 {
395 assert(tls);
396 if (global_cacert == NULL) {
397 ESP_LOGE(TAG, "global_cacert is NULL");
398 return ESP_ERR_INVALID_STATE;
399 }
400 tls->cacert_ptr = global_cacert;
401 mbedtls_ssl_conf_authmode(&tls->conf, MBEDTLS_SSL_VERIFY_REQUIRED);
402 mbedtls_ssl_conf_ca_chain(&tls->conf, tls->cacert_ptr, NULL);
403 return ESP_OK;
404 }
405
406 #ifdef CONFIG_ESP_TLS_SERVER
407 #ifdef CONFIG_ESP_TLS_SERVER_SESSION_TICKETS
esp_mbedtls_server_session_ticket_write(void * p_ticket,const mbedtls_ssl_session * session,unsigned char * start,const unsigned char * end,size_t * tlen,uint32_t * lifetime)408 int esp_mbedtls_server_session_ticket_write(void *p_ticket, const mbedtls_ssl_session *session, unsigned char *start, const unsigned char *end, size_t *tlen, uint32_t *lifetime)
409 {
410 int ret = mbedtls_ssl_ticket_write(p_ticket, session, start, end, tlen, lifetime);
411 #ifndef NDEBUG
412 if (ret != 0) {
413 ESP_LOGE(TAG, "Writing session ticket resulted in error code -0x%04X", -ret);
414 mbedtls_print_error_msg(ret);
415 }
416 #endif
417 return ret;
418 }
419
esp_mbedtls_server_session_ticket_parse(void * p_ticket,mbedtls_ssl_session * session,unsigned char * buf,size_t len)420 int esp_mbedtls_server_session_ticket_parse(void *p_ticket, mbedtls_ssl_session *session, unsigned char *buf, size_t len)
421 {
422 int ret = mbedtls_ssl_ticket_parse(p_ticket, session, buf, len);
423 #ifndef NDEBUG
424 if (ret != 0) {
425 ESP_LOGD(TAG, "Parsing session ticket resulted in error code -0x%04X", -ret);
426 mbedtls_print_error_msg(ret);
427 }
428 #endif
429 return ret;
430 }
431
esp_mbedtls_server_session_ticket_ctx_init(esp_tls_server_session_ticket_ctx_t * ctx)432 esp_err_t esp_mbedtls_server_session_ticket_ctx_init(esp_tls_server_session_ticket_ctx_t *ctx)
433 {
434 if (!ctx) {
435 return ESP_ERR_INVALID_ARG;
436 }
437 mbedtls_ctr_drbg_init(&ctx->ctr_drbg);
438 mbedtls_entropy_init(&ctx->entropy);
439 mbedtls_ssl_ticket_init(&ctx->ticket_ctx);
440 int ret;
441 esp_err_t esp_ret;
442 if ((ret = mbedtls_ctr_drbg_seed(&ctx->ctr_drbg,
443 mbedtls_entropy_func, &ctx->entropy, NULL, 0)) != 0) {
444 ESP_LOGE(TAG, "mbedtls_ctr_drbg_seed returned -0x%04X", -ret);
445 mbedtls_print_error_msg(ret);
446 esp_ret = ESP_ERR_MBEDTLS_CTR_DRBG_SEED_FAILED;
447 goto exit;
448 }
449
450 if((ret = mbedtls_ssl_ticket_setup(&ctx->ticket_ctx,
451 mbedtls_ctr_drbg_random, &ctx->ctr_drbg,
452 MBEDTLS_CIPHER_AES_256_GCM,
453 CONFIG_ESP_TLS_SERVER_SESSION_TICKET_TIMEOUT)) != 0) {
454 ESP_LOGE(TAG, "mbedtls_ssl_ticket_setup returned -0x%04X", -ret);
455 mbedtls_print_error_msg(ret);
456 esp_ret = ESP_ERR_MBEDTLS_SSL_TICKET_SETUP_FAILED;
457 goto exit;
458 }
459 return ESP_OK;
460 exit:
461 esp_mbedtls_server_session_ticket_ctx_free(ctx);
462 return esp_ret;
463 }
464
esp_mbedtls_server_session_ticket_ctx_free(esp_tls_server_session_ticket_ctx_t * ctx)465 void esp_mbedtls_server_session_ticket_ctx_free(esp_tls_server_session_ticket_ctx_t *ctx)
466 {
467 if (ctx) {
468 mbedtls_ssl_ticket_free(&ctx->ticket_ctx);
469 mbedtls_ctr_drbg_init(&ctx->ctr_drbg);
470 mbedtls_entropy_free(&ctx->entropy);
471 }
472 }
473 #endif
474
set_server_config(esp_tls_cfg_server_t * cfg,esp_tls_t * tls)475 esp_err_t set_server_config(esp_tls_cfg_server_t *cfg, esp_tls_t *tls)
476 {
477 assert(cfg != NULL);
478 assert(tls != NULL);
479 int ret;
480 esp_err_t esp_ret;
481 if ((ret = mbedtls_ssl_config_defaults(&tls->conf,
482 MBEDTLS_SSL_IS_SERVER,
483 MBEDTLS_SSL_TRANSPORT_STREAM,
484 MBEDTLS_SSL_PRESET_DEFAULT)) != 0) {
485 ESP_LOGE(TAG, "mbedtls_ssl_config_defaults returned -0x%04X", -ret);
486 mbedtls_print_error_msg(ret);
487 ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ESP_TLS_ERR_TYPE_MBEDTLS, -ret);
488 return ESP_ERR_MBEDTLS_SSL_CONFIG_DEFAULTS_FAILED;
489 }
490
491 #ifdef CONFIG_MBEDTLS_SSL_ALPN
492 if (cfg->alpn_protos) {
493 mbedtls_ssl_conf_alpn_protocols(&tls->conf, cfg->alpn_protos);
494 }
495 #endif
496
497 if (cfg->cacert_buf != NULL) {
498 esp_ret = set_ca_cert(tls, cfg->cacert_buf, cfg->cacert_bytes);
499 if (esp_ret != ESP_OK) {
500 return esp_ret;
501 }
502 } else {
503 mbedtls_ssl_conf_authmode(&tls->conf, MBEDTLS_SSL_VERIFY_OPTIONAL);
504 }
505
506 if (cfg->servercert_buf != NULL && cfg->serverkey_buf != NULL) {
507 esp_tls_pki_t pki = {
508 .public_cert = &tls->servercert,
509 .pk_key = &tls->serverkey,
510 .publiccert_pem_buf = cfg->servercert_buf,
511 .publiccert_pem_bytes = cfg->servercert_bytes,
512 .privkey_pem_buf = cfg->serverkey_buf,
513 .privkey_pem_bytes = cfg->serverkey_bytes,
514 .privkey_password = cfg->serverkey_password,
515 .privkey_password_len = cfg->serverkey_password_len,
516 };
517 esp_ret = set_pki_context(tls, &pki);
518 if (esp_ret != ESP_OK) {
519 ESP_LOGE(TAG, "Failed to set server pki context");
520 return esp_ret;
521 }
522 } else {
523 ESP_LOGE(TAG, "Missing server certificate and/or key");
524 return ESP_ERR_INVALID_STATE;
525 }
526
527 #ifdef CONFIG_ESP_TLS_SERVER_SESSION_TICKETS
528 if (cfg->ticket_ctx) {
529 ESP_LOGD(TAG, "Enabling server-side tls session ticket support");
530
531 mbedtls_ssl_conf_session_tickets_cb( &tls->conf,
532 esp_mbedtls_server_session_ticket_write,
533 esp_mbedtls_server_session_ticket_parse,
534 &cfg->ticket_ctx->ticket_ctx );
535 }
536 #endif
537
538 return ESP_OK;
539 }
540 #endif /* ! CONFIG_ESP_TLS_SERVER */
541
set_client_config(const char * hostname,size_t hostlen,esp_tls_cfg_t * cfg,esp_tls_t * tls)542 esp_err_t set_client_config(const char *hostname, size_t hostlen, esp_tls_cfg_t *cfg, esp_tls_t *tls)
543 {
544 assert(cfg != NULL);
545 assert(tls != NULL);
546 int ret;
547 if (!cfg->skip_common_name) {
548 char *use_host = NULL;
549 if (cfg->common_name != NULL) {
550 use_host = strndup(cfg->common_name, strlen(cfg->common_name));
551 } else {
552 use_host = strndup(hostname, hostlen);
553 }
554
555 if (use_host == NULL) {
556 return ESP_ERR_NO_MEM;
557 }
558 /* Hostname set here should match CN in server certificate */
559 if ((ret = mbedtls_ssl_set_hostname(&tls->ssl, use_host)) != 0) {
560 ESP_LOGE(TAG, "mbedtls_ssl_set_hostname returned -0x%04X", -ret);
561 mbedtls_print_error_msg(ret);
562 ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ESP_TLS_ERR_TYPE_MBEDTLS, -ret);
563 free(use_host);
564 return ESP_ERR_MBEDTLS_SSL_SET_HOSTNAME_FAILED;
565 }
566 free(use_host);
567 }
568
569 if ((ret = mbedtls_ssl_config_defaults(&tls->conf,
570 MBEDTLS_SSL_IS_CLIENT,
571 MBEDTLS_SSL_TRANSPORT_STREAM,
572 MBEDTLS_SSL_PRESET_DEFAULT)) != 0) {
573 ESP_LOGE(TAG, "mbedtls_ssl_config_defaults returned -0x%04X", -ret);
574 mbedtls_print_error_msg(ret);
575 ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ESP_TLS_ERR_TYPE_MBEDTLS, -ret);
576 return ESP_ERR_MBEDTLS_SSL_CONFIG_DEFAULTS_FAILED;
577 }
578
579 #ifdef CONFIG_MBEDTLS_SSL_RENEGOTIATION
580 mbedtls_ssl_conf_renegotiation(&tls->conf, MBEDTLS_SSL_RENEGOTIATION_ENABLED);
581 #endif
582
583 if (cfg->alpn_protos) {
584 #ifdef CONFIG_MBEDTLS_SSL_ALPN
585 if ((ret = mbedtls_ssl_conf_alpn_protocols(&tls->conf, cfg->alpn_protos)) != 0) {
586 ESP_LOGE(TAG, "mbedtls_ssl_conf_alpn_protocols returned -0x%04X", -ret);
587 ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ESP_TLS_ERR_TYPE_MBEDTLS, -ret);
588 mbedtls_print_error_msg(ret);
589 return ESP_ERR_MBEDTLS_SSL_CONF_ALPN_PROTOCOLS_FAILED;
590 }
591 #else
592 ESP_LOGE(TAG, "alpn_protos configured but not enabled in menuconfig: Please enable MBEDTLS_SSL_ALPN option");
593 return ESP_ERR_INVALID_STATE;
594 #endif
595 }
596
597 #ifdef CONFIG_ESP_TLS_CLIENT_SESSION_TICKETS
598 ESP_LOGD(TAG, "Enabling client-side tls session ticket support");
599 mbedtls_ssl_conf_session_tickets(&tls->conf, MBEDTLS_SSL_SESSION_TICKETS_ENABLED);
600 mbedtls_ssl_conf_renegotiation(&tls->conf, MBEDTLS_SSL_RENEGOTIATION_ENABLED);
601
602 #endif /* CONFIG_ESP_TLS_CLIENT_SESSION_TICKETS */
603
604 if (cfg->crt_bundle_attach != NULL) {
605 #ifdef CONFIG_MBEDTLS_CERTIFICATE_BUNDLE
606 ESP_LOGD(TAG, "Use certificate bundle");
607 mbedtls_ssl_conf_authmode(&tls->conf, MBEDTLS_SSL_VERIFY_REQUIRED);
608 cfg->crt_bundle_attach(&tls->conf);
609 #else //CONFIG_MBEDTLS_CERTIFICATE_BUNDLE
610 ESP_LOGE(TAG, "use_crt_bundle configured but not enabled in menuconfig: Please enable MBEDTLS_CERTIFICATE_BUNDLE option");
611 return ESP_ERR_INVALID_STATE;
612 #endif
613 } else if (cfg->use_global_ca_store == true) {
614 esp_err_t esp_ret = set_global_ca_store(tls);
615 if (esp_ret != ESP_OK) {
616 return esp_ret;
617 }
618 } else if (cfg->cacert_buf != NULL) {
619 esp_err_t esp_ret = set_ca_cert(tls, cfg->cacert_buf, cfg->cacert_bytes);
620 if (esp_ret != ESP_OK) {
621 return esp_ret;
622 }
623 mbedtls_ssl_conf_ca_chain(&tls->conf, tls->cacert_ptr, NULL);
624 } else if (cfg->psk_hint_key) {
625 #if defined(CONFIG_ESP_TLS_PSK_VERIFICATION)
626 //
627 // PSK encryption mode is configured only if no certificate supplied and psk pointer not null
628 ESP_LOGD(TAG, "ssl psk authentication");
629 ret = mbedtls_ssl_conf_psk(&tls->conf, cfg->psk_hint_key->key, cfg->psk_hint_key->key_size,
630 (const unsigned char *)cfg->psk_hint_key->hint, strlen(cfg->psk_hint_key->hint));
631 if (ret != 0) {
632 ESP_LOGE(TAG, "mbedtls_ssl_conf_psk returned -0x%04X", -ret);
633 mbedtls_print_error_msg(ret);
634 ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ESP_TLS_ERR_TYPE_MBEDTLS, -ret);
635 return ESP_ERR_MBEDTLS_SSL_CONF_PSK_FAILED;
636 }
637 #else
638 ESP_LOGE(TAG, "psk_hint_key configured but not enabled in menuconfig: Please enable ESP_TLS_PSK_VERIFICATION option");
639 return ESP_ERR_INVALID_STATE;
640 #endif
641 #ifdef CONFIG_ESP_TLS_CLIENT_SESSION_TICKETS
642 } else if (cfg->client_session != NULL) {
643 ESP_LOGD(TAG, "Resuing the saved client session");
644 #endif
645 } else {
646 #ifdef CONFIG_ESP_TLS_SKIP_SERVER_CERT_VERIFY
647 mbedtls_ssl_conf_authmode(&tls->conf, MBEDTLS_SSL_VERIFY_NONE);
648 #else
649 ESP_LOGE(TAG, "No server verification option set in esp_tls_cfg_t structure. Check esp_tls API reference");
650 return ESP_ERR_MBEDTLS_SSL_SETUP_FAILED;
651 #endif
652 }
653
654 if (cfg->use_secure_element) {
655 #ifdef CONFIG_ESP_TLS_USE_SECURE_ELEMENT
656 ret = esp_set_atecc608a_pki_context(tls, (esp_tls_cfg_t *)cfg);
657 if (ret != ESP_OK) {
658 return ret;
659 }
660 #else
661 ESP_LOGE(TAG, "Please enable secure element support for ESP-TLS in menuconfig");
662 return ESP_FAIL;
663 #endif /* CONFIG_ESP_TLS_USE_SECURE_ELEMENT */
664 } else if (cfg->ds_data != NULL) {
665 #ifdef CONFIG_ESP_TLS_USE_DS_PERIPHERAL
666 if (cfg->clientcert_pem_buf == NULL) {
667 ESP_LOGE(TAG, "Client certificate is also required with the DS parameters");
668 return ESP_ERR_INVALID_STATE;
669 }
670 esp_ds_set_session_timeout(cfg->timeout_ms);
671 /* set private key pointer to NULL since the DS peripheral with its own configuration data is used */
672 esp_tls_pki_t pki = {
673 .public_cert = &tls->clientcert,
674 .pk_key = &tls->clientkey,
675 .publiccert_pem_buf = cfg->clientcert_buf,
676 .publiccert_pem_bytes = cfg->clientcert_bytes,
677 .privkey_pem_buf = NULL,
678 .privkey_pem_bytes = 0,
679 .privkey_password = NULL,
680 .privkey_password_len = 0,
681 .esp_ds_data = cfg->ds_data,
682 };
683
684 esp_err_t esp_ret = set_pki_context(tls, &pki);
685 if (esp_ret != ESP_OK) {
686 ESP_LOGE(TAG, "Failed to set client pki context for the DS peripheral, returned [0x%04X] (%s)", ret, esp_err_to_name(esp_ret));
687 return esp_ret;
688 }
689 #else
690 ESP_LOGE(TAG, "Please enable the DS peripheral support for the ESP-TLS in menuconfig. (only supported for the ESP32-S2 chip)");
691 return ESP_FAIL;
692 #endif
693 } else if (cfg->clientcert_pem_buf != NULL && cfg->clientkey_pem_buf != NULL) {
694 esp_tls_pki_t pki = {
695 .public_cert = &tls->clientcert,
696 .pk_key = &tls->clientkey,
697 .publiccert_pem_buf = cfg->clientcert_buf,
698 .publiccert_pem_bytes = cfg->clientcert_bytes,
699 .privkey_pem_buf = cfg->clientkey_buf,
700 .privkey_pem_bytes = cfg->clientkey_bytes,
701 .privkey_password = cfg->clientkey_password,
702 .privkey_password_len = cfg->clientkey_password_len,
703 };
704 esp_err_t esp_ret = set_pki_context(tls, &pki);
705 if (esp_ret != ESP_OK) {
706 ESP_LOGE(TAG, "Failed to set client pki context");
707 return esp_ret;
708 }
709 } else if (cfg->clientcert_buf != NULL || cfg->clientkey_buf != NULL) {
710 ESP_LOGE(TAG, "You have to provide both clientcert_buf and clientkey_buf for mutual authentication");
711 return ESP_ERR_INVALID_STATE;
712 }
713 return ESP_OK;
714 }
715
716 #ifdef CONFIG_ESP_TLS_SERVER
717 /**
718 * @brief Create TLS/SSL server session
719 */
esp_mbedtls_server_session_create(esp_tls_cfg_server_t * cfg,int sockfd,esp_tls_t * tls)720 int esp_mbedtls_server_session_create(esp_tls_cfg_server_t *cfg, int sockfd, esp_tls_t *tls)
721 {
722 if (tls == NULL || cfg == NULL) {
723 return -1;
724 }
725 tls->role = ESP_TLS_SERVER;
726 tls->sockfd = sockfd;
727 esp_err_t esp_ret = esp_create_mbedtls_handle(NULL, 0, cfg, tls);
728 if (esp_ret != ESP_OK) {
729 ESP_LOGE(TAG, "create_ssl_handle failed, returned [0x%04X] (%s)", esp_ret, esp_err_to_name(esp_ret));
730 ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ESP_TLS_ERR_TYPE_ESP, esp_ret);
731 tls->conn_state = ESP_TLS_FAIL;
732 return -1;
733 }
734 tls->read = esp_mbedtls_read;
735 tls->write = esp_mbedtls_write;
736 int ret;
737 while ((ret = mbedtls_ssl_handshake(&tls->ssl)) != 0) {
738 if (ret != ESP_TLS_ERR_SSL_WANT_READ && ret != ESP_TLS_ERR_SSL_WANT_WRITE) {
739 ESP_LOGE(TAG, "mbedtls_ssl_handshake returned -0x%04X", -ret);
740 mbedtls_print_error_msg(ret);
741 tls->conn_state = ESP_TLS_FAIL;
742 return ret;
743 }
744 }
745 return 0;
746 }
747 /**
748 * @brief Close the server side TLS/SSL connection and free any allocated resources.
749 */
esp_mbedtls_server_session_delete(esp_tls_t * tls)750 void esp_mbedtls_server_session_delete(esp_tls_t *tls)
751 {
752 if (tls != NULL) {
753 esp_mbedtls_cleanup(tls);
754 esp_tls_internal_event_tracker_destroy(tls->error_handle);
755 free(tls);
756 }
757 };
758 #endif /* ! CONFIG_ESP_TLS_SERVER */
759
esp_mbedtls_init_global_ca_store(void)760 esp_err_t esp_mbedtls_init_global_ca_store(void)
761 {
762 if (global_cacert == NULL) {
763 global_cacert = (mbedtls_x509_crt *)calloc(1, sizeof(mbedtls_x509_crt));
764 if (global_cacert == NULL) {
765 ESP_LOGE(TAG, "global_cacert not allocated");
766 return ESP_ERR_NO_MEM;
767 }
768 mbedtls_x509_crt_init(global_cacert);
769 }
770 return ESP_OK;
771 }
772
esp_mbedtls_set_global_ca_store(const unsigned char * cacert_pem_buf,const unsigned int cacert_pem_bytes)773 esp_err_t esp_mbedtls_set_global_ca_store(const unsigned char *cacert_pem_buf, const unsigned int cacert_pem_bytes)
774 {
775 #ifdef CONFIG_MBEDTLS_DYNAMIC_FREE_CA_CERT
776 ESP_LOGE(TAG, "Please disable dynamic freeing of ca cert in mbedtls (CONFIG_MBEDTLS_DYNAMIC_FREE_CA_CERT)\n in order to use the global ca_store");
777 return ESP_FAIL;
778 #endif
779 if (cacert_pem_buf == NULL) {
780 ESP_LOGE(TAG, "cacert_pem_buf is null");
781 return ESP_ERR_INVALID_ARG;
782 }
783 int ret;
784 if (global_cacert == NULL) {
785 ret = esp_mbedtls_init_global_ca_store();
786 if (ret != ESP_OK) {
787 return ret;
788 }
789 }
790 ret = mbedtls_x509_crt_parse(global_cacert, cacert_pem_buf, cacert_pem_bytes);
791 if (ret < 0) {
792 ESP_LOGE(TAG, "mbedtls_x509_crt_parse returned -0x%04X", -ret);
793 mbedtls_print_error_msg(ret);
794 mbedtls_x509_crt_free(global_cacert);
795 free(global_cacert);
796 global_cacert = NULL;
797 return ESP_FAIL;
798 } else if (ret > 0) {
799 ESP_LOGE(TAG, "mbedtls_x509_crt_parse was partly successful. No. of failed certificates: %d", ret);
800 return ESP_ERR_MBEDTLS_CERT_PARTLY_OK;
801 }
802 return ESP_OK;
803 }
804
esp_mbedtls_get_global_ca_store(void)805 mbedtls_x509_crt *esp_mbedtls_get_global_ca_store(void)
806 {
807 return global_cacert;
808 }
809
esp_mbedtls_free_global_ca_store(void)810 void esp_mbedtls_free_global_ca_store(void)
811 {
812 if (global_cacert) {
813 mbedtls_x509_crt_free(global_cacert);
814 free(global_cacert);
815 global_cacert = NULL;
816 }
817 }
818
819 #ifdef CONFIG_ESP_TLS_USE_SECURE_ELEMENT
esp_init_atecc608a(uint8_t i2c_addr)820 static esp_err_t esp_init_atecc608a(uint8_t i2c_addr)
821 {
822 cfg_ateccx08a_i2c_default.atcai2c.address = i2c_addr;
823 int ret = atcab_init(&cfg_ateccx08a_i2c_default);
824 if(ret != 0) {
825 ESP_LOGE(TAG, "Failed to initialize atca device, returned -0x%04X", -ret);
826 return ESP_FAIL;
827 }
828 return ESP_OK;
829 }
830
esp_set_atecc608a_pki_context(esp_tls_t * tls,esp_tls_cfg_t * cfg)831 static esp_err_t esp_set_atecc608a_pki_context(esp_tls_t *tls, esp_tls_cfg_t *cfg)
832 {
833 int ret = 0;
834 esp_err_t esp_ret = ESP_FAIL;
835 ESP_LOGI(TAG, "Initialize the ATECC interface...");
836 (void)esp_ret;
837 (void)cert_def;
838 #if defined(CONFIG_ATECC608A_TNG) || defined(CONFIG_ATECC608A_TFLEX)
839 #ifdef CONFIG_ATECC608A_TNG
840 esp_ret = esp_init_atecc608a(ATECC608A_TNG_SLAVE_ADDR);
841 if (ret != ESP_OK) {
842 return ESP_ERR_ESP_TLS_SE_FAILED;
843 }
844 #elif CONFIG_ATECC608A_TFLEX /* CONFIG_ATECC608A_TNG */
845 esp_ret = esp_init_atecc608a(ATECC608A_TFLEX_SLAVE_ADDR);
846 if (ret != ESP_OK) {
847 return ESP_ERR_ESP_TLS_SE_FAILED;
848 }
849 #endif /* CONFIG_ATECC608A_TFLEX */
850 mbedtls_x509_crt_init(&tls->clientcert);
851 ret = tng_get_device_cert_def(&cert_def);
852 if (ret != 0) {
853 ESP_LOGE(TAG, "Failed to get device cert def");
854 return ESP_ERR_ESP_TLS_SE_FAILED;
855 }
856
857 /* Extract the device certificate and convert to mbedtls cert */
858 ret = atca_mbedtls_cert_add(&tls->clientcert, cert_def);
859 if (ret != 0) {
860 ESP_LOGE(TAG, "Failed to parse cert from device, return 0x%04X", ret);
861 mbedtls_print_error_msg(ret);
862 return ESP_ERR_ESP_TLS_SE_FAILED;
863 }
864 #elif CONFIG_ATECC608A_TCUSTOM
865 esp_ret = esp_init_atecc608a(ATECC608A_TCUSTOM_SLAVE_ADDR);
866 if (ret != ESP_OK) {
867 return ESP_ERR_ESP_TLS_SE_FAILED;
868 }
869 mbedtls_x509_crt_init(&tls->clientcert);
870
871 if(cfg->clientcert_buf != NULL) {
872 ret = mbedtls_x509_crt_parse(&tls->clientcert, (const unsigned char*)cfg->clientcert_buf, cfg->clientcert_bytes);
873 if (ret < 0) {
874 ESP_LOGE(TAG, "mbedtls_x509_crt_parse returned -0x%04X", -ret);
875 mbedtls_print_error_msg(ret);
876 ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ESP_TLS_ERR_TYPE_MBEDTLS, -ret);
877 return ESP_ERR_MBEDTLS_X509_CRT_PARSE_FAILED;
878 }
879 } else {
880 ESP_LOGE(TAG, "Device certificate must be provided for TrustCustom Certs");
881 return ESP_FAIL;
882 }
883 #endif /* CONFIG_ATECC608A_TCUSTOM */
884 ret = atca_mbedtls_pk_init(&tls->clientkey, 0);
885 if (ret != 0) {
886 ESP_LOGE(TAG, "Failed to parse key from device");
887 ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ESP_TLS_ERR_TYPE_MBEDTLS, -ret);
888 mbedtls_print_error_msg(ret);
889 return ESP_ERR_ESP_TLS_SE_FAILED;
890 }
891
892 ret = mbedtls_ssl_conf_own_cert(&tls->conf, &tls->clientcert, &tls->clientkey);
893 if (ret != 0) {
894 ESP_LOGE(TAG, "Failed to configure client cert, returned -0x%04X", ret);
895 mbedtls_print_error_msg(ret);
896 ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ESP_TLS_ERR_TYPE_MBEDTLS, -ret);
897 return ESP_ERR_ESP_TLS_SE_FAILED;
898 }
899 return ESP_OK;
900 }
901 #endif /* CONFIG_ESP_TLS_USE_SECURE_ELEMENT */
902
903 #ifdef CONFIG_ESP_TLS_USE_DS_PERIPHERAL
esp_mbedtls_init_pk_ctx_for_ds(const void * pki)904 static esp_err_t esp_mbedtls_init_pk_ctx_for_ds(const void *pki)
905 {
906 int ret = -1;
907 /* initialize the mbedtls pk context with rsa context */
908 mbedtls_rsa_context rsakey;
909 mbedtls_rsa_init(&rsakey, MBEDTLS_RSA_PKCS_V15, 0);
910 if ((ret = mbedtls_pk_setup_rsa_alt(((const esp_tls_pki_t*)pki)->pk_key, &rsakey, NULL, esp_ds_rsa_sign,
911 esp_ds_get_keylen )) != 0) {
912 ESP_LOGE(TAG, "Error in mbedtls_pk_setup_rsa_alt, returned -0x%04X", -ret);
913 mbedtls_print_error_msg(ret);
914 return ESP_FAIL;
915 }
916 ret = esp_ds_init_data_ctx(((const esp_tls_pki_t*)pki)->esp_ds_data);
917 if (ret != ESP_OK) {
918 ESP_LOGE(TAG, "Failed to initialize DS parameters from nvs");
919 return ESP_FAIL;
920 }
921 ESP_LOGD(TAG, "DS peripheral params initialized.");
922 return ESP_OK;
923 }
924 #endif /* CONFIG_ESP_TLS_USE_DS_PERIPHERAL */
925