2 * Copyright (c) 2011 Apple Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
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.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
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.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
31 #include <sys/systm.h>
33 #include <net/if_types.h>
34 #include <net/if_utun.h>
36 #include <net/if_utun_crypto.h>
37 #include <net/if_utun_crypto_ipsec.h>
38 #include <net/if_utun_crypto_dtls.h>
41 utun_ctl_init_crypto (void)
43 utun_ctl_init_crypto_dtls();
47 utun_cleanup_crypto (struct utun_pcb
*pcb
)
50 utun_cleanup_all_crypto_ipsec(pcb
);
52 utun_cleanup_all_crypto_dtls(pcb
);
53 pcb
->utun_flags
&= ~UTUN_FLAGS_CRYPTO
;
57 utun_ctl_enable_crypto (__unused kern_ctl_ref kctlref
,
58 __unused u_int32_t unit
,
59 __unused
void *unitinfo
,
64 struct utun_pcb
*pcb
= unitinfo
;
67 * - verify the crypto context args passed from user-land.
68 * - check the size of the argument buffer.
69 * - check the direction (IN or OUT)
70 * - check the type (IPSec or DTLS)
71 * - ensure that the crypto context is *not* already valid (don't recreate already valid context).
72 * - we have only one context per direction and type.
73 * - any error should be equivalent to noop.
75 if (len
< UTUN_CRYPTO_ARGS_HDR_SIZE
) {
79 utun_crypto_args_t
*crypto_args
= (__typeof__(crypto_args
))data
;
80 utun_crypto_ctx_t
*crypto_ctx
;
82 if (crypto_args
->ver
== 0 || crypto_args
->ver
>= UTUN_CRYPTO_ARGS_VER_MAX
) {
83 printf("%s: ver check failed %d\n", __FUNCTION__
, crypto_args
->ver
);
86 if (crypto_args
->type
== 0 || crypto_args
->type
>= UTUN_CRYPTO_TYPE_MAX
) {
87 printf("%s: type check failed %d\n", __FUNCTION__
, crypto_args
->type
);
90 if (len
< UTUN_CRYPTO_ARGS_TOTAL_SIZE(crypto_args
)) {
91 printf("%s: vlen check failed (%d,%d)\n", __FUNCTION__
,
92 (int)len
, (int)UTUN_CRYPTO_ARGS_TOTAL_SIZE(crypto_args
));
95 if (crypto_args
->args_ulen
!= sizeof(crypto_args
->u
)) {
96 printf("%s: compatibility mode\n", __FUNCTION__
);
100 if (crypto_args
->type
== UTUN_CRYPTO_TYPE_IPSEC
) {
101 utun_ctl_enable_crypto_ipsec(pcb
, crypto_args
);
104 if (crypto_args
->type
== UTUN_CRYPTO_TYPE_DTLS
) {
105 utun_ctl_enable_crypto_dtls(pcb
, crypto_args
);
108 return EPROTONOSUPPORT
;
110 for (idx
= 0; idx
< UTUN_CRYPTO_DIR_TO_IDX(UTUN_CRYPTO_DIR_MAX
); idx
++) {
111 crypto_ctx
= &pcb
->utun_crypto_ctx
[idx
];
112 if (crypto_ctx
->valid
) {
116 crypto_ctx
->type
= crypto_args
->type
;
117 LIST_INIT(&crypto_ctx
->keys_listhead
);
118 LIST_INIT(&crypto_ctx
->framer_listheads
[UTUN_CRYPTO_INNER_TYPE_TO_IDX(UTUN_CRYPTO_INNER_TYPE_IPv4
)]);
119 LIST_INIT(&crypto_ctx
->framer_listheads
[UTUN_CRYPTO_INNER_TYPE_TO_IDX(UTUN_CRYPTO_INNER_TYPE_IPv6
)]);
120 crypto_ctx
->valid
= 1;
121 printf("%s: initialized framer lists\n", __FUNCTION__
);
123 // data traffic is stopped by default
124 pcb
->utun_flags
|= (UTUN_FLAGS_CRYPTO
| UTUN_FLAGS_CRYPTO_STOP_DATA_TRAFFIC
);
130 utun_ctl_disable_crypto (__unused kern_ctl_ref kctlref
,
131 __unused u_int32_t unit
,
132 __unused
void *unitinfo
,
137 struct utun_pcb
*pcb
= unitinfo
;
140 * - verify the crypto context args passed from user-land.
141 * - check the size of the argument buffer.
142 * - check the direction (IN or OUT)
143 * - check the type (IPSec or DTLS)
144 * - ensure that the crypto context *is* already valid (don't release invalid context).
145 * - we have only one context per direction and type.
146 * - ensure that the crypto context has no crypto material.
147 * - any error should be equivalent to noop.
149 if (len
< UTUN_CRYPTO_ARGS_HDR_SIZE
) {
152 utun_crypto_args_t
*crypto_args
= (__typeof__(crypto_args
))data
;
154 if (crypto_args
->ver
== 0 || crypto_args
->ver
>= UTUN_CRYPTO_ARGS_VER_MAX
) {
155 printf("%s: ver check failed %d\n", __FUNCTION__
, crypto_args
->ver
);
158 if (crypto_args
->type
== 0 || crypto_args
->type
>= UTUN_CRYPTO_TYPE_MAX
) {
159 printf("%s: type check failed %d\n", __FUNCTION__
, crypto_args
->type
);
162 if (len
< UTUN_CRYPTO_ARGS_TOTAL_SIZE(crypto_args
)) {
163 printf("%s: vlen check failed (%d,%d)\n", __FUNCTION__
,
164 (int)len
, (int)UTUN_CRYPTO_ARGS_TOTAL_SIZE(crypto_args
));
167 if (crypto_args
->args_ulen
!= sizeof(crypto_args
->u
)) {
168 printf("%s: compatibility mode\n", __FUNCTION__
);
172 if (crypto_args
->type
== UTUN_CRYPTO_TYPE_IPSEC
) {
173 utun_ctl_disable_crypto_ipsec(pcb
);
176 if (crypto_args
->type
== UTUN_CRYPTO_TYPE_DTLS
) {
177 utun_ctl_disable_crypto_dtls(pcb
);
180 return EPROTONOSUPPORT
;
183 pcb
->utun_flags
&= ~(UTUN_FLAGS_CRYPTO
| UTUN_FLAGS_CRYPTO_STOP_DATA_TRAFFIC
);
188 utun_ctl_config_crypto_keys (__unused kern_ctl_ref kctlref
,
189 __unused u_int32_t unit
,
190 __unused
void *unitinfo
,
195 struct utun_pcb
*pcb
= unitinfo
;
198 * - verify the crypto material args passed from user-land.
199 * - check the size of the argument buffer.
200 * - check the direction (IN or OUT)
201 * - check the type (IPSec only)
202 * - crypto material direction and type must match the associated crypto context's.
203 * - we can have a list of crypto materials per context.
204 * - ensure that the crypto context is already valid (don't add crypto material to invalid context).
205 * - any error should be equivalent to noop.
207 if (len
< UTUN_CRYPTO_KEYS_ARGS_HDR_SIZE
) {
211 utun_crypto_keys_args_t
*crypto_keys_args
= (__typeof__(crypto_keys_args
))data
;
212 utun_crypto_ctx_t
*crypto_ctx
;
213 utun_crypto_keys_t
*crypto_keys
= NULL
;
215 if (crypto_keys_args
->ver
== 0 || crypto_keys_args
->ver
>= UTUN_CRYPTO_KEYS_ARGS_VER_MAX
) {
216 printf("%s: ver check failed %d\n", __FUNCTION__
, crypto_keys_args
->ver
);
219 if (crypto_keys_args
->dir
== 0 || crypto_keys_args
->dir
>= UTUN_CRYPTO_DIR_MAX
) {
220 printf("%s: dir check failed %d\n", __FUNCTION__
, crypto_keys_args
->dir
);
223 if (crypto_keys_args
->type
== 0 || crypto_keys_args
->type
>= UTUN_CRYPTO_TYPE_MAX
) {
224 printf("%s: type check failed %d\n", __FUNCTION__
, crypto_keys_args
->type
);
227 if (len
< UTUN_CRYPTO_KEYS_ARGS_TOTAL_SIZE(crypto_keys_args
)) {
228 printf("%s: vlen check failed (%d,%d)\n", __FUNCTION__
,
229 (int)len
, (int)UTUN_CRYPTO_KEYS_ARGS_TOTAL_SIZE(crypto_keys_args
));
232 idx
= UTUN_CRYPTO_DIR_TO_IDX(crypto_keys_args
->dir
);
233 crypto_ctx
= &pcb
->utun_crypto_ctx
[idx
];
234 if (!crypto_ctx
->valid
) {
237 if (crypto_keys_args
->type
!= crypto_ctx
->type
) {
238 // can't add keymat to context with different crypto type
241 crypto_keys
= utun_alloc(sizeof(*crypto_keys
));
245 bzero(crypto_keys
, sizeof(*crypto_keys
));
246 if (crypto_keys_args
->args_ulen
!= sizeof(crypto_keys_args
->u
)) {
247 printf("%s: compatibility mode\n", __FUNCTION__
);
250 // branch-off for ipsec vs. dtls
252 if (crypto_keys_args
->type
== UTUN_CRYPTO_TYPE_IPSEC
) {
254 if ((err
= utun_ctl_config_crypto_keys_ipsec(pcb
, crypto_keys_args
, crypto_keys
))) {
255 utun_free(crypto_keys
);
262 utun_free(crypto_keys
);
263 return EPROTONOSUPPORT
;
265 crypto_keys
->type
= crypto_keys_args
->type
;
266 LIST_INSERT_HEAD(&crypto_ctx
->keys_listhead
, crypto_keys
, chain
);
267 crypto_keys
->valid
= 1;
274 utun_ctl_unconfig_crypto_keys (__unused kern_ctl_ref kctlref
,
275 __unused u_int32_t unit
,
276 __unused
void *unitinfo
,
281 struct utun_pcb
*pcb
= unitinfo
;
284 * - verify the crypto material args passed from user-land.
285 * - check the size of the argument buffer.
286 * - check the direction (IN or OUT)
287 * - check the type (IPSec only)
288 * - crypto material direction and type must match the associated crypto context's.
289 * - we can have a list of crypto materials per context.
290 * - ensure that the crypto context is already valid (don't add crypto material to invalid context).
291 * - any error should be equivalent to noop.
293 if (len
< UTUN_CRYPTO_KEYS_ARGS_HDR_SIZE
) {
297 utun_crypto_keys_args_t
*crypto_keys_args
= (__typeof__(crypto_keys_args
))data
;
298 utun_crypto_ctx_t
*crypto_ctx
;
299 utun_crypto_keys_t
*cur_crypto_keys
, *nxt_crypto_keys
;
301 if (crypto_keys_args
->ver
== 0 || crypto_keys_args
->ver
>= UTUN_CRYPTO_KEYS_ARGS_VER_MAX
) {
302 printf("%s: ver check failed %d\n", __FUNCTION__
, crypto_keys_args
->ver
);
305 if (crypto_keys_args
->dir
== 0 || crypto_keys_args
->dir
>= UTUN_CRYPTO_DIR_MAX
) {
306 printf("%s: dir check failed %d\n", __FUNCTION__
, crypto_keys_args
->dir
);
309 if (crypto_keys_args
->type
== 0 || crypto_keys_args
->type
>= UTUN_CRYPTO_TYPE_MAX
) {
310 printf("%s: type check failed %d\n", __FUNCTION__
, crypto_keys_args
->type
);
313 if (len
< UTUN_CRYPTO_KEYS_ARGS_TOTAL_SIZE(crypto_keys_args
)) {
314 printf("%s: vlen check failed (%d,%d)\n", __FUNCTION__
,
315 (int)len
, (int)UTUN_CRYPTO_KEYS_ARGS_TOTAL_SIZE(crypto_keys_args
));
318 idx
= UTUN_CRYPTO_DIR_TO_IDX(crypto_keys_args
->dir
);
319 crypto_ctx
= &pcb
->utun_crypto_ctx
[idx
];
320 if (!crypto_ctx
->valid
) {
323 if (crypto_keys_args
->type
!= crypto_ctx
->type
) {
324 // can't add keymat to context with different crypto type
327 if (crypto_keys_args
->args_ulen
!= sizeof(crypto_keys_args
->u
)) {
328 printf("%s: compatibility mode\n", __FUNCTION__
);
331 // traverse crypto materials looking for the right one
332 for (cur_crypto_keys
= (__typeof__(cur_crypto_keys
))LIST_FIRST(&crypto_ctx
->keys_listhead
);
333 cur_crypto_keys
!= NULL
;
334 cur_crypto_keys
= nxt_crypto_keys
) {
335 nxt_crypto_keys
= (__typeof__(nxt_crypto_keys
))LIST_NEXT(cur_crypto_keys
, chain
);
336 // branch-off for ipsec vs. dtls
338 if (crypto_keys_args
->type
== UTUN_CRYPTO_TYPE_IPSEC
) {
339 if (crypto_keys_args
->u
.ipsec_v1
.spi
== cur_crypto_keys
->state
.u
.ipsec
.spi
) {
341 if ((err
= utun_ctl_unconfig_crypto_keys_ipsec(crypto_keys_args
, cur_crypto_keys
))) {
344 LIST_REMOVE(cur_crypto_keys
, chain
);
345 bzero(cur_crypto_keys
, sizeof(*cur_crypto_keys
));
346 utun_free(cur_crypto_keys
);
353 return EPROTONOSUPPORT
;
356 // TODO: if there is no SA left, ensure utun can't decrypt/encrypt packets directly. it should rely on the vpnplugin for that.
363 utun_ctl_config_crypto_framer (__unused kern_ctl_ref kctlref
,
364 __unused u_int32_t unit
,
365 __unused
void *unitinfo
,
370 struct utun_pcb
*pcb
= unitinfo
;
373 * - verify the crypto material args passed from user-land.
374 * - check the size of the argument buffer.
375 * - check the direction (IN or OUT)
376 * - check the type (DTLS only)
377 * - crypto material direction and type must match the associated crypto context's.
378 * - we can have a list of crypto materials per context.
379 * - ensure that the crypto context is already valid (don't add crypto material to invalid context).
380 * - any error should be equivalent to noop.
382 if (len
< UTUN_CRYPTO_FRAMER_ARGS_HDR_SIZE
) {
386 utun_crypto_framer_args_t
*framer_args
= (__typeof__(framer_args
))data
;
387 utun_crypto_ctx_t
*crypto_ctx
;
389 if (framer_args
->ver
== 0 || framer_args
->ver
>= UTUN_CRYPTO_FRAMER_ARGS_VER_MAX
) {
390 printf("%s: ver check failed %d\n", __FUNCTION__
, (int)framer_args
->ver
);
393 if (framer_args
->dir
== 0 || framer_args
->dir
>= UTUN_CRYPTO_DIR_MAX
) {
394 printf("%s: dir check failed %d\n", __FUNCTION__
, (int)framer_args
->dir
);
397 if (framer_args
->type
== 0 || framer_args
->type
>= UTUN_CRYPTO_TYPE_MAX
) {
398 printf("%s: type check failed %d\n", __FUNCTION__
, (int)framer_args
->type
);
401 if (len
< UTUN_CRYPTO_FRAMER_ARGS_TOTAL_SIZE(framer_args
)) {
402 printf("%s: vlen check failed (%d,%d)\n", __FUNCTION__
,
403 (int)len
, (int)UTUN_CRYPTO_FRAMER_ARGS_TOTAL_SIZE(framer_args
));
406 idx
= UTUN_CRYPTO_DIR_TO_IDX(framer_args
->dir
);
407 crypto_ctx
= &pcb
->utun_crypto_ctx
[idx
];
408 if (!crypto_ctx
->valid
) {
411 if (framer_args
->type
!= crypto_ctx
->type
) {
412 // can't add keymat to context with different crypto type
415 if (framer_args
->args_ulen
!= sizeof(framer_args
->u
)) {
416 printf("%s: compatibility mode\n", __FUNCTION__
);
420 // branch-off for ipsec vs. dtls
421 if (framer_args
->type
== UTUN_CRYPTO_TYPE_DTLS
) {
423 if ((err
= utun_ctl_config_crypto_dtls_framer(crypto_ctx
, framer_args
))) {
428 return EPROTONOSUPPORT
;
436 utun_ctl_unconfig_crypto_framer (__unused kern_ctl_ref kctlref
,
437 __unused u_int32_t unit
,
438 __unused
void *unitinfo
,
443 struct utun_pcb
*pcb
= unitinfo
;
446 * - verify the crypto material args passed from user-land.
447 * - check the size of the argument buffer.
448 * - check the direction (IN or OUT)
449 * - check the type (DTLS only)
450 * - crypto material direction and type must match the associated crypto context's.
451 * - we can have a list of crypto materials per context.
452 * - ensure that the crypto context is already valid (don't add crypto material to invalid context).
453 * - any error should be equivalent to noop.
455 if (len
< UTUN_CRYPTO_FRAMER_ARGS_HDR_SIZE
) {
459 utun_crypto_framer_args_t
*framer_args
= (__typeof__(framer_args
))data
;
460 utun_crypto_ctx_t
*crypto_ctx
;
462 if (framer_args
->ver
== 0 || framer_args
->ver
>= UTUN_CRYPTO_FRAMER_ARGS_VER_MAX
) {
463 printf("%s: ver check failed %d\n", __FUNCTION__
, (int)framer_args
->ver
);
466 if (framer_args
->dir
== 0 || framer_args
->dir
>= UTUN_CRYPTO_DIR_MAX
) {
467 printf("%s: dir check failed %d\n", __FUNCTION__
, (int)framer_args
->dir
);
470 if (framer_args
->type
== 0 || framer_args
->type
>= UTUN_CRYPTO_TYPE_MAX
) {
471 printf("%s: type check failed %d\n", __FUNCTION__
, (int)framer_args
->type
);
474 if (len
< UTUN_CRYPTO_FRAMER_ARGS_TOTAL_SIZE(framer_args
)) {
475 printf("%s: vlen check failed (%d,%d)\n", __FUNCTION__
,
476 (int)len
, (int)UTUN_CRYPTO_FRAMER_ARGS_TOTAL_SIZE(framer_args
));
479 idx
= UTUN_CRYPTO_DIR_TO_IDX(framer_args
->dir
);
480 crypto_ctx
= &pcb
->utun_crypto_ctx
[idx
];
481 if (!crypto_ctx
->valid
) {
484 if (framer_args
->type
!= crypto_ctx
->type
) {
485 // can't add keymat to context with different crypto type
488 if (framer_args
->args_ulen
!= sizeof(framer_args
->u
)) {
489 printf("%s: compatibility mode\n", __FUNCTION__
);
492 // branch-off for ipsec vs. dtls
493 if (framer_args
->type
== UTUN_CRYPTO_TYPE_DTLS
) {
495 if ((err
= utun_ctl_unconfig_crypto_dtls_framer(crypto_ctx
, framer_args
))) {
500 return EPROTONOSUPPORT
;
508 utun_ctl_generate_crypto_keys_idx (__unused kern_ctl_ref kctlref
,
509 __unused u_int32_t unit
,
510 __unused
void *unitinfo
,
515 struct utun_pcb
*pcb
= unitinfo
;
518 * - verify the crypto material index args passed from user-land.
519 * - check the size of the argument buffer.
520 * - check the direction (IN or OUT)
521 * - check the type (IPSec only)
522 * - crypto material direction and type must match the associated crypto context's.
523 * - we can have a list of crypto materials per context.
524 * - any error should be equivalent to noop.
526 if (*len
< UTUN_CRYPTO_KEYS_IDX_ARGS_HDR_SIZE
) {
530 utun_crypto_keys_idx_args_t
*crypto_keys_idx_args
= (__typeof__(crypto_keys_idx_args
))data
;
531 utun_crypto_ctx_t
*crypto_ctx
;
533 if (crypto_keys_idx_args
->ver
== 0 || crypto_keys_idx_args
->ver
>= UTUN_CRYPTO_KEYS_ARGS_VER_MAX
) {
534 printf("%s: ver check failed %d\n", __FUNCTION__
, crypto_keys_idx_args
->ver
);
537 if (crypto_keys_idx_args
->dir
== 0 || crypto_keys_idx_args
->dir
>= UTUN_CRYPTO_DIR_MAX
) {
538 printf("%s: dir check failed %d\n", __FUNCTION__
, crypto_keys_idx_args
->dir
);
541 if (crypto_keys_idx_args
->type
== 0 || crypto_keys_idx_args
->type
>= UTUN_CRYPTO_TYPE_MAX
) {
542 printf("%s: type check failed %d\n", __FUNCTION__
, crypto_keys_idx_args
->type
);
545 if (*len
< UTUN_CRYPTO_KEYS_IDX_ARGS_TOTAL_SIZE(crypto_keys_idx_args
)) {
546 printf("%s: vlen check failed (%d,%d)\n", __FUNCTION__
,
547 (int)*len
, (int)UTUN_CRYPTO_KEYS_IDX_ARGS_TOTAL_SIZE(crypto_keys_idx_args
));
550 idx
= UTUN_CRYPTO_DIR_TO_IDX(crypto_keys_idx_args
->dir
);
551 crypto_ctx
= &pcb
->utun_crypto_ctx
[idx
];
552 if (!crypto_ctx
->valid
) {
555 if (crypto_keys_idx_args
->type
!= crypto_ctx
->type
) {
556 // can't add keymat to context with different crypto type
559 if (crypto_keys_idx_args
->args_ulen
!= sizeof(crypto_keys_idx_args
->u
)) {
560 printf("%s: compatibility mode\n", __FUNCTION__
);
563 // traverse crypto materials looking for the right one
564 // branch-off for ipsec vs. dtls
566 if (crypto_keys_idx_args
->type
== UTUN_CRYPTO_TYPE_IPSEC
) {
568 if ((err
= utun_ctl_generate_crypto_keys_idx_ipsec(crypto_keys_idx_args
))) {
575 return EPROTONOSUPPORT
;
583 utun_ctl_stop_crypto_data_traffic (__unused kern_ctl_ref kctlref
,
584 __unused u_int32_t unit
,
585 __unused
void *unitinfo
,
590 struct utun_pcb
*pcb
= unitinfo
;
593 * - verify the crypto context args passed from user-land.
594 * - check the size of the argument buffer.
595 * - check the direction (IN or OUT)
596 * - check the type (IPSec or DTLS)
597 * - ensure that the crypto context *is* already valid (don't release invalid context).
598 * - we have only one context per direction and type.
599 * - ensure that the crypto context has no crypto material.
600 * - any error should be equivalent to noop.
602 if (len
< UTUN_CRYPTO_ARGS_HDR_SIZE
) {
605 utun_crypto_args_t
*crypto_args
= (__typeof__(crypto_args
))data
;
607 if (crypto_args
->ver
== 0 || crypto_args
->ver
>= UTUN_CRYPTO_ARGS_VER_MAX
) {
608 printf("%s: ver check failed %d\n", __FUNCTION__
, crypto_args
->ver
);
611 if (crypto_args
->type
== 0 || crypto_args
->type
>= UTUN_CRYPTO_TYPE_MAX
) {
612 printf("%s: type check failed %d\n", __FUNCTION__
, crypto_args
->type
);
615 if (len
< UTUN_CRYPTO_ARGS_TOTAL_SIZE(crypto_args
)) {
616 printf("%s: vlen check failed (%d,%d)\n", __FUNCTION__
,
617 (int)len
, (int)UTUN_CRYPTO_ARGS_TOTAL_SIZE(crypto_args
));
620 if (crypto_args
->args_ulen
!= sizeof(crypto_args
->u
)) {
621 printf("%s: compatibility mode\n", __FUNCTION__
);
624 if ((pcb
->utun_flags
& UTUN_FLAGS_CRYPTO
) == 0) {
625 printf("%s: crypto is already disabled\n", __FUNCTION__
);
629 if (crypto_args
->type
== UTUN_CRYPTO_TYPE_IPSEC
) {
631 } else if (crypto_args
->type
== UTUN_CRYPTO_TYPE_DTLS
) {
632 utun_ctl_stop_datatraffic_crypto_dtls(pcb
);
635 return EPROTONOSUPPORT
;
638 pcb
->utun_flags
|= UTUN_FLAGS_CRYPTO_STOP_DATA_TRAFFIC
;
643 utun_ctl_start_crypto_data_traffic (__unused kern_ctl_ref kctlref
,
644 __unused u_int32_t unit
,
645 __unused
void *unitinfo
,
650 struct utun_pcb
*pcb
= unitinfo
;
653 * - verify the crypto context args passed from user-land.
654 * - check the size of the argument buffer.
655 * - check the direction (IN or OUT)
656 * - check the type (IPSec or DTLS)
657 * - ensure that the crypto context *is* already valid (don't release invalid context).
658 * - we have only one context per direction and type.
659 * - ensure that the crypto context has no crypto material.
660 * - any error should be equivalent to noop.
662 if (len
< UTUN_CRYPTO_ARGS_HDR_SIZE
) {
665 utun_crypto_args_t
*crypto_args
= (__typeof__(crypto_args
))data
;
667 if (crypto_args
->ver
== 0 || crypto_args
->ver
>= UTUN_CRYPTO_ARGS_VER_MAX
) {
668 printf("%s: ver check failed %d\n", __FUNCTION__
, crypto_args
->ver
);
671 if (crypto_args
->type
== 0 || crypto_args
->type
>= UTUN_CRYPTO_TYPE_MAX
) {
672 printf("%s: type check failed %d\n", __FUNCTION__
, crypto_args
->type
);
675 if (len
< UTUN_CRYPTO_ARGS_TOTAL_SIZE(crypto_args
)) {
676 printf("%s: vlen check failed (%d,%d)\n", __FUNCTION__
,
677 (int)len
, (int)UTUN_CRYPTO_ARGS_TOTAL_SIZE(crypto_args
));
680 if (crypto_args
->args_ulen
!= sizeof(crypto_args
->u
)) {
681 printf("%s: compatibility mode\n", __FUNCTION__
);
684 if ((pcb
->utun_flags
& UTUN_FLAGS_CRYPTO
) == 0) {
685 printf("%s: crypto is already disabled\n", __FUNCTION__
);
689 if (crypto_args
->type
== UTUN_CRYPTO_TYPE_IPSEC
) {
691 } else if (crypto_args
->type
== UTUN_CRYPTO_TYPE_DTLS
) {
692 utun_ctl_start_datatraffic_crypto_dtls(pcb
);
695 return EPROTONOSUPPORT
;
698 pcb
->utun_flags
&= ~UTUN_FLAGS_CRYPTO_STOP_DATA_TRAFFIC
;
703 utun_pkt_crypto_output (struct utun_pcb
*pcb
, mbuf_t
*m
)
705 int idx
= UTUN_CRYPTO_DIR_TO_IDX(UTUN_CRYPTO_DIR_OUT
);
706 if (!pcb
->utun_crypto_ctx
[idx
].valid
) {
707 printf("%s: context is invalid %d\n", __FUNCTION__
, pcb
->utun_crypto_ctx
[idx
].valid
);
711 if (pcb
->utun_crypto_ctx
[idx
].type
== UTUN_CRYPTO_TYPE_IPSEC
) {
712 return(utun_pkt_ipsec_output(pcb
, m
));
715 if (pcb
->utun_crypto_ctx
[idx
].type
== UTUN_CRYPTO_TYPE_DTLS
) {
716 return(utun_pkt_dtls_output(pcb
, m
));
719 printf("%s: type is invalid %d\n", __FUNCTION__
, pcb
->utun_crypto_ctx
[idx
].type
);