xref: /xnu-10002.61.3/bsd/netinet6/in6_cga.c (revision 0f4c859e951fba394238ab619495c4e1d54d0f34)
1*0f4c859eSApple OSS Distributions /*
2*0f4c859eSApple OSS Distributions  * Copyright (c) 2013-2021 Apple Inc. All rights reserved.
3*0f4c859eSApple OSS Distributions  *
4*0f4c859eSApple OSS Distributions  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5*0f4c859eSApple OSS Distributions  *
6*0f4c859eSApple OSS Distributions  * This file contains Original Code and/or Modifications of Original Code
7*0f4c859eSApple OSS Distributions  * as defined in and that are subject to the Apple Public Source License
8*0f4c859eSApple OSS Distributions  * Version 2.0 (the 'License'). You may not use this file except in
9*0f4c859eSApple OSS Distributions  * compliance with the License. The rights granted to you under the License
10*0f4c859eSApple OSS Distributions  * may not be used to create, or enable the creation or redistribution of,
11*0f4c859eSApple OSS Distributions  * unlawful or unlicensed copies of an Apple operating system, or to
12*0f4c859eSApple OSS Distributions  * circumvent, violate, or enable the circumvention or violation of, any
13*0f4c859eSApple OSS Distributions  * terms of an Apple operating system software license agreement.
14*0f4c859eSApple OSS Distributions  *
15*0f4c859eSApple OSS Distributions  * Please obtain a copy of the License at
16*0f4c859eSApple OSS Distributions  * http://www.opensource.apple.com/apsl/ and read it before using this file.
17*0f4c859eSApple OSS Distributions  *
18*0f4c859eSApple OSS Distributions  * The Original Code and all software distributed under the License are
19*0f4c859eSApple OSS Distributions  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20*0f4c859eSApple OSS Distributions  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21*0f4c859eSApple OSS Distributions  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22*0f4c859eSApple OSS Distributions  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23*0f4c859eSApple OSS Distributions  * Please see the License for the specific language governing rights and
24*0f4c859eSApple OSS Distributions  * limitations under the License.
25*0f4c859eSApple OSS Distributions  *
26*0f4c859eSApple OSS Distributions  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27*0f4c859eSApple OSS Distributions  */
28*0f4c859eSApple OSS Distributions 
29*0f4c859eSApple OSS Distributions #include <sys/types.h>
30*0f4c859eSApple OSS Distributions #include <sys/malloc.h>
31*0f4c859eSApple OSS Distributions 
32*0f4c859eSApple OSS Distributions #include <kern/locks.h>
33*0f4c859eSApple OSS Distributions 
34*0f4c859eSApple OSS Distributions #include <libkern/crypto/sha1.h>
35*0f4c859eSApple OSS Distributions 
36*0f4c859eSApple OSS Distributions #include <net/if.h>
37*0f4c859eSApple OSS Distributions 
38*0f4c859eSApple OSS Distributions #include <netinet/in.h>
39*0f4c859eSApple OSS Distributions #include <netinet6/in6_var.h>
40*0f4c859eSApple OSS Distributions #include <netinet/ip6.h>
41*0f4c859eSApple OSS Distributions #include <netinet6/ip6_var.h>
42*0f4c859eSApple OSS Distributions #include <netinet6/nd6.h>
43*0f4c859eSApple OSS Distributions 
44*0f4c859eSApple OSS Distributions #define IN6_CGA_HASH1_LENGTH    8
45*0f4c859eSApple OSS Distributions #define IN6_CGA_HASH2_LENGTH    14
46*0f4c859eSApple OSS Distributions #define IN6_CGA_PREPARE_ZEROES  9
47*0f4c859eSApple OSS Distributions 
48*0f4c859eSApple OSS Distributions struct in6_cga_hash1 {
49*0f4c859eSApple OSS Distributions 	u_int8_t octets[IN6_CGA_HASH1_LENGTH];
50*0f4c859eSApple OSS Distributions };
51*0f4c859eSApple OSS Distributions 
52*0f4c859eSApple OSS Distributions struct in6_cga_hash2 {
53*0f4c859eSApple OSS Distributions 	u_int8_t octets[IN6_CGA_HASH2_LENGTH];
54*0f4c859eSApple OSS Distributions };
55*0f4c859eSApple OSS Distributions 
56*0f4c859eSApple OSS Distributions struct in6_cga_singleton {
57*0f4c859eSApple OSS Distributions 	boolean_t cga_initialized;
58*0f4c859eSApple OSS Distributions 	decl_lck_mtx_data(, cga_mutex);
59*0f4c859eSApple OSS Distributions 	struct in6_cga_prepare cga_prepare;
60*0f4c859eSApple OSS Distributions 	struct iovec cga_pubkey;
61*0f4c859eSApple OSS Distributions 	struct iovec cga_privkey;
62*0f4c859eSApple OSS Distributions };
63*0f4c859eSApple OSS Distributions 
64*0f4c859eSApple OSS Distributions static struct in6_cga_singleton in6_cga = {
65*0f4c859eSApple OSS Distributions 	.cga_initialized = FALSE,
66*0f4c859eSApple OSS Distributions 	.cga_mutex = {},
67*0f4c859eSApple OSS Distributions 	.cga_prepare = {
68*0f4c859eSApple OSS Distributions 		.cga_modifier = {},
69*0f4c859eSApple OSS Distributions 		.cga_security_level = 0,
70*0f4c859eSApple OSS Distributions 	},
71*0f4c859eSApple OSS Distributions 	.cga_pubkey = {
72*0f4c859eSApple OSS Distributions 		.iov_base = NULL,
73*0f4c859eSApple OSS Distributions 		.iov_len = 0,
74*0f4c859eSApple OSS Distributions 	},
75*0f4c859eSApple OSS Distributions 	.cga_privkey = {
76*0f4c859eSApple OSS Distributions 		.iov_base = NULL,
77*0f4c859eSApple OSS Distributions 		.iov_len = 0,
78*0f4c859eSApple OSS Distributions 	},
79*0f4c859eSApple OSS Distributions };
80*0f4c859eSApple OSS Distributions 
81*0f4c859eSApple OSS Distributions static void
in6_cga_node_lock_assert(int owned)82*0f4c859eSApple OSS Distributions in6_cga_node_lock_assert(int owned)
83*0f4c859eSApple OSS Distributions {
84*0f4c859eSApple OSS Distributions #if !MACH_ASSERT
85*0f4c859eSApple OSS Distributions #pragma unused(owned)
86*0f4c859eSApple OSS Distributions #endif
87*0f4c859eSApple OSS Distributions 	VERIFY(in6_cga.cga_initialized);
88*0f4c859eSApple OSS Distributions 	LCK_MTX_ASSERT(&in6_cga.cga_mutex, owned);
89*0f4c859eSApple OSS Distributions }
90*0f4c859eSApple OSS Distributions 
91*0f4c859eSApple OSS Distributions static boolean_t
in6_cga_is_prepare_valid(const struct in6_cga_prepare * prepare,const struct iovec * pubkey)92*0f4c859eSApple OSS Distributions in6_cga_is_prepare_valid(const struct in6_cga_prepare *prepare,
93*0f4c859eSApple OSS Distributions     const struct iovec *pubkey)
94*0f4c859eSApple OSS Distributions {
95*0f4c859eSApple OSS Distributions 	static const u_int8_t zeroes[IN6_CGA_PREPARE_ZEROES] = { };
96*0f4c859eSApple OSS Distributions 	SHA1_CTX ctx;
97*0f4c859eSApple OSS Distributions 	u_int8_t sha1[SHA1_RESULTLEN];
98*0f4c859eSApple OSS Distributions 	u_int i, n;
99*0f4c859eSApple OSS Distributions 
100*0f4c859eSApple OSS Distributions 	VERIFY(prepare != NULL);
101*0f4c859eSApple OSS Distributions 	VERIFY(pubkey != NULL && pubkey->iov_base != NULL);
102*0f4c859eSApple OSS Distributions 
103*0f4c859eSApple OSS Distributions 	if (prepare->cga_security_level == 0) {
104*0f4c859eSApple OSS Distributions 		return TRUE;
105*0f4c859eSApple OSS Distributions 	}
106*0f4c859eSApple OSS Distributions 
107*0f4c859eSApple OSS Distributions 	if (prepare->cga_security_level > 7) {
108*0f4c859eSApple OSS Distributions 		return FALSE;
109*0f4c859eSApple OSS Distributions 	}
110*0f4c859eSApple OSS Distributions 
111*0f4c859eSApple OSS Distributions 	SHA1Init(&ctx);
112*0f4c859eSApple OSS Distributions 	SHA1Update(&ctx, &prepare->cga_modifier.octets,
113*0f4c859eSApple OSS Distributions 	    IN6_CGA_MODIFIER_LENGTH);
114*0f4c859eSApple OSS Distributions 	SHA1Update(&ctx, &zeroes, IN6_CGA_PREPARE_ZEROES);
115*0f4c859eSApple OSS Distributions 	SHA1Update(&ctx, pubkey->iov_base, pubkey->iov_len);
116*0f4c859eSApple OSS Distributions 	/* FUTURE: extension fields */
117*0f4c859eSApple OSS Distributions 	SHA1Final(sha1, &ctx);
118*0f4c859eSApple OSS Distributions 
119*0f4c859eSApple OSS Distributions 	n = 2 * (u_int) prepare->cga_security_level;
120*0f4c859eSApple OSS Distributions 	VERIFY(n < SHA1_RESULTLEN);
121*0f4c859eSApple OSS Distributions 	for (i = 0; i < n; ++i) {
122*0f4c859eSApple OSS Distributions 		if (sha1[i] != 0) {
123*0f4c859eSApple OSS Distributions 			return FALSE;
124*0f4c859eSApple OSS Distributions 		}
125*0f4c859eSApple OSS Distributions 	}
126*0f4c859eSApple OSS Distributions 
127*0f4c859eSApple OSS Distributions 	return TRUE;
128*0f4c859eSApple OSS Distributions }
129*0f4c859eSApple OSS Distributions 
130*0f4c859eSApple OSS Distributions /*
131*0f4c859eSApple OSS Distributions  * @brief Generate interface identifier for CGA
132*0f4c859eSApple OSS Distributions  *      XXX You may notice that following does not really
133*0f4c859eSApple OSS Distributions  *      mirror what is decribed in:
134*0f4c859eSApple OSS Distributions  *      https://tools.ietf.org/html/rfc3972#section-4
135*0f4c859eSApple OSS Distributions  *      By design kernel here will assume that that
136*0f4c859eSApple OSS Distributions  *      modifier has been converged on by userspace
137*0f4c859eSApple OSS Distributions  *      for first part of the algorithm for the given
138*0f4c859eSApple OSS Distributions  *      security level.
139*0f4c859eSApple OSS Distributions  *      We are not doing that yet but that's how the code
140*0f4c859eSApple OSS Distributions  *      below is written. So really we are starting
141*0f4c859eSApple OSS Distributions  *      from bullet 4 of the algorithm.
142*0f4c859eSApple OSS Distributions  *
143*0f4c859eSApple OSS Distributions  * @param prepare Pointer to object containing modifier,
144*0f4c859eSApple OSS Distributions  *      security level & extension to be used.
145*0f4c859eSApple OSS Distributions  * @param pubkey Public key used for IID generation
146*0f4c859eSApple OSS Distributions  * @param collisions Collission count on DAD failure
147*0f4c859eSApple OSS Distributions  *      XXX We are not really re-generating IID on DAD
148*0f4c859eSApple OSS Distributions  *      failures for now.
149*0f4c859eSApple OSS Distributions  * @param in6 Pointer to the address containing
150*0f4c859eSApple OSS Distributions  *      the prefix.
151*0f4c859eSApple OSS Distributions  *
152*0f4c859eSApple OSS Distributions  * @return void
153*0f4c859eSApple OSS Distributions  */
154*0f4c859eSApple OSS Distributions static void
in6_cga_generate_iid(const struct in6_cga_prepare * prepare,const struct iovec * pubkey,u_int8_t collisions,struct in6_addr * in6,struct ifnet * ifp)155*0f4c859eSApple OSS Distributions in6_cga_generate_iid(const struct in6_cga_prepare *prepare,
156*0f4c859eSApple OSS Distributions     const struct iovec *pubkey, u_int8_t collisions,
157*0f4c859eSApple OSS Distributions     struct in6_addr *in6, struct ifnet *ifp)
158*0f4c859eSApple OSS Distributions {
159*0f4c859eSApple OSS Distributions 	SHA1_CTX ctx;
160*0f4c859eSApple OSS Distributions 	u_int8_t sha1[SHA1_RESULTLEN];
161*0f4c859eSApple OSS Distributions 
162*0f4c859eSApple OSS Distributions 	VERIFY(prepare != NULL);
163*0f4c859eSApple OSS Distributions 	VERIFY(prepare->cga_security_level < 8);
164*0f4c859eSApple OSS Distributions 	VERIFY(pubkey != NULL && pubkey->iov_base != NULL);
165*0f4c859eSApple OSS Distributions 	VERIFY(in6 != NULL);
166*0f4c859eSApple OSS Distributions 
167*0f4c859eSApple OSS Distributions 	SHA1Init(&ctx);
168*0f4c859eSApple OSS Distributions 	SHA1Update(&ctx, &prepare->cga_modifier.octets, 16);
169*0f4c859eSApple OSS Distributions 	SHA1Update(&ctx, in6->s6_addr, 8);
170*0f4c859eSApple OSS Distributions 	SHA1Update(&ctx, &collisions, 1);
171*0f4c859eSApple OSS Distributions 	SHA1Update(&ctx, pubkey->iov_base, pubkey->iov_len);
172*0f4c859eSApple OSS Distributions 	if (ifp->network_id_len) {
173*0f4c859eSApple OSS Distributions 		SHA1Update(&ctx, &ifp->network_id, ifp->network_id_len);
174*0f4c859eSApple OSS Distributions 	}
175*0f4c859eSApple OSS Distributions 	/* FUTURE: extension fields */
176*0f4c859eSApple OSS Distributions 	SHA1Final(sha1, &ctx);
177*0f4c859eSApple OSS Distributions 
178*0f4c859eSApple OSS Distributions 	in6->s6_addr8[8] =
179*0f4c859eSApple OSS Distributions 	    (u_int8_t)((prepare->cga_security_level << 5) | (sha1[0] & 0x1c));
180*0f4c859eSApple OSS Distributions 	in6->s6_addr8[9] = sha1[1];
181*0f4c859eSApple OSS Distributions 	in6->s6_addr8[10] = sha1[2];
182*0f4c859eSApple OSS Distributions 	in6->s6_addr8[11] = sha1[3];
183*0f4c859eSApple OSS Distributions 	in6->s6_addr8[12] = sha1[4];
184*0f4c859eSApple OSS Distributions 	in6->s6_addr8[13] = sha1[5];
185*0f4c859eSApple OSS Distributions 	in6->s6_addr8[14] = sha1[6];
186*0f4c859eSApple OSS Distributions 	in6->s6_addr8[15] = sha1[7];
187*0f4c859eSApple OSS Distributions }
188*0f4c859eSApple OSS Distributions 
189*0f4c859eSApple OSS Distributions void
in6_cga_init(void)190*0f4c859eSApple OSS Distributions in6_cga_init(void)
191*0f4c859eSApple OSS Distributions {
192*0f4c859eSApple OSS Distributions 	lck_mtx_init(&in6_cga.cga_mutex, &ifa_mtx_grp, &ifa_mtx_attr);
193*0f4c859eSApple OSS Distributions 	in6_cga.cga_initialized = TRUE;
194*0f4c859eSApple OSS Distributions }
195*0f4c859eSApple OSS Distributions 
196*0f4c859eSApple OSS Distributions void
in6_cga_node_lock(void)197*0f4c859eSApple OSS Distributions in6_cga_node_lock(void)
198*0f4c859eSApple OSS Distributions {
199*0f4c859eSApple OSS Distributions 	VERIFY(in6_cga.cga_initialized);
200*0f4c859eSApple OSS Distributions 	lck_mtx_lock(&in6_cga.cga_mutex);
201*0f4c859eSApple OSS Distributions }
202*0f4c859eSApple OSS Distributions 
203*0f4c859eSApple OSS Distributions void
in6_cga_node_unlock(void)204*0f4c859eSApple OSS Distributions in6_cga_node_unlock(void)
205*0f4c859eSApple OSS Distributions {
206*0f4c859eSApple OSS Distributions 	VERIFY(in6_cga.cga_initialized);
207*0f4c859eSApple OSS Distributions 	lck_mtx_unlock(&in6_cga.cga_mutex);
208*0f4c859eSApple OSS Distributions }
209*0f4c859eSApple OSS Distributions 
210*0f4c859eSApple OSS Distributions void
in6_cga_query(struct in6_cga_nodecfg * cfg)211*0f4c859eSApple OSS Distributions in6_cga_query(struct in6_cga_nodecfg *cfg)
212*0f4c859eSApple OSS Distributions {
213*0f4c859eSApple OSS Distributions 	VERIFY(cfg != NULL);
214*0f4c859eSApple OSS Distributions 	in6_cga_node_lock_assert(LCK_MTX_ASSERT_OWNED);
215*0f4c859eSApple OSS Distributions 
216*0f4c859eSApple OSS Distributions 	cfg->cga_pubkey = in6_cga.cga_pubkey;
217*0f4c859eSApple OSS Distributions 	cfg->cga_prepare = in6_cga.cga_prepare;
218*0f4c859eSApple OSS Distributions }
219*0f4c859eSApple OSS Distributions 
220*0f4c859eSApple OSS Distributions int
in6_cga_start(const struct in6_cga_nodecfg * cfg)221*0f4c859eSApple OSS Distributions in6_cga_start(const struct in6_cga_nodecfg *cfg)
222*0f4c859eSApple OSS Distributions {
223*0f4c859eSApple OSS Distributions 	struct iovec privkey, pubkey;
224*0f4c859eSApple OSS Distributions 	const struct in6_cga_prepare *prepare;
225*0f4c859eSApple OSS Distributions 	caddr_t pubkeycopy, privkeycopy;
226*0f4c859eSApple OSS Distributions 
227*0f4c859eSApple OSS Distributions 	VERIFY(cfg != NULL);
228*0f4c859eSApple OSS Distributions 	in6_cga_node_lock_assert(LCK_MTX_ASSERT_OWNED);
229*0f4c859eSApple OSS Distributions 
230*0f4c859eSApple OSS Distributions 	privkey = cfg->cga_privkey;
231*0f4c859eSApple OSS Distributions 	if (privkey.iov_base == NULL || privkey.iov_len == 0 ||
232*0f4c859eSApple OSS Distributions 	    privkey.iov_len >= IN6_CGA_KEY_MAXSIZE) {
233*0f4c859eSApple OSS Distributions 		return EINVAL;
234*0f4c859eSApple OSS Distributions 	}
235*0f4c859eSApple OSS Distributions 	pubkey = cfg->cga_pubkey;
236*0f4c859eSApple OSS Distributions 	if (pubkey.iov_base == NULL || pubkey.iov_len == 0 ||
237*0f4c859eSApple OSS Distributions 	    pubkey.iov_len >= IN6_CGA_KEY_MAXSIZE) {
238*0f4c859eSApple OSS Distributions 		return EINVAL;
239*0f4c859eSApple OSS Distributions 	}
240*0f4c859eSApple OSS Distributions 	prepare = &cfg->cga_prepare;
241*0f4c859eSApple OSS Distributions 
242*0f4c859eSApple OSS Distributions 	if (!in6_cga_is_prepare_valid(prepare, &pubkey)) {
243*0f4c859eSApple OSS Distributions 		return EINVAL;
244*0f4c859eSApple OSS Distributions 	}
245*0f4c859eSApple OSS Distributions 
246*0f4c859eSApple OSS Distributions 	in6_cga.cga_prepare = *prepare;
247*0f4c859eSApple OSS Distributions 
248*0f4c859eSApple OSS Distributions 	privkeycopy = (caddr_t)kalloc_data(privkey.iov_len, Z_WAITOK);
249*0f4c859eSApple OSS Distributions 	if (privkeycopy == NULL) {
250*0f4c859eSApple OSS Distributions 		return ENOMEM;
251*0f4c859eSApple OSS Distributions 	}
252*0f4c859eSApple OSS Distributions 
253*0f4c859eSApple OSS Distributions 	pubkeycopy = (caddr_t)kalloc_data(pubkey.iov_len, Z_WAITOK);
254*0f4c859eSApple OSS Distributions 	if (pubkeycopy == NULL) {
255*0f4c859eSApple OSS Distributions 		if (privkeycopy != NULL) {
256*0f4c859eSApple OSS Distributions 			kfree_data(privkeycopy, privkey.iov_len);
257*0f4c859eSApple OSS Distributions 		}
258*0f4c859eSApple OSS Distributions 		return ENOMEM;
259*0f4c859eSApple OSS Distributions 	}
260*0f4c859eSApple OSS Distributions 
261*0f4c859eSApple OSS Distributions 	bcopy(privkey.iov_base, privkeycopy, privkey.iov_len);
262*0f4c859eSApple OSS Distributions 	privkey.iov_base = privkeycopy;
263*0f4c859eSApple OSS Distributions 	if (in6_cga.cga_privkey.iov_base != NULL) {
264*0f4c859eSApple OSS Distributions 		kfree_data(in6_cga.cga_privkey.iov_base, in6_cga.cga_privkey.iov_len);
265*0f4c859eSApple OSS Distributions 	}
266*0f4c859eSApple OSS Distributions 	in6_cga.cga_privkey = privkey;
267*0f4c859eSApple OSS Distributions 
268*0f4c859eSApple OSS Distributions 	bcopy(pubkey.iov_base, pubkeycopy, pubkey.iov_len);
269*0f4c859eSApple OSS Distributions 	pubkey.iov_base = pubkeycopy;
270*0f4c859eSApple OSS Distributions 	if (in6_cga.cga_pubkey.iov_base != NULL) {
271*0f4c859eSApple OSS Distributions 		kfree_data(in6_cga.cga_pubkey.iov_base, in6_cga.cga_pubkey.iov_len);
272*0f4c859eSApple OSS Distributions 	}
273*0f4c859eSApple OSS Distributions 	in6_cga.cga_pubkey = pubkey;
274*0f4c859eSApple OSS Distributions 
275*0f4c859eSApple OSS Distributions 	return 0;
276*0f4c859eSApple OSS Distributions }
277*0f4c859eSApple OSS Distributions 
278*0f4c859eSApple OSS Distributions int
in6_cga_stop(void)279*0f4c859eSApple OSS Distributions in6_cga_stop(void)
280*0f4c859eSApple OSS Distributions {
281*0f4c859eSApple OSS Distributions 	in6_cga_node_lock_assert(LCK_MTX_ASSERT_OWNED);
282*0f4c859eSApple OSS Distributions 
283*0f4c859eSApple OSS Distributions 	if (in6_cga.cga_privkey.iov_base != NULL) {
284*0f4c859eSApple OSS Distributions 		kfree_data(in6_cga.cga_privkey.iov_base, in6_cga.cga_privkey.iov_len);
285*0f4c859eSApple OSS Distributions 		in6_cga.cga_privkey.iov_base = NULL;
286*0f4c859eSApple OSS Distributions 		in6_cga.cga_privkey.iov_len = 0;
287*0f4c859eSApple OSS Distributions 	}
288*0f4c859eSApple OSS Distributions 
289*0f4c859eSApple OSS Distributions 	if (in6_cga.cga_pubkey.iov_base != NULL) {
290*0f4c859eSApple OSS Distributions 		kfree_data(in6_cga.cga_pubkey.iov_base, in6_cga.cga_pubkey.iov_len);
291*0f4c859eSApple OSS Distributions 		in6_cga.cga_pubkey.iov_base = NULL;
292*0f4c859eSApple OSS Distributions 		in6_cga.cga_pubkey.iov_len = 0;
293*0f4c859eSApple OSS Distributions 	}
294*0f4c859eSApple OSS Distributions 
295*0f4c859eSApple OSS Distributions 	return 0;
296*0f4c859eSApple OSS Distributions }
297*0f4c859eSApple OSS Distributions 
298*0f4c859eSApple OSS Distributions ssize_t
in6_cga_parameters_prepare(void * output,size_t max,const struct in6_addr * prefix,u_int8_t collisions,const struct in6_cga_modifier * modifier)299*0f4c859eSApple OSS Distributions in6_cga_parameters_prepare(void *output, size_t max,
300*0f4c859eSApple OSS Distributions     const struct in6_addr *prefix, u_int8_t collisions,
301*0f4c859eSApple OSS Distributions     const struct in6_cga_modifier *modifier)
302*0f4c859eSApple OSS Distributions {
303*0f4c859eSApple OSS Distributions 	caddr_t cursor;
304*0f4c859eSApple OSS Distributions 
305*0f4c859eSApple OSS Distributions 	in6_cga_node_lock_assert(LCK_MTX_ASSERT_OWNED);
306*0f4c859eSApple OSS Distributions 
307*0f4c859eSApple OSS Distributions 	if (in6_cga.cga_pubkey.iov_len == 0) {
308*0f4c859eSApple OSS Distributions 		/* No public key */
309*0f4c859eSApple OSS Distributions 		return EINVAL;
310*0f4c859eSApple OSS Distributions 	}
311*0f4c859eSApple OSS Distributions 
312*0f4c859eSApple OSS Distributions 	if (output == NULL ||
313*0f4c859eSApple OSS Distributions 	    max < in6_cga.cga_pubkey.iov_len + sizeof(modifier->octets) + 9) {
314*0f4c859eSApple OSS Distributions 		/* Output buffer error */
315*0f4c859eSApple OSS Distributions 		return EINVAL;
316*0f4c859eSApple OSS Distributions 	}
317*0f4c859eSApple OSS Distributions 
318*0f4c859eSApple OSS Distributions 	cursor = output;
319*0f4c859eSApple OSS Distributions 	if (modifier == NULL) {
320*0f4c859eSApple OSS Distributions 		modifier = &in6_cga.cga_prepare.cga_modifier;
321*0f4c859eSApple OSS Distributions 	}
322*0f4c859eSApple OSS Distributions 	if (prefix == NULL) {
323*0f4c859eSApple OSS Distributions 		static const struct in6_addr llprefix = {{{ 0xfe, 0x80 }}};
324*0f4c859eSApple OSS Distributions 		prefix = &llprefix;
325*0f4c859eSApple OSS Distributions 	}
326*0f4c859eSApple OSS Distributions 
327*0f4c859eSApple OSS Distributions 	bcopy(&modifier->octets, cursor, sizeof(modifier->octets));
328*0f4c859eSApple OSS Distributions 	cursor += sizeof(modifier->octets);
329*0f4c859eSApple OSS Distributions 
330*0f4c859eSApple OSS Distributions 	*cursor++ = (char) collisions;
331*0f4c859eSApple OSS Distributions 
332*0f4c859eSApple OSS Distributions 	bcopy(&prefix->s6_addr[0], cursor, 8);
333*0f4c859eSApple OSS Distributions 	cursor += 8;
334*0f4c859eSApple OSS Distributions 
335*0f4c859eSApple OSS Distributions 	bcopy(in6_cga.cga_pubkey.iov_base, cursor, in6_cga.cga_pubkey.iov_len);
336*0f4c859eSApple OSS Distributions 	cursor += in6_cga.cga_pubkey.iov_len;
337*0f4c859eSApple OSS Distributions 
338*0f4c859eSApple OSS Distributions 	/* FUTURE: Extension fields */
339*0f4c859eSApple OSS Distributions 
340*0f4c859eSApple OSS Distributions 	return (ssize_t)(cursor - (caddr_t)output);
341*0f4c859eSApple OSS Distributions }
342*0f4c859eSApple OSS Distributions 
343*0f4c859eSApple OSS Distributions int
in6_cga_generate(struct in6_cga_prepare * prepare,u_int8_t collisions,struct in6_addr * in6,struct ifnet * ifp)344*0f4c859eSApple OSS Distributions in6_cga_generate(struct in6_cga_prepare *prepare, u_int8_t collisions,
345*0f4c859eSApple OSS Distributions     struct in6_addr *in6, struct ifnet *ifp)
346*0f4c859eSApple OSS Distributions {
347*0f4c859eSApple OSS Distributions 	int error;
348*0f4c859eSApple OSS Distributions 	const struct iovec *pubkey;
349*0f4c859eSApple OSS Distributions 
350*0f4c859eSApple OSS Distributions 	in6_cga_node_lock_assert(LCK_MTX_ASSERT_OWNED);
351*0f4c859eSApple OSS Distributions 	VERIFY(in6 != NULL);
352*0f4c859eSApple OSS Distributions 
353*0f4c859eSApple OSS Distributions 	if (prepare == NULL) {
354*0f4c859eSApple OSS Distributions 		prepare = &in6_cga.cga_prepare;
355*0f4c859eSApple OSS Distributions 	} else {
356*0f4c859eSApple OSS Distributions 		prepare->cga_security_level =
357*0f4c859eSApple OSS Distributions 		    in6_cga.cga_prepare.cga_security_level;
358*0f4c859eSApple OSS Distributions 	}
359*0f4c859eSApple OSS Distributions 
360*0f4c859eSApple OSS Distributions 	pubkey = &in6_cga.cga_pubkey;
361*0f4c859eSApple OSS Distributions 
362*0f4c859eSApple OSS Distributions 	if (pubkey->iov_base != NULL) {
363*0f4c859eSApple OSS Distributions 		in6_cga_generate_iid(prepare, pubkey, collisions, in6, ifp);
364*0f4c859eSApple OSS Distributions 		error = 0;
365*0f4c859eSApple OSS Distributions 	} else {
366*0f4c859eSApple OSS Distributions 		error = EADDRNOTAVAIL;
367*0f4c859eSApple OSS Distributions 	}
368*0f4c859eSApple OSS Distributions 
369*0f4c859eSApple OSS Distributions 	return error;
370*0f4c859eSApple OSS Distributions }
371*0f4c859eSApple OSS Distributions 
372*0f4c859eSApple OSS Distributions /* End of file */
373