1 /*
2 * Copyright (c) 2008-2021 Apple Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28
29 /* $FreeBSD: src/sys/netinet6/esp_core.c,v 1.1.2.4 2002/03/26 10:12:29 ume Exp $ */
30 /* $KAME: esp_core.c,v 1.50 2000/11/02 12:27:38 itojun Exp $ */
31
32 /*
33 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
34 * All rights reserved.
35 *
36 * Redistribution and use in source and binary forms, with or without
37 * modification, are permitted provided that the following conditions
38 * are met:
39 * 1. Redistributions of source code must retain the above copyright
40 * notice, this list of conditions and the following disclaimer.
41 * 2. Redistributions in binary form must reproduce the above copyright
42 * notice, this list of conditions and the following disclaimer in the
43 * documentation and/or other materials provided with the distribution.
44 * 3. Neither the name of the project nor the names of its contributors
45 * may be used to endorse or promote products derived from this software
46 * without specific prior written permission.
47 *
48 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
49 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
50 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
51 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
52 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
53 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
54 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
55 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
56 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
57 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
58 * SUCH DAMAGE.
59 */
60
61 #define _IP_VHL
62
63 #include <sys/param.h>
64 #include <sys/systm.h>
65 #include <sys/malloc.h>
66 #include <sys/mbuf.h>
67 #include <sys/domain.h>
68 #include <sys/protosw.h>
69 #include <sys/socket.h>
70 #include <sys/errno.h>
71 #include <sys/time.h>
72 #include <sys/kernel.h>
73 #include <sys/syslog.h>
74
75 #include <kern/locks.h>
76
77 #include <net/if.h>
78 #include <net/multi_layer_pkt_log.h>
79 #include <net/route.h>
80
81 #include <netinet/in.h>
82 #include <netinet/in_var.h>
83 #include <netinet/ip6.h>
84 #include <netinet6/ip6_var.h>
85 #include <netinet/icmp6.h>
86
87 #include <netinet6/ipsec.h>
88 #include <netinet6/ipsec6.h>
89 #include <netinet6/ah.h>
90 #include <netinet6/ah6.h>
91 #include <netinet6/esp.h>
92 #include <netinet6/esp6.h>
93 #include <netinet6/esp_rijndael.h>
94 #include <netinet6/esp_chachapoly.h>
95 #include <net/pfkeyv2.h>
96 #include <netkey/keydb.h>
97 #include <netkey/key.h>
98 #include <libkern/crypto/des.h>
99
100 #include <net/net_osdep.h>
101
102 #include <sys/kdebug.h>
103 #define DBG_LAYER_BEG NETDBG_CODE(DBG_NETIPSEC, 1)
104 #define DBG_LAYER_END NETDBG_CODE(DBG_NETIPSEC, 3)
105 #define DBG_FNC_ESPAUTH NETDBG_CODE(DBG_NETIPSEC, (8 << 8))
106 #define MAX_SBUF_LEN 2000
107
108 os_log_t esp_mpkl_log_object = NULL;
109
110 static int esp_null_mature(struct secasvar *);
111 static int esp_null_decrypt(struct mbuf *, size_t,
112 struct secasvar *, const struct esp_algorithm *, int);
113 static int esp_null_encrypt(struct mbuf *, size_t, size_t,
114 struct secasvar *, const struct esp_algorithm *, int);
115 static int esp_descbc_mature(struct secasvar *);
116 static int esp_descbc_ivlen(const struct esp_algorithm *,
117 struct secasvar *);
118 static int esp_des_schedule(const struct esp_algorithm *,
119 struct secasvar *);
120 static size_t esp_des_schedlen(const struct esp_algorithm *);
121 static int esp_des_blockdecrypt(const struct esp_algorithm *,
122 struct secasvar *, u_int8_t *, u_int8_t *);
123 static int esp_des_blockencrypt(const struct esp_algorithm *,
124 struct secasvar *, u_int8_t *, u_int8_t *);
125 static int esp_cbc_mature(struct secasvar *);
126 static int esp_3des_schedule(const struct esp_algorithm *,
127 struct secasvar *);
128 static size_t esp_3des_schedlen(const struct esp_algorithm *);
129 static int esp_3des_blockdecrypt(const struct esp_algorithm *,
130 struct secasvar *, u_int8_t *, u_int8_t *);
131 static int esp_3des_blockencrypt(const struct esp_algorithm *,
132 struct secasvar *, u_int8_t *, u_int8_t *);
133 static int esp_common_ivlen(const struct esp_algorithm *,
134 struct secasvar *);
135 static int esp_cbc_decrypt(struct mbuf *, size_t,
136 struct secasvar *, const struct esp_algorithm *, int);
137 static int esp_cbc_encrypt(struct mbuf *, size_t, size_t,
138 struct secasvar *, const struct esp_algorithm *, int);
139 static int esp_gcm_mature(struct secasvar *);
140
141 #define MAXIVLEN 16
142
143 #define ESP_AESGCM_KEYLEN128 160 // 16-bytes key + 4 bytes salt
144 #define ESP_AESGCM_KEYLEN192 224 // 24-bytes key + 4 bytes salt
145 #define ESP_AESGCM_KEYLEN256 288 // 32-bytes key + 4 bytes salt
146
147 static const struct esp_algorithm des_cbc = {
148 .padbound = 8,
149 .ivlenval = -1,
150 .mature = esp_descbc_mature,
151 .keymin = 64,
152 .keymax = 64,
153 .schedlen = esp_des_schedlen,
154 .name = "des-cbc",
155 .ivlen = esp_descbc_ivlen,
156 .decrypt = esp_cbc_decrypt,
157 .encrypt = esp_cbc_encrypt,
158 .schedule = esp_des_schedule,
159 .blockdecrypt = esp_des_blockdecrypt,
160 .blockencrypt = esp_des_blockencrypt,
161 .icvlen = 0,
162 .finalizedecrypt = NULL,
163 .finalizeencrypt = NULL
164 };
165
166 static const struct esp_algorithm des3_cbc = {
167 .padbound = 8,
168 .ivlenval = 8,
169 .mature = esp_cbc_mature,
170 .keymin = 192,
171 .keymax = 192,
172 .schedlen = esp_3des_schedlen,
173 .name = "3des-cbc",
174 .ivlen = esp_common_ivlen,
175 .decrypt = esp_cbc_decrypt,
176 .encrypt = esp_cbc_encrypt,
177 .schedule = esp_3des_schedule,
178 .blockdecrypt = esp_3des_blockdecrypt,
179 .blockencrypt = esp_3des_blockencrypt,
180 .icvlen = 0,
181 .finalizedecrypt = NULL,
182 .finalizeencrypt = NULL
183 };
184
185 static const struct esp_algorithm null_esp = {
186 .padbound = 1,
187 .ivlenval = 0,
188 .mature = esp_null_mature,
189 .keymin = 0,
190 .keymax = 2048,
191 .schedlen = NULL,
192 .name = "null",
193 .ivlen = esp_common_ivlen,
194 .decrypt = esp_null_decrypt,
195 .encrypt = esp_null_encrypt,
196 .schedule = NULL,
197 .blockdecrypt = NULL,
198 .blockencrypt = NULL,
199 .icvlen = 0,
200 .finalizedecrypt = NULL,
201 .finalizeencrypt = NULL
202 };
203
204 static const struct esp_algorithm aes_cbc = {
205 .padbound = 16,
206 .ivlenval = 16,
207 .mature = esp_cbc_mature,
208 .keymin = 128,
209 .keymax = 256,
210 .schedlen = esp_aes_schedlen,
211 .name = "aes-cbc",
212 .ivlen = esp_common_ivlen,
213 .decrypt = esp_cbc_decrypt_aes,
214 .encrypt = esp_cbc_encrypt_aes,
215 .schedule = esp_aes_schedule,
216 .blockdecrypt = NULL,
217 .blockencrypt = NULL,
218 .icvlen = 0,
219 .finalizedecrypt = NULL,
220 .finalizeencrypt = NULL
221 };
222
223 static const struct esp_algorithm aes_gcm = {
224 .padbound = 4,
225 .ivlenval = 8,
226 .mature = esp_gcm_mature,
227 .keymin = ESP_AESGCM_KEYLEN128,
228 .keymax = ESP_AESGCM_KEYLEN256,
229 .schedlen = esp_gcm_schedlen,
230 .name = "aes-gcm",
231 .ivlen = esp_gcm_ivlen,
232 .decrypt = esp_gcm_decrypt_aes,
233 .encrypt = esp_gcm_encrypt_aes,
234 .schedule = esp_gcm_schedule,
235 .blockdecrypt = NULL,
236 .blockencrypt = NULL,
237 .icvlen = 16,
238 .finalizedecrypt = esp_gcm_decrypt_finalize,
239 .finalizeencrypt = esp_gcm_encrypt_finalize
240 };
241
242 static const struct esp_algorithm chacha_poly = {
243 .padbound = ESP_CHACHAPOLY_PAD_BOUND,
244 .ivlenval = ESP_CHACHAPOLY_IV_LEN,
245 .mature = esp_chachapoly_mature,
246 .keymin = ESP_CHACHAPOLY_KEYBITS_WITH_SALT,
247 .keymax = ESP_CHACHAPOLY_KEYBITS_WITH_SALT,
248 .schedlen = esp_chachapoly_schedlen,
249 .name = "chacha-poly",
250 .ivlen = esp_chachapoly_ivlen,
251 .decrypt = esp_chachapoly_decrypt,
252 .encrypt = esp_chachapoly_encrypt,
253 .schedule = esp_chachapoly_schedule,
254 .blockdecrypt = NULL,
255 .blockencrypt = NULL,
256 .icvlen = ESP_CHACHAPOLY_ICV_LEN,
257 .finalizedecrypt = esp_chachapoly_decrypt_finalize,
258 .finalizeencrypt = esp_chachapoly_encrypt_finalize
259 };
260
261 /*
262 * If any algorithm requires more than 2048 bits (256 bytes) of key material,
263 * update IPSEC_KEY_ENCRYPT_MAX_BYTES in ipsec.h
264 */
265 static const struct esp_algorithm *esp_algorithms[] = {
266 &des_cbc,
267 &des3_cbc,
268 &null_esp,
269 &aes_cbc,
270 &aes_gcm,
271 &chacha_poly,
272 };
273
274 const struct esp_algorithm *
esp_algorithm_lookup(int idx)275 esp_algorithm_lookup(int idx)
276 {
277 switch (idx) {
278 case SADB_EALG_DESCBC:
279 return &des_cbc;
280 case SADB_EALG_3DESCBC:
281 return &des3_cbc;
282 case SADB_EALG_NULL:
283 return &null_esp;
284 case SADB_X_EALG_RIJNDAELCBC:
285 return &aes_cbc;
286 case SADB_X_EALG_AES_GCM:
287 return &aes_gcm;
288 case SADB_X_EALG_CHACHA20POLY1305:
289 return &chacha_poly;
290 default:
291 return NULL;
292 }
293 }
294
295 int
esp_max_ivlen(void)296 esp_max_ivlen(void)
297 {
298 int idx;
299 int ivlen;
300
301 ivlen = 0;
302 for (idx = 0; idx < sizeof(esp_algorithms) / sizeof(esp_algorithms[0]);
303 idx++) {
304 if (esp_algorithms[idx]->ivlenval > ivlen) {
305 ivlen = esp_algorithms[idx]->ivlenval;
306 }
307 }
308
309 return ivlen;
310 }
311
312 int
esp_schedule(const struct esp_algorithm * algo,struct secasvar * sav)313 esp_schedule(const struct esp_algorithm *algo, struct secasvar *sav)
314 {
315 int error;
316
317 /* check for key length */
318 if (_KEYBITS(sav->key_enc) < algo->keymin ||
319 _KEYBITS(sav->key_enc) > algo->keymax) {
320 ipseclog((LOG_ERR,
321 "esp_schedule %s: unsupported key length %d: "
322 "needs %d to %d bits\n", algo->name, _KEYBITS(sav->key_enc),
323 algo->keymin, algo->keymax));
324 return EINVAL;
325 }
326
327 lck_mtx_lock(sadb_mutex);
328 /* already allocated */
329 if (sav->sched && sav->schedlen != 0) {
330 lck_mtx_unlock(sadb_mutex);
331 return 0;
332 }
333
334 /* prevent disallowed implicit IV */
335 if (((sav->flags & SADB_X_EXT_IIV) != 0) &&
336 (sav->alg_enc != SADB_X_EALG_AES_GCM) &&
337 (sav->alg_enc != SADB_X_EALG_CHACHA20POLY1305)) {
338 ipseclog((LOG_ERR,
339 "esp_schedule %s: implicit IV not allowed\n",
340 algo->name));
341 lck_mtx_unlock(sadb_mutex);
342 return EINVAL;
343 }
344
345 /* no schedule necessary */
346 if (!algo->schedule || !algo->schedlen) {
347 lck_mtx_unlock(sadb_mutex);
348 return 0;
349 }
350
351 sav->schedlen = (*algo->schedlen)(algo);
352 if ((signed) sav->schedlen < 0) {
353 lck_mtx_unlock(sadb_mutex);
354 return EINVAL;
355 }
356
357 //#### that malloc should be replaced by a saved buffer...
358 sav->sched = kalloc_data(sav->schedlen, Z_NOWAIT);
359 if (!sav->sched) {
360 sav->schedlen = 0;
361 lck_mtx_unlock(sadb_mutex);
362 return ENOBUFS;
363 }
364
365 error = (*algo->schedule)(algo, sav);
366 if (error) {
367 ipseclog((LOG_ERR, "esp_schedule %s: error %d\n",
368 algo->name, error));
369 bzero(sav->sched, sav->schedlen);
370 kfree_data(sav->sched, sav->schedlen);
371 sav->sched = NULL;
372 sav->schedlen = 0;
373 }
374 lck_mtx_unlock(sadb_mutex);
375 return error;
376 }
377
378 static int
esp_null_mature(__unused struct secasvar * sav)379 esp_null_mature(
380 __unused struct secasvar *sav)
381 {
382 /* anything is okay */
383 return 0;
384 }
385
386 static int
esp_null_decrypt(__unused struct mbuf * m,__unused size_t off,__unused struct secasvar * sav,__unused const struct esp_algorithm * algo,__unused int ivlen)387 esp_null_decrypt(
388 __unused struct mbuf *m,
389 __unused size_t off, /* offset to ESP header */
390 __unused struct secasvar *sav,
391 __unused const struct esp_algorithm *algo,
392 __unused int ivlen)
393 {
394 return 0; /* do nothing */
395 }
396
397 static int
esp_null_encrypt(__unused struct mbuf * m,__unused size_t off,__unused size_t plen,__unused struct secasvar * sav,__unused const struct esp_algorithm * algo,__unused int ivlen)398 esp_null_encrypt(
399 __unused struct mbuf *m,
400 __unused size_t off, /* offset to ESP header */
401 __unused size_t plen, /* payload length (to be encrypted) */
402 __unused struct secasvar *sav,
403 __unused const struct esp_algorithm *algo,
404 __unused int ivlen)
405 {
406 return 0; /* do nothing */
407 }
408
409 static int
esp_descbc_mature(struct secasvar * sav)410 esp_descbc_mature(struct secasvar *sav)
411 {
412 const struct esp_algorithm *algo;
413
414 if (!(sav->flags & SADB_X_EXT_OLD) && (sav->flags & SADB_X_EXT_IV4B)) {
415 ipseclog((LOG_ERR, "esp_cbc_mature: "
416 "algorithm incompatible with 4 octets IV length\n"));
417 return 1;
418 }
419
420 if (!sav->key_enc) {
421 ipseclog((LOG_ERR, "esp_descbc_mature: no key is given.\n"));
422 return 1;
423 }
424
425 algo = esp_algorithm_lookup(sav->alg_enc);
426 if (!algo) {
427 ipseclog((LOG_ERR,
428 "esp_descbc_mature: unsupported algorithm.\n"));
429 return 1;
430 }
431
432 if (_KEYBITS(sav->key_enc) < algo->keymin ||
433 _KEYBITS(sav->key_enc) > algo->keymax) {
434 ipseclog((LOG_ERR,
435 "esp_descbc_mature: invalid key length %d.\n",
436 _KEYBITS(sav->key_enc)));
437 return 1;
438 }
439
440 /* weak key check */
441 if (des_is_weak_key((des_cblock *)_KEYBUF(sav->key_enc))) {
442 ipseclog((LOG_ERR,
443 "esp_descbc_mature: weak key was passed.\n"));
444 return 1;
445 }
446
447 return 0;
448 }
449
450 static int
esp_descbc_ivlen(__unused const struct esp_algorithm * algo,struct secasvar * sav)451 esp_descbc_ivlen(
452 __unused const struct esp_algorithm *algo,
453 struct secasvar *sav)
454 {
455 if (!sav) {
456 return 8;
457 }
458 if ((sav->flags & SADB_X_EXT_OLD) && (sav->flags & SADB_X_EXT_IV4B)) {
459 return 4;
460 }
461 if (!(sav->flags & SADB_X_EXT_OLD) && (sav->flags & SADB_X_EXT_DERIV)) {
462 return 4;
463 }
464 return 8;
465 }
466
467 static size_t
esp_des_schedlen(__unused const struct esp_algorithm * algo)468 esp_des_schedlen(
469 __unused const struct esp_algorithm *algo)
470 {
471 return sizeof(des_ecb_key_schedule);
472 }
473
474 static int
esp_des_schedule(__unused const struct esp_algorithm * algo,struct secasvar * sav)475 esp_des_schedule(
476 __unused const struct esp_algorithm *algo,
477 struct secasvar *sav)
478 {
479 LCK_MTX_ASSERT(sadb_mutex, LCK_MTX_ASSERT_OWNED);
480 if (des_ecb_key_sched((des_cblock *)_KEYBUF(sav->key_enc),
481 (des_ecb_key_schedule *)sav->sched)) {
482 return EINVAL;
483 } else {
484 return 0;
485 }
486 }
487
488 static int
esp_des_blockdecrypt(__unused const struct esp_algorithm * algo,struct secasvar * sav,u_int8_t * s,u_int8_t * d)489 esp_des_blockdecrypt(
490 __unused const struct esp_algorithm *algo,
491 struct secasvar *sav,
492 u_int8_t *s,
493 u_int8_t *d)
494 {
495 /* assumption: d has a good alignment */
496 bcopy(s, d, sizeof(DES_LONG) * 2);
497 return des_ecb_encrypt((des_cblock *)d, (des_cblock *)d,
498 (des_ecb_key_schedule *)sav->sched, DES_DECRYPT);
499 }
500
501 static int
esp_des_blockencrypt(__unused const struct esp_algorithm * algo,struct secasvar * sav,u_int8_t * s,u_int8_t * d)502 esp_des_blockencrypt(
503 __unused const struct esp_algorithm *algo,
504 struct secasvar *sav,
505 u_int8_t *s,
506 u_int8_t *d)
507 {
508 /* assumption: d has a good alignment */
509 bcopy(s, d, sizeof(DES_LONG) * 2);
510 return des_ecb_encrypt((des_cblock *)d, (des_cblock *)d,
511 (des_ecb_key_schedule *)sav->sched, DES_ENCRYPT);
512 }
513
514 static int
esp_cbc_mature(struct secasvar * sav)515 esp_cbc_mature(struct secasvar *sav)
516 {
517 int keylen;
518 const struct esp_algorithm *algo;
519
520 if (sav->flags & SADB_X_EXT_OLD) {
521 ipseclog((LOG_ERR,
522 "esp_cbc_mature: algorithm incompatible with esp-old\n"));
523 return 1;
524 }
525 if (sav->flags & SADB_X_EXT_DERIV) {
526 ipseclog((LOG_ERR,
527 "esp_cbc_mature: algorithm incompatible with derived\n"));
528 return 1;
529 }
530
531 if (!sav->key_enc) {
532 ipseclog((LOG_ERR, "esp_cbc_mature: no key is given.\n"));
533 return 1;
534 }
535
536 algo = esp_algorithm_lookup(sav->alg_enc);
537 if (!algo) {
538 ipseclog((LOG_ERR,
539 "esp_cbc_mature: unsupported algorithm.\n"));
540 return 1;
541 }
542
543 keylen = sav->key_enc->sadb_key_bits;
544 if (keylen < algo->keymin || algo->keymax < keylen) {
545 ipseclog((LOG_ERR,
546 "esp_cbc_mature %s: invalid key length %d.\n",
547 algo->name, sav->key_enc->sadb_key_bits));
548 return 1;
549 }
550 switch (sav->alg_enc) {
551 case SADB_EALG_3DESCBC:
552 /* weak key check */
553 if (des_is_weak_key((des_cblock *)_KEYBUF(sav->key_enc)) ||
554 des_is_weak_key((des_cblock *)(_KEYBUF(sav->key_enc) + 8)) ||
555 des_is_weak_key((des_cblock *)(_KEYBUF(sav->key_enc) + 16))) {
556 ipseclog((LOG_ERR,
557 "esp_cbc_mature %s: weak key was passed.\n",
558 algo->name));
559 return 1;
560 }
561 break;
562 case SADB_X_EALG_RIJNDAELCBC:
563 /* allows specific key sizes only */
564 if (!(keylen == 128 || keylen == 192 || keylen == 256)) {
565 ipseclog((LOG_ERR,
566 "esp_cbc_mature %s: invalid key length %d.\n",
567 algo->name, keylen));
568 return 1;
569 }
570 break;
571 }
572
573 return 0;
574 }
575
576 static int
esp_gcm_mature(struct secasvar * sav)577 esp_gcm_mature(struct secasvar *sav)
578 {
579 int keylen;
580 const struct esp_algorithm *algo;
581
582 if (sav->flags & SADB_X_EXT_OLD) {
583 ipseclog((LOG_ERR,
584 "esp_gcm_mature: algorithm incompatible with esp-old\n"));
585 return 1;
586 }
587 if (sav->flags & SADB_X_EXT_DERIV) {
588 ipseclog((LOG_ERR,
589 "esp_gcm_mature: algorithm incompatible with derived\n"));
590 return 1;
591 }
592
593 if (!sav->key_enc) {
594 ipseclog((LOG_ERR, "esp_gcm_mature: no key is given.\n"));
595 return 1;
596 }
597
598 algo = esp_algorithm_lookup(sav->alg_enc);
599 if (!algo) {
600 ipseclog((LOG_ERR,
601 "esp_gcm_mature: unsupported algorithm.\n"));
602 return 1;
603 }
604
605 keylen = sav->key_enc->sadb_key_bits;
606 if (keylen < algo->keymin || algo->keymax < keylen) {
607 ipseclog((LOG_ERR,
608 "esp_gcm_mature %s: invalid key length %d.\n",
609 algo->name, sav->key_enc->sadb_key_bits));
610 return 1;
611 }
612 switch (sav->alg_enc) {
613 case SADB_X_EALG_AES_GCM:
614 /* allows specific key sizes only */
615 if (!(keylen == ESP_AESGCM_KEYLEN128 || keylen == ESP_AESGCM_KEYLEN192 || keylen == ESP_AESGCM_KEYLEN256)) {
616 ipseclog((LOG_ERR,
617 "esp_gcm_mature %s: invalid key length %d.\n",
618 algo->name, keylen));
619 return 1;
620 }
621 break;
622 default:
623 ipseclog((LOG_ERR,
624 "esp_gcm_mature %s: invalid algo %d.\n", algo->name, sav->alg_enc));
625 return 1;
626 }
627
628 return 0;
629 }
630
631 static size_t
esp_3des_schedlen(__unused const struct esp_algorithm * algo)632 esp_3des_schedlen(
633 __unused const struct esp_algorithm *algo)
634 {
635 return sizeof(des3_ecb_key_schedule);
636 }
637
638 static int
esp_3des_schedule(__unused const struct esp_algorithm * algo,struct secasvar * sav)639 esp_3des_schedule(
640 __unused const struct esp_algorithm *algo,
641 struct secasvar *sav)
642 {
643 LCK_MTX_ASSERT(sadb_mutex, LCK_MTX_ASSERT_OWNED);
644
645 if (des3_ecb_key_sched((des_cblock *)_KEYBUF(sav->key_enc),
646 (des3_ecb_key_schedule *)sav->sched)) {
647 return EINVAL;
648 } else {
649 return 0;
650 }
651 }
652
653 static int
esp_3des_blockdecrypt(__unused const struct esp_algorithm * algo,struct secasvar * sav,u_int8_t * s,u_int8_t * d)654 esp_3des_blockdecrypt(
655 __unused const struct esp_algorithm *algo,
656 struct secasvar *sav,
657 u_int8_t *s,
658 u_int8_t *d)
659 {
660 /* assumption: d has a good alignment */
661 bcopy(s, d, sizeof(DES_LONG) * 2);
662 return des3_ecb_encrypt((des_cblock *)d, (des_cblock *)d,
663 (des3_ecb_key_schedule *)sav->sched, DES_DECRYPT);
664 }
665
666 static int
esp_3des_blockencrypt(__unused const struct esp_algorithm * algo,struct secasvar * sav,u_int8_t * s,u_int8_t * d)667 esp_3des_blockencrypt(
668 __unused const struct esp_algorithm *algo,
669 struct secasvar *sav,
670 u_int8_t *s,
671 u_int8_t *d)
672 {
673 /* assumption: d has a good alignment */
674 bcopy(s, d, sizeof(DES_LONG) * 2);
675 return des3_ecb_encrypt((des_cblock *)d, (des_cblock *)d,
676 (des3_ecb_key_schedule *)sav->sched, DES_ENCRYPT);
677 }
678
679 static int
esp_common_ivlen(const struct esp_algorithm * algo,__unused struct secasvar * sav)680 esp_common_ivlen(
681 const struct esp_algorithm *algo,
682 __unused struct secasvar *sav)
683 {
684 if (!algo) {
685 panic("esp_common_ivlen: unknown algorithm");
686 }
687 return algo->ivlenval;
688 }
689
690 static int
esp_cbc_decrypt(struct mbuf * m,size_t off,struct secasvar * sav,const struct esp_algorithm * algo,int ivlen)691 esp_cbc_decrypt(struct mbuf *m, size_t off, struct secasvar *sav,
692 const struct esp_algorithm *algo, int ivlen)
693 {
694 struct mbuf *s;
695 struct mbuf *d, *d0, *dp;
696 int soff, doff; /* offset from the head of chain, to head of this mbuf */
697 int sn, dn; /* offset from the head of the mbuf, to meat */
698 size_t ivoff, bodyoff;
699 u_int8_t iv[MAXIVLEN] __attribute__((aligned(4))), *ivp;
700 u_int8_t *sbuf = NULL, *sp, *sp_unaligned;
701 u_int8_t *p, *q;
702 struct mbuf *scut;
703 int scutoff;
704 int i, result = 0;
705 int blocklen;
706 int derived;
707
708 if (ivlen != sav->ivlen || ivlen > sizeof(iv)) {
709 ipseclog((LOG_ERR, "esp_cbc_decrypt %s: "
710 "unsupported ivlen %d\n", algo->name, ivlen));
711 m_freem(m);
712 return EINVAL;
713 }
714
715 /* assumes blocklen == padbound */
716 blocklen = algo->padbound;
717
718 #if DIAGNOSTIC
719 if (blocklen > sizeof(iv)) {
720 ipseclog((LOG_ERR, "esp_cbc_decrypt %s: "
721 "unsupported blocklen %d\n", algo->name, blocklen));
722 m_freem(m);
723 return EINVAL;
724 }
725 #endif
726
727 if (sav->flags & SADB_X_EXT_OLD) {
728 /* RFC 1827 */
729 ivoff = off + sizeof(struct esp);
730 bodyoff = off + sizeof(struct esp) + ivlen;
731 derived = 0;
732 } else {
733 /* RFC 2406 */
734 if (sav->flags & SADB_X_EXT_DERIV) {
735 /*
736 * draft-ietf-ipsec-ciph-des-derived-00.txt
737 * uses sequence number field as IV field.
738 */
739 ivoff = off + sizeof(struct esp);
740 bodyoff = off + sizeof(struct esp) + sizeof(u_int32_t);
741 ivlen = sizeof(u_int32_t);
742 derived = 1;
743 } else {
744 ivoff = off + sizeof(struct newesp);
745 bodyoff = off + sizeof(struct newesp) + ivlen;
746 derived = 0;
747 }
748 }
749
750 VERIFY(ivoff <= INT_MAX);
751 /* grab iv */
752 m_copydata(m, (int)ivoff, ivlen, (caddr_t) iv);
753
754 /* extend iv */
755 if (ivlen == blocklen) {
756 ;
757 } else if (ivlen == 4 && blocklen == 8) {
758 bcopy(&iv[0], &iv[4], 4);
759 iv[4] ^= 0xff;
760 iv[5] ^= 0xff;
761 iv[6] ^= 0xff;
762 iv[7] ^= 0xff;
763 } else {
764 ipseclog((LOG_ERR, "esp_cbc_encrypt %s: "
765 "unsupported ivlen/blocklen: %d %d\n",
766 algo->name, ivlen, blocklen));
767 m_freem(m);
768 return EINVAL;
769 }
770
771 if (m->m_pkthdr.len < bodyoff) {
772 ipseclog((LOG_ERR, "esp_cbc_decrypt %s: bad len %d/%u\n",
773 algo->name, m->m_pkthdr.len, (u_int32_t)bodyoff));
774 m_freem(m);
775 return EINVAL;
776 }
777 if ((m->m_pkthdr.len - bodyoff) % blocklen) {
778 ipseclog((LOG_ERR, "esp_cbc_decrypt %s: "
779 "payload length must be multiple of %d\n",
780 algo->name, blocklen));
781 m_freem(m);
782 return EINVAL;
783 }
784
785 s = m;
786 d = d0 = dp = NULL;
787 soff = doff = sn = dn = 0;
788 ivp = sp = NULL;
789
790 /* skip bodyoff */
791 while (soff < bodyoff) {
792 if (soff + s->m_len > bodyoff) {
793 sn = (int)(bodyoff - soff);
794 break;
795 }
796
797 soff += s->m_len;
798 s = s->m_next;
799 }
800 scut = s;
801 scutoff = sn;
802
803 /* skip over empty mbuf */
804 while (s && s->m_len == 0) {
805 s = s->m_next;
806 }
807
808 // Allocate blocksized buffer for unaligned or non-contiguous access
809 sbuf = (u_int8_t *)kalloc_data(blocklen, Z_NOWAIT);
810 if (sbuf == NULL) {
811 return ENOBUFS;
812 }
813 while (soff < m->m_pkthdr.len) {
814 /* source */
815 if (sn + blocklen <= s->m_len) {
816 /* body is continuous */
817 sp = mtod(s, u_int8_t *) + sn;
818 } else {
819 /* body is non-continuous */
820 m_copydata(s, sn, blocklen, (caddr_t) sbuf);
821 sp = sbuf;
822 }
823
824 /* destination */
825 if (!d || dn + blocklen > d->m_len) {
826 if (d) {
827 dp = d;
828 }
829 MGET(d, M_DONTWAIT, MT_DATA);
830 i = m->m_pkthdr.len - (soff + sn);
831 if (d && i > MLEN) {
832 MCLGET(d, M_DONTWAIT);
833 if ((d->m_flags & M_EXT) == 0) {
834 m_free(d);
835 d = NULL;
836 }
837 }
838 if (!d) {
839 m_freem(m);
840 if (d0) {
841 m_freem(d0);
842 }
843 result = ENOBUFS;
844 goto end;
845 }
846 if (!d0) {
847 d0 = d;
848 }
849 if (dp) {
850 dp->m_next = d;
851 }
852
853 // try to make mbuf data aligned
854 if (!IPSEC_IS_P2ALIGNED(d->m_data)) {
855 m_adj(d, IPSEC_GET_P2UNALIGNED_OFS(d->m_data));
856 }
857
858 d->m_len = 0;
859 d->m_len = (int)((M_TRAILINGSPACE(d) / blocklen) * blocklen);
860 if (d->m_len > i) {
861 d->m_len = i;
862 }
863 dn = 0;
864 }
865
866 /* decrypt */
867 // check input pointer alignment and use a separate aligned buffer (if sp is unaligned on 4-byte boundary).
868 if (IPSEC_IS_P2ALIGNED(sp)) {
869 sp_unaligned = NULL;
870 } else {
871 sp_unaligned = sp;
872 sp = sbuf;
873 memcpy(sp, sp_unaligned, blocklen);
874 }
875 // no need to check output pointer alignment
876 (*algo->blockdecrypt)(algo, sav, sp, mtod(d, u_int8_t *) + dn);
877
878 // update unaligned pointers
879 if (!IPSEC_IS_P2ALIGNED(sp_unaligned)) {
880 sp = sp_unaligned;
881 }
882
883 /* xor */
884 p = ivp ? ivp : iv;
885 q = mtod(d, u_int8_t *) + dn;
886 for (i = 0; i < blocklen; i++) {
887 q[i] ^= p[i];
888 }
889
890 /* next iv */
891 if (sp == sbuf) {
892 bcopy(sbuf, iv, blocklen);
893 ivp = NULL;
894 } else {
895 ivp = sp;
896 }
897
898 sn += blocklen;
899 dn += blocklen;
900
901 /* find the next source block */
902 while (s && sn >= s->m_len) {
903 sn -= s->m_len;
904 soff += s->m_len;
905 s = s->m_next;
906 }
907 }
908
909 m_freem(scut->m_next);
910 scut->m_len = scutoff;
911 scut->m_next = d0;
912
913 /* just in case */
914 bzero(iv, sizeof(iv));
915 bzero(sbuf, blocklen);
916 end:
917 if (sbuf != NULL) {
918 kfree_data(sbuf, blocklen);
919 }
920 return result;
921 }
922
923 static int
esp_cbc_encrypt(struct mbuf * m,size_t off,__unused size_t plen,struct secasvar * sav,const struct esp_algorithm * algo,int ivlen)924 esp_cbc_encrypt(
925 struct mbuf *m,
926 size_t off,
927 __unused size_t plen,
928 struct secasvar *sav,
929 const struct esp_algorithm *algo,
930 int ivlen)
931 {
932 struct mbuf *s;
933 struct mbuf *d, *d0, *dp;
934 int soff, doff; /* offset from the head of chain, to head of this mbuf */
935 int sn, dn; /* offset from the head of the mbuf, to meat */
936 size_t ivoff, bodyoff;
937 u_int8_t iv[MAXIVLEN] __attribute__((aligned(4))), *ivp;
938 u_int8_t *sbuf = NULL, *sp, *sp_unaligned;
939 u_int8_t *p, *q;
940 struct mbuf *scut;
941 int scutoff;
942 int i, result = 0;
943 int blocklen;
944 int derived;
945
946 if (ivlen != sav->ivlen || ivlen > sizeof(iv)) {
947 ipseclog((LOG_ERR, "esp_cbc_encrypt %s: "
948 "unsupported ivlen %d\n", algo->name, ivlen));
949 m_freem(m);
950 return EINVAL;
951 }
952
953 /* assumes blocklen == padbound */
954 blocklen = algo->padbound;
955
956 #if DIAGNOSTIC
957 if (blocklen > sizeof(iv)) {
958 ipseclog((LOG_ERR, "esp_cbc_encrypt %s: "
959 "unsupported blocklen %d\n", algo->name, blocklen));
960 m_freem(m);
961 return EINVAL;
962 }
963 #endif
964
965 if (sav->flags & SADB_X_EXT_OLD) {
966 /* RFC 1827 */
967 ivoff = off + sizeof(struct esp);
968 bodyoff = off + sizeof(struct esp) + ivlen;
969 derived = 0;
970 } else {
971 /* RFC 2406 */
972 if (sav->flags & SADB_X_EXT_DERIV) {
973 /*
974 * draft-ietf-ipsec-ciph-des-derived-00.txt
975 * uses sequence number field as IV field.
976 */
977 ivoff = off + sizeof(struct esp);
978 bodyoff = off + sizeof(struct esp) + sizeof(u_int32_t);
979 ivlen = sizeof(u_int32_t);
980 derived = 1;
981 } else {
982 ivoff = off + sizeof(struct newesp);
983 bodyoff = off + sizeof(struct newesp) + ivlen;
984 derived = 0;
985 }
986 }
987
988 VERIFY(ivoff <= INT_MAX);
989
990 /* put iv into the packet. if we are in derived mode, use seqno. */
991 if (derived) {
992 m_copydata(m, (int)ivoff, ivlen, (caddr_t) iv);
993 } else {
994 bcopy(sav->iv, iv, ivlen);
995 /* maybe it is better to overwrite dest, not source */
996 m_copyback(m, (int)ivoff, ivlen, (caddr_t) iv);
997 }
998
999 /* extend iv */
1000 if (ivlen == blocklen) {
1001 ;
1002 } else if (ivlen == 4 && blocklen == 8) {
1003 bcopy(&iv[0], &iv[4], 4);
1004 iv[4] ^= 0xff;
1005 iv[5] ^= 0xff;
1006 iv[6] ^= 0xff;
1007 iv[7] ^= 0xff;
1008 } else {
1009 ipseclog((LOG_ERR, "esp_cbc_encrypt %s: "
1010 "unsupported ivlen/blocklen: %d %d\n",
1011 algo->name, ivlen, blocklen));
1012 m_freem(m);
1013 return EINVAL;
1014 }
1015
1016 if (m->m_pkthdr.len < bodyoff) {
1017 ipseclog((LOG_ERR, "esp_cbc_encrypt %s: bad len %d/%u\n",
1018 algo->name, m->m_pkthdr.len, (u_int32_t)bodyoff));
1019 m_freem(m);
1020 return EINVAL;
1021 }
1022 if ((m->m_pkthdr.len - bodyoff) % blocklen) {
1023 ipseclog((LOG_ERR, "esp_cbc_encrypt %s: "
1024 "payload length must be multiple of %u\n",
1025 algo->name, (u_int32_t)algo->padbound));
1026 m_freem(m);
1027 return EINVAL;
1028 }
1029
1030 s = m;
1031 d = d0 = dp = NULL;
1032 soff = doff = sn = dn = 0;
1033 ivp = sp = NULL;
1034
1035 /* skip bodyoff */
1036 while (soff < bodyoff) {
1037 if (soff + s->m_len > bodyoff) {
1038 sn = (int)(bodyoff - soff);
1039 break;
1040 }
1041
1042 soff += s->m_len;
1043 s = s->m_next;
1044 }
1045 scut = s;
1046 scutoff = sn;
1047
1048 /* skip over empty mbuf */
1049 while (s && s->m_len == 0) {
1050 s = s->m_next;
1051 }
1052
1053 // Allocate blocksized buffer for unaligned or non-contiguous access
1054 sbuf = (u_int8_t *)kalloc_data(blocklen, Z_NOWAIT);
1055 if (sbuf == NULL) {
1056 return ENOBUFS;
1057 }
1058 while (soff < m->m_pkthdr.len) {
1059 /* source */
1060 if (sn + blocklen <= s->m_len) {
1061 /* body is continuous */
1062 sp = mtod(s, u_int8_t *) + sn;
1063 } else {
1064 /* body is non-continuous */
1065 m_copydata(s, sn, blocklen, (caddr_t) sbuf);
1066 sp = sbuf;
1067 }
1068
1069 /* destination */
1070 if (!d || dn + blocklen > d->m_len) {
1071 if (d) {
1072 dp = d;
1073 }
1074 MGET(d, M_DONTWAIT, MT_DATA);
1075 i = m->m_pkthdr.len - (soff + sn);
1076 if (d && i > MLEN) {
1077 MCLGET(d, M_DONTWAIT);
1078 if ((d->m_flags & M_EXT) == 0) {
1079 m_free(d);
1080 d = NULL;
1081 }
1082 }
1083 if (!d) {
1084 m_freem(m);
1085 if (d0) {
1086 m_freem(d0);
1087 }
1088 result = ENOBUFS;
1089 goto end;
1090 }
1091 if (!d0) {
1092 d0 = d;
1093 }
1094 if (dp) {
1095 dp->m_next = d;
1096 }
1097
1098 // try to make mbuf data aligned
1099 if (!IPSEC_IS_P2ALIGNED(d->m_data)) {
1100 m_adj(d, IPSEC_GET_P2UNALIGNED_OFS(d->m_data));
1101 }
1102
1103 d->m_len = 0;
1104 d->m_len = (int)((M_TRAILINGSPACE(d) / blocklen) * blocklen);
1105 if (d->m_len > i) {
1106 d->m_len = i;
1107 }
1108 dn = 0;
1109 }
1110
1111 /* xor */
1112 p = ivp ? ivp : iv;
1113 q = sp;
1114 for (i = 0; i < blocklen; i++) {
1115 q[i] ^= p[i];
1116 }
1117
1118 /* encrypt */
1119 // check input pointer alignment and use a separate aligned buffer (if sp is not aligned on 4-byte boundary).
1120 if (IPSEC_IS_P2ALIGNED(sp)) {
1121 sp_unaligned = NULL;
1122 } else {
1123 sp_unaligned = sp;
1124 sp = sbuf;
1125 memcpy(sp, sp_unaligned, blocklen);
1126 }
1127 // no need to check output pointer alignment
1128 (*algo->blockencrypt)(algo, sav, sp, mtod(d, u_int8_t *) + dn);
1129
1130 // update unaligned pointers
1131 if (!IPSEC_IS_P2ALIGNED(sp_unaligned)) {
1132 sp = sp_unaligned;
1133 }
1134
1135 /* next iv */
1136 ivp = mtod(d, u_int8_t *) + dn;
1137
1138 sn += blocklen;
1139 dn += blocklen;
1140
1141 /* find the next source block */
1142 while (s && sn >= s->m_len) {
1143 sn -= s->m_len;
1144 soff += s->m_len;
1145 s = s->m_next;
1146 }
1147 }
1148
1149 m_freem(scut->m_next);
1150 scut->m_len = scutoff;
1151 scut->m_next = d0;
1152
1153 /* just in case */
1154 bzero(iv, sizeof(iv));
1155 bzero(sbuf, blocklen);
1156
1157 key_sa_stir_iv(sav);
1158 end:
1159 if (sbuf != NULL) {
1160 kfree_data(sbuf, blocklen);
1161 }
1162 return result;
1163 }
1164
1165 /*------------------------------------------------------------*/
1166
1167 /* does not free m0 on error */
1168 int
esp_auth(struct mbuf * m0,size_t skip,size_t length,struct secasvar * sav,u_char * sum)1169 esp_auth(
1170 struct mbuf *m0,
1171 size_t skip, /* offset to ESP header */
1172 size_t length, /* payload length */
1173 struct secasvar *sav,
1174 u_char *sum)
1175 {
1176 struct mbuf *m;
1177 size_t off;
1178 struct ah_algorithm_state s;
1179 u_char sumbuf[AH_MAXSUMSIZE] __attribute__((aligned(4)));
1180 const struct ah_algorithm *algo;
1181 size_t siz;
1182 int error;
1183
1184 /* sanity checks */
1185 if (m0->m_pkthdr.len < skip) {
1186 ipseclog((LOG_DEBUG, "esp_auth: mbuf length < skip\n"));
1187 return EINVAL;
1188 }
1189 if (m0->m_pkthdr.len < skip + length) {
1190 ipseclog((LOG_DEBUG,
1191 "esp_auth: mbuf length < skip + length\n"));
1192 return EINVAL;
1193 }
1194
1195 KERNEL_DEBUG(DBG_FNC_ESPAUTH | DBG_FUNC_START, skip, length, 0, 0, 0);
1196 /*
1197 * length of esp part (excluding authentication data) must be 4n,
1198 * since nexthdr must be at offset 4n+3.
1199 */
1200 if (length % 4) {
1201 ipseclog((LOG_ERR, "esp_auth: length is not multiple of 4\n"));
1202 KERNEL_DEBUG(DBG_FNC_ESPAUTH | DBG_FUNC_END, 1, 0, 0, 0, 0);
1203 return EINVAL;
1204 }
1205 if (!sav) {
1206 ipseclog((LOG_DEBUG, "esp_auth: NULL SA passed\n"));
1207 KERNEL_DEBUG(DBG_FNC_ESPAUTH | DBG_FUNC_END, 2, 0, 0, 0, 0);
1208 return EINVAL;
1209 }
1210 algo = ah_algorithm_lookup(sav->alg_auth);
1211 if (!algo) {
1212 ipseclog((LOG_ERR,
1213 "esp_auth: bad ESP auth algorithm passed: %d\n",
1214 sav->alg_auth));
1215 KERNEL_DEBUG(DBG_FNC_ESPAUTH | DBG_FUNC_END, 3, 0, 0, 0, 0);
1216 return EINVAL;
1217 }
1218
1219 m = m0;
1220 off = 0;
1221
1222 siz = (((*algo->sumsiz)(sav) + 3) & ~(4 - 1));
1223 if (sizeof(sumbuf) < siz) {
1224 ipseclog((LOG_DEBUG,
1225 "esp_auth: AH_MAXSUMSIZE is too small: siz=%u\n",
1226 (u_int32_t)siz));
1227 KERNEL_DEBUG(DBG_FNC_ESPAUTH | DBG_FUNC_END, 4, 0, 0, 0, 0);
1228 return EINVAL;
1229 }
1230
1231 /* skip the header */
1232 while (skip) {
1233 if (!m) {
1234 panic("mbuf chain?");
1235 }
1236 if (m->m_len <= skip) {
1237 skip -= m->m_len;
1238 m = m->m_next;
1239 off = 0;
1240 } else {
1241 off = skip;
1242 skip = 0;
1243 }
1244 }
1245
1246 error = (*algo->init)(&s, sav);
1247 if (error) {
1248 KERNEL_DEBUG(DBG_FNC_ESPAUTH | DBG_FUNC_END, 5, 0, 0, 0, 0);
1249 return error;
1250 }
1251 while (0 < length) {
1252 if (!m) {
1253 panic("mbuf chain?");
1254 }
1255
1256 if (m->m_len - off < length) {
1257 (*algo->update)(&s, (caddr_t)(mtod(m, u_char *) + off),
1258 m->m_len - off);
1259 length -= m->m_len - off;
1260 m = m->m_next;
1261 off = 0;
1262 } else {
1263 (*algo->update)(&s, (caddr_t)(mtod(m, u_char *) + off), length);
1264 break;
1265 }
1266 }
1267 (*algo->result)(&s, (caddr_t) sumbuf, sizeof(sumbuf));
1268 bcopy(sumbuf, sum, siz); /*XXX*/
1269 KERNEL_DEBUG(DBG_FNC_ESPAUTH | DBG_FUNC_END, 6, 0, 0, 0, 0);
1270 return 0;
1271 }
1272
1273 void
esp_init(void)1274 esp_init(void)
1275 {
1276 static int esp_initialized = 0;
1277
1278 if (esp_initialized) {
1279 return;
1280 }
1281
1282 esp_initialized = 1;
1283
1284 esp_mpkl_log_object = MPKL_CREATE_LOGOBJECT("com.apple.xnu.esp");
1285 if (esp_mpkl_log_object == NULL) {
1286 panic("MPKL_CREATE_LOGOBJECT for ESP failed");
1287 }
1288
1289 return;
1290 }
1291