Pull up following revision(s) (requested by maxv in ticket #1532): sys/netipsec/xform_ah.c: 1.77 via patch sys/netipsec/xform_esp.c: 1.73 via patch sys/netipsec/xform_ipip.c: 1.56-1.57 via patch Reinforce and clarify. -- Add missing NULL check. Normally that's not triggerable remotely, since we are guaranteed that 8 bytes are valid at mbuf+skip. -- Fix use-after-free. There is a path where the mbuf gets pulled up without a proper mtod afterwards: 218 ipo = mtod(m, struct ip *); 281 m = m_pullup(m, hlen); 232 ipo->ip_src.s_addr Found by Mootja. Meanwhile it seems to me that 'ipo' should be set to NULL if the inner packet is IPv6, but I'll revisit that later. -- As I said in my last commit in this file, ipo should be set to NULL; otherwise the 'local address spoofing' check below is always wrong on IPv6.diff -r1.37.6.3 -r1.37.6.4 src/sys/netipsec/xform_ah.c
(snj)
--- src/sys/netipsec/xform_ah.c 2018/02/15 16:50:01 1.37.6.3
+++ src/sys/netipsec/xform_ah.c 2018/03/13 17:18:12 1.37.6.4
@@ -1,1372 +1,1365 @@ | @@ -1,1372 +1,1365 @@ | |||
1 | /* $NetBSD: xform_ah.c,v 1.37.6.3 2018/02/15 16:50:01 martin Exp $ */ | 1 | /* $NetBSD: xform_ah.c,v 1.37.6.4 2018/03/13 17:18:12 snj Exp $ */ | |
2 | /* $FreeBSD: src/sys/netipsec/xform_ah.c,v 1.1.4.1 2003/01/24 05:11:36 sam Exp $ */ | 2 | /* $FreeBSD: src/sys/netipsec/xform_ah.c,v 1.1.4.1 2003/01/24 05:11:36 sam Exp $ */ | |
3 | /* $OpenBSD: ip_ah.c,v 1.63 2001/06/26 06:18:58 angelos Exp $ */ | 3 | /* $OpenBSD: ip_ah.c,v 1.63 2001/06/26 06:18:58 angelos Exp $ */ | |
4 | /* | 4 | /* | |
5 | * The authors of this code are John Ioannidis (ji@tla.org), | 5 | * The authors of this code are John Ioannidis (ji@tla.org), | |
6 | * Angelos D. Keromytis (kermit@csd.uch.gr) and | 6 | * Angelos D. Keromytis (kermit@csd.uch.gr) and | |
7 | * Niels Provos (provos@physnet.uni-hamburg.de). | 7 | * Niels Provos (provos@physnet.uni-hamburg.de). | |
8 | * | 8 | * | |
9 | * The original version of this code was written by John Ioannidis | 9 | * The original version of this code was written by John Ioannidis | |
10 | * for BSD/OS in Athens, Greece, in November 1995. | 10 | * for BSD/OS in Athens, Greece, in November 1995. | |
11 | * | 11 | * | |
12 | * Ported to OpenBSD and NetBSD, with additional transforms, in December 1996, | 12 | * Ported to OpenBSD and NetBSD, with additional transforms, in December 1996, | |
13 | * by Angelos D. Keromytis. | 13 | * by Angelos D. Keromytis. | |
14 | * | 14 | * | |
15 | * Additional transforms and features in 1997 and 1998 by Angelos D. Keromytis | 15 | * Additional transforms and features in 1997 and 1998 by Angelos D. Keromytis | |
16 | * and Niels Provos. | 16 | * and Niels Provos. | |
17 | * | 17 | * | |
18 | * Additional features in 1999 by Angelos D. Keromytis and Niklas Hallqvist. | 18 | * Additional features in 1999 by Angelos D. Keromytis and Niklas Hallqvist. | |
19 | * | 19 | * | |
20 | * Copyright (c) 1995, 1996, 1997, 1998, 1999 by John Ioannidis, | 20 | * Copyright (c) 1995, 1996, 1997, 1998, 1999 by John Ioannidis, | |
21 | * Angelos D. Keromytis and Niels Provos. | 21 | * Angelos D. Keromytis and Niels Provos. | |
22 | * Copyright (c) 1999 Niklas Hallqvist. | 22 | * Copyright (c) 1999 Niklas Hallqvist. | |
23 | * Copyright (c) 2001 Angelos D. Keromytis. | 23 | * Copyright (c) 2001 Angelos D. Keromytis. | |
24 | * | 24 | * | |
25 | * Permission to use, copy, and modify this software with or without fee | 25 | * Permission to use, copy, and modify this software with or without fee | |
26 | * is hereby granted, provided that this entire notice is included in | 26 | * is hereby granted, provided that this entire notice is included in | |
27 | * all copies of any software which is or includes a copy or | 27 | * all copies of any software which is or includes a copy or | |
28 | * modification of this software. | 28 | * modification of this software. | |
29 | * You may use this code under the GNU public license if you so wish. Please | 29 | * You may use this code under the GNU public license if you so wish. Please | |
30 | * contribute changes back to the authors under this freer than GPL license | 30 | * contribute changes back to the authors under this freer than GPL license | |
31 | * so that we may further the use of strong encryption without limitations to | 31 | * so that we may further the use of strong encryption without limitations to | |
32 | * all. | 32 | * all. | |
33 | * | 33 | * | |
34 | * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR | 34 | * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR | |
35 | * IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY | 35 | * IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY | |
36 | * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE | 36 | * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE | |
37 | * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR | 37 | * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR | |
38 | * PURPOSE. | 38 | * PURPOSE. | |
39 | */ | 39 | */ | |
40 | 40 | |||
41 | #include <sys/cdefs.h> | 41 | #include <sys/cdefs.h> | |
42 | __KERNEL_RCSID(0, "$NetBSD: xform_ah.c,v 1.37.6.3 2018/02/15 16:50:01 martin Exp $"); | 42 | __KERNEL_RCSID(0, "$NetBSD: xform_ah.c,v 1.37.6.4 2018/03/13 17:18:12 snj Exp $"); | |
43 | 43 | |||
44 | #include "opt_inet.h" | 44 | #include "opt_inet.h" | |
45 | #ifdef __FreeBSD__ | 45 | #ifdef __FreeBSD__ | |
46 | #include "opt_inet6.h" | 46 | #include "opt_inet6.h" | |
47 | #endif | 47 | #endif | |
48 | 48 | |||
49 | #include <sys/param.h> | 49 | #include <sys/param.h> | |
50 | #include <sys/systm.h> | 50 | #include <sys/systm.h> | |
51 | #include <sys/mbuf.h> | 51 | #include <sys/mbuf.h> | |
52 | #include <sys/socket.h> | 52 | #include <sys/socket.h> | |
53 | #include <sys/syslog.h> | 53 | #include <sys/syslog.h> | |
54 | #include <sys/kernel.h> | 54 | #include <sys/kernel.h> | |
55 | #include <sys/sysctl.h> | 55 | #include <sys/sysctl.h> | |
56 | #include <sys/socketvar.h> /* for softnet_lock */ | 56 | #include <sys/socketvar.h> /* for softnet_lock */ | |
57 | 57 | |||
58 | #include <net/if.h> | 58 | #include <net/if.h> | |
59 | 59 | |||
60 | #include <netinet/in.h> | 60 | #include <netinet/in.h> | |
61 | #include <netinet/in_systm.h> | 61 | #include <netinet/in_systm.h> | |
62 | #include <netinet/ip.h> | 62 | #include <netinet/ip.h> | |
63 | #include <netinet/ip_ecn.h> | 63 | #include <netinet/ip_ecn.h> | |
64 | #include <netinet/ip6.h> | 64 | #include <netinet/ip6.h> | |
65 | 65 | |||
66 | #include <net/route.h> | 66 | #include <net/route.h> | |
67 | #include <netipsec/ipsec.h> | 67 | #include <netipsec/ipsec.h> | |
68 | #include <netipsec/ipsec_private.h> | 68 | #include <netipsec/ipsec_private.h> | |
69 | #include <netipsec/ah.h> | 69 | #include <netipsec/ah.h> | |
70 | #include <netipsec/ah_var.h> | 70 | #include <netipsec/ah_var.h> | |
71 | #include <netipsec/xform.h> | 71 | #include <netipsec/xform.h> | |
72 | 72 | |||
73 | #ifdef INET6 | 73 | #ifdef INET6 | |
74 | #include <netinet6/ip6_var.h> | 74 | #include <netinet6/ip6_var.h> | |
75 | #include <netinet6/scope6_var.h> | 75 | #include <netinet6/scope6_var.h> | |
76 | #include <netipsec/ipsec6.h> | 76 | #include <netipsec/ipsec6.h> | |
77 | # ifdef __FreeBSD__ | 77 | # ifdef __FreeBSD__ | |
78 | # include <netinet6/ip6_ecn.h> | 78 | # include <netinet6/ip6_ecn.h> | |
79 | # endif | 79 | # endif | |
80 | #endif | 80 | #endif | |
81 | 81 | |||
82 | #include <netipsec/key.h> | 82 | #include <netipsec/key.h> | |
83 | #include <netipsec/key_debug.h> | 83 | #include <netipsec/key_debug.h> | |
84 | #include <netipsec/ipsec_osdep.h> | 84 | #include <netipsec/ipsec_osdep.h> | |
85 | 85 | |||
86 | #include <opencrypto/cryptodev.h> | 86 | #include <opencrypto/cryptodev.h> | |
87 | 87 | |||
88 | /* | 88 | /* | |
89 | * Return header size in bytes. The old protocol did not support | 89 | * Return header size in bytes. The old protocol did not support | |
90 | * the replay counter; the new protocol always includes the counter. | 90 | * the replay counter; the new protocol always includes the counter. | |
91 | */ | 91 | */ | |
92 | #define HDRSIZE(sav) \ | 92 | #define HDRSIZE(sav) \ | |
93 | (((sav)->flags & SADB_X_EXT_OLD) ? \ | 93 | (((sav)->flags & SADB_X_EXT_OLD) ? \ | |
94 | sizeof (struct ah) : sizeof (struct ah) + sizeof (u_int32_t)) | 94 | sizeof (struct ah) : sizeof (struct ah) + sizeof (u_int32_t)) | |
95 | /* | 95 | /* | |
96 | * Return authenticator size in bytes. The old protocol is known | 96 | * Return authenticator size in bytes. The old protocol is known | |
97 | * to use a fixed 16-byte authenticator. The new algorithm gets | 97 | * to use a fixed 16-byte authenticator. The new algorithm gets | |
98 | * this size from the xform but is (currently) always 12. | 98 | * this size from the xform but is (currently) always 12. | |
99 | */ | 99 | */ | |
100 | #define AUTHSIZE(sav) \ | 100 | #define AUTHSIZE(sav) \ | |
101 | ((sav->flags & SADB_X_EXT_OLD) ? 16 : (sav)->tdb_authalgxform->authsize) | 101 | ((sav->flags & SADB_X_EXT_OLD) ? 16 : (sav)->tdb_authalgxform->authsize) | |
102 | 102 | |||
103 | percpu_t *ahstat_percpu; | 103 | percpu_t *ahstat_percpu; | |
104 | 104 | |||
105 | int ah_enable = 1; /* control flow of packets with AH */ | 105 | int ah_enable = 1; /* control flow of packets with AH */ | |
106 | int ip4_ah_cleartos = 1; /* clear ip_tos when doing AH calc */ | 106 | int ip4_ah_cleartos = 1; /* clear ip_tos when doing AH calc */ | |
107 | 107 | |||
108 | #ifdef __FreeBSD__ | 108 | #ifdef __FreeBSD__ | |
109 | SYSCTL_DECL(_net_inet_ah); | 109 | SYSCTL_DECL(_net_inet_ah); | |
110 | SYSCTL_INT(_net_inet_ah, OID_AUTO, | 110 | SYSCTL_INT(_net_inet_ah, OID_AUTO, | |
111 | ah_enable, CTLFLAG_RW, &ah_enable, 0, ""); | 111 | ah_enable, CTLFLAG_RW, &ah_enable, 0, ""); | |
112 | SYSCTL_INT(_net_inet_ah, OID_AUTO, | 112 | SYSCTL_INT(_net_inet_ah, OID_AUTO, | |
113 | ah_cleartos, CTLFLAG_RW, &ip4_ah_cleartos, 0, ""); | 113 | ah_cleartos, CTLFLAG_RW, &ip4_ah_cleartos, 0, ""); | |
114 | SYSCTL_STRUCT(_net_inet_ah, IPSECCTL_STATS, | 114 | SYSCTL_STRUCT(_net_inet_ah, IPSECCTL_STATS, | |
115 | stats, CTLFLAG_RD, &ahstat, ahstat, ""); | 115 | stats, CTLFLAG_RD, &ahstat, ahstat, ""); | |
116 | 116 | |||
117 | #endif /* __FreeBSD__ */ | 117 | #endif /* __FreeBSD__ */ | |
118 | 118 | |||
119 | static unsigned char ipseczeroes[256]; /* larger than an ip6 extension hdr */ | 119 | static unsigned char ipseczeroes[256]; /* larger than an ip6 extension hdr */ | |
120 | 120 | |||
121 | static int ah_input_cb(struct cryptop*); | 121 | static int ah_input_cb(struct cryptop*); | |
122 | static int ah_output_cb(struct cryptop*); | 122 | static int ah_output_cb(struct cryptop*); | |
123 | 123 | |||
124 | /* | 124 | /* | |
125 | * NB: this is public for use by the PF_KEY support. | 125 | * NB: this is public for use by the PF_KEY support. | |
126 | */ | 126 | */ | |
127 | const struct auth_hash * | 127 | const struct auth_hash * | |
128 | ah_algorithm_lookup(int alg) | 128 | ah_algorithm_lookup(int alg) | |
129 | { | 129 | { | |
130 | if (alg >= AH_ALG_MAX) | 130 | if (alg >= AH_ALG_MAX) | |
131 | return NULL; | 131 | return NULL; | |
132 | switch (alg) { | 132 | switch (alg) { | |
133 | case SADB_X_AALG_NULL: | 133 | case SADB_X_AALG_NULL: | |
134 | return &auth_hash_null; | 134 | return &auth_hash_null; | |
135 | case SADB_AALG_MD5HMAC: | 135 | case SADB_AALG_MD5HMAC: | |
136 | return &auth_hash_hmac_md5_96; | 136 | return &auth_hash_hmac_md5_96; | |
137 | case SADB_AALG_SHA1HMAC: | 137 | case SADB_AALG_SHA1HMAC: | |
138 | return &auth_hash_hmac_sha1_96; | 138 | return &auth_hash_hmac_sha1_96; | |
139 | case SADB_X_AALG_RIPEMD160HMAC: | 139 | case SADB_X_AALG_RIPEMD160HMAC: | |
140 | return &auth_hash_hmac_ripemd_160_96; | 140 | return &auth_hash_hmac_ripemd_160_96; | |
141 | case SADB_X_AALG_MD5: | 141 | case SADB_X_AALG_MD5: | |
142 | return &auth_hash_key_md5; | 142 | return &auth_hash_key_md5; | |
143 | case SADB_X_AALG_SHA: | 143 | case SADB_X_AALG_SHA: | |
144 | return &auth_hash_key_sha1; | 144 | return &auth_hash_key_sha1; | |
145 | case SADB_X_AALG_SHA2_256: | 145 | case SADB_X_AALG_SHA2_256: | |
146 | return &auth_hash_hmac_sha2_256; | 146 | return &auth_hash_hmac_sha2_256; | |
147 | case SADB_X_AALG_SHA2_384: | 147 | case SADB_X_AALG_SHA2_384: | |
148 | return &auth_hash_hmac_sha2_384; | 148 | return &auth_hash_hmac_sha2_384; | |
149 | case SADB_X_AALG_SHA2_512: | 149 | case SADB_X_AALG_SHA2_512: | |
150 | return &auth_hash_hmac_sha2_512; | 150 | return &auth_hash_hmac_sha2_512; | |
151 | case SADB_X_AALG_AES_XCBC_MAC: | 151 | case SADB_X_AALG_AES_XCBC_MAC: | |
152 | return &auth_hash_aes_xcbc_mac_96; | 152 | return &auth_hash_aes_xcbc_mac_96; | |
153 | } | 153 | } | |
154 | return NULL; | 154 | return NULL; | |
155 | } | 155 | } | |
156 | 156 | |||
157 | size_t | 157 | size_t | |
158 | ah_hdrsiz(const struct secasvar *sav) | 158 | ah_hdrsiz(const struct secasvar *sav) | |
159 | { | 159 | { | |
160 | size_t size; | 160 | size_t size; | |
161 | 161 | |||
162 | if (sav != NULL) { | 162 | if (sav != NULL) { | |
163 | int authsize; | 163 | int authsize; | |
164 | IPSEC_ASSERT(sav->tdb_authalgxform != NULL, | 164 | IPSEC_ASSERT(sav->tdb_authalgxform != NULL, | |
165 | ("ah_hdrsiz: null xform")); | 165 | ("ah_hdrsiz: null xform")); | |
166 | /*XXX not right for null algorithm--does it matter??*/ | 166 | /*XXX not right for null algorithm--does it matter??*/ | |
167 | authsize = AUTHSIZE(sav); | 167 | authsize = AUTHSIZE(sav); | |
168 | size = roundup(authsize, sizeof (u_int32_t)) + HDRSIZE(sav); | 168 | size = roundup(authsize, sizeof (u_int32_t)) + HDRSIZE(sav); | |
169 | } else { | 169 | } else { | |
170 | /* default guess */ | 170 | /* default guess */ | |
171 | size = sizeof (struct ah) + sizeof (u_int32_t) + 16; | 171 | size = sizeof (struct ah) + sizeof (u_int32_t) + 16; | |
172 | } | 172 | } | |
173 | return size; | 173 | return size; | |
174 | } | 174 | } | |
175 | 175 | |||
176 | /* | 176 | /* | |
177 | * NB: public for use by esp_init. | 177 | * NB: public for use by esp_init. | |
178 | */ | 178 | */ | |
179 | int | 179 | int | |
180 | ah_init0(struct secasvar *sav, const struct xformsw *xsp, | 180 | ah_init0(struct secasvar *sav, const struct xformsw *xsp, | |
181 | struct cryptoini *cria) | 181 | struct cryptoini *cria) | |
182 | { | 182 | { | |
183 | const struct auth_hash *thash; | 183 | const struct auth_hash *thash; | |
184 | int keylen; | 184 | int keylen; | |
185 | 185 | |||
186 | thash = ah_algorithm_lookup(sav->alg_auth); | 186 | thash = ah_algorithm_lookup(sav->alg_auth); | |
187 | if (thash == NULL) { | 187 | if (thash == NULL) { | |
188 | DPRINTF(("ah_init: unsupported authentication algorithm %u\n", | 188 | DPRINTF(("ah_init: unsupported authentication algorithm %u\n", | |
189 | sav->alg_auth)); | 189 | sav->alg_auth)); | |
190 | return EINVAL; | 190 | return EINVAL; | |
191 | } | 191 | } | |
192 | /* | 192 | /* | |
193 | * Verify the replay state block allocation is consistent with | 193 | * Verify the replay state block allocation is consistent with | |
194 | * the protocol type. We check here so we can make assumptions | 194 | * the protocol type. We check here so we can make assumptions | |
195 | * later during protocol processing. | 195 | * later during protocol processing. | |
196 | */ | 196 | */ | |
197 | /* NB: replay state is setup elsewhere (sigh) */ | 197 | /* NB: replay state is setup elsewhere (sigh) */ | |
198 | if (((sav->flags&SADB_X_EXT_OLD) == 0) ^ (sav->replay != NULL)) { | 198 | if (((sav->flags&SADB_X_EXT_OLD) == 0) ^ (sav->replay != NULL)) { | |
199 | DPRINTF(("ah_init: replay state block inconsistency, " | 199 | DPRINTF(("ah_init: replay state block inconsistency, " | |
200 | "%s algorithm %s replay state\n", | 200 | "%s algorithm %s replay state\n", | |
201 | (sav->flags & SADB_X_EXT_OLD) ? "old" : "new", | 201 | (sav->flags & SADB_X_EXT_OLD) ? "old" : "new", | |
202 | sav->replay == NULL ? "without" : "with")); | 202 | sav->replay == NULL ? "without" : "with")); | |
203 | return EINVAL; | 203 | return EINVAL; | |
204 | } | 204 | } | |
205 | if (sav->key_auth == NULL) { | 205 | if (sav->key_auth == NULL) { | |
206 | DPRINTF(("ah_init: no authentication key for %s " | 206 | DPRINTF(("ah_init: no authentication key for %s " | |
207 | "algorithm\n", thash->name)); | 207 | "algorithm\n", thash->name)); | |
208 | return EINVAL; | 208 | return EINVAL; | |
209 | } | 209 | } | |
210 | keylen = _KEYLEN(sav->key_auth); | 210 | keylen = _KEYLEN(sav->key_auth); | |
211 | if (keylen != thash->keysize && thash->keysize != 0) { | 211 | if (keylen != thash->keysize && thash->keysize != 0) { | |
212 | DPRINTF(("ah_init: invalid keylength %d, algorithm " | 212 | DPRINTF(("ah_init: invalid keylength %d, algorithm " | |
213 | "%s requires keysize %d\n", | 213 | "%s requires keysize %d\n", | |
214 | keylen, thash->name, thash->keysize)); | 214 | keylen, thash->name, thash->keysize)); | |
215 | return EINVAL; | 215 | return EINVAL; | |
216 | } | 216 | } | |
217 | 217 | |||
218 | sav->tdb_xform = xsp; | 218 | sav->tdb_xform = xsp; | |
219 | sav->tdb_authalgxform = thash; | 219 | sav->tdb_authalgxform = thash; | |
220 | 220 | |||
221 | /* Initialize crypto session. */ | 221 | /* Initialize crypto session. */ | |
222 | memset(cria, 0, sizeof (*cria)); | 222 | memset(cria, 0, sizeof (*cria)); | |
223 | cria->cri_alg = sav->tdb_authalgxform->type; | 223 | cria->cri_alg = sav->tdb_authalgxform->type; | |
224 | cria->cri_klen = _KEYBITS(sav->key_auth); | 224 | cria->cri_klen = _KEYBITS(sav->key_auth); | |
225 | cria->cri_key = _KEYBUF(sav->key_auth); | 225 | cria->cri_key = _KEYBUF(sav->key_auth); | |
226 | 226 | |||
227 | return 0; | 227 | return 0; | |
228 | } | 228 | } | |
229 | 229 | |||
230 | /* | 230 | /* | |
231 | * ah_init() is called when an SPI is being set up. | 231 | * ah_init() is called when an SPI is being set up. | |
232 | */ | 232 | */ | |
233 | static int | 233 | static int | |
234 | ah_init(struct secasvar *sav, const struct xformsw *xsp) | 234 | ah_init(struct secasvar *sav, const struct xformsw *xsp) | |
235 | { | 235 | { | |
236 | struct cryptoini cria; | 236 | struct cryptoini cria; | |
237 | int error; | 237 | int error; | |
238 | 238 | |||
239 | error = ah_init0(sav, xsp, &cria); | 239 | error = ah_init0(sav, xsp, &cria); | |
240 | if (!error) | 240 | if (!error) | |
241 | error = crypto_newsession(&sav->tdb_cryptoid, | 241 | error = crypto_newsession(&sav->tdb_cryptoid, | |
242 | &cria, crypto_support); | 242 | &cria, crypto_support); | |
243 | return error; | 243 | return error; | |
244 | } | 244 | } | |
245 | 245 | |||
246 | /* | 246 | /* | |
247 | * Paranoia. | 247 | * Paranoia. | |
248 | * | 248 | * | |
249 | * NB: public for use by esp_zeroize (XXX). | 249 | * NB: public for use by esp_zeroize (XXX). | |
250 | */ | 250 | */ | |
251 | int | 251 | int | |
252 | ah_zeroize(struct secasvar *sav) | 252 | ah_zeroize(struct secasvar *sav) | |
253 | { | 253 | { | |
254 | int err; | 254 | int err; | |
255 | 255 | |||
256 | if (sav->key_auth) | 256 | if (sav->key_auth) | |
257 | memset(_KEYBUF(sav->key_auth), 0, _KEYLEN(sav->key_auth)); | 257 | memset(_KEYBUF(sav->key_auth), 0, _KEYLEN(sav->key_auth)); | |
258 | 258 | |||
259 | err = crypto_freesession(sav->tdb_cryptoid); | 259 | err = crypto_freesession(sav->tdb_cryptoid); | |
260 | sav->tdb_cryptoid = 0; | 260 | sav->tdb_cryptoid = 0; | |
261 | sav->tdb_authalgxform = NULL; | 261 | sav->tdb_authalgxform = NULL; | |
262 | sav->tdb_xform = NULL; | 262 | sav->tdb_xform = NULL; | |
263 | return err; | 263 | return err; | |
264 | } | 264 | } | |
265 | 265 | |||
266 | /* | 266 | /* | |
267 | * Massage IPv4/IPv6 headers for AH processing. | 267 | * Massage IPv4/IPv6 headers for AH processing. | |
268 | */ | 268 | */ | |
269 | static int | 269 | static int | |
270 | ah_massage_headers(struct mbuf **m0, int proto, int skip, int alg, int out) | 270 | ah_massage_headers(struct mbuf **m0, int proto, int skip, int alg, int out) | |
271 | { | 271 | { | |
272 | struct mbuf *m = *m0; | 272 | struct mbuf *m = *m0; | |
273 | unsigned char *ptr; | 273 | unsigned char *ptr; | |
274 | int off, count; | 274 | int off, count; | |
275 | 275 | |||
276 | #ifdef INET | 276 | #ifdef INET | |
277 | struct ip *ip; | 277 | struct ip *ip; | |
278 | #endif /* INET */ | 278 | #endif /* INET */ | |
279 | 279 | |||
280 | #ifdef INET6 | 280 | #ifdef INET6 | |
281 | struct ip6_ext *ip6e; | 281 | struct ip6_ext *ip6e; | |
282 | struct ip6_hdr ip6; | 282 | struct ip6_hdr ip6; | |
283 | int alloc, ad, nxt; | 283 | int alloc, ad, nxt; | |
284 | #endif /* INET6 */ | 284 | #endif /* INET6 */ | |
285 | 285 | |||
286 | switch (proto) { | 286 | switch (proto) { | |
287 | #ifdef INET | 287 | #ifdef INET | |
288 | case AF_INET: | 288 | case AF_INET: | |
289 | /* | 289 | /* | |
290 | * This is the least painful way of dealing with IPv4 header | 290 | * This is the least painful way of dealing with IPv4 header | |
291 | * and option processing -- just make sure they're in | 291 | * and option processing -- just make sure they're in | |
292 | * contiguous memory. | 292 | * contiguous memory. | |
293 | */ | 293 | */ | |
294 | *m0 = m = m_pullup(m, skip); | 294 | *m0 = m = m_pullup(m, skip); | |
295 | if (m == NULL) { | 295 | if (m == NULL) { | |
296 | DPRINTF(("ah_massage_headers: m_pullup failed\n")); | 296 | DPRINTF(("ah_massage_headers: m_pullup failed\n")); | |
297 | return ENOBUFS; | 297 | return ENOBUFS; | |
298 | } | 298 | } | |
299 | 299 | |||
300 | /* Fix the IP header */ | 300 | /* Fix the IP header */ | |
301 | ip = mtod(m, struct ip *); | 301 | ip = mtod(m, struct ip *); | |
302 | if (ip4_ah_cleartos) | 302 | if (ip4_ah_cleartos) | |
303 | ip->ip_tos = 0; | 303 | ip->ip_tos = 0; | |
304 | ip->ip_ttl = 0; | 304 | ip->ip_ttl = 0; | |
305 | ip->ip_sum = 0; | 305 | ip->ip_sum = 0; | |
306 | ip->ip_off = htons(ntohs(ip->ip_off) & ip4_ah_offsetmask); | 306 | ip->ip_off = htons(ntohs(ip->ip_off) & ip4_ah_offsetmask); | |
307 | 307 | |||
308 | /* | 308 | /* | |
309 | * On FreeBSD, ip_off and ip_len assumed in host endian; | 309 | * On FreeBSD, ip_off and ip_len assumed in host endian; | |
310 | * they are converted (if necessary) by ip_input(). | 310 | * they are converted (if necessary) by ip_input(). | |
311 | * On NetBSD, ip_off and ip_len are in network byte order. | 311 | * On NetBSD, ip_off and ip_len are in network byte order. | |
312 | * They must be massaged back to network byte order | 312 | * They must be massaged back to network byte order | |
313 | * before verifying the HMAC. Moreover, on FreeBSD, | 313 | * before verifying the HMAC. Moreover, on FreeBSD, | |
314 | * we should add `skip' back into the massaged ip_len | 314 | * we should add `skip' back into the massaged ip_len | |
315 | * (presumably ip_input() deducted it before we got here?) | 315 | * (presumably ip_input() deducted it before we got here?) | |
316 | * whereas on NetBSD, we should not. | 316 | * whereas on NetBSD, we should not. | |
317 | */ | 317 | */ | |
318 | #ifdef __FreeBSD__ | 318 | #ifdef __FreeBSD__ | |
319 | #define TOHOST(x) (x) | 319 | #define TOHOST(x) (x) | |
320 | #else | 320 | #else | |
321 | #define TOHOST(x) (ntohs(x)) | 321 | #define TOHOST(x) (ntohs(x)) | |
322 | #endif | 322 | #endif | |
323 | if (!out) { | 323 | if (!out) { | |
324 | u_int16_t inlen = TOHOST(ip->ip_len); | 324 | u_int16_t inlen = TOHOST(ip->ip_len); | |
325 | 325 | |||
326 | #ifdef __FreeBSD__ | 326 | #ifdef __FreeBSD__ | |
327 | ip->ip_len = htons(inlen + skip); | 327 | ip->ip_len = htons(inlen + skip); | |
328 | #else /*!__FreeBSD__ */ | 328 | #else /*!__FreeBSD__ */ | |
329 | ip->ip_len = htons(inlen); | 329 | ip->ip_len = htons(inlen); | |
330 | #endif /*!__FreeBSD__ */ | 330 | #endif /*!__FreeBSD__ */ | |
331 | 331 | |||
332 | if (alg == CRYPTO_MD5_KPDK || alg == CRYPTO_SHA1_KPDK) | 332 | if (alg == CRYPTO_MD5_KPDK || alg == CRYPTO_SHA1_KPDK) | |
333 | ip->ip_off &= IP_OFF_CONVERT(IP_DF); | 333 | ip->ip_off &= IP_OFF_CONVERT(IP_DF); | |
334 | else | 334 | else | |
335 | ip->ip_off = 0; | 335 | ip->ip_off = 0; | |
336 | } else { | 336 | } else { | |
337 | if (alg == CRYPTO_MD5_KPDK || alg == CRYPTO_SHA1_KPDK) | 337 | if (alg == CRYPTO_MD5_KPDK || alg == CRYPTO_SHA1_KPDK) | |
338 | ip->ip_off &= IP_OFF_CONVERT(IP_DF); | 338 | ip->ip_off &= IP_OFF_CONVERT(IP_DF); | |
339 | else | 339 | else | |
340 | ip->ip_off = 0; | 340 | ip->ip_off = 0; | |
341 | } | 341 | } | |
342 | 342 | |||
343 | ptr = mtod(m, unsigned char *); | 343 | ptr = mtod(m, unsigned char *); | |
344 | 344 | |||
345 | /* IPv4 option processing */ | 345 | /* IPv4 option processing */ | |
346 | for (off = sizeof(struct ip); off < skip;) { | 346 | for (off = sizeof(struct ip); off < skip;) { | |
347 | if (ptr[off] == IPOPT_EOL || ptr[off] == IPOPT_NOP || | 347 | if (ptr[off] == IPOPT_EOL || ptr[off] == IPOPT_NOP || | |
348 | off + 1 < skip) | 348 | off + 1 < skip) | |
349 | ; | 349 | ; | |
350 | else { | 350 | else { | |
351 | DPRINTF(("ah_massage_headers: illegal IPv4 " | 351 | DPRINTF(("ah_massage_headers: illegal IPv4 " | |
352 | "option length for option %d\n", | 352 | "option length for option %d\n", | |
353 | ptr[off])); | 353 | ptr[off])); | |
354 | 354 | |||
355 | m_freem(m); | 355 | m_freem(m); | |
356 | return EINVAL; | 356 | return EINVAL; | |
357 | } | 357 | } | |
358 | 358 | |||
359 | switch (ptr[off]) { | 359 | switch (ptr[off]) { | |
360 | case IPOPT_EOL: | 360 | case IPOPT_EOL: | |
361 | off = skip; /* End the loop. */ | 361 | off = skip; /* End the loop. */ | |
362 | break; | 362 | break; | |
363 | 363 | |||
364 | case IPOPT_NOP: | 364 | case IPOPT_NOP: | |
365 | off++; | 365 | off++; | |
366 | break; | 366 | break; | |
367 | 367 | |||
368 | case IPOPT_SECURITY: /* 0x82 */ | 368 | case IPOPT_SECURITY: /* 0x82 */ | |
369 | case 0x85: /* Extended security. */ | 369 | case 0x85: /* Extended security. */ | |
370 | case 0x86: /* Commercial security. */ | 370 | case 0x86: /* Commercial security. */ | |
371 | case 0x94: /* Router alert */ | 371 | case 0x94: /* Router alert */ | |
372 | case 0x95: /* RFC1770 */ | 372 | case 0x95: /* RFC1770 */ | |
373 | /* Sanity check for option length. */ | 373 | /* Sanity check for option length. */ | |
374 | if (ptr[off + 1] < 2) { | 374 | if (ptr[off + 1] < 2) { | |
375 | DPRINTF(("ah_massage_headers: " | 375 | DPRINTF(("ah_massage_headers: " | |
376 | "illegal IPv4 option length for " | 376 | "illegal IPv4 option length for " | |
377 | "option %d\n", ptr[off])); | 377 | "option %d\n", ptr[off])); | |
378 | 378 | |||
379 | m_freem(m); | 379 | m_freem(m); | |
380 | return EINVAL; | 380 | return EINVAL; | |
381 | } | 381 | } | |
382 | 382 | |||
383 | off += ptr[off + 1]; | 383 | off += ptr[off + 1]; | |
384 | break; | 384 | break; | |
385 | 385 | |||
386 | case IPOPT_LSRR: | 386 | case IPOPT_LSRR: | |
387 | case IPOPT_SSRR: | 387 | case IPOPT_SSRR: | |
388 | /* Sanity check for option length. */ | 388 | /* Sanity check for option length. */ | |
389 | if (ptr[off + 1] < 2) { | 389 | if (ptr[off + 1] < 2) { | |
390 | DPRINTF(("ah_massage_headers: " | 390 | DPRINTF(("ah_massage_headers: " | |
391 | "illegal IPv4 option length for " | 391 | "illegal IPv4 option length for " | |
392 | "option %d\n", ptr[off])); | 392 | "option %d\n", ptr[off])); | |
393 | 393 | |||
394 | m_freem(m); | 394 | m_freem(m); | |
395 | return EINVAL; | 395 | return EINVAL; | |
396 | } | 396 | } | |
397 | 397 | |||
398 | /* | 398 | /* | |
399 | * On output, if we have either of the | 399 | * On output, if we have either of the | |
400 | * source routing options, we should | 400 | * source routing options, we should | |
401 | * swap the destination address of the | 401 | * swap the destination address of the | |
402 | * IP header with the last address | 402 | * IP header with the last address | |
403 | * specified in the option, as that is | 403 | * specified in the option, as that is | |
404 | * what the destination's IP header | 404 | * what the destination's IP header | |
405 | * will look like. | 405 | * will look like. | |
406 | */ | 406 | */ | |
407 | if (out) | 407 | if (out) | |
408 | bcopy(ptr + off + ptr[off + 1] - | 408 | bcopy(ptr + off + ptr[off + 1] - | |
409 | sizeof(struct in_addr), | 409 | sizeof(struct in_addr), | |
410 | &(ip->ip_dst), sizeof(struct in_addr)); | 410 | &(ip->ip_dst), sizeof(struct in_addr)); | |
411 | 411 | |||
412 | /* Fall through */ | 412 | /* Fall through */ | |
413 | default: | 413 | default: | |
414 | /* Sanity check for option length. */ | 414 | /* Sanity check for option length. */ | |
415 | if (ptr[off + 1] < 2) { | 415 | if (ptr[off + 1] < 2) { | |
416 | DPRINTF(("ah_massage_headers: " | 416 | DPRINTF(("ah_massage_headers: " | |
417 | "illegal IPv4 option length for " | 417 | "illegal IPv4 option length for " | |
418 | "option %d\n", ptr[off])); | 418 | "option %d\n", ptr[off])); | |
419 | m_freem(m); | 419 | m_freem(m); | |
420 | return EINVAL; | 420 | return EINVAL; | |
421 | } | 421 | } | |
422 | 422 | |||
423 | /* Zeroize all other options. */ | 423 | /* Zeroize all other options. */ | |
424 | count = ptr[off + 1]; | 424 | count = ptr[off + 1]; | |
425 | memcpy(ptr + off, ipseczeroes, count); | 425 | memcpy(ptr + off, ipseczeroes, count); | |
426 | off += count; | 426 | off += count; | |
427 | break; | 427 | break; | |
428 | } | 428 | } | |
429 | 429 | |||
430 | /* Sanity check. */ | 430 | /* Sanity check. */ | |
431 | if (off > skip) { | 431 | if (off > skip) { | |
432 | DPRINTF(("ah_massage_headers(): malformed " | 432 | DPRINTF(("ah_massage_headers(): malformed " | |
433 | "IPv4 options header\n")); | 433 | "IPv4 options header\n")); | |
434 | 434 | |||
435 | m_freem(m); | 435 | m_freem(m); | |
436 | return EINVAL; | 436 | return EINVAL; | |
437 | } | 437 | } | |
438 | } | 438 | } | |
439 | 439 | |||
440 | break; | 440 | break; | |
441 | #endif /* INET */ | 441 | #endif /* INET */ | |
442 | 442 | |||
443 | #ifdef INET6 | 443 | #ifdef INET6 | |
444 | case AF_INET6: /* Ugly... */ | 444 | case AF_INET6: /* Ugly... */ | |
445 | /* Copy and "cook" the IPv6 header. */ | 445 | /* Copy and "cook" the IPv6 header. */ | |
446 | m_copydata(m, 0, sizeof(ip6), &ip6); | 446 | m_copydata(m, 0, sizeof(ip6), &ip6); | |
447 | 447 | |||
448 | /* We don't do IPv6 Jumbograms. */ | 448 | /* We don't do IPv6 Jumbograms. */ | |
449 | if (ip6.ip6_plen == 0) { | 449 | if (ip6.ip6_plen == 0) { | |
450 | DPRINTF(("ah_massage_headers: unsupported IPv6 jumbogram\n")); | 450 | DPRINTF(("ah_massage_headers: unsupported IPv6 jumbogram\n")); | |
451 | m_freem(m); | 451 | m_freem(m); | |
452 | return EMSGSIZE; | 452 | return EMSGSIZE; | |
453 | } | 453 | } | |
454 | 454 | |||
455 | ip6.ip6_flow = 0; | 455 | ip6.ip6_flow = 0; | |
456 | ip6.ip6_hlim = 0; | 456 | ip6.ip6_hlim = 0; | |
457 | ip6.ip6_vfc &= ~IPV6_VERSION_MASK; | 457 | ip6.ip6_vfc &= ~IPV6_VERSION_MASK; | |
458 | ip6.ip6_vfc |= IPV6_VERSION; | 458 | ip6.ip6_vfc |= IPV6_VERSION; | |
459 | 459 | |||
460 | /* Scoped address handling. */ | 460 | /* Scoped address handling. */ | |
461 | if (IN6_IS_SCOPE_LINKLOCAL(&ip6.ip6_src)) | 461 | if (IN6_IS_SCOPE_LINKLOCAL(&ip6.ip6_src)) | |
462 | ip6.ip6_src.s6_addr16[1] = 0; | 462 | ip6.ip6_src.s6_addr16[1] = 0; | |
463 | if (IN6_IS_SCOPE_LINKLOCAL(&ip6.ip6_dst)) | 463 | if (IN6_IS_SCOPE_LINKLOCAL(&ip6.ip6_dst)) | |
464 | ip6.ip6_dst.s6_addr16[1] = 0; | 464 | ip6.ip6_dst.s6_addr16[1] = 0; | |
465 | 465 | |||
466 | /* Done with IPv6 header. */ | 466 | /* Done with IPv6 header. */ | |
467 | m_copyback(m, 0, sizeof(struct ip6_hdr), &ip6); | 467 | m_copyback(m, 0, sizeof(struct ip6_hdr), &ip6); | |
468 | 468 | |||
469 | /* Let's deal with the remaining headers (if any). */ | 469 | /* Let's deal with the remaining headers (if any). */ | |
470 | if (skip - sizeof(struct ip6_hdr) > 0) { | 470 | if (skip - sizeof(struct ip6_hdr) > 0) { | |
471 | if (m->m_len <= skip) { | 471 | if (m->m_len <= skip) { | |
472 | ptr = (unsigned char *) malloc( | 472 | ptr = (unsigned char *) malloc( | |
473 | skip - sizeof(struct ip6_hdr), | 473 | skip - sizeof(struct ip6_hdr), | |
474 | M_XDATA, M_NOWAIT); | 474 | M_XDATA, M_NOWAIT); | |
475 | if (ptr == NULL) { | 475 | if (ptr == NULL) { | |
476 | DPRINTF(("ah_massage_headers: failed " | 476 | DPRINTF(("ah_massage_headers: failed " | |
477 | "to allocate memory for IPv6 " | 477 | "to allocate memory for IPv6 " | |
478 | "headers\n")); | 478 | "headers\n")); | |
479 | m_freem(m); | 479 | m_freem(m); | |
480 | return ENOBUFS; | 480 | return ENOBUFS; | |
481 | } | 481 | } | |
482 | 482 | |||
483 | /* | 483 | /* | |
484 | * Copy all the protocol headers after | 484 | * Copy all the protocol headers after | |
485 | * the IPv6 header. | 485 | * the IPv6 header. | |
486 | */ | 486 | */ | |
487 | m_copydata(m, sizeof(struct ip6_hdr), | 487 | m_copydata(m, sizeof(struct ip6_hdr), | |
488 | skip - sizeof(struct ip6_hdr), ptr); | 488 | skip - sizeof(struct ip6_hdr), ptr); | |
489 | alloc = 1; | 489 | alloc = 1; | |
490 | } else { | 490 | } else { | |
491 | /* No need to allocate memory. */ | 491 | /* No need to allocate memory. */ | |
492 | ptr = mtod(m, unsigned char *) + | 492 | ptr = mtod(m, unsigned char *) + | |
493 | sizeof(struct ip6_hdr); | 493 | sizeof(struct ip6_hdr); | |
494 | alloc = 0; | 494 | alloc = 0; | |
495 | } | 495 | } | |
496 | } else | 496 | } else | |
497 | break; | 497 | break; | |
498 | 498 | |||
499 | nxt = ip6.ip6_nxt & 0xff; /* Next header type. */ | 499 | nxt = ip6.ip6_nxt & 0xff; /* Next header type. */ | |
500 | 500 | |||
501 | for (off = 0; off < skip - sizeof(struct ip6_hdr);) | 501 | for (off = 0; off < skip - sizeof(struct ip6_hdr);) { | |
502 | int noff; | |||
503 | ||||
502 | switch (nxt) { | 504 | switch (nxt) { | |
503 | case IPPROTO_HOPOPTS: | 505 | case IPPROTO_HOPOPTS: | |
504 | case IPPROTO_DSTOPTS: | 506 | case IPPROTO_DSTOPTS: | |
505 | ip6e = (struct ip6_ext *) (ptr + off); | 507 | ip6e = (struct ip6_ext *)(ptr + off); | |
508 | noff = off + ((ip6e->ip6e_len + 1) << 3); | |||
509 | ||||
510 | /* Sanity check. */ | |||
511 | if (noff > skip - sizeof(struct ip6_hdr)) { | |||
512 | goto error6; | |||
513 | } | |||
506 | 514 | |||
507 | /* | 515 | /* | |
508 | * Process the mutable/immutable | 516 | * Zero out mutable options. | |
509 | * options -- borrows heavily from the | |||
510 | * KAME code. | |||
511 | */ | 517 | */ | |
512 | for (count = off + sizeof(struct ip6_ext); | 518 | for (count = off + sizeof(struct ip6_ext); | |
513 | count < off + ((ip6e->ip6e_len + 1) << 3);) { | 519 | count < noff;) { | |
514 | if (ptr[count] == IP6OPT_PAD1) { | 520 | if (ptr[count] == IP6OPT_PAD1) { | |
515 | count++; | 521 | count++; | |
516 | continue; /* Skip padding. */ | 522 | continue; | |
517 | } | |||
518 | ||||
519 | /* Sanity check. */ | |||
520 | if (count > off + | |||
521 | ((ip6e->ip6e_len + 1) << 3)) { | |||
522 | m_freem(m); | |||
523 | ||||
524 | /* Free, if we allocated. */ | |||
525 | if (alloc) | |||
526 | free(ptr, M_XDATA); | |||
527 | return EINVAL; | |||
528 | } | 523 | } | |
529 | 524 | |||
530 | ad = ptr[count + 1] + 2; | 525 | ad = ptr[count + 1] + 2; | |
531 | 526 | |||
532 | /* If mutable option, zeroize. */ | 527 | if (count + ad > noff) { | |
533 | if (ptr[count] & IP6OPT_MUTABLE) | 528 | goto error6; | |
534 | memcpy(ptr + count, ipseczeroes, | 529 | } | |
535 | ad); | 530 | ||
531 | if (ptr[count] & IP6OPT_MUTABLE) { | |||
532 | memset(ptr + count, 0, ad); | |||
533 | } | |||
536 | 534 | |||
537 | count += ad; | 535 | count += ad; | |
536 | } | |||
538 | 537 | |||
539 | /* Sanity check. */ | 538 | if (count != noff) { | |
540 | if (count > | 539 | goto error6; | |
541 | skip - sizeof(struct ip6_hdr)) { | |||
542 | m_freem(m); | |||
543 | ||||
544 | /* Free, if we allocated. */ | |||
545 | if (alloc) | |||
546 | free(ptr, M_XDATA); | |||
547 | return EINVAL; | |||
548 | } | |||
549 | } | 540 | } | |
550 | 541 | |||
551 | /* Advance. */ | 542 | /* Advance. */ | |
552 | off += ((ip6e->ip6e_len + 1) << 3); | 543 | off += ((ip6e->ip6e_len + 1) << 3); | |
553 | nxt = ip6e->ip6e_nxt; | 544 | nxt = ip6e->ip6e_nxt; | |
554 | break; | 545 | break; | |
555 | 546 | |||
556 | case IPPROTO_ROUTING: | 547 | case IPPROTO_ROUTING: | |
557 | /* | 548 | /* | |
558 | * Always include routing headers in | 549 | * Always include routing headers in | |
559 | * computation. | 550 | * computation. | |
560 | */ | 551 | */ | |
561 | { | 552 | { | |
562 | struct ip6_rthdr *rh; | 553 | struct ip6_rthdr *rh; | |
563 | 554 | |||
564 | ip6e = (struct ip6_ext *) (ptr + off); | 555 | ip6e = (struct ip6_ext *) (ptr + off); | |
565 | rh = (struct ip6_rthdr *)(ptr + off); | 556 | rh = (struct ip6_rthdr *)(ptr + off); | |
566 | /* | 557 | /* | |
567 | * must adjust content to make it look like | 558 | * must adjust content to make it look like | |
568 | * its final form (as seen at the final | 559 | * its final form (as seen at the final | |
569 | * destination). | 560 | * destination). | |
570 | * we only know how to massage type 0 routing | 561 | * we only know how to massage type 0 routing | |
571 | * header. | 562 | * header. | |
572 | */ | 563 | */ | |
573 | if (out && rh->ip6r_type == IPV6_RTHDR_TYPE_0) { | 564 | if (out && rh->ip6r_type == IPV6_RTHDR_TYPE_0) { | |
574 | struct ip6_rthdr0 *rh0; | 565 | struct ip6_rthdr0 *rh0; | |
575 | struct in6_addr *addr, finaldst; | 566 | struct in6_addr *addr, finaldst; | |
576 | int i; | 567 | int i; | |
577 | 568 | |||
578 | rh0 = (struct ip6_rthdr0 *)rh; | 569 | rh0 = (struct ip6_rthdr0 *)rh; | |
579 | addr = (struct in6_addr *)(rh0 + 1); | 570 | addr = (struct in6_addr *)(rh0 + 1); | |
580 | 571 | |||
581 | for (i = 0; i < rh0->ip6r0_segleft; i++) | 572 | for (i = 0; i < rh0->ip6r0_segleft; i++) | |
582 | in6_clearscope(&addr[i]); | 573 | in6_clearscope(&addr[i]); | |
583 | 574 | |||
584 | finaldst = addr[rh0->ip6r0_segleft - 1]; | 575 | finaldst = addr[rh0->ip6r0_segleft - 1]; | |
585 | memmove(&addr[1], &addr[0], | 576 | memmove(&addr[1], &addr[0], | |
586 | sizeof(struct in6_addr) * | 577 | sizeof(struct in6_addr) * | |
587 | (rh0->ip6r0_segleft - 1)); | 578 | (rh0->ip6r0_segleft - 1)); | |
588 | 579 | |||
589 | m_copydata(m, 0, sizeof(ip6), &ip6); | 580 | m_copydata(m, 0, sizeof(ip6), &ip6); | |
590 | addr[0] = ip6.ip6_dst; | 581 | addr[0] = ip6.ip6_dst; | |
591 | ip6.ip6_dst = finaldst; | 582 | ip6.ip6_dst = finaldst; | |
592 | m_copyback(m, 0, sizeof(ip6), &ip6); | 583 | m_copyback(m, 0, sizeof(ip6), &ip6); | |
593 | 584 | |||
594 | rh0->ip6r0_segleft = 0; | 585 | rh0->ip6r0_segleft = 0; | |
595 | } | 586 | } | |
596 | 587 | |||
597 | /* advance */ | 588 | /* advance */ | |
598 | off += ((ip6e->ip6e_len + 1) << 3); | 589 | off += ((ip6e->ip6e_len + 1) << 3); | |
599 | nxt = ip6e->ip6e_nxt; | 590 | nxt = ip6e->ip6e_nxt; | |
600 | break; | 591 | break; | |
601 | } | 592 | } | |
602 | 593 | |||
603 | default: | 594 | default: | |
604 | DPRINTF(("ah_massage_headers: unexpected " | 595 | DPRINTF(("ah_massage_headers: unexpected " | |
605 | "IPv6 header type %d", off)); | 596 | "IPv6 header type %d", off)); | |
597 | error6: | |||
606 | if (alloc) | 598 | if (alloc) | |
607 | free(ptr, M_XDATA); | 599 | free(ptr, M_XDATA); | |
608 | m_freem(m); | 600 | m_freem(m); | |
609 | return EINVAL; | 601 | return EINVAL; | |
610 | } | 602 | } | |
603 | } | |||
611 | 604 | |||
612 | /* Copyback and free, if we allocated. */ | 605 | /* Copyback and free, if we allocated. */ | |
613 | if (alloc) { | 606 | if (alloc) { | |
614 | m_copyback(m, sizeof(struct ip6_hdr), | 607 | m_copyback(m, sizeof(struct ip6_hdr), | |
615 | skip - sizeof(struct ip6_hdr), ptr); | 608 | skip - sizeof(struct ip6_hdr), ptr); | |
616 | free(ptr, M_XDATA); | 609 | free(ptr, M_XDATA); | |
617 | } | 610 | } | |
618 | 611 | |||
619 | break; | 612 | break; | |
620 | #endif /* INET6 */ | 613 | #endif /* INET6 */ | |
621 | } | 614 | } | |
622 | 615 | |||
623 | return 0; | 616 | return 0; | |
624 | } | 617 | } | |
625 | 618 | |||
626 | /* | 619 | /* | |
627 | * ah_input() gets called to verify that an input packet | 620 | * ah_input() gets called to verify that an input packet | |
628 | * passes authentication. | 621 | * passes authentication. | |
629 | */ | 622 | */ | |
630 | static int | 623 | static int | |
631 | ah_input(struct mbuf *m, const struct secasvar *sav, int skip, int protoff) | 624 | ah_input(struct mbuf *m, const struct secasvar *sav, int skip, int protoff) | |
632 | { | 625 | { | |
633 | const struct auth_hash *ahx; | 626 | const struct auth_hash *ahx; | |
634 | struct tdb_ident *tdbi; | 627 | struct tdb_ident *tdbi; | |
635 | struct tdb_crypto *tc; | 628 | struct tdb_crypto *tc; | |
636 | struct m_tag *mtag; | 629 | struct m_tag *mtag; | |
637 | struct newah *ah; | 630 | struct newah *ah; | |
638 | int hl, rplen, authsize, error; | 631 | int hl, rplen, authsize, error; | |
639 | uint8_t nxt; | 632 | uint8_t nxt; | |
640 | 633 | |||
641 | struct cryptodesc *crda; | 634 | struct cryptodesc *crda; | |
642 | struct cryptop *crp; | 635 | struct cryptop *crp; | |
643 | 636 | |||
644 | IPSEC_SPLASSERT_SOFTNET("ah_input"); | 637 | IPSEC_SPLASSERT_SOFTNET("ah_input"); | |
645 | 638 | |||
646 | IPSEC_ASSERT(sav != NULL, ("ah_input: null SA")); | 639 | IPSEC_ASSERT(sav != NULL, ("ah_input: null SA")); | |
647 | IPSEC_ASSERT(sav->key_auth != NULL, | 640 | IPSEC_ASSERT(sav->key_auth != NULL, | |
648 | ("ah_input: null authentication key")); | 641 | ("ah_input: null authentication key")); | |
649 | IPSEC_ASSERT(sav->tdb_authalgxform != NULL, | 642 | IPSEC_ASSERT(sav->tdb_authalgxform != NULL, | |
650 | ("ah_input: null authentication xform")); | 643 | ("ah_input: null authentication xform")); | |
651 | 644 | |||
652 | /* Figure out header size. */ | 645 | /* Figure out header size. */ | |
653 | rplen = HDRSIZE(sav); | 646 | rplen = HDRSIZE(sav); | |
654 | 647 | |||
655 | /* XXX don't pullup, just copy header */ | 648 | /* XXX don't pullup, just copy header */ | |
656 | IP6_EXTHDR_GET(ah, struct newah *, m, skip, rplen); | 649 | IP6_EXTHDR_GET(ah, struct newah *, m, skip, rplen); | |
657 | if (ah == NULL) { | 650 | if (ah == NULL) { | |
658 | DPRINTF(("ah_input: cannot pullup header\n")); | 651 | DPRINTF(("ah_input: cannot pullup header\n")); | |
659 | AH_STATINC(AH_STAT_HDROPS); /*XXX*/ | 652 | AH_STATINC(AH_STAT_HDROPS); /*XXX*/ | |
660 | m_freem(m); | 653 | m_freem(m); | |
661 | return ENOBUFS; | 654 | return ENOBUFS; | |
662 | } | 655 | } | |
663 | 656 | |||
664 | nxt = ah->ah_nxt; | 657 | nxt = ah->ah_nxt; | |
665 | 658 | |||
666 | /* Check replay window, if applicable. */ | 659 | /* Check replay window, if applicable. */ | |
667 | if (sav->replay && !ipsec_chkreplay(ntohl(ah->ah_seq), sav)) { | 660 | if (sav->replay && !ipsec_chkreplay(ntohl(ah->ah_seq), sav)) { | |
668 | AH_STATINC(AH_STAT_REPLAY); | 661 | AH_STATINC(AH_STAT_REPLAY); | |
669 | DPRINTF(("ah_input: packet replay failure: %s\n", | 662 | DPRINTF(("ah_input: packet replay failure: %s\n", | |
670 | ipsec_logsastr(sav))); | 663 | ipsec_logsastr(sav))); | |
671 | m_freem(m); | 664 | m_freem(m); | |
672 | return ENOBUFS; | 665 | return ENOBUFS; | |
673 | } | 666 | } | |
674 | 667 | |||
675 | /* Verify AH header length. */ | 668 | /* Verify AH header length. */ | |
676 | hl = ah->ah_len * sizeof (u_int32_t); | 669 | hl = ah->ah_len * sizeof (u_int32_t); | |
677 | ahx = sav->tdb_authalgxform; | 670 | ahx = sav->tdb_authalgxform; | |
678 | authsize = AUTHSIZE(sav); | 671 | authsize = AUTHSIZE(sav); | |
679 | if (hl != authsize + rplen - sizeof (struct ah)) { | 672 | if (hl != authsize + rplen - sizeof (struct ah)) { | |
680 | DPRINTF(("ah_input: bad authenticator length %u (expecting %lu)" | 673 | DPRINTF(("ah_input: bad authenticator length %u (expecting %lu)" | |
681 | " for packet in SA %s/%08lx\n", | 674 | " for packet in SA %s/%08lx\n", | |
682 | hl, (u_long) (authsize + rplen - sizeof (struct ah)), | 675 | hl, (u_long) (authsize + rplen - sizeof (struct ah)), | |
683 | ipsec_address(&sav->sah->saidx.dst), | 676 | ipsec_address(&sav->sah->saidx.dst), | |
684 | (u_long) ntohl(sav->spi))); | 677 | (u_long) ntohl(sav->spi))); | |
685 | AH_STATINC(AH_STAT_BADAUTHL); | 678 | AH_STATINC(AH_STAT_BADAUTHL); | |
686 | m_freem(m); | 679 | m_freem(m); | |
687 | return EACCES; | 680 | return EACCES; | |
688 | } | 681 | } | |
689 | if (skip + authsize + rplen > m->m_pkthdr.len) { | 682 | if (skip + authsize + rplen > m->m_pkthdr.len) { | |
690 | DPRINTF(("%s: bad mbuf length %u (expecting >= %lu)" | 683 | DPRINTF(("%s: bad mbuf length %u (expecting >= %lu)" | |
691 | " for packet in SA %s/%08lx\n", __func__, | 684 | " for packet in SA %s/%08lx\n", __func__, | |
692 | m->m_pkthdr.len, (u_long)(skip + authsize + rplen), | 685 | m->m_pkthdr.len, (u_long)(skip + authsize + rplen), | |
693 | ipsec_address(&sav->sah->saidx.dst), | 686 | ipsec_address(&sav->sah->saidx.dst), | |
694 | (u_long) ntohl(sav->spi))); | 687 | (u_long) ntohl(sav->spi))); | |
695 | AH_STATINC(AH_STAT_BADAUTHL); | 688 | AH_STATINC(AH_STAT_BADAUTHL); | |
696 | m_freem(m); | 689 | m_freem(m); | |
697 | return EACCES; | 690 | return EACCES; | |
698 | } | 691 | } | |
699 | 692 | |||
700 | AH_STATADD(AH_STAT_IBYTES, m->m_pkthdr.len - skip - hl); | 693 | AH_STATADD(AH_STAT_IBYTES, m->m_pkthdr.len - skip - hl); | |
701 | 694 | |||
702 | /* Get crypto descriptors. */ | 695 | /* Get crypto descriptors. */ | |
703 | crp = crypto_getreq(1); | 696 | crp = crypto_getreq(1); | |
704 | if (crp == NULL) { | 697 | if (crp == NULL) { | |
705 | DPRINTF(("ah_input: failed to acquire crypto descriptor\n")); | 698 | DPRINTF(("ah_input: failed to acquire crypto descriptor\n")); | |
706 | AH_STATINC(AH_STAT_CRYPTO); | 699 | AH_STATINC(AH_STAT_CRYPTO); | |
707 | m_freem(m); | 700 | m_freem(m); | |
708 | return ENOBUFS; | 701 | return ENOBUFS; | |
709 | } | 702 | } | |
710 | 703 | |||
711 | crda = crp->crp_desc; | 704 | crda = crp->crp_desc; | |
712 | IPSEC_ASSERT(crda != NULL, ("ah_input: null crypto descriptor")); | 705 | IPSEC_ASSERT(crda != NULL, ("ah_input: null crypto descriptor")); | |
713 | 706 | |||
714 | crda->crd_skip = 0; | 707 | crda->crd_skip = 0; | |
715 | crda->crd_len = m->m_pkthdr.len; | 708 | crda->crd_len = m->m_pkthdr.len; | |
716 | crda->crd_inject = skip + rplen; | 709 | crda->crd_inject = skip + rplen; | |
717 | 710 | |||
718 | /* Authentication operation. */ | 711 | /* Authentication operation. */ | |
719 | crda->crd_alg = ahx->type; | 712 | crda->crd_alg = ahx->type; | |
720 | crda->crd_key = _KEYBUF(sav->key_auth); | 713 | crda->crd_key = _KEYBUF(sav->key_auth); | |
721 | crda->crd_klen = _KEYBITS(sav->key_auth); | 714 | crda->crd_klen = _KEYBITS(sav->key_auth); | |
722 | 715 | |||
723 | /* Find out if we've already done crypto. */ | 716 | /* Find out if we've already done crypto. */ | |
724 | for (mtag = m_tag_find(m, PACKET_TAG_IPSEC_IN_CRYPTO_DONE, NULL); | 717 | for (mtag = m_tag_find(m, PACKET_TAG_IPSEC_IN_CRYPTO_DONE, NULL); | |
725 | mtag != NULL; | 718 | mtag != NULL; | |
726 | mtag = m_tag_find(m, PACKET_TAG_IPSEC_IN_CRYPTO_DONE, mtag)) { | 719 | mtag = m_tag_find(m, PACKET_TAG_IPSEC_IN_CRYPTO_DONE, mtag)) { | |
727 | tdbi = (struct tdb_ident *) (mtag + 1); | 720 | tdbi = (struct tdb_ident *) (mtag + 1); | |
728 | if (tdbi->proto == sav->sah->saidx.proto && | 721 | if (tdbi->proto == sav->sah->saidx.proto && | |
729 | tdbi->spi == sav->spi && | 722 | tdbi->spi == sav->spi && | |
730 | !memcmp(&tdbi->dst, &sav->sah->saidx.dst, | 723 | !memcmp(&tdbi->dst, &sav->sah->saidx.dst, | |
731 | sizeof (union sockaddr_union))) | 724 | sizeof (union sockaddr_union))) | |
732 | break; | 725 | break; | |
733 | } | 726 | } | |
734 | 727 | |||
735 | /* Allocate IPsec-specific opaque crypto info. */ | 728 | /* Allocate IPsec-specific opaque crypto info. */ | |
736 | if (mtag == NULL) { | 729 | if (mtag == NULL) { | |
737 | tc = (struct tdb_crypto *) malloc(sizeof (struct tdb_crypto) + | 730 | tc = (struct tdb_crypto *) malloc(sizeof (struct tdb_crypto) + | |
738 | skip + rplen + authsize, M_XDATA, M_NOWAIT|M_ZERO); | 731 | skip + rplen + authsize, M_XDATA, M_NOWAIT|M_ZERO); | |
739 | } else { | 732 | } else { | |
740 | /* Hash verification has already been done successfully. */ | 733 | /* Hash verification has already been done successfully. */ | |
741 | tc = (struct tdb_crypto *) malloc(sizeof (struct tdb_crypto), | 734 | tc = (struct tdb_crypto *) malloc(sizeof (struct tdb_crypto), | |
742 | M_XDATA, M_NOWAIT|M_ZERO); | 735 | M_XDATA, M_NOWAIT|M_ZERO); | |
743 | } | 736 | } | |
744 | if (tc == NULL) { | 737 | if (tc == NULL) { | |
745 | DPRINTF(("ah_input: failed to allocate tdb_crypto\n")); | 738 | DPRINTF(("ah_input: failed to allocate tdb_crypto\n")); | |
746 | AH_STATINC(AH_STAT_CRYPTO); | 739 | AH_STATINC(AH_STAT_CRYPTO); | |
747 | crypto_freereq(crp); | 740 | crypto_freereq(crp); | |
748 | m_freem(m); | 741 | m_freem(m); | |
749 | return ENOBUFS; | 742 | return ENOBUFS; | |
750 | } | 743 | } | |
751 | 744 | |||
752 | error = m_makewritable(&m, 0, skip + rplen + authsize, M_NOWAIT); | 745 | error = m_makewritable(&m, 0, skip + rplen + authsize, M_NOWAIT); | |
753 | if (error) { | 746 | if (error) { | |
754 | m_freem(m); | 747 | m_freem(m); | |
755 | DPRINTF(("ah_input: failed to copyback_cow\n")); | 748 | DPRINTF(("ah_input: failed to copyback_cow\n")); | |
756 | AH_STATINC(AH_STAT_HDROPS); | 749 | AH_STATINC(AH_STAT_HDROPS); | |
757 | free(tc, M_XDATA); | 750 | free(tc, M_XDATA); | |
758 | crypto_freereq(crp); | 751 | crypto_freereq(crp); | |
759 | return error; | 752 | return error; | |
760 | } | 753 | } | |
761 | 754 | |||
762 | /* Only save information if crypto processing is needed. */ | 755 | /* Only save information if crypto processing is needed. */ | |
763 | if (mtag == NULL) { | 756 | if (mtag == NULL) { | |
764 | /* | 757 | /* | |
765 | * Save the authenticator, the skipped portion of the packet, | 758 | * Save the authenticator, the skipped portion of the packet, | |
766 | * and the AH header. | 759 | * and the AH header. | |
767 | */ | 760 | */ | |
768 | m_copydata(m, 0, skip + rplen + authsize, (tc + 1)); | 761 | m_copydata(m, 0, skip + rplen + authsize, (tc + 1)); | |
769 | 762 | |||
770 | /* Zeroize the authenticator on the packet. */ | 763 | /* Zeroize the authenticator on the packet. */ | |
771 | m_copyback(m, skip + rplen, authsize, ipseczeroes); | 764 | m_copyback(m, skip + rplen, authsize, ipseczeroes); | |
772 | 765 | |||
773 | /* "Massage" the packet headers for crypto processing. */ | 766 | /* "Massage" the packet headers for crypto processing. */ | |
774 | error = ah_massage_headers(&m, sav->sah->saidx.dst.sa.sa_family, | 767 | error = ah_massage_headers(&m, sav->sah->saidx.dst.sa.sa_family, | |
775 | skip, ahx->type, 0); | 768 | skip, ahx->type, 0); | |
776 | if (error != 0) { | 769 | if (error != 0) { | |
777 | /* NB: mbuf is free'd by ah_massage_headers */ | 770 | /* NB: mbuf is free'd by ah_massage_headers */ | |
778 | AH_STATINC(AH_STAT_HDROPS); | 771 | AH_STATINC(AH_STAT_HDROPS); | |
779 | free(tc, M_XDATA); | 772 | free(tc, M_XDATA); | |
780 | crypto_freereq(crp); | 773 | crypto_freereq(crp); | |
781 | return error; | 774 | return error; | |
782 | } | 775 | } | |
783 | } | 776 | } | |
784 | 777 | |||
785 | /* Crypto operation descriptor. */ | 778 | /* Crypto operation descriptor. */ | |
786 | crp->crp_ilen = m->m_pkthdr.len; /* Total input length. */ | 779 | crp->crp_ilen = m->m_pkthdr.len; /* Total input length. */ | |
787 | crp->crp_flags = CRYPTO_F_IMBUF; | 780 | crp->crp_flags = CRYPTO_F_IMBUF; | |
788 | crp->crp_buf = m; | 781 | crp->crp_buf = m; | |
789 | crp->crp_callback = ah_input_cb; | 782 | crp->crp_callback = ah_input_cb; | |
790 | crp->crp_sid = sav->tdb_cryptoid; | 783 | crp->crp_sid = sav->tdb_cryptoid; | |
791 | crp->crp_opaque = tc; | 784 | crp->crp_opaque = tc; | |
792 | 785 | |||
793 | /* These are passed as-is to the callback. */ | 786 | /* These are passed as-is to the callback. */ | |
794 | tc->tc_spi = sav->spi; | 787 | tc->tc_spi = sav->spi; | |
795 | tc->tc_dst = sav->sah->saidx.dst; | 788 | tc->tc_dst = sav->sah->saidx.dst; | |
796 | tc->tc_proto = sav->sah->saidx.proto; | 789 | tc->tc_proto = sav->sah->saidx.proto; | |
797 | tc->tc_nxt = nxt; | 790 | tc->tc_nxt = nxt; | |
798 | tc->tc_protoff = protoff; | 791 | tc->tc_protoff = protoff; | |
799 | tc->tc_skip = skip; | 792 | tc->tc_skip = skip; | |
800 | tc->tc_ptr = mtag; /* Save the mtag we've identified. */ | 793 | tc->tc_ptr = mtag; /* Save the mtag we've identified. */ | |
801 | 794 | |||
802 | DPRINTF(("ah: hash over %d bytes, skip %d: " | 795 | DPRINTF(("ah: hash over %d bytes, skip %d: " | |
803 | "crda len %d skip %d inject %d\n", | 796 | "crda len %d skip %d inject %d\n", | |
804 | crp->crp_ilen, tc->tc_skip, | 797 | crp->crp_ilen, tc->tc_skip, | |
805 | crda->crd_len, crda->crd_skip, crda->crd_inject)); | 798 | crda->crd_len, crda->crd_skip, crda->crd_inject)); | |
806 | 799 | |||
807 | if (mtag == NULL) | 800 | if (mtag == NULL) | |
808 | return crypto_dispatch(crp); | 801 | return crypto_dispatch(crp); | |
809 | else | 802 | else | |
810 | return ah_input_cb(crp); | 803 | return ah_input_cb(crp); | |
811 | } | 804 | } | |
812 | 805 | |||
813 | #ifdef INET6 | 806 | #ifdef INET6 | |
814 | #define IPSEC_COMMON_INPUT_CB(m, sav, skip, protoff, mtag) do { \ | 807 | #define IPSEC_COMMON_INPUT_CB(m, sav, skip, protoff, mtag) do { \ | |
815 | if (saidx->dst.sa.sa_family == AF_INET6) { \ | 808 | if (saidx->dst.sa.sa_family == AF_INET6) { \ | |
816 | error = ipsec6_common_input_cb(m, sav, skip, protoff, mtag); \ | 809 | error = ipsec6_common_input_cb(m, sav, skip, protoff, mtag); \ | |
817 | } else { \ | 810 | } else { \ | |
818 | error = ipsec4_common_input_cb(m, sav, skip, protoff, mtag); \ | 811 | error = ipsec4_common_input_cb(m, sav, skip, protoff, mtag); \ | |
819 | } \ | 812 | } \ | |
820 | } while (0) | 813 | } while (0) | |
821 | #else | 814 | #else | |
822 | #define IPSEC_COMMON_INPUT_CB(m, sav, skip, protoff, mtag) \ | 815 | #define IPSEC_COMMON_INPUT_CB(m, sav, skip, protoff, mtag) \ | |
823 | (error = ipsec4_common_input_cb(m, sav, skip, protoff, mtag)) | 816 | (error = ipsec4_common_input_cb(m, sav, skip, protoff, mtag)) | |
824 | #endif | 817 | #endif | |
825 | 818 | |||
826 | /* | 819 | /* | |
827 | * AH input callback from the crypto driver. | 820 | * AH input callback from the crypto driver. | |
828 | */ | 821 | */ | |
829 | static int | 822 | static int | |
830 | ah_input_cb(struct cryptop *crp) | 823 | ah_input_cb(struct cryptop *crp) | |
831 | { | 824 | { | |
832 | int rplen, error, skip, protoff; | 825 | int rplen, error, skip, protoff; | |
833 | unsigned char calc[AH_ALEN_MAX]; | 826 | unsigned char calc[AH_ALEN_MAX]; | |
834 | struct mbuf *m; | 827 | struct mbuf *m; | |
835 | struct cryptodesc *crd; | 828 | struct cryptodesc *crd; | |
836 | const struct auth_hash *ahx; | 829 | const struct auth_hash *ahx; | |
837 | struct tdb_crypto *tc; | 830 | struct tdb_crypto *tc; | |
838 | struct m_tag *mtag; | 831 | struct m_tag *mtag; | |
839 | struct secasvar *sav; | 832 | struct secasvar *sav; | |
840 | struct secasindex *saidx; | 833 | struct secasindex *saidx; | |
841 | u_int8_t nxt; | 834 | u_int8_t nxt; | |
842 | char *ptr; | 835 | char *ptr; | |
843 | int s, authsize; | 836 | int s, authsize; | |
844 | u_int16_t dport = 0; | 837 | u_int16_t dport = 0; | |
845 | u_int16_t sport = 0; | 838 | u_int16_t sport = 0; | |
846 | #ifdef IPSEC_NAT_T | 839 | #ifdef IPSEC_NAT_T | |
847 | struct m_tag * tag = NULL; | 840 | struct m_tag * tag = NULL; | |
848 | #endif | 841 | #endif | |
849 | 842 | |||
850 | crd = crp->crp_desc; | 843 | crd = crp->crp_desc; | |
851 | 844 | |||
852 | tc = (struct tdb_crypto *) crp->crp_opaque; | 845 | tc = (struct tdb_crypto *) crp->crp_opaque; | |
853 | IPSEC_ASSERT(tc != NULL, ("ah_input_cb: null opaque crypto data area!")); | 846 | IPSEC_ASSERT(tc != NULL, ("ah_input_cb: null opaque crypto data area!")); | |
854 | skip = tc->tc_skip; | 847 | skip = tc->tc_skip; | |
855 | nxt = tc->tc_nxt; | 848 | nxt = tc->tc_nxt; | |
856 | protoff = tc->tc_protoff; | 849 | protoff = tc->tc_protoff; | |
857 | mtag = (struct m_tag *) tc->tc_ptr; | 850 | mtag = (struct m_tag *) tc->tc_ptr; | |
858 | m = (struct mbuf *) crp->crp_buf; | 851 | m = (struct mbuf *) crp->crp_buf; | |
859 | 852 | |||
860 | 853 | |||
861 | #ifdef IPSEC_NAT_T | 854 | #ifdef IPSEC_NAT_T | |
862 | /* find the source port for NAT-T */ | 855 | /* find the source port for NAT-T */ | |
863 | if ((tag = m_tag_find(m, PACKET_TAG_IPSEC_NAT_T_PORTS, NULL))) { | 856 | if ((tag = m_tag_find(m, PACKET_TAG_IPSEC_NAT_T_PORTS, NULL))) { | |
864 | sport = ((u_int16_t *)(tag + 1))[0]; | 857 | sport = ((u_int16_t *)(tag + 1))[0]; | |
865 | dport = ((u_int16_t *)(tag + 1))[1]; | 858 | dport = ((u_int16_t *)(tag + 1))[1]; | |
866 | } | 859 | } | |
867 | #endif | 860 | #endif | |
868 | 861 | |||
869 | s = splsoftnet(); | 862 | s = splsoftnet(); | |
870 | mutex_enter(softnet_lock); | 863 | mutex_enter(softnet_lock); | |
871 | 864 | |||
872 | sav = KEY_ALLOCSA(&tc->tc_dst, tc->tc_proto, tc->tc_spi, sport, dport); | 865 | sav = KEY_ALLOCSA(&tc->tc_dst, tc->tc_proto, tc->tc_spi, sport, dport); | |
873 | if (sav == NULL) { | 866 | if (sav == NULL) { | |
874 | AH_STATINC(AH_STAT_NOTDB); | 867 | AH_STATINC(AH_STAT_NOTDB); | |
875 | DPRINTF(("ah_input_cb: SA expired while in crypto\n")); | 868 | DPRINTF(("ah_input_cb: SA expired while in crypto\n")); | |
876 | error = ENOBUFS; /*XXX*/ | 869 | error = ENOBUFS; /*XXX*/ | |
877 | goto bad; | 870 | goto bad; | |
878 | } | 871 | } | |
879 | 872 | |||
880 | saidx = &sav->sah->saidx; | 873 | saidx = &sav->sah->saidx; | |
881 | IPSEC_ASSERT(saidx->dst.sa.sa_family == AF_INET || | 874 | IPSEC_ASSERT(saidx->dst.sa.sa_family == AF_INET || | |
882 | saidx->dst.sa.sa_family == AF_INET6, | 875 | saidx->dst.sa.sa_family == AF_INET6, | |
883 | ("ah_input_cb: unexpected protocol family %u", | 876 | ("ah_input_cb: unexpected protocol family %u", | |
884 | saidx->dst.sa.sa_family)); | 877 | saidx->dst.sa.sa_family)); | |
885 | 878 | |||
886 | ahx = sav->tdb_authalgxform; | 879 | ahx = sav->tdb_authalgxform; | |
887 | 880 | |||
888 | /* Check for crypto errors. */ | 881 | /* Check for crypto errors. */ | |
889 | if (crp->crp_etype) { | 882 | if (crp->crp_etype) { | |
890 | if (sav->tdb_cryptoid != 0) | 883 | if (sav->tdb_cryptoid != 0) | |
891 | sav->tdb_cryptoid = crp->crp_sid; | 884 | sav->tdb_cryptoid = crp->crp_sid; | |
892 | 885 | |||
893 | if (crp->crp_etype == EAGAIN) { | 886 | if (crp->crp_etype == EAGAIN) { | |
894 | mutex_exit(softnet_lock); | 887 | mutex_exit(softnet_lock); | |
895 | splx(s); | 888 | splx(s); | |
896 | return crypto_dispatch(crp); | 889 | return crypto_dispatch(crp); | |
897 | } | 890 | } | |
898 | 891 | |||
899 | AH_STATINC(AH_STAT_NOXFORM); | 892 | AH_STATINC(AH_STAT_NOXFORM); | |
900 | DPRINTF(("ah_input_cb: crypto error %d\n", crp->crp_etype)); | 893 | DPRINTF(("ah_input_cb: crypto error %d\n", crp->crp_etype)); | |
901 | error = crp->crp_etype; | 894 | error = crp->crp_etype; | |
902 | goto bad; | 895 | goto bad; | |
903 | } else { | 896 | } else { | |
904 | AH_STATINC(AH_STAT_HIST + sav->alg_auth); | 897 | AH_STATINC(AH_STAT_HIST + sav->alg_auth); | |
905 | crypto_freereq(crp); /* No longer needed. */ | 898 | crypto_freereq(crp); /* No longer needed. */ | |
906 | crp = NULL; | 899 | crp = NULL; | |
907 | } | 900 | } | |
908 | 901 | |||
909 | /* Shouldn't happen... */ | 902 | /* Shouldn't happen... */ | |
910 | if (m == NULL) { | 903 | if (m == NULL) { | |
911 | AH_STATINC(AH_STAT_CRYPTO); | 904 | AH_STATINC(AH_STAT_CRYPTO); | |
912 | DPRINTF(("ah_input_cb: bogus returned buffer from crypto\n")); | 905 | DPRINTF(("ah_input_cb: bogus returned buffer from crypto\n")); | |
913 | error = EINVAL; | 906 | error = EINVAL; | |
914 | goto bad; | 907 | goto bad; | |
915 | } | 908 | } | |
916 | 909 | |||
917 | /* Figure out header size. */ | 910 | /* Figure out header size. */ | |
918 | rplen = HDRSIZE(sav); | 911 | rplen = HDRSIZE(sav); | |
919 | authsize = AUTHSIZE(sav); | 912 | authsize = AUTHSIZE(sav); | |
920 | 913 | |||
921 | if (ipsec_debug) | 914 | if (ipsec_debug) | |
922 | memset(calc, 0, sizeof(calc)); | 915 | memset(calc, 0, sizeof(calc)); | |
923 | 916 | |||
924 | /* Copy authenticator off the packet. */ | 917 | /* Copy authenticator off the packet. */ | |
925 | m_copydata(m, skip + rplen, authsize, calc); | 918 | m_copydata(m, skip + rplen, authsize, calc); | |
926 | 919 | |||
927 | /* | 920 | /* | |
928 | * If we have an mtag, we don't need to verify the authenticator -- | 921 | * If we have an mtag, we don't need to verify the authenticator -- | |
929 | * it has been verified by an IPsec-aware NIC. | 922 | * it has been verified by an IPsec-aware NIC. | |
930 | */ | 923 | */ | |
931 | if (mtag == NULL) { | 924 | if (mtag == NULL) { | |
932 | ptr = (char *) (tc + 1); | 925 | ptr = (char *) (tc + 1); | |
933 | 926 | |||
934 | /* Verify authenticator. */ | 927 | /* Verify authenticator. */ | |
935 | if (memcmp(ptr + skip + rplen, calc, authsize)) { | 928 | if (memcmp(ptr + skip + rplen, calc, authsize)) { | |
936 | u_int8_t *pppp = ptr + skip+rplen; | 929 | u_int8_t *pppp = ptr + skip+rplen; | |
937 | DPRINTF(("ah_input: authentication hash mismatch " \ | 930 | DPRINTF(("ah_input: authentication hash mismatch " \ | |
938 | "over %d bytes " \ | 931 | "over %d bytes " \ | |
939 | "for packet in SA %s/%08lx:\n" \ | 932 | "for packet in SA %s/%08lx:\n" \ | |
940 | "%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x, " \ | 933 | "%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x, " \ | |
941 | "%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x\n", | 934 | "%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x\n", | |
942 | authsize, | 935 | authsize, | |
943 | ipsec_address(&saidx->dst), | 936 | ipsec_address(&saidx->dst), | |
944 | (u_long) ntohl(sav->spi), | 937 | (u_long) ntohl(sav->spi), | |
945 | calc[0], calc[1], calc[2], calc[3], | 938 | calc[0], calc[1], calc[2], calc[3], | |
946 | calc[4], calc[5], calc[6], calc[7], | 939 | calc[4], calc[5], calc[6], calc[7], | |
947 | calc[8], calc[9], calc[10], calc[11], | 940 | calc[8], calc[9], calc[10], calc[11], | |
948 | pppp[0], pppp[1], pppp[2], pppp[3], | 941 | pppp[0], pppp[1], pppp[2], pppp[3], | |
949 | pppp[4], pppp[5], pppp[6], pppp[7], | 942 | pppp[4], pppp[5], pppp[6], pppp[7], | |
950 | pppp[8], pppp[9], pppp[10], pppp[11] | 943 | pppp[8], pppp[9], pppp[10], pppp[11] | |
951 | )); | 944 | )); | |
952 | AH_STATINC(AH_STAT_BADAUTH); | 945 | AH_STATINC(AH_STAT_BADAUTH); | |
953 | error = EACCES; | 946 | error = EACCES; | |
954 | goto bad; | 947 | goto bad; | |
955 | } | 948 | } | |
956 | 949 | |||
957 | /* Fix the Next Protocol field. */ | 950 | /* Fix the Next Protocol field. */ | |
958 | ((u_int8_t *) ptr)[protoff] = nxt; | 951 | ((u_int8_t *) ptr)[protoff] = nxt; | |
959 | 952 | |||
960 | /* Copyback the saved (uncooked) network headers. */ | 953 | /* Copyback the saved (uncooked) network headers. */ | |
961 | m_copyback(m, 0, skip, ptr); | 954 | m_copyback(m, 0, skip, ptr); | |
962 | } else { | 955 | } else { | |
963 | /* Fix the Next Protocol field. */ | 956 | /* Fix the Next Protocol field. */ | |
964 | m_copyback(m, protoff, sizeof(u_int8_t), &nxt); | 957 | m_copyback(m, protoff, sizeof(u_int8_t), &nxt); | |
965 | } | 958 | } | |
966 | 959 | |||
967 | free(tc, M_XDATA), tc = NULL; /* No longer needed */ | 960 | free(tc, M_XDATA), tc = NULL; /* No longer needed */ | |
968 | 961 | |||
969 | /* | 962 | /* | |
970 | * Header is now authenticated. | 963 | * Header is now authenticated. | |
971 | */ | 964 | */ | |
972 | m->m_flags |= M_AUTHIPHDR|M_AUTHIPDGM; | 965 | m->m_flags |= M_AUTHIPHDR|M_AUTHIPDGM; | |
973 | 966 | |||
974 | /* | 967 | /* | |
975 | * Update replay sequence number, if appropriate. | 968 | * Update replay sequence number, if appropriate. | |
976 | */ | 969 | */ | |
977 | if (sav->replay) { | 970 | if (sav->replay) { | |
978 | u_int32_t seq; | 971 | u_int32_t seq; | |
979 | 972 | |||
980 | m_copydata(m, skip + offsetof(struct newah, ah_seq), | 973 | m_copydata(m, skip + offsetof(struct newah, ah_seq), | |
981 | sizeof (seq), &seq); | 974 | sizeof (seq), &seq); | |
982 | if (ipsec_updatereplay(ntohl(seq), sav)) { | 975 | if (ipsec_updatereplay(ntohl(seq), sav)) { | |
983 | AH_STATINC(AH_STAT_REPLAY); | 976 | AH_STATINC(AH_STAT_REPLAY); | |
984 | error = ENOBUFS; /*XXX as above*/ | 977 | error = ENOBUFS; /*XXX as above*/ | |
985 | goto bad; | 978 | goto bad; | |
986 | } | 979 | } | |
987 | } | 980 | } | |
988 | 981 | |||
989 | /* | 982 | /* | |
990 | * Remove the AH header and authenticator from the mbuf. | 983 | * Remove the AH header and authenticator from the mbuf. | |
991 | */ | 984 | */ | |
992 | error = m_striphdr(m, skip, rplen + authsize); | 985 | error = m_striphdr(m, skip, rplen + authsize); | |
993 | if (error) { | 986 | if (error) { | |
994 | DPRINTF(("ah_input_cb: mangled mbuf chain for SA %s/%08lx\n", | 987 | DPRINTF(("ah_input_cb: mangled mbuf chain for SA %s/%08lx\n", | |
995 | ipsec_address(&saidx->dst), (u_long) ntohl(sav->spi))); | 988 | ipsec_address(&saidx->dst), (u_long) ntohl(sav->spi))); | |
996 | 989 | |||
997 | AH_STATINC(AH_STAT_HDROPS); | 990 | AH_STATINC(AH_STAT_HDROPS); | |
998 | goto bad; | 991 | goto bad; | |
999 | } | 992 | } | |
1000 | 993 | |||
1001 | IPSEC_COMMON_INPUT_CB(m, sav, skip, protoff, mtag); | 994 | IPSEC_COMMON_INPUT_CB(m, sav, skip, protoff, mtag); | |
1002 | 995 | |||
1003 | KEY_FREESAV(&sav); | 996 | KEY_FREESAV(&sav); | |
1004 | mutex_exit(softnet_lock); | 997 | mutex_exit(softnet_lock); | |
1005 | splx(s); | 998 | splx(s); | |
1006 | return error; | 999 | return error; | |
1007 | bad: | 1000 | bad: | |
1008 | if (sav) | 1001 | if (sav) | |
1009 | KEY_FREESAV(&sav); | 1002 | KEY_FREESAV(&sav); | |
1010 | mutex_exit(softnet_lock); | 1003 | mutex_exit(softnet_lock); | |
1011 | splx(s); | 1004 | splx(s); | |
1012 | if (m != NULL) | 1005 | if (m != NULL) | |
1013 | m_freem(m); | 1006 | m_freem(m); | |
1014 | if (tc != NULL) | 1007 | if (tc != NULL) | |
1015 | free(tc, M_XDATA); | 1008 | free(tc, M_XDATA); | |
1016 | if (crp != NULL) | 1009 | if (crp != NULL) | |
1017 | crypto_freereq(crp); | 1010 | crypto_freereq(crp); | |
1018 | return error; | 1011 | return error; | |
1019 | } | 1012 | } | |
1020 | 1013 | |||
1021 | /* | 1014 | /* | |
1022 | * AH output routine, called by ipsec[46]_process_packet(). | 1015 | * AH output routine, called by ipsec[46]_process_packet(). | |
1023 | */ | 1016 | */ | |
1024 | static int | 1017 | static int | |
1025 | ah_output( | 1018 | ah_output( | |
1026 | struct mbuf *m, | 1019 | struct mbuf *m, | |
1027 | struct ipsecrequest *isr, | 1020 | struct ipsecrequest *isr, | |
1028 | struct mbuf **mp, | 1021 | struct mbuf **mp, | |
1029 | int skip, | 1022 | int skip, | |
1030 | int protoff | 1023 | int protoff | |
1031 | ) | 1024 | ) | |
1032 | { | 1025 | { | |
1033 | const struct secasvar *sav; | 1026 | const struct secasvar *sav; | |
1034 | const struct auth_hash *ahx; | 1027 | const struct auth_hash *ahx; | |
1035 | struct cryptodesc *crda; | 1028 | struct cryptodesc *crda; | |
1036 | struct tdb_crypto *tc; | 1029 | struct tdb_crypto *tc; | |
1037 | struct mbuf *mi; | 1030 | struct mbuf *mi; | |
1038 | struct cryptop *crp; | 1031 | struct cryptop *crp; | |
1039 | u_int16_t iplen; | 1032 | u_int16_t iplen; | |
1040 | int error, rplen, authsize, maxpacketsize, roff; | 1033 | int error, rplen, authsize, maxpacketsize, roff; | |
1041 | u_int8_t prot; | 1034 | u_int8_t prot; | |
1042 | struct newah *ah; | 1035 | struct newah *ah; | |
1043 | 1036 | |||
1044 | IPSEC_SPLASSERT_SOFTNET("ah_output"); | 1037 | IPSEC_SPLASSERT_SOFTNET("ah_output"); | |
1045 | 1038 | |||
1046 | sav = isr->sav; | 1039 | sav = isr->sav; | |
1047 | IPSEC_ASSERT(sav != NULL, ("ah_output: null SA")); | 1040 | IPSEC_ASSERT(sav != NULL, ("ah_output: null SA")); | |
1048 | ahx = sav->tdb_authalgxform; | 1041 | ahx = sav->tdb_authalgxform; | |
1049 | IPSEC_ASSERT(ahx != NULL, ("ah_output: null authentication xform")); | 1042 | IPSEC_ASSERT(ahx != NULL, ("ah_output: null authentication xform")); | |
1050 | 1043 | |||
1051 | AH_STATINC(AH_STAT_OUTPUT); | 1044 | AH_STATINC(AH_STAT_OUTPUT); | |
1052 | 1045 | |||
1053 | /* Figure out header size. */ | 1046 | /* Figure out header size. */ | |
1054 | rplen = HDRSIZE(sav); | 1047 | rplen = HDRSIZE(sav); | |
1055 | 1048 | |||
1056 | /* Check for maximum packet size violations. */ | 1049 | /* Check for maximum packet size violations. */ | |
1057 | switch (sav->sah->saidx.dst.sa.sa_family) { | 1050 | switch (sav->sah->saidx.dst.sa.sa_family) { | |
1058 | #ifdef INET | 1051 | #ifdef INET | |
1059 | case AF_INET: | 1052 | case AF_INET: | |
1060 | maxpacketsize = IP_MAXPACKET; | 1053 | maxpacketsize = IP_MAXPACKET; | |
1061 | break; | 1054 | break; | |
1062 | #endif /* INET */ | 1055 | #endif /* INET */ | |
1063 | #ifdef INET6 | 1056 | #ifdef INET6 | |
1064 | case AF_INET6: | 1057 | case AF_INET6: | |
1065 | maxpacketsize = IPV6_MAXPACKET; | 1058 | maxpacketsize = IPV6_MAXPACKET; | |
1066 | break; | 1059 | break; | |
1067 | #endif /* INET6 */ | 1060 | #endif /* INET6 */ | |
1068 | default: | 1061 | default: | |
1069 | DPRINTF(("ah_output: unknown/unsupported protocol " | 1062 | DPRINTF(("ah_output: unknown/unsupported protocol " | |
1070 | "family %u, SA %s/%08lx\n", | 1063 | "family %u, SA %s/%08lx\n", | |
1071 | sav->sah->saidx.dst.sa.sa_family, | 1064 | sav->sah->saidx.dst.sa.sa_family, | |
1072 | ipsec_address(&sav->sah->saidx.dst), | 1065 | ipsec_address(&sav->sah->saidx.dst), | |
1073 | (u_long) ntohl(sav->spi))); | 1066 | (u_long) ntohl(sav->spi))); | |
1074 | AH_STATINC(AH_STAT_NOPF); | 1067 | AH_STATINC(AH_STAT_NOPF); | |
1075 | error = EPFNOSUPPORT; | 1068 | error = EPFNOSUPPORT; | |
1076 | goto bad; | 1069 | goto bad; | |
1077 | } | 1070 | } | |
1078 | authsize = AUTHSIZE(sav); | 1071 | authsize = AUTHSIZE(sav); | |
1079 | if (rplen + authsize + m->m_pkthdr.len > maxpacketsize) { | 1072 | if (rplen + authsize + m->m_pkthdr.len > maxpacketsize) { | |
1080 | DPRINTF(("ah_output: packet in SA %s/%08lx got too big " | 1073 | DPRINTF(("ah_output: packet in SA %s/%08lx got too big " | |
1081 | "(len %u, max len %u)\n", | 1074 | "(len %u, max len %u)\n", | |
1082 | ipsec_address(&sav->sah->saidx.dst), | 1075 | ipsec_address(&sav->sah->saidx.dst), | |
1083 | (u_long) ntohl(sav->spi), | 1076 | (u_long) ntohl(sav->spi), | |
1084 | rplen + authsize + m->m_pkthdr.len, maxpacketsize)); | 1077 | rplen + authsize + m->m_pkthdr.len, maxpacketsize)); | |
1085 | AH_STATINC(AH_STAT_TOOBIG); | 1078 | AH_STATINC(AH_STAT_TOOBIG); | |
1086 | error = EMSGSIZE; | 1079 | error = EMSGSIZE; | |
1087 | goto bad; | 1080 | goto bad; | |
1088 | } | 1081 | } | |
1089 | 1082 | |||
1090 | /* Update the counters. */ | 1083 | /* Update the counters. */ | |
1091 | AH_STATADD(AH_STAT_OBYTES, m->m_pkthdr.len - skip); | 1084 | AH_STATADD(AH_STAT_OBYTES, m->m_pkthdr.len - skip); | |
1092 | 1085 | |||
1093 | m = m_clone(m); | 1086 | m = m_clone(m); | |
1094 | if (m == NULL) { | 1087 | if (m == NULL) { | |
1095 | DPRINTF(("ah_output: cannot clone mbuf chain, SA %s/%08lx\n", | 1088 | DPRINTF(("ah_output: cannot clone mbuf chain, SA %s/%08lx\n", | |
1096 | ipsec_address(&sav->sah->saidx.dst), | 1089 | ipsec_address(&sav->sah->saidx.dst), | |
1097 | (u_long) ntohl(sav->spi))); | 1090 | (u_long) ntohl(sav->spi))); | |
1098 | AH_STATINC(AH_STAT_HDROPS); | 1091 | AH_STATINC(AH_STAT_HDROPS); | |
1099 | error = ENOBUFS; | 1092 | error = ENOBUFS; | |
1100 | goto bad; | 1093 | goto bad; | |
1101 | } | 1094 | } | |
1102 | 1095 | |||
1103 | /* Inject AH header. */ | 1096 | /* Inject AH header. */ | |
1104 | mi = m_makespace(m, skip, rplen + authsize, &roff); | 1097 | mi = m_makespace(m, skip, rplen + authsize, &roff); | |
1105 | if (mi == NULL) { | 1098 | if (mi == NULL) { | |
1106 | DPRINTF(("ah_output: failed to inject %u byte AH header for SA " | 1099 | DPRINTF(("ah_output: failed to inject %u byte AH header for SA " | |
1107 | "%s/%08lx\n", | 1100 | "%s/%08lx\n", | |
1108 | rplen + authsize, | 1101 | rplen + authsize, | |
1109 | ipsec_address(&sav->sah->saidx.dst), | 1102 | ipsec_address(&sav->sah->saidx.dst), | |
1110 | (u_long) ntohl(sav->spi))); | 1103 | (u_long) ntohl(sav->spi))); | |
1111 | AH_STATINC(AH_STAT_HDROPS); /*XXX differs from openbsd */ | 1104 | AH_STATINC(AH_STAT_HDROPS); /*XXX differs from openbsd */ | |
1112 | error = ENOBUFS; | 1105 | error = ENOBUFS; | |
1113 | goto bad; | 1106 | goto bad; | |
1114 | } | 1107 | } | |
1115 | 1108 | |||
1116 | /* | 1109 | /* | |
1117 | * The AH header is guaranteed by m_makespace() to be in | 1110 | * The AH header is guaranteed by m_makespace() to be in | |
1118 | * contiguous memory, at roff bytes offset into the returned mbuf. | 1111 | * contiguous memory, at roff bytes offset into the returned mbuf. | |
1119 | */ | 1112 | */ | |
1120 | ah = (struct newah *)(mtod(mi, char *) + roff); | 1113 | ah = (struct newah *)(mtod(mi, char *) + roff); | |
1121 | 1114 | |||
1122 | /* Initialize the AH header. */ | 1115 | /* Initialize the AH header. */ | |
1123 | m_copydata(m, protoff, sizeof(u_int8_t), &ah->ah_nxt); | 1116 | m_copydata(m, protoff, sizeof(u_int8_t), &ah->ah_nxt); | |
1124 | ah->ah_len = (rplen + authsize - sizeof(struct ah)) / sizeof(u_int32_t); | 1117 | ah->ah_len = (rplen + authsize - sizeof(struct ah)) / sizeof(u_int32_t); | |
1125 | ah->ah_reserve = 0; | 1118 | ah->ah_reserve = 0; | |
1126 | ah->ah_spi = sav->spi; | 1119 | ah->ah_spi = sav->spi; | |
1127 | 1120 | |||
1128 | /* Zeroize authenticator. */ | 1121 | /* Zeroize authenticator. */ | |
1129 | m_copyback(m, skip + rplen, authsize, ipseczeroes); | 1122 | m_copyback(m, skip + rplen, authsize, ipseczeroes); | |
1130 | 1123 | |||
1131 | /* Insert packet replay counter, as requested. */ | 1124 | /* Insert packet replay counter, as requested. */ | |
1132 | if (sav->replay) { | 1125 | if (sav->replay) { | |
1133 | if (sav->replay->count == ~0 && | 1126 | if (sav->replay->count == ~0 && | |
1134 | (sav->flags & SADB_X_EXT_CYCSEQ) == 0) { | 1127 | (sav->flags & SADB_X_EXT_CYCSEQ) == 0) { | |
1135 | DPRINTF(("ah_output: replay counter wrapped for SA " | 1128 | DPRINTF(("ah_output: replay counter wrapped for SA " | |
1136 | "%s/%08lx\n", | 1129 | "%s/%08lx\n", | |
1137 | ipsec_address(&sav->sah->saidx.dst), | 1130 | ipsec_address(&sav->sah->saidx.dst), | |
1138 | (u_long) ntohl(sav->spi))); | 1131 | (u_long) ntohl(sav->spi))); | |
1139 | AH_STATINC(AH_STAT_WRAP); | 1132 | AH_STATINC(AH_STAT_WRAP); | |
1140 | error = EINVAL; | 1133 | error = EINVAL; | |
1141 | goto bad; | 1134 | goto bad; | |
1142 | } | 1135 | } | |
1143 | #ifdef IPSEC_DEBUG | 1136 | #ifdef IPSEC_DEBUG | |
1144 | /* Emulate replay attack when ipsec_replay is TRUE. */ | 1137 | /* Emulate replay attack when ipsec_replay is TRUE. */ | |
1145 | if (!ipsec_replay) | 1138 | if (!ipsec_replay) | |
1146 | #endif | 1139 | #endif | |
1147 | sav->replay->count++; | 1140 | sav->replay->count++; | |
1148 | ah->ah_seq = htonl(sav->replay->count); | 1141 | ah->ah_seq = htonl(sav->replay->count); | |
1149 | } | 1142 | } | |
1150 | 1143 | |||
1151 | /* Get crypto descriptors. */ | 1144 | /* Get crypto descriptors. */ | |
1152 | crp = crypto_getreq(1); | 1145 | crp = crypto_getreq(1); | |
1153 | if (crp == NULL) { | 1146 | if (crp == NULL) { | |
1154 | DPRINTF(("ah_output: failed to acquire crypto descriptors\n")); | 1147 | DPRINTF(("ah_output: failed to acquire crypto descriptors\n")); | |
1155 | AH_STATINC(AH_STAT_CRYPTO); | 1148 | AH_STATINC(AH_STAT_CRYPTO); | |
1156 | error = ENOBUFS; | 1149 | error = ENOBUFS; | |
1157 | goto bad; | 1150 | goto bad; | |
1158 | } | 1151 | } | |
1159 | 1152 | |||
1160 | crda = crp->crp_desc; | 1153 | crda = crp->crp_desc; | |
1161 | 1154 | |||
1162 | crda->crd_skip = 0; | 1155 | crda->crd_skip = 0; | |
1163 | crda->crd_inject = skip + rplen; | 1156 | crda->crd_inject = skip + rplen; | |
1164 | crda->crd_len = m->m_pkthdr.len; | 1157 | crda->crd_len = m->m_pkthdr.len; | |
1165 | 1158 | |||
1166 | /* Authentication operation. */ | 1159 | /* Authentication operation. */ | |
1167 | crda->crd_alg = ahx->type; | 1160 | crda->crd_alg = ahx->type; | |
1168 | crda->crd_key = _KEYBUF(sav->key_auth); | 1161 | crda->crd_key = _KEYBUF(sav->key_auth); | |
1169 | crda->crd_klen = _KEYBITS(sav->key_auth); | 1162 | crda->crd_klen = _KEYBITS(sav->key_auth); | |
1170 | 1163 | |||
1171 | /* Allocate IPsec-specific opaque crypto info. */ | 1164 | /* Allocate IPsec-specific opaque crypto info. */ | |
1172 | tc = (struct tdb_crypto *) malloc( | 1165 | tc = (struct tdb_crypto *) malloc( | |
1173 | sizeof(struct tdb_crypto) + skip, M_XDATA, M_NOWAIT|M_ZERO); | 1166 | sizeof(struct tdb_crypto) + skip, M_XDATA, M_NOWAIT|M_ZERO); | |
1174 | if (tc == NULL) { | 1167 | if (tc == NULL) { | |
1175 | crypto_freereq(crp); | 1168 | crypto_freereq(crp); | |
1176 | DPRINTF(("ah_output: failed to allocate tdb_crypto\n")); | 1169 | DPRINTF(("ah_output: failed to allocate tdb_crypto\n")); | |
1177 | AH_STATINC(AH_STAT_CRYPTO); | 1170 | AH_STATINC(AH_STAT_CRYPTO); | |
1178 | error = ENOBUFS; | 1171 | error = ENOBUFS; | |
1179 | goto bad; | 1172 | goto bad; | |
1180 | } | 1173 | } | |
1181 | 1174 | |||
1182 | /* Save the skipped portion of the packet. */ | 1175 | /* Save the skipped portion of the packet. */ | |
1183 | m_copydata(m, 0, skip, (tc + 1)); | 1176 | m_copydata(m, 0, skip, (tc + 1)); | |
1184 | 1177 | |||
1185 | /* | 1178 | /* | |
1186 | * Fix IP header length on the header used for | 1179 | * Fix IP header length on the header used for | |
1187 | * authentication. We don't need to fix the original | 1180 | * authentication. We don't need to fix the original | |
1188 | * header length as it will be fixed by our caller. | 1181 | * header length as it will be fixed by our caller. | |
1189 | */ | 1182 | */ | |
1190 | switch (sav->sah->saidx.dst.sa.sa_family) { | 1183 | switch (sav->sah->saidx.dst.sa.sa_family) { | |
1191 | #ifdef INET | 1184 | #ifdef INET | |
1192 | case AF_INET: | 1185 | case AF_INET: | |
1193 | bcopy(((char *)(tc + 1)) + | 1186 | bcopy(((char *)(tc + 1)) + | |
1194 | offsetof(struct ip, ip_len), | 1187 | offsetof(struct ip, ip_len), | |
1195 | &iplen, sizeof(u_int16_t)); | 1188 | &iplen, sizeof(u_int16_t)); | |
1196 | iplen = htons(ntohs(iplen) + rplen + authsize); | 1189 | iplen = htons(ntohs(iplen) + rplen + authsize); | |
1197 | m_copyback(m, offsetof(struct ip, ip_len), | 1190 | m_copyback(m, offsetof(struct ip, ip_len), | |
1198 | sizeof(u_int16_t), &iplen); | 1191 | sizeof(u_int16_t), &iplen); | |
1199 | break; | 1192 | break; | |
1200 | #endif /* INET */ | 1193 | #endif /* INET */ | |
1201 | 1194 | |||
1202 | #ifdef INET6 | 1195 | #ifdef INET6 | |
1203 | case AF_INET6: | 1196 | case AF_INET6: | |
1204 | bcopy(((char *)(tc + 1)) + | 1197 | bcopy(((char *)(tc + 1)) + | |
1205 | offsetof(struct ip6_hdr, ip6_plen), | 1198 | offsetof(struct ip6_hdr, ip6_plen), | |
1206 | &iplen, sizeof(u_int16_t)); | 1199 | &iplen, sizeof(u_int16_t)); | |
1207 | iplen = htons(ntohs(iplen) + rplen + authsize); | 1200 | iplen = htons(ntohs(iplen) + rplen + authsize); | |
1208 | m_copyback(m, offsetof(struct ip6_hdr, ip6_plen), | 1201 | m_copyback(m, offsetof(struct ip6_hdr, ip6_plen), | |
1209 | sizeof(u_int16_t), &iplen); | 1202 | sizeof(u_int16_t), &iplen); | |
1210 | break; | 1203 | break; | |
1211 | #endif /* INET6 */ | 1204 | #endif /* INET6 */ | |
1212 | } | 1205 | } | |
1213 | 1206 | |||
1214 | /* Fix the Next Header field in saved header. */ | 1207 | /* Fix the Next Header field in saved header. */ | |
1215 | ((u_int8_t *) (tc + 1))[protoff] = IPPROTO_AH; | 1208 | ((u_int8_t *) (tc + 1))[protoff] = IPPROTO_AH; | |
1216 | 1209 | |||
1217 | /* Update the Next Protocol field in the IP header. */ | 1210 | /* Update the Next Protocol field in the IP header. */ | |
1218 | prot = IPPROTO_AH; | 1211 | prot = IPPROTO_AH; | |
1219 | m_copyback(m, protoff, sizeof(u_int8_t), &prot); | 1212 | m_copyback(m, protoff, sizeof(u_int8_t), &prot); | |
1220 | 1213 | |||
1221 | /* "Massage" the packet headers for crypto processing. */ | 1214 | /* "Massage" the packet headers for crypto processing. */ | |
1222 | error = ah_massage_headers(&m, sav->sah->saidx.dst.sa.sa_family, | 1215 | error = ah_massage_headers(&m, sav->sah->saidx.dst.sa.sa_family, | |
1223 | skip, ahx->type, 1); | 1216 | skip, ahx->type, 1); | |
1224 | if (error != 0) { | 1217 | if (error != 0) { | |
1225 | m = NULL; /* mbuf was free'd by ah_massage_headers. */ | 1218 | m = NULL; /* mbuf was free'd by ah_massage_headers. */ | |
1226 | free(tc, M_XDATA); | 1219 | free(tc, M_XDATA); | |
1227 | crypto_freereq(crp); | 1220 | crypto_freereq(crp); | |
1228 | goto bad; | 1221 | goto bad; | |
1229 | } | 1222 | } | |
1230 | 1223 | |||
1231 | /* Crypto operation descriptor. */ | 1224 | /* Crypto operation descriptor. */ | |
1232 | crp->crp_ilen = m->m_pkthdr.len; /* Total input length. */ | 1225 | crp->crp_ilen = m->m_pkthdr.len; /* Total input length. */ | |
1233 | crp->crp_flags = CRYPTO_F_IMBUF; | 1226 | crp->crp_flags = CRYPTO_F_IMBUF; | |
1234 | crp->crp_buf = m; | 1227 | crp->crp_buf = m; | |
1235 | crp->crp_callback = ah_output_cb; | 1228 | crp->crp_callback = ah_output_cb; | |
1236 | crp->crp_sid = sav->tdb_cryptoid; | 1229 | crp->crp_sid = sav->tdb_cryptoid; | |
1237 | crp->crp_opaque = tc; | 1230 | crp->crp_opaque = tc; | |
1238 | 1231 | |||
1239 | /* These are passed as-is to the callback. */ | 1232 | /* These are passed as-is to the callback. */ | |
1240 | tc->tc_isr = isr; | 1233 | tc->tc_isr = isr; | |
1241 | tc->tc_spi = sav->spi; | 1234 | tc->tc_spi = sav->spi; | |
1242 | tc->tc_dst = sav->sah->saidx.dst; | 1235 | tc->tc_dst = sav->sah->saidx.dst; | |
1243 | tc->tc_proto = sav->sah->saidx.proto; | 1236 | tc->tc_proto = sav->sah->saidx.proto; | |
1244 | tc->tc_skip = skip; | 1237 | tc->tc_skip = skip; | |
1245 | tc->tc_protoff = protoff; | 1238 | tc->tc_protoff = protoff; | |
1246 | 1239 | |||
1247 | return crypto_dispatch(crp); | 1240 | return crypto_dispatch(crp); | |
1248 | bad: | 1241 | bad: | |
1249 | if (m) | 1242 | if (m) | |
1250 | m_freem(m); | 1243 | m_freem(m); | |
1251 | return (error); | 1244 | return (error); | |
1252 | } | 1245 | } | |
1253 | 1246 | |||
1254 | /* | 1247 | /* | |
1255 | * AH output callback from the crypto driver. | 1248 | * AH output callback from the crypto driver. | |
1256 | */ | 1249 | */ | |
1257 | static int | 1250 | static int | |
1258 | ah_output_cb(struct cryptop *crp) | 1251 | ah_output_cb(struct cryptop *crp) | |
1259 | { | 1252 | { | |
1260 | int skip, protoff, error; | 1253 | int skip, protoff, error; | |
1261 | struct tdb_crypto *tc; | 1254 | struct tdb_crypto *tc; | |
1262 | struct ipsecrequest *isr; | 1255 | struct ipsecrequest *isr; | |
1263 | struct secasvar *sav; | 1256 | struct secasvar *sav; | |
1264 | struct mbuf *m; | 1257 | struct mbuf *m; | |
1265 | void *ptr; | 1258 | void *ptr; | |
1266 | int s, err; | 1259 | int s, err; | |
1267 | 1260 | |||
1268 | tc = (struct tdb_crypto *) crp->crp_opaque; | 1261 | tc = (struct tdb_crypto *) crp->crp_opaque; | |
1269 | IPSEC_ASSERT(tc != NULL, ("ah_output_cb: null opaque data area!")); | 1262 | IPSEC_ASSERT(tc != NULL, ("ah_output_cb: null opaque data area!")); | |
1270 | skip = tc->tc_skip; | 1263 | skip = tc->tc_skip; | |
1271 | protoff = tc->tc_protoff; | 1264 | protoff = tc->tc_protoff; | |
1272 | ptr = (tc + 1); | 1265 | ptr = (tc + 1); | |
1273 | m = (struct mbuf *) crp->crp_buf; | 1266 | m = (struct mbuf *) crp->crp_buf; | |
1274 | 1267 | |||
1275 | s = splsoftnet(); | 1268 | s = splsoftnet(); | |
1276 | mutex_enter(softnet_lock); | 1269 | mutex_enter(softnet_lock); | |
1277 | 1270 | |||
1278 | isr = tc->tc_isr; | 1271 | isr = tc->tc_isr; | |
1279 | sav = KEY_ALLOCSA(&tc->tc_dst, tc->tc_proto, tc->tc_spi, 0, 0); | 1272 | sav = KEY_ALLOCSA(&tc->tc_dst, tc->tc_proto, tc->tc_spi, 0, 0); | |
1280 | if (sav == NULL) { | 1273 | if (sav == NULL) { | |
1281 | AH_STATINC(AH_STAT_NOTDB); | 1274 | AH_STATINC(AH_STAT_NOTDB); | |
1282 | DPRINTF(("ah_output_cb: SA expired while in crypto\n")); | 1275 | DPRINTF(("ah_output_cb: SA expired while in crypto\n")); | |
1283 | error = ENOBUFS; /*XXX*/ | 1276 | error = ENOBUFS; /*XXX*/ | |
1284 | goto bad; | 1277 | goto bad; | |
1285 | } | 1278 | } | |
1286 | IPSEC_ASSERT(isr->sav == sav, ("ah_output_cb: SA changed\n")); | 1279 | IPSEC_ASSERT(isr->sav == sav, ("ah_output_cb: SA changed\n")); | |
1287 | 1280 | |||
1288 | /* Check for crypto errors. */ | 1281 | /* Check for crypto errors. */ | |
1289 | if (crp->crp_etype) { | 1282 | if (crp->crp_etype) { | |
1290 | if (sav->tdb_cryptoid != 0) | 1283 | if (sav->tdb_cryptoid != 0) | |
1291 | sav->tdb_cryptoid = crp->crp_sid; | 1284 | sav->tdb_cryptoid = crp->crp_sid; | |
1292 | 1285 | |||
1293 | if (crp->crp_etype == EAGAIN) { | 1286 | if (crp->crp_etype == EAGAIN) { | |
1294 | KEY_FREESAV(&sav); | 1287 | KEY_FREESAV(&sav); | |
1295 | mutex_exit(softnet_lock); | 1288 | mutex_exit(softnet_lock); | |
1296 | splx(s); | 1289 | splx(s); | |
1297 | return crypto_dispatch(crp); | 1290 | return crypto_dispatch(crp); | |
1298 | } | 1291 | } | |
1299 | 1292 | |||
1300 | AH_STATINC(AH_STAT_NOXFORM); | 1293 | AH_STATINC(AH_STAT_NOXFORM); | |
1301 | DPRINTF(("ah_output_cb: crypto error %d\n", crp->crp_etype)); | 1294 | DPRINTF(("ah_output_cb: crypto error %d\n", crp->crp_etype)); | |
1302 | error = crp->crp_etype; | 1295 | error = crp->crp_etype; | |
1303 | goto bad; | 1296 | goto bad; | |
1304 | } | 1297 | } | |
1305 | 1298 | |||
1306 | /* Shouldn't happen... */ | 1299 | /* Shouldn't happen... */ | |
1307 | if (m == NULL) { | 1300 | if (m == NULL) { | |
1308 | AH_STATINC(AH_STAT_CRYPTO); | 1301 | AH_STATINC(AH_STAT_CRYPTO); | |
1309 | DPRINTF(("ah_output_cb: bogus returned buffer from crypto\n")); | 1302 | DPRINTF(("ah_output_cb: bogus returned buffer from crypto\n")); | |
1310 | error = EINVAL; | 1303 | error = EINVAL; | |
1311 | goto bad; | 1304 | goto bad; | |
1312 | } | 1305 | } | |
1313 | AH_STATINC(AH_STAT_HIST + sav->alg_auth); | 1306 | AH_STATINC(AH_STAT_HIST + sav->alg_auth); | |
1314 | 1307 | |||
1315 | /* | 1308 | /* | |
1316 | * Copy original headers (with the new protocol number) back | 1309 | * Copy original headers (with the new protocol number) back | |
1317 | * in place. | 1310 | * in place. | |
1318 | */ | 1311 | */ | |
1319 | m_copyback(m, 0, skip, ptr); | 1312 | m_copyback(m, 0, skip, ptr); | |
1320 | 1313 | |||
1321 | /* No longer needed. */ | 1314 | /* No longer needed. */ | |
1322 | free(tc, M_XDATA); | 1315 | free(tc, M_XDATA); | |
1323 | crypto_freereq(crp); | 1316 | crypto_freereq(crp); | |
1324 | 1317 | |||
1325 | #ifdef IPSEC_DEBUG | 1318 | #ifdef IPSEC_DEBUG | |
1326 | /* Emulate man-in-the-middle attack when ipsec_integrity is TRUE. */ | 1319 | /* Emulate man-in-the-middle attack when ipsec_integrity is TRUE. */ | |
1327 | if (ipsec_integrity) { | 1320 | if (ipsec_integrity) { | |
1328 | int alen; | 1321 | int alen; | |
1329 | 1322 | |||
1330 | /* | 1323 | /* | |
1331 | * Corrupt HMAC if we want to test integrity verification of | 1324 | * Corrupt HMAC if we want to test integrity verification of | |
1332 | * the other side. | 1325 | * the other side. | |
1333 | */ | 1326 | */ | |
1334 | alen = AUTHSIZE(sav); | 1327 | alen = AUTHSIZE(sav); | |
1335 | m_copyback(m, m->m_pkthdr.len - alen, alen, ipseczeroes); | 1328 | m_copyback(m, m->m_pkthdr.len - alen, alen, ipseczeroes); | |
1336 | } | 1329 | } | |
1337 | #endif | 1330 | #endif | |
1338 | 1331 | |||
1339 | /* NB: m is reclaimed by ipsec_process_done. */ | 1332 | /* NB: m is reclaimed by ipsec_process_done. */ | |
1340 | err = ipsec_process_done(m, isr); | 1333 | err = ipsec_process_done(m, isr); | |
1341 | KEY_FREESAV(&sav); | 1334 | KEY_FREESAV(&sav); | |
1342 | mutex_exit(softnet_lock); | 1335 | mutex_exit(softnet_lock); | |
1343 | splx(s); | 1336 | splx(s); | |
1344 | return err; | 1337 | return err; | |
1345 | bad: | 1338 | bad: | |
1346 | if (sav) | 1339 | if (sav) | |
1347 | KEY_FREESAV(&sav); | 1340 | KEY_FREESAV(&sav); | |
1348 | mutex_exit(softnet_lock); | 1341 | mutex_exit(softnet_lock); | |
1349 | splx(s); | 1342 | splx(s); | |
1350 | if (m) | 1343 | if (m) | |
1351 | m_freem(m); | 1344 | m_freem(m); | |
1352 | free(tc, M_XDATA); | 1345 | free(tc, M_XDATA); | |
1353 | crypto_freereq(crp); | 1346 | crypto_freereq(crp); | |
1354 | return error; | 1347 | return error; | |
1355 | } | 1348 | } | |
1356 | 1349 | |||
1357 | static struct xformsw ah_xformsw = { | 1350 | static struct xformsw ah_xformsw = { | |
1358 | XF_AH, XFT_AUTH, "IPsec AH", | 1351 | XF_AH, XFT_AUTH, "IPsec AH", | |
1359 | ah_init, ah_zeroize, ah_input, ah_output, | 1352 | ah_init, ah_zeroize, ah_input, ah_output, | |
1360 | NULL, | 1353 | NULL, | |
1361 | }; | 1354 | }; | |
1362 | 1355 | |||
1363 | INITFN void | 1356 | INITFN void | |
1364 | ah_attach(void) | 1357 | ah_attach(void) | |
1365 | { | 1358 | { | |
1366 | ahstat_percpu = percpu_alloc(sizeof(uint64_t) * AH_NSTATS); | 1359 | ahstat_percpu = percpu_alloc(sizeof(uint64_t) * AH_NSTATS); | |
1367 | xform_register(&ah_xformsw); | 1360 | xform_register(&ah_xformsw); | |
1368 | } | 1361 | } | |
1369 | 1362 | |||
1370 | #ifdef __FreeBSD__ | 1363 | #ifdef __FreeBSD__ | |
1371 | SYSINIT(ah_xform_init, SI_SUB_PROTO_DOMAIN, SI_ORDER_MIDDLE, ah_attach, NULL); | 1364 | SYSINIT(ah_xform_init, SI_SUB_PROTO_DOMAIN, SI_ORDER_MIDDLE, ah_attach, NULL); | |
1372 | #endif | 1365 | #endif |
--- src/sys/netipsec/xform_esp.c 2012/01/25 20:31:23 1.40
+++ src/sys/netipsec/xform_esp.c 2018/03/13 17:18:12 1.40.6.1
@@ -1,1103 +1,1107 @@ | @@ -1,1103 +1,1107 @@ | |||
1 | /* $NetBSD: xform_esp.c,v 1.40 2012/01/25 20:31:23 drochner Exp $ */ | 1 | /* $NetBSD: xform_esp.c,v 1.40.6.1 2018/03/13 17:18:12 snj Exp $ */ | |
2 | /* $FreeBSD: src/sys/netipsec/xform_esp.c,v 1.2.2.1 2003/01/24 05:11:36 sam Exp $ */ | 2 | /* $FreeBSD: src/sys/netipsec/xform_esp.c,v 1.2.2.1 2003/01/24 05:11:36 sam Exp $ */ | |
3 | /* $OpenBSD: ip_esp.c,v 1.69 2001/06/26 06:18:59 angelos Exp $ */ | 3 | /* $OpenBSD: ip_esp.c,v 1.69 2001/06/26 06:18:59 angelos Exp $ */ | |
4 | 4 | |||
5 | /* | 5 | /* | |
6 | * The authors of this code are John Ioannidis (ji@tla.org), | 6 | * The authors of this code are John Ioannidis (ji@tla.org), | |
7 | * Angelos D. Keromytis (kermit@csd.uch.gr) and | 7 | * Angelos D. Keromytis (kermit@csd.uch.gr) and | |
8 | * Niels Provos (provos@physnet.uni-hamburg.de). | 8 | * Niels Provos (provos@physnet.uni-hamburg.de). | |
9 | * | 9 | * | |
10 | * The original version of this code was written by John Ioannidis | 10 | * The original version of this code was written by John Ioannidis | |
11 | * for BSD/OS in Athens, Greece, in November 1995. | 11 | * for BSD/OS in Athens, Greece, in November 1995. | |
12 | * | 12 | * | |
13 | * Ported to OpenBSD and NetBSD, with additional transforms, in December 1996, | 13 | * Ported to OpenBSD and NetBSD, with additional transforms, in December 1996, | |
14 | * by Angelos D. Keromytis. | 14 | * by Angelos D. Keromytis. | |
15 | * | 15 | * | |
16 | * Additional transforms and features in 1997 and 1998 by Angelos D. Keromytis | 16 | * Additional transforms and features in 1997 and 1998 by Angelos D. Keromytis | |
17 | * and Niels Provos. | 17 | * and Niels Provos. | |
18 | * | 18 | * | |
19 | * Additional features in 1999 by Angelos D. Keromytis. | 19 | * Additional features in 1999 by Angelos D. Keromytis. | |
20 | * | 20 | * | |
21 | * Copyright (C) 1995, 1996, 1997, 1998, 1999 by John Ioannidis, | 21 | * Copyright (C) 1995, 1996, 1997, 1998, 1999 by John Ioannidis, | |
22 | * Angelos D. Keromytis and Niels Provos. | 22 | * Angelos D. Keromytis and Niels Provos. | |
23 | * Copyright (c) 2001 Angelos D. Keromytis. | 23 | * Copyright (c) 2001 Angelos D. Keromytis. | |
24 | * | 24 | * | |
25 | * Permission to use, copy, and modify this software with or without fee | 25 | * Permission to use, copy, and modify this software with or without fee | |
26 | * is hereby granted, provided that this entire notice is included in | 26 | * is hereby granted, provided that this entire notice is included in | |
27 | * all copies of any software which is or includes a copy or | 27 | * all copies of any software which is or includes a copy or | |
28 | * modification of this software. | 28 | * modification of this software. | |
29 | * You may use this code under the GNU public license if you so wish. Please | 29 | * You may use this code under the GNU public license if you so wish. Please | |
30 | * contribute changes back to the authors under this freer than GPL license | 30 | * contribute changes back to the authors under this freer than GPL license | |
31 | * so that we may further the use of strong encryption without limitations to | 31 | * so that we may further the use of strong encryption without limitations to | |
32 | * all. | 32 | * all. | |
33 | * | 33 | * | |
34 | * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR | 34 | * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR | |
35 | * IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY | 35 | * IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY | |
36 | * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE | 36 | * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE | |
37 | * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR | 37 | * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR | |
38 | * PURPOSE. | 38 | * PURPOSE. | |
39 | */ | 39 | */ | |
40 | 40 | |||
41 | #include <sys/cdefs.h> | 41 | #include <sys/cdefs.h> | |
42 | __KERNEL_RCSID(0, "$NetBSD: xform_esp.c,v 1.40 2012/01/25 20:31:23 drochner Exp $"); | 42 | __KERNEL_RCSID(0, "$NetBSD: xform_esp.c,v 1.40.6.1 2018/03/13 17:18:12 snj Exp $"); | |
43 | 43 | |||
44 | #include "opt_inet.h" | 44 | #include "opt_inet.h" | |
45 | #ifdef __FreeBSD__ | 45 | #ifdef __FreeBSD__ | |
46 | #include "opt_inet6.h" | 46 | #include "opt_inet6.h" | |
47 | #endif | 47 | #endif | |
48 | 48 | |||
49 | #include <sys/param.h> | 49 | #include <sys/param.h> | |
50 | #include <sys/systm.h> | 50 | #include <sys/systm.h> | |
51 | #include <sys/mbuf.h> | 51 | #include <sys/mbuf.h> | |
52 | #include <sys/socket.h> | 52 | #include <sys/socket.h> | |
53 | #include <sys/syslog.h> | 53 | #include <sys/syslog.h> | |
54 | #include <sys/kernel.h> | 54 | #include <sys/kernel.h> | |
55 | /*#include <sys/random.h>*/ | 55 | /*#include <sys/random.h>*/ | |
56 | #include <sys/sysctl.h> | 56 | #include <sys/sysctl.h> | |
57 | #include <sys/socketvar.h> /* for softnet_lock */ | 57 | #include <sys/socketvar.h> /* for softnet_lock */ | |
58 | 58 | |||
59 | #include <net/if.h> | 59 | #include <net/if.h> | |
60 | 60 | |||
61 | #include <netinet/in.h> | 61 | #include <netinet/in.h> | |
62 | #include <netinet/in_systm.h> | 62 | #include <netinet/in_systm.h> | |
63 | #include <netinet/ip.h> | 63 | #include <netinet/ip.h> | |
64 | #include <netinet/ip_ecn.h> | 64 | #include <netinet/ip_ecn.h> | |
65 | #include <netinet/ip6.h> | 65 | #include <netinet/ip6.h> | |
66 | 66 | |||
67 | #include <net/route.h> | 67 | #include <net/route.h> | |
68 | #include <netipsec/ipsec.h> | 68 | #include <netipsec/ipsec.h> | |
69 | #include <netipsec/ipsec_private.h> | 69 | #include <netipsec/ipsec_private.h> | |
70 | #include <netipsec/ah.h> | 70 | #include <netipsec/ah.h> | |
71 | #include <netipsec/ah_var.h> | 71 | #include <netipsec/ah_var.h> | |
72 | #include <netipsec/esp.h> | 72 | #include <netipsec/esp.h> | |
73 | #include <netipsec/esp_var.h> | 73 | #include <netipsec/esp_var.h> | |
74 | #include <netipsec/xform.h> | 74 | #include <netipsec/xform.h> | |
75 | 75 | |||
76 | #ifdef INET6 | 76 | #ifdef INET6 | |
77 | #include <netinet6/ip6_var.h> | 77 | #include <netinet6/ip6_var.h> | |
78 | #include <netipsec/ipsec6.h> | 78 | #include <netipsec/ipsec6.h> | |
79 | # ifdef __FreeBSD__ | 79 | # ifdef __FreeBSD__ | |
80 | # include <netinet6/ip6_ecn.h> | 80 | # include <netinet6/ip6_ecn.h> | |
81 | # endif | 81 | # endif | |
82 | #endif | 82 | #endif | |
83 | 83 | |||
84 | #include <netipsec/key.h> | 84 | #include <netipsec/key.h> | |
85 | #include <netipsec/key_debug.h> | 85 | #include <netipsec/key_debug.h> | |
86 | 86 | |||
87 | #include <netipsec/ipsec_osdep.h> | 87 | #include <netipsec/ipsec_osdep.h> | |
88 | 88 | |||
89 | #include <opencrypto/cryptodev.h> | 89 | #include <opencrypto/cryptodev.h> | |
90 | #include <opencrypto/xform.h> | 90 | #include <opencrypto/xform.h> | |
91 | 91 | |||
92 | percpu_t *espstat_percpu; | 92 | percpu_t *espstat_percpu; | |
93 | 93 | |||
94 | int esp_enable = 1; | 94 | int esp_enable = 1; | |
95 | 95 | |||
96 | #ifdef __FreeBSD__ | 96 | #ifdef __FreeBSD__ | |
97 | SYSCTL_DECL(_net_inet_esp); | 97 | SYSCTL_DECL(_net_inet_esp); | |
98 | SYSCTL_INT(_net_inet_esp, OID_AUTO, | 98 | SYSCTL_INT(_net_inet_esp, OID_AUTO, | |
99 | esp_enable, CTLFLAG_RW, &esp_enable, 0, ""); | 99 | esp_enable, CTLFLAG_RW, &esp_enable, 0, ""); | |
100 | SYSCTL_STRUCT(_net_inet_esp, IPSECCTL_STATS, | 100 | SYSCTL_STRUCT(_net_inet_esp, IPSECCTL_STATS, | |
101 | stats, CTLFLAG_RD, &espstat, espstat, ""); | 101 | stats, CTLFLAG_RD, &espstat, espstat, ""); | |
102 | #endif /* __FreeBSD__ */ | 102 | #endif /* __FreeBSD__ */ | |
103 | 103 | |||
104 | static int esp_max_ivlen; /* max iv length over all algorithms */ | 104 | static int esp_max_ivlen; /* max iv length over all algorithms */ | |
105 | 105 | |||
106 | static int esp_input_cb(struct cryptop *op); | 106 | static int esp_input_cb(struct cryptop *op); | |
107 | static int esp_output_cb(struct cryptop *crp); | 107 | static int esp_output_cb(struct cryptop *crp); | |
108 | 108 | |||
109 | /* | 109 | /* | |
110 | * NB: this is public for use by the PF_KEY support. | 110 | * NB: this is public for use by the PF_KEY support. | |
111 | * NB: if you add support here; be sure to add code to esp_attach below! | 111 | * NB: if you add support here; be sure to add code to esp_attach below! | |
112 | */ | 112 | */ | |
113 | const struct enc_xform * | 113 | const struct enc_xform * | |
114 | esp_algorithm_lookup(int alg) | 114 | esp_algorithm_lookup(int alg) | |
115 | { | 115 | { | |
116 | if (alg >= ESP_ALG_MAX) | 116 | if (alg >= ESP_ALG_MAX) | |
117 | return NULL; | 117 | return NULL; | |
118 | switch (alg) { | 118 | switch (alg) { | |
119 | case SADB_EALG_DESCBC: | 119 | case SADB_EALG_DESCBC: | |
120 | return &enc_xform_des; | 120 | return &enc_xform_des; | |
121 | case SADB_EALG_3DESCBC: | 121 | case SADB_EALG_3DESCBC: | |
122 | return &enc_xform_3des; | 122 | return &enc_xform_3des; | |
123 | case SADB_X_EALG_AES: | 123 | case SADB_X_EALG_AES: | |
124 | return &enc_xform_rijndael128; | 124 | return &enc_xform_rijndael128; | |
125 | case SADB_X_EALG_BLOWFISHCBC: | 125 | case SADB_X_EALG_BLOWFISHCBC: | |
126 | return &enc_xform_blf; | 126 | return &enc_xform_blf; | |
127 | case SADB_X_EALG_CAST128CBC: | 127 | case SADB_X_EALG_CAST128CBC: | |
128 | return &enc_xform_cast5; | 128 | return &enc_xform_cast5; | |
129 | case SADB_X_EALG_SKIPJACK: | 129 | case SADB_X_EALG_SKIPJACK: | |
130 | return &enc_xform_skipjack; | 130 | return &enc_xform_skipjack; | |
131 | case SADB_X_EALG_CAMELLIACBC: | 131 | case SADB_X_EALG_CAMELLIACBC: | |
132 | return &enc_xform_camellia; | 132 | return &enc_xform_camellia; | |
133 | case SADB_X_EALG_AESCTR: | 133 | case SADB_X_EALG_AESCTR: | |
134 | return &enc_xform_aes_ctr; | 134 | return &enc_xform_aes_ctr; | |
135 | case SADB_X_EALG_AESGCM16: | 135 | case SADB_X_EALG_AESGCM16: | |
136 | return &enc_xform_aes_gcm; | 136 | return &enc_xform_aes_gcm; | |
137 | case SADB_X_EALG_AESGMAC: | 137 | case SADB_X_EALG_AESGMAC: | |
138 | return &enc_xform_aes_gmac; | 138 | return &enc_xform_aes_gmac; | |
139 | case SADB_EALG_NULL: | 139 | case SADB_EALG_NULL: | |
140 | return &enc_xform_null; | 140 | return &enc_xform_null; | |
141 | } | 141 | } | |
142 | return NULL; | 142 | return NULL; | |
143 | } | 143 | } | |
144 | 144 | |||
145 | size_t | 145 | size_t | |
146 | esp_hdrsiz(const struct secasvar *sav) | 146 | esp_hdrsiz(const struct secasvar *sav) | |
147 | { | 147 | { | |
148 | size_t size; | 148 | size_t size; | |
149 | 149 | |||
150 | if (sav != NULL) { | 150 | if (sav != NULL) { | |
151 | /*XXX not right for null algorithm--does it matter??*/ | 151 | /*XXX not right for null algorithm--does it matter??*/ | |
152 | IPSEC_ASSERT(sav->tdb_encalgxform != NULL, | 152 | IPSEC_ASSERT(sav->tdb_encalgxform != NULL, | |
153 | ("esp_hdrsiz: SA with null xform")); | 153 | ("esp_hdrsiz: SA with null xform")); | |
154 | if (sav->flags & SADB_X_EXT_OLD) | 154 | if (sav->flags & SADB_X_EXT_OLD) | |
155 | size = sizeof (struct esp); | 155 | size = sizeof (struct esp); | |
156 | else | 156 | else | |
157 | size = sizeof (struct newesp); | 157 | size = sizeof (struct newesp); | |
158 | size += sav->tdb_encalgxform->ivsize + 9; | 158 | size += sav->tdb_encalgxform->ivsize + 9; | |
159 | /*XXX need alg check???*/ | 159 | /*XXX need alg check???*/ | |
160 | if (sav->tdb_authalgxform != NULL && sav->replay) | 160 | if (sav->tdb_authalgxform != NULL && sav->replay) | |
161 | size += ah_hdrsiz(sav); | 161 | size += ah_hdrsiz(sav); | |
162 | } else { | 162 | } else { | |
163 | /* | 163 | /* | |
164 | * base header size | 164 | * base header size | |
165 | * + max iv length for CBC mode | 165 | * + max iv length for CBC mode | |
166 | * + max pad length | 166 | * + max pad length | |
167 | * + sizeof (pad length field) | 167 | * + sizeof (pad length field) | |
168 | * + sizeof (next header field) | 168 | * + sizeof (next header field) | |
169 | * + max icv supported. | 169 | * + max icv supported. | |
170 | */ | 170 | */ | |
171 | size = sizeof (struct newesp) + esp_max_ivlen + 9 + 16; | 171 | size = sizeof (struct newesp) + esp_max_ivlen + 9 + 16; | |
172 | } | 172 | } | |
173 | return size; | 173 | return size; | |
174 | } | 174 | } | |
175 | 175 | |||
176 | /* | 176 | /* | |
177 | * esp_init() is called when an SPI is being set up. | 177 | * esp_init() is called when an SPI is being set up. | |
178 | */ | 178 | */ | |
179 | static int | 179 | static int | |
180 | esp_init(struct secasvar *sav, const struct xformsw *xsp) | 180 | esp_init(struct secasvar *sav, const struct xformsw *xsp) | |
181 | { | 181 | { | |
182 | const struct enc_xform *txform; | 182 | const struct enc_xform *txform; | |
183 | struct cryptoini cria, crie; | 183 | struct cryptoini cria, crie; | |
184 | int keylen; | 184 | int keylen; | |
185 | int error; | 185 | int error; | |
186 | 186 | |||
187 | txform = esp_algorithm_lookup(sav->alg_enc); | 187 | txform = esp_algorithm_lookup(sav->alg_enc); | |
188 | if (txform == NULL) { | 188 | if (txform == NULL) { | |
189 | DPRINTF(("esp_init: unsupported encryption algorithm %d\n", | 189 | DPRINTF(("esp_init: unsupported encryption algorithm %d\n", | |
190 | sav->alg_enc)); | 190 | sav->alg_enc)); | |
191 | return EINVAL; | 191 | return EINVAL; | |
192 | } | 192 | } | |
193 | if (sav->key_enc == NULL) { | 193 | if (sav->key_enc == NULL) { | |
194 | DPRINTF(("esp_init: no encoding key for %s algorithm\n", | 194 | DPRINTF(("esp_init: no encoding key for %s algorithm\n", | |
195 | txform->name)); | 195 | txform->name)); | |
196 | return EINVAL; | 196 | return EINVAL; | |
197 | } | 197 | } | |
198 | if ((sav->flags&(SADB_X_EXT_OLD|SADB_X_EXT_IV4B)) == SADB_X_EXT_IV4B) { | 198 | if ((sav->flags&(SADB_X_EXT_OLD|SADB_X_EXT_IV4B)) == SADB_X_EXT_IV4B) { | |
199 | DPRINTF(("esp_init: 4-byte IV not supported with protocol\n")); | 199 | DPRINTF(("esp_init: 4-byte IV not supported with protocol\n")); | |
200 | return EINVAL; | 200 | return EINVAL; | |
201 | } | 201 | } | |
202 | keylen = _KEYLEN(sav->key_enc); | 202 | keylen = _KEYLEN(sav->key_enc); | |
203 | if (txform->minkey > keylen || keylen > txform->maxkey) { | 203 | if (txform->minkey > keylen || keylen > txform->maxkey) { | |
204 | DPRINTF(("esp_init: invalid key length %u, must be in " | 204 | DPRINTF(("esp_init: invalid key length %u, must be in " | |
205 | "the range [%u..%u] for algorithm %s\n", | 205 | "the range [%u..%u] for algorithm %s\n", | |
206 | keylen, txform->minkey, txform->maxkey, | 206 | keylen, txform->minkey, txform->maxkey, | |
207 | txform->name)); | 207 | txform->name)); | |
208 | return EINVAL; | 208 | return EINVAL; | |
209 | } | 209 | } | |
210 | 210 | |||
211 | sav->ivlen = txform->ivsize; | 211 | sav->ivlen = txform->ivsize; | |
212 | 212 | |||
213 | /* | 213 | /* | |
214 | * Setup AH-related state. | 214 | * Setup AH-related state. | |
215 | */ | 215 | */ | |
216 | if (sav->alg_auth != 0) { | 216 | if (sav->alg_auth != 0) { | |
217 | error = ah_init0(sav, xsp, &cria); | 217 | error = ah_init0(sav, xsp, &cria); | |
218 | if (error) | 218 | if (error) | |
219 | return error; | 219 | return error; | |
220 | } | 220 | } | |
221 | 221 | |||
222 | /* NB: override anything set in ah_init0 */ | 222 | /* NB: override anything set in ah_init0 */ | |
223 | sav->tdb_xform = xsp; | 223 | sav->tdb_xform = xsp; | |
224 | sav->tdb_encalgxform = txform; | 224 | sav->tdb_encalgxform = txform; | |
225 | 225 | |||
226 | if (sav->alg_enc == SADB_X_EALG_AESGCM16 || | 226 | if (sav->alg_enc == SADB_X_EALG_AESGCM16 || | |
227 | sav->alg_enc == SADB_X_EALG_AESGMAC) { | 227 | sav->alg_enc == SADB_X_EALG_AESGMAC) { | |
228 | switch (keylen) { | 228 | switch (keylen) { | |
229 | case 20: | 229 | case 20: | |
230 | sav->alg_auth = SADB_X_AALG_AES128GMAC; | 230 | sav->alg_auth = SADB_X_AALG_AES128GMAC; | |
231 | sav->tdb_authalgxform = &auth_hash_gmac_aes_128; | 231 | sav->tdb_authalgxform = &auth_hash_gmac_aes_128; | |
232 | break; | 232 | break; | |
233 | case 28: | 233 | case 28: | |
234 | sav->alg_auth = SADB_X_AALG_AES192GMAC; | 234 | sav->alg_auth = SADB_X_AALG_AES192GMAC; | |
235 | sav->tdb_authalgxform = &auth_hash_gmac_aes_192; | 235 | sav->tdb_authalgxform = &auth_hash_gmac_aes_192; | |
236 | break; | 236 | break; | |
237 | case 36: | 237 | case 36: | |
238 | sav->alg_auth = SADB_X_AALG_AES256GMAC; | 238 | sav->alg_auth = SADB_X_AALG_AES256GMAC; | |
239 | sav->tdb_authalgxform = &auth_hash_gmac_aes_256; | 239 | sav->tdb_authalgxform = &auth_hash_gmac_aes_256; | |
240 | break; | 240 | break; | |
241 | } | 241 | } | |
242 | memset(&cria, 0, sizeof(cria)); | 242 | memset(&cria, 0, sizeof(cria)); | |
243 | cria.cri_alg = sav->tdb_authalgxform->type; | 243 | cria.cri_alg = sav->tdb_authalgxform->type; | |
244 | cria.cri_klen = _KEYBITS(sav->key_enc); | 244 | cria.cri_klen = _KEYBITS(sav->key_enc); | |
245 | cria.cri_key = _KEYBUF(sav->key_enc); | 245 | cria.cri_key = _KEYBUF(sav->key_enc); | |
246 | } | 246 | } | |
247 | 247 | |||
248 | /* Initialize crypto session. */ | 248 | /* Initialize crypto session. */ | |
249 | memset(&crie, 0, sizeof (crie)); | 249 | memset(&crie, 0, sizeof (crie)); | |
250 | crie.cri_alg = sav->tdb_encalgxform->type; | 250 | crie.cri_alg = sav->tdb_encalgxform->type; | |
251 | crie.cri_klen = _KEYBITS(sav->key_enc); | 251 | crie.cri_klen = _KEYBITS(sav->key_enc); | |
252 | crie.cri_key = _KEYBUF(sav->key_enc); | 252 | crie.cri_key = _KEYBUF(sav->key_enc); | |
253 | /* XXX Rounds ? */ | 253 | /* XXX Rounds ? */ | |
254 | 254 | |||
255 | if (sav->tdb_authalgxform && sav->tdb_encalgxform) { | 255 | if (sav->tdb_authalgxform && sav->tdb_encalgxform) { | |
256 | /* init both auth & enc */ | 256 | /* init both auth & enc */ | |
257 | crie.cri_next = &cria; | 257 | crie.cri_next = &cria; | |
258 | error = crypto_newsession(&sav->tdb_cryptoid, | 258 | error = crypto_newsession(&sav->tdb_cryptoid, | |
259 | &crie, crypto_support); | 259 | &crie, crypto_support); | |
260 | } else if (sav->tdb_encalgxform) { | 260 | } else if (sav->tdb_encalgxform) { | |
261 | error = crypto_newsession(&sav->tdb_cryptoid, | 261 | error = crypto_newsession(&sav->tdb_cryptoid, | |
262 | &crie, crypto_support); | 262 | &crie, crypto_support); | |
263 | } else if (sav->tdb_authalgxform) { | 263 | } else if (sav->tdb_authalgxform) { | |
264 | error = crypto_newsession(&sav->tdb_cryptoid, | 264 | error = crypto_newsession(&sav->tdb_cryptoid, | |
265 | &cria, crypto_support); | 265 | &cria, crypto_support); | |
266 | } else { | 266 | } else { | |
267 | /* XXX cannot happen? */ | 267 | /* XXX cannot happen? */ | |
268 | DPRINTF(("esp_init: no encoding OR authentication xform!\n")); | 268 | DPRINTF(("esp_init: no encoding OR authentication xform!\n")); | |
269 | error = EINVAL; | 269 | error = EINVAL; | |
270 | } | 270 | } | |
271 | return error; | 271 | return error; | |
272 | } | 272 | } | |
273 | 273 | |||
274 | /* | 274 | /* | |
275 | * Paranoia. | 275 | * Paranoia. | |
276 | */ | 276 | */ | |
277 | static int | 277 | static int | |
278 | esp_zeroize(struct secasvar *sav) | 278 | esp_zeroize(struct secasvar *sav) | |
279 | { | 279 | { | |
280 | /* NB: ah_zerorize free's the crypto session state */ | 280 | /* NB: ah_zerorize free's the crypto session state */ | |
281 | int error = ah_zeroize(sav); | 281 | int error = ah_zeroize(sav); | |
282 | 282 | |||
283 | if (sav->key_enc) | 283 | if (sav->key_enc) | |
284 | memset(_KEYBUF(sav->key_enc), 0, _KEYLEN(sav->key_enc)); | 284 | memset(_KEYBUF(sav->key_enc), 0, _KEYLEN(sav->key_enc)); | |
285 | sav->tdb_encalgxform = NULL; | 285 | sav->tdb_encalgxform = NULL; | |
286 | sav->tdb_xform = NULL; | 286 | sav->tdb_xform = NULL; | |
287 | return error; | 287 | return error; | |
288 | } | 288 | } | |
289 | 289 | |||
290 | /* | 290 | /* | |
291 | * ESP input processing, called (eventually) through the protocol switch. | 291 | * ESP input processing, called (eventually) through the protocol switch. | |
292 | */ | 292 | */ | |
293 | static int | 293 | static int | |
294 | esp_input(struct mbuf *m, const struct secasvar *sav, int skip, int protoff) | 294 | esp_input(struct mbuf *m, const struct secasvar *sav, int skip, int protoff) | |
295 | { | 295 | { | |
296 | const struct auth_hash *esph; | 296 | const struct auth_hash *esph; | |
297 | const struct enc_xform *espx; | 297 | const struct enc_xform *espx; | |
298 | struct tdb_ident *tdbi; | 298 | struct tdb_ident *tdbi; | |
299 | struct tdb_crypto *tc; | 299 | struct tdb_crypto *tc; | |
300 | int plen, alen, hlen, error; | 300 | int plen, alen, hlen, error; | |
301 | struct m_tag *mtag; | 301 | struct m_tag *mtag; | |
302 | struct newesp *esp; | 302 | struct newesp *esp; | |
303 | 303 | |||
304 | struct cryptodesc *crde; | 304 | struct cryptodesc *crde; | |
305 | struct cryptop *crp; | 305 | struct cryptop *crp; | |
306 | 306 | |||
307 | IPSEC_SPLASSERT_SOFTNET("esp_input"); | 307 | IPSEC_SPLASSERT_SOFTNET("esp_input"); | |
308 | 308 | |||
309 | IPSEC_ASSERT(sav != NULL, ("esp_input: null SA")); | 309 | IPSEC_ASSERT(sav != NULL, ("esp_input: null SA")); | |
310 | IPSEC_ASSERT(sav->tdb_encalgxform != NULL, | 310 | IPSEC_ASSERT(sav->tdb_encalgxform != NULL, | |
311 | ("esp_input: null encoding xform")); | 311 | ("esp_input: null encoding xform")); | |
312 | IPSEC_ASSERT((skip&3) == 0 && (m->m_pkthdr.len&3) == 0, | 312 | IPSEC_ASSERT((skip&3) == 0 && (m->m_pkthdr.len&3) == 0, | |
313 | ("esp_input: misaligned packet, skip %u pkt len %u", | 313 | ("esp_input: misaligned packet, skip %u pkt len %u", | |
314 | skip, m->m_pkthdr.len)); | 314 | skip, m->m_pkthdr.len)); | |
315 | 315 | |||
316 | /* XXX don't pullup, just copy header */ | 316 | /* XXX don't pullup, just copy header */ | |
317 | IP6_EXTHDR_GET(esp, struct newesp *, m, skip, sizeof (struct newesp)); | 317 | IP6_EXTHDR_GET(esp, struct newesp *, m, skip, sizeof (struct newesp)); | |
318 | if (esp == NULL) { | |||
319 | /* m already freed */ | |||
320 | return EINVAL; | |||
321 | } | |||
318 | 322 | |||
319 | esph = sav->tdb_authalgxform; | 323 | esph = sav->tdb_authalgxform; | |
320 | espx = sav->tdb_encalgxform; | 324 | espx = sav->tdb_encalgxform; | |
321 | 325 | |||
322 | /* Determine the ESP header length */ | 326 | /* Determine the ESP header length */ | |
323 | if (sav->flags & SADB_X_EXT_OLD) | 327 | if (sav->flags & SADB_X_EXT_OLD) | |
324 | hlen = sizeof (struct esp) + sav->ivlen; | 328 | hlen = sizeof (struct esp) + sav->ivlen; | |
325 | else | 329 | else | |
326 | hlen = sizeof (struct newesp) + sav->ivlen; | 330 | hlen = sizeof (struct newesp) + sav->ivlen; | |
327 | /* Authenticator hash size */ | 331 | /* Authenticator hash size */ | |
328 | alen = esph ? esph->authsize : 0; | 332 | alen = esph ? esph->authsize : 0; | |
329 | 333 | |||
330 | /* | 334 | /* | |
331 | * Verify payload length is multiple of encryption algorithm | 335 | * Verify payload length is multiple of encryption algorithm | |
332 | * block size. | 336 | * block size. | |
333 | * | 337 | * | |
334 | * NB: This works for the null algorithm because the blocksize | 338 | * NB: This works for the null algorithm because the blocksize | |
335 | * is 4 and all packets must be 4-byte aligned regardless | 339 | * is 4 and all packets must be 4-byte aligned regardless | |
336 | * of the algorithm. | 340 | * of the algorithm. | |
337 | */ | 341 | */ | |
338 | plen = m->m_pkthdr.len - (skip + hlen + alen); | 342 | plen = m->m_pkthdr.len - (skip + hlen + alen); | |
339 | if ((plen & (espx->blocksize - 1)) || (plen <= 0)) { | 343 | if ((plen & (espx->blocksize - 1)) || (plen <= 0)) { | |
340 | DPRINTF(("esp_input: " | 344 | DPRINTF(("esp_input: " | |
341 | "payload of %d octets not a multiple of %d octets," | 345 | "payload of %d octets not a multiple of %d octets," | |
342 | " SA %s/%08lx\n", | 346 | " SA %s/%08lx\n", | |
343 | plen, espx->blocksize, | 347 | plen, espx->blocksize, | |
344 | ipsec_address(&sav->sah->saidx.dst), | 348 | ipsec_address(&sav->sah->saidx.dst), | |
345 | (u_long) ntohl(sav->spi))); | 349 | (u_long) ntohl(sav->spi))); | |
346 | ESP_STATINC(ESP_STAT_BADILEN); | 350 | ESP_STATINC(ESP_STAT_BADILEN); | |
347 | m_freem(m); | 351 | m_freem(m); | |
348 | return EINVAL; | 352 | return EINVAL; | |
349 | } | 353 | } | |
350 | 354 | |||
351 | /* | 355 | /* | |
352 | * Check sequence number. | 356 | * Check sequence number. | |
353 | */ | 357 | */ | |
354 | if (esph && sav->replay && !ipsec_chkreplay(ntohl(esp->esp_seq), sav)) { | 358 | if (esph && sav->replay && !ipsec_chkreplay(ntohl(esp->esp_seq), sav)) { | |
355 | DPRINTF(("esp_input: packet replay check for %s\n", | 359 | DPRINTF(("esp_input: packet replay check for %s\n", | |
356 | ipsec_logsastr(sav))); /*XXX*/ | 360 | ipsec_logsastr(sav))); /*XXX*/ | |
357 | ESP_STATINC(ESP_STAT_REPLAY); | 361 | ESP_STATINC(ESP_STAT_REPLAY); | |
358 | m_freem(m); | 362 | m_freem(m); | |
359 | return ENOBUFS; /*XXX*/ | 363 | return ENOBUFS; /*XXX*/ | |
360 | } | 364 | } | |
361 | 365 | |||
362 | /* Update the counters */ | 366 | /* Update the counters */ | |
363 | ESP_STATADD(ESP_STAT_IBYTES, m->m_pkthdr.len - skip - hlen - alen); | 367 | ESP_STATADD(ESP_STAT_IBYTES, m->m_pkthdr.len - skip - hlen - alen); | |
364 | 368 | |||
365 | /* Find out if we've already done crypto */ | 369 | /* Find out if we've already done crypto */ | |
366 | for (mtag = m_tag_find(m, PACKET_TAG_IPSEC_IN_CRYPTO_DONE, NULL); | 370 | for (mtag = m_tag_find(m, PACKET_TAG_IPSEC_IN_CRYPTO_DONE, NULL); | |
367 | mtag != NULL; | 371 | mtag != NULL; | |
368 | mtag = m_tag_find(m, PACKET_TAG_IPSEC_IN_CRYPTO_DONE, mtag)) { | 372 | mtag = m_tag_find(m, PACKET_TAG_IPSEC_IN_CRYPTO_DONE, mtag)) { | |
369 | tdbi = (struct tdb_ident *) (mtag + 1); | 373 | tdbi = (struct tdb_ident *) (mtag + 1); | |
370 | if (tdbi->proto == sav->sah->saidx.proto && | 374 | if (tdbi->proto == sav->sah->saidx.proto && | |
371 | tdbi->spi == sav->spi && | 375 | tdbi->spi == sav->spi && | |
372 | !memcmp(&tdbi->dst, &sav->sah->saidx.dst, | 376 | !memcmp(&tdbi->dst, &sav->sah->saidx.dst, | |
373 | sizeof(union sockaddr_union))) | 377 | sizeof(union sockaddr_union))) | |
374 | break; | 378 | break; | |
375 | } | 379 | } | |
376 | 380 | |||
377 | /* Get crypto descriptors */ | 381 | /* Get crypto descriptors */ | |
378 | crp = crypto_getreq(esph && espx ? 2 : 1); | 382 | crp = crypto_getreq(esph && espx ? 2 : 1); | |
379 | if (crp == NULL) { | 383 | if (crp == NULL) { | |
380 | DPRINTF(("esp_input: failed to acquire crypto descriptors\n")); | 384 | DPRINTF(("esp_input: failed to acquire crypto descriptors\n")); | |
381 | ESP_STATINC(ESP_STAT_CRYPTO); | 385 | ESP_STATINC(ESP_STAT_CRYPTO); | |
382 | m_freem(m); | 386 | m_freem(m); | |
383 | return ENOBUFS; | 387 | return ENOBUFS; | |
384 | } | 388 | } | |
385 | 389 | |||
386 | /* Get IPsec-specific opaque pointer */ | 390 | /* Get IPsec-specific opaque pointer */ | |
387 | if (esph == NULL || mtag != NULL) | 391 | if (esph == NULL || mtag != NULL) | |
388 | tc = (struct tdb_crypto *) malloc(sizeof(struct tdb_crypto), | 392 | tc = (struct tdb_crypto *) malloc(sizeof(struct tdb_crypto), | |
389 | M_XDATA, M_NOWAIT|M_ZERO); | 393 | M_XDATA, M_NOWAIT|M_ZERO); | |
390 | else | 394 | else | |
391 | tc = (struct tdb_crypto *) malloc(sizeof(struct tdb_crypto) + alen, | 395 | tc = (struct tdb_crypto *) malloc(sizeof(struct tdb_crypto) + alen, | |
392 | M_XDATA, M_NOWAIT|M_ZERO); | 396 | M_XDATA, M_NOWAIT|M_ZERO); | |
393 | if (tc == NULL) { | 397 | if (tc == NULL) { | |
394 | crypto_freereq(crp); | 398 | crypto_freereq(crp); | |
395 | DPRINTF(("esp_input: failed to allocate tdb_crypto\n")); | 399 | DPRINTF(("esp_input: failed to allocate tdb_crypto\n")); | |
396 | ESP_STATINC(ESP_STAT_CRYPTO); | 400 | ESP_STATINC(ESP_STAT_CRYPTO); | |
397 | m_freem(m); | 401 | m_freem(m); | |
398 | return ENOBUFS; | 402 | return ENOBUFS; | |
399 | } | 403 | } | |
400 | 404 | |||
401 | error = m_makewritable(&m, 0, m->m_pkthdr.len, M_NOWAIT); | 405 | error = m_makewritable(&m, 0, m->m_pkthdr.len, M_NOWAIT); | |
402 | if (error) { | 406 | if (error) { | |
403 | m_freem(m); | 407 | m_freem(m); | |
404 | free(tc, M_XDATA); | 408 | free(tc, M_XDATA); | |
405 | crypto_freereq(crp); | 409 | crypto_freereq(crp); | |
406 | DPRINTF(("esp_input: m_makewritable failed\n")); | 410 | DPRINTF(("esp_input: m_makewritable failed\n")); | |
407 | ESP_STATINC(ESP_STAT_CRYPTO); | 411 | ESP_STATINC(ESP_STAT_CRYPTO); | |
408 | return error; | 412 | return error; | |
409 | } | 413 | } | |
410 | 414 | |||
411 | tc->tc_ptr = mtag; | 415 | tc->tc_ptr = mtag; | |
412 | 416 | |||
413 | if (esph) { | 417 | if (esph) { | |
414 | struct cryptodesc *crda = crp->crp_desc; | 418 | struct cryptodesc *crda = crp->crp_desc; | |
415 | 419 | |||
416 | IPSEC_ASSERT(crda != NULL, ("esp_input: null ah crypto descriptor")); | 420 | IPSEC_ASSERT(crda != NULL, ("esp_input: null ah crypto descriptor")); | |
417 | 421 | |||
418 | /* Authentication descriptor */ | 422 | /* Authentication descriptor */ | |
419 | crda->crd_skip = skip; | 423 | crda->crd_skip = skip; | |
420 | if (espx && espx->type == CRYPTO_AES_GCM_16) | 424 | if (espx && espx->type == CRYPTO_AES_GCM_16) | |
421 | crda->crd_len = hlen - sav->ivlen; | 425 | crda->crd_len = hlen - sav->ivlen; | |
422 | else | 426 | else | |
423 | crda->crd_len = m->m_pkthdr.len - (skip + alen); | 427 | crda->crd_len = m->m_pkthdr.len - (skip + alen); | |
424 | crda->crd_inject = m->m_pkthdr.len - alen; | 428 | crda->crd_inject = m->m_pkthdr.len - alen; | |
425 | 429 | |||
426 | crda->crd_alg = esph->type; | 430 | crda->crd_alg = esph->type; | |
427 | if (espx && (espx->type == CRYPTO_AES_GCM_16 || | 431 | if (espx && (espx->type == CRYPTO_AES_GCM_16 || | |
428 | espx->type == CRYPTO_AES_GMAC)) { | 432 | espx->type == CRYPTO_AES_GMAC)) { | |
429 | crda->crd_key = _KEYBUF(sav->key_enc); | 433 | crda->crd_key = _KEYBUF(sav->key_enc); | |
430 | crda->crd_klen = _KEYBITS(sav->key_enc); | 434 | crda->crd_klen = _KEYBITS(sav->key_enc); | |
431 | } else { | 435 | } else { | |
432 | crda->crd_key = _KEYBUF(sav->key_auth); | 436 | crda->crd_key = _KEYBUF(sav->key_auth); | |
433 | crda->crd_klen = _KEYBITS(sav->key_auth); | 437 | crda->crd_klen = _KEYBITS(sav->key_auth); | |
434 | } | 438 | } | |
435 | 439 | |||
436 | /* Copy the authenticator */ | 440 | /* Copy the authenticator */ | |
437 | if (mtag == NULL) | 441 | if (mtag == NULL) | |
438 | m_copydata(m, m->m_pkthdr.len - alen, alen, | 442 | m_copydata(m, m->m_pkthdr.len - alen, alen, | |
439 | (tc + 1)); | 443 | (tc + 1)); | |
440 | 444 | |||
441 | /* Chain authentication request */ | 445 | /* Chain authentication request */ | |
442 | crde = crda->crd_next; | 446 | crde = crda->crd_next; | |
443 | } else { | 447 | } else { | |
444 | crde = crp->crp_desc; | 448 | crde = crp->crp_desc; | |
445 | } | 449 | } | |
446 | 450 | |||
447 | /* Crypto operation descriptor */ | 451 | /* Crypto operation descriptor */ | |
448 | crp->crp_ilen = m->m_pkthdr.len; /* Total input length */ | 452 | crp->crp_ilen = m->m_pkthdr.len; /* Total input length */ | |
449 | crp->crp_flags = CRYPTO_F_IMBUF; | 453 | crp->crp_flags = CRYPTO_F_IMBUF; | |
450 | crp->crp_buf = m; | 454 | crp->crp_buf = m; | |
451 | crp->crp_callback = esp_input_cb; | 455 | crp->crp_callback = esp_input_cb; | |
452 | crp->crp_sid = sav->tdb_cryptoid; | 456 | crp->crp_sid = sav->tdb_cryptoid; | |
453 | crp->crp_opaque = tc; | 457 | crp->crp_opaque = tc; | |
454 | 458 | |||
455 | /* These are passed as-is to the callback */ | 459 | /* These are passed as-is to the callback */ | |
456 | tc->tc_spi = sav->spi; | 460 | tc->tc_spi = sav->spi; | |
457 | tc->tc_dst = sav->sah->saidx.dst; | 461 | tc->tc_dst = sav->sah->saidx.dst; | |
458 | tc->tc_proto = sav->sah->saidx.proto; | 462 | tc->tc_proto = sav->sah->saidx.proto; | |
459 | tc->tc_protoff = protoff; | 463 | tc->tc_protoff = protoff; | |
460 | tc->tc_skip = skip; | 464 | tc->tc_skip = skip; | |
461 | 465 | |||
462 | /* Decryption descriptor */ | 466 | /* Decryption descriptor */ | |
463 | if (espx) { | 467 | if (espx) { | |
464 | IPSEC_ASSERT(crde != NULL, ("esp_input: null esp crypto descriptor")); | 468 | IPSEC_ASSERT(crde != NULL, ("esp_input: null esp crypto descriptor")); | |
465 | crde->crd_skip = skip + hlen; | 469 | crde->crd_skip = skip + hlen; | |
466 | if (espx->type == CRYPTO_AES_GMAC) | 470 | if (espx->type == CRYPTO_AES_GMAC) | |
467 | crde->crd_len = 0; | 471 | crde->crd_len = 0; | |
468 | else | 472 | else | |
469 | crde->crd_len = m->m_pkthdr.len - (skip + hlen + alen); | 473 | crde->crd_len = m->m_pkthdr.len - (skip + hlen + alen); | |
470 | crde->crd_inject = skip + hlen - sav->ivlen; | 474 | crde->crd_inject = skip + hlen - sav->ivlen; | |
471 | 475 | |||
472 | crde->crd_alg = espx->type; | 476 | crde->crd_alg = espx->type; | |
473 | crde->crd_key = _KEYBUF(sav->key_enc); | 477 | crde->crd_key = _KEYBUF(sav->key_enc); | |
474 | crde->crd_klen = _KEYBITS(sav->key_enc); | 478 | crde->crd_klen = _KEYBITS(sav->key_enc); | |
475 | /* XXX Rounds ? */ | 479 | /* XXX Rounds ? */ | |
476 | } | 480 | } | |
477 | 481 | |||
478 | if (mtag == NULL) | 482 | if (mtag == NULL) | |
479 | return crypto_dispatch(crp); | 483 | return crypto_dispatch(crp); | |
480 | else | 484 | else | |
481 | return esp_input_cb(crp); | 485 | return esp_input_cb(crp); | |
482 | } | 486 | } | |
483 | 487 | |||
484 | #ifdef INET6 | 488 | #ifdef INET6 | |
485 | #define IPSEC_COMMON_INPUT_CB(m, sav, skip, protoff, mtag) do { \ | 489 | #define IPSEC_COMMON_INPUT_CB(m, sav, skip, protoff, mtag) do { \ | |
486 | if (saidx->dst.sa.sa_family == AF_INET6) { \ | 490 | if (saidx->dst.sa.sa_family == AF_INET6) { \ | |
487 | error = ipsec6_common_input_cb(m, sav, skip, protoff, mtag); \ | 491 | error = ipsec6_common_input_cb(m, sav, skip, protoff, mtag); \ | |
488 | } else { \ | 492 | } else { \ | |
489 | error = ipsec4_common_input_cb(m, sav, skip, protoff, mtag); \ | 493 | error = ipsec4_common_input_cb(m, sav, skip, protoff, mtag); \ | |
490 | } \ | 494 | } \ | |
491 | } while (0) | 495 | } while (0) | |
492 | #else | 496 | #else | |
493 | #define IPSEC_COMMON_INPUT_CB(m, sav, skip, protoff, mtag) \ | 497 | #define IPSEC_COMMON_INPUT_CB(m, sav, skip, protoff, mtag) \ | |
494 | (error = ipsec4_common_input_cb(m, sav, skip, protoff, mtag)) | 498 | (error = ipsec4_common_input_cb(m, sav, skip, protoff, mtag)) | |
495 | #endif | 499 | #endif | |
496 | 500 | |||
497 | /* | 501 | /* | |
498 | * ESP input callback from the crypto driver. | 502 | * ESP input callback from the crypto driver. | |
499 | */ | 503 | */ | |
500 | static int | 504 | static int | |
501 | esp_input_cb(struct cryptop *crp) | 505 | esp_input_cb(struct cryptop *crp) | |
502 | { | 506 | { | |
503 | u_int8_t lastthree[3], aalg[AH_ALEN_MAX]; | 507 | u_int8_t lastthree[3], aalg[AH_ALEN_MAX]; | |
504 | int s, hlen, skip, protoff, error; | 508 | int s, hlen, skip, protoff, error; | |
505 | struct mbuf *m; | 509 | struct mbuf *m; | |
506 | struct cryptodesc *crd; | 510 | struct cryptodesc *crd; | |
507 | const struct auth_hash *esph; | 511 | const struct auth_hash *esph; | |
508 | const struct enc_xform *espx; | 512 | const struct enc_xform *espx; | |
509 | struct tdb_crypto *tc; | 513 | struct tdb_crypto *tc; | |
510 | struct m_tag *mtag; | 514 | struct m_tag *mtag; | |
511 | struct secasvar *sav; | 515 | struct secasvar *sav; | |
512 | struct secasindex *saidx; | 516 | struct secasindex *saidx; | |
513 | void *ptr; | 517 | void *ptr; | |
514 | u_int16_t dport = 0; | 518 | u_int16_t dport = 0; | |
515 | u_int16_t sport = 0; | 519 | u_int16_t sport = 0; | |
516 | #ifdef IPSEC_NAT_T | 520 | #ifdef IPSEC_NAT_T | |
517 | struct m_tag * tag = NULL; | 521 | struct m_tag * tag = NULL; | |
518 | #endif | 522 | #endif | |
519 | 523 | |||
520 | crd = crp->crp_desc; | 524 | crd = crp->crp_desc; | |
521 | IPSEC_ASSERT(crd != NULL, ("esp_input_cb: null crypto descriptor!")); | 525 | IPSEC_ASSERT(crd != NULL, ("esp_input_cb: null crypto descriptor!")); | |
522 | 526 | |||
523 | tc = (struct tdb_crypto *) crp->crp_opaque; | 527 | tc = (struct tdb_crypto *) crp->crp_opaque; | |
524 | IPSEC_ASSERT(tc != NULL, ("esp_input_cb: null opaque crypto data area!")); | 528 | IPSEC_ASSERT(tc != NULL, ("esp_input_cb: null opaque crypto data area!")); | |
525 | skip = tc->tc_skip; | 529 | skip = tc->tc_skip; | |
526 | protoff = tc->tc_protoff; | 530 | protoff = tc->tc_protoff; | |
527 | mtag = (struct m_tag *) tc->tc_ptr; | 531 | mtag = (struct m_tag *) tc->tc_ptr; | |
528 | m = (struct mbuf *) crp->crp_buf; | 532 | m = (struct mbuf *) crp->crp_buf; | |
529 | 533 | |||
530 | #ifdef IPSEC_NAT_T | 534 | #ifdef IPSEC_NAT_T | |
531 | /* find the source port for NAT-T */ | 535 | /* find the source port for NAT-T */ | |
532 | if ((tag = m_tag_find(m, PACKET_TAG_IPSEC_NAT_T_PORTS, NULL))) { | 536 | if ((tag = m_tag_find(m, PACKET_TAG_IPSEC_NAT_T_PORTS, NULL))) { | |
533 | sport = ((u_int16_t *)(tag + 1))[0]; | 537 | sport = ((u_int16_t *)(tag + 1))[0]; | |
534 | dport = ((u_int16_t *)(tag + 1))[1]; | 538 | dport = ((u_int16_t *)(tag + 1))[1]; | |
535 | } | 539 | } | |
536 | #endif | 540 | #endif | |
537 | 541 | |||
538 | s = splsoftnet(); | 542 | s = splsoftnet(); | |
539 | mutex_enter(softnet_lock); | 543 | mutex_enter(softnet_lock); | |
540 | 544 | |||
541 | sav = KEY_ALLOCSA(&tc->tc_dst, tc->tc_proto, tc->tc_spi, sport, dport); | 545 | sav = KEY_ALLOCSA(&tc->tc_dst, tc->tc_proto, tc->tc_spi, sport, dport); | |
542 | if (sav == NULL) { | 546 | if (sav == NULL) { | |
543 | ESP_STATINC(ESP_STAT_NOTDB); | 547 | ESP_STATINC(ESP_STAT_NOTDB); | |
544 | DPRINTF(("esp_input_cb: SA expired while in crypto " | 548 | DPRINTF(("esp_input_cb: SA expired while in crypto " | |
545 | "(SA %s/%08lx proto %u)\n", ipsec_address(&tc->tc_dst), | 549 | "(SA %s/%08lx proto %u)\n", ipsec_address(&tc->tc_dst), | |
546 | (u_long) ntohl(tc->tc_spi), tc->tc_proto)); | 550 | (u_long) ntohl(tc->tc_spi), tc->tc_proto)); | |
547 | error = ENOBUFS; /*XXX*/ | 551 | error = ENOBUFS; /*XXX*/ | |
548 | goto bad; | 552 | goto bad; | |
549 | } | 553 | } | |
550 | 554 | |||
551 | saidx = &sav->sah->saidx; | 555 | saidx = &sav->sah->saidx; | |
552 | IPSEC_ASSERT(saidx->dst.sa.sa_family == AF_INET || | 556 | IPSEC_ASSERT(saidx->dst.sa.sa_family == AF_INET || | |
553 | saidx->dst.sa.sa_family == AF_INET6, | 557 | saidx->dst.sa.sa_family == AF_INET6, | |
554 | ("esp_input_cb: unexpected protocol family %u", | 558 | ("esp_input_cb: unexpected protocol family %u", | |
555 | saidx->dst.sa.sa_family)); | 559 | saidx->dst.sa.sa_family)); | |
556 | 560 | |||
557 | esph = sav->tdb_authalgxform; | 561 | esph = sav->tdb_authalgxform; | |
558 | espx = sav->tdb_encalgxform; | 562 | espx = sav->tdb_encalgxform; | |
559 | 563 | |||
560 | /* Check for crypto errors */ | 564 | /* Check for crypto errors */ | |
561 | if (crp->crp_etype) { | 565 | if (crp->crp_etype) { | |
562 | /* Reset the session ID */ | 566 | /* Reset the session ID */ | |
563 | if (sav->tdb_cryptoid != 0) | 567 | if (sav->tdb_cryptoid != 0) | |
564 | sav->tdb_cryptoid = crp->crp_sid; | 568 | sav->tdb_cryptoid = crp->crp_sid; | |
565 | 569 | |||
566 | if (crp->crp_etype == EAGAIN) { | 570 | if (crp->crp_etype == EAGAIN) { | |
567 | KEY_FREESAV(&sav); | 571 | KEY_FREESAV(&sav); | |
568 | mutex_exit(softnet_lock); | 572 | mutex_exit(softnet_lock); | |
569 | splx(s); | 573 | splx(s); | |
570 | return crypto_dispatch(crp); | 574 | return crypto_dispatch(crp); | |
571 | } | 575 | } | |
572 | 576 | |||
573 | ESP_STATINC(ESP_STAT_NOXFORM); | 577 | ESP_STATINC(ESP_STAT_NOXFORM); | |
574 | DPRINTF(("esp_input_cb: crypto error %d\n", crp->crp_etype)); | 578 | DPRINTF(("esp_input_cb: crypto error %d\n", crp->crp_etype)); | |
575 | error = crp->crp_etype; | 579 | error = crp->crp_etype; | |
576 | goto bad; | 580 | goto bad; | |
577 | } | 581 | } | |
578 | 582 | |||
579 | /* Shouldn't happen... */ | 583 | /* Shouldn't happen... */ | |
580 | if (m == NULL) { | 584 | if (m == NULL) { | |
581 | ESP_STATINC(ESP_STAT_CRYPTO); | 585 | ESP_STATINC(ESP_STAT_CRYPTO); | |
582 | DPRINTF(("esp_input_cb: bogus returned buffer from crypto\n")); | 586 | DPRINTF(("esp_input_cb: bogus returned buffer from crypto\n")); | |
583 | error = EINVAL; | 587 | error = EINVAL; | |
584 | goto bad; | 588 | goto bad; | |
585 | } | 589 | } | |
586 | ESP_STATINC(ESP_STAT_HIST + sav->alg_enc); | 590 | ESP_STATINC(ESP_STAT_HIST + sav->alg_enc); | |
587 | 591 | |||
588 | /* If authentication was performed, check now. */ | 592 | /* If authentication was performed, check now. */ | |
589 | if (esph != NULL) { | 593 | if (esph != NULL) { | |
590 | /* | 594 | /* | |
591 | * If we have a tag, it means an IPsec-aware NIC did | 595 | * If we have a tag, it means an IPsec-aware NIC did | |
592 | * the verification for us. Otherwise we need to | 596 | * the verification for us. Otherwise we need to | |
593 | * check the authentication calculation. | 597 | * check the authentication calculation. | |
594 | */ | 598 | */ | |
595 | AH_STATINC(AH_STAT_HIST + sav->alg_auth); | 599 | AH_STATINC(AH_STAT_HIST + sav->alg_auth); | |
596 | if (mtag == NULL) { | 600 | if (mtag == NULL) { | |
597 | /* Copy the authenticator from the packet */ | 601 | /* Copy the authenticator from the packet */ | |
598 | m_copydata(m, m->m_pkthdr.len - esph->authsize, | 602 | m_copydata(m, m->m_pkthdr.len - esph->authsize, | |
599 | esph->authsize, aalg); | 603 | esph->authsize, aalg); | |
600 | 604 | |||
601 | ptr = (tc + 1); | 605 | ptr = (tc + 1); | |
602 | 606 | |||
603 | /* Verify authenticator */ | 607 | /* Verify authenticator */ | |
604 | if (memcmp(ptr, aalg, esph->authsize) != 0) { | 608 | if (memcmp(ptr, aalg, esph->authsize) != 0) { | |
605 | DPRINTF(("esp_input_cb: " | 609 | DPRINTF(("esp_input_cb: " | |
606 | "authentication hash mismatch for packet in SA %s/%08lx\n", | 610 | "authentication hash mismatch for packet in SA %s/%08lx\n", | |
607 | ipsec_address(&saidx->dst), | 611 | ipsec_address(&saidx->dst), | |
608 | (u_long) ntohl(sav->spi))); | 612 | (u_long) ntohl(sav->spi))); | |
609 | ESP_STATINC(ESP_STAT_BADAUTH); | 613 | ESP_STATINC(ESP_STAT_BADAUTH); | |
610 | error = EACCES; | 614 | error = EACCES; | |
611 | goto bad; | 615 | goto bad; | |
612 | } | 616 | } | |
613 | } | 617 | } | |
614 | 618 | |||
615 | /* Remove trailing authenticator */ | 619 | /* Remove trailing authenticator */ | |
616 | m_adj(m, -(esph->authsize)); | 620 | m_adj(m, -(esph->authsize)); | |
617 | } | 621 | } | |
618 | 622 | |||
619 | /* Release the crypto descriptors */ | 623 | /* Release the crypto descriptors */ | |
620 | free(tc, M_XDATA), tc = NULL; | 624 | free(tc, M_XDATA), tc = NULL; | |
621 | crypto_freereq(crp), crp = NULL; | 625 | crypto_freereq(crp), crp = NULL; | |
622 | 626 | |||
623 | /* | 627 | /* | |
624 | * Packet is now decrypted. | 628 | * Packet is now decrypted. | |
625 | */ | 629 | */ | |
626 | m->m_flags |= M_DECRYPTED; | 630 | m->m_flags |= M_DECRYPTED; | |
627 | 631 | |||
628 | /* | 632 | /* | |
629 | * Update replay sequence number, if appropriate. | 633 | * Update replay sequence number, if appropriate. | |
630 | */ | 634 | */ | |
631 | if (sav->replay) { | 635 | if (sav->replay) { | |
632 | u_int32_t seq; | 636 | u_int32_t seq; | |
633 | 637 | |||
634 | m_copydata(m, skip + offsetof(struct newesp, esp_seq), | 638 | m_copydata(m, skip + offsetof(struct newesp, esp_seq), | |
635 | sizeof (seq), &seq); | 639 | sizeof (seq), &seq); | |
636 | if (ipsec_updatereplay(ntohl(seq), sav)) { | 640 | if (ipsec_updatereplay(ntohl(seq), sav)) { | |
637 | DPRINTF(("%s: packet replay check for %s\n", __func__, | 641 | DPRINTF(("%s: packet replay check for %s\n", __func__, | |
638 | ipsec_logsastr(sav))); | 642 | ipsec_logsastr(sav))); | |
639 | ESP_STATINC(ESP_STAT_REPLAY); | 643 | ESP_STATINC(ESP_STAT_REPLAY); | |
640 | error = ENOBUFS; | 644 | error = ENOBUFS; | |
641 | goto bad; | 645 | goto bad; | |
642 | } | 646 | } | |
643 | } | 647 | } | |
644 | 648 | |||
645 | /* Determine the ESP header length */ | 649 | /* Determine the ESP header length */ | |
646 | if (sav->flags & SADB_X_EXT_OLD) | 650 | if (sav->flags & SADB_X_EXT_OLD) | |
647 | hlen = sizeof (struct esp) + sav->ivlen; | 651 | hlen = sizeof (struct esp) + sav->ivlen; | |
648 | else | 652 | else | |
649 | hlen = sizeof (struct newesp) + sav->ivlen; | 653 | hlen = sizeof (struct newesp) + sav->ivlen; | |
650 | 654 | |||
651 | /* Remove the ESP header and IV from the mbuf. */ | 655 | /* Remove the ESP header and IV from the mbuf. */ | |
652 | error = m_striphdr(m, skip, hlen); | 656 | error = m_striphdr(m, skip, hlen); | |
653 | if (error) { | 657 | if (error) { | |
654 | ESP_STATINC(ESP_STAT_HDROPS); | 658 | ESP_STATINC(ESP_STAT_HDROPS); | |
655 | DPRINTF(("esp_input_cb: bad mbuf chain, SA %s/%08lx\n", | 659 | DPRINTF(("esp_input_cb: bad mbuf chain, SA %s/%08lx\n", | |
656 | ipsec_address(&sav->sah->saidx.dst), | 660 | ipsec_address(&sav->sah->saidx.dst), | |
657 | (u_long) ntohl(sav->spi))); | 661 | (u_long) ntohl(sav->spi))); | |
658 | goto bad; | 662 | goto bad; | |
659 | } | 663 | } | |
660 | 664 | |||
661 | /* Save the last three bytes of decrypted data */ | 665 | /* Save the last three bytes of decrypted data */ | |
662 | m_copydata(m, m->m_pkthdr.len - 3, 3, lastthree); | 666 | m_copydata(m, m->m_pkthdr.len - 3, 3, lastthree); | |
663 | 667 | |||
664 | /* Verify pad length */ | 668 | /* Verify pad length */ | |
665 | if (lastthree[1] + 2 > m->m_pkthdr.len - skip) { | 669 | if (lastthree[1] + 2 > m->m_pkthdr.len - skip) { | |
666 | ESP_STATINC(ESP_STAT_BADILEN); | 670 | ESP_STATINC(ESP_STAT_BADILEN); | |
667 | DPRINTF(("esp_input_cb: invalid padding length %d " | 671 | DPRINTF(("esp_input_cb: invalid padding length %d " | |
668 | "for %u byte packet in SA %s/%08lx\n", | 672 | "for %u byte packet in SA %s/%08lx\n", | |
669 | lastthree[1], m->m_pkthdr.len - skip, | 673 | lastthree[1], m->m_pkthdr.len - skip, | |
670 | ipsec_address(&sav->sah->saidx.dst), | 674 | ipsec_address(&sav->sah->saidx.dst), | |
671 | (u_long) ntohl(sav->spi))); | 675 | (u_long) ntohl(sav->spi))); | |
672 | error = EINVAL; | 676 | error = EINVAL; | |
673 | goto bad; | 677 | goto bad; | |
674 | } | 678 | } | |
675 | 679 | |||
676 | /* Verify correct decryption by checking the last padding bytes */ | 680 | /* Verify correct decryption by checking the last padding bytes */ | |
677 | if ((sav->flags & SADB_X_EXT_PMASK) != SADB_X_EXT_PRAND) { | 681 | if ((sav->flags & SADB_X_EXT_PMASK) != SADB_X_EXT_PRAND) { | |
678 | if (lastthree[1] != lastthree[0] && lastthree[1] != 0) { | 682 | if (lastthree[1] != lastthree[0] && lastthree[1] != 0) { | |
679 | ESP_STATINC(ESP_STAT_BADENC); | 683 | ESP_STATINC(ESP_STAT_BADENC); | |
680 | DPRINTF(("esp_input_cb: decryption failed " | 684 | DPRINTF(("esp_input_cb: decryption failed " | |
681 | "for packet in SA %s/%08lx\n", | 685 | "for packet in SA %s/%08lx\n", | |
682 | ipsec_address(&sav->sah->saidx.dst), | 686 | ipsec_address(&sav->sah->saidx.dst), | |
683 | (u_long) ntohl(sav->spi))); | 687 | (u_long) ntohl(sav->spi))); | |
684 | DPRINTF(("esp_input_cb: %x %x\n", lastthree[0], lastthree[1])); | 688 | DPRINTF(("esp_input_cb: %x %x\n", lastthree[0], lastthree[1])); | |
685 | error = EINVAL; | 689 | error = EINVAL; | |
686 | goto bad; | 690 | goto bad; | |
687 | } | 691 | } | |
688 | } | 692 | } | |
689 | 693 | |||
690 | /* Trim the mbuf chain to remove trailing authenticator and padding */ | 694 | /* Trim the mbuf chain to remove trailing authenticator and padding */ | |
691 | m_adj(m, -(lastthree[1] + 2)); | 695 | m_adj(m, -(lastthree[1] + 2)); | |
692 | 696 | |||
693 | /* Restore the Next Protocol field */ | 697 | /* Restore the Next Protocol field */ | |
694 | m_copyback(m, protoff, sizeof (u_int8_t), lastthree + 2); | 698 | m_copyback(m, protoff, sizeof (u_int8_t), lastthree + 2); | |
695 | 699 | |||
696 | IPSEC_COMMON_INPUT_CB(m, sav, skip, protoff, mtag); | 700 | IPSEC_COMMON_INPUT_CB(m, sav, skip, protoff, mtag); | |
697 | 701 | |||
698 | KEY_FREESAV(&sav); | 702 | KEY_FREESAV(&sav); | |
699 | mutex_exit(softnet_lock); | 703 | mutex_exit(softnet_lock); | |
700 | splx(s); | 704 | splx(s); | |
701 | return error; | 705 | return error; | |
702 | bad: | 706 | bad: | |
703 | if (sav) | 707 | if (sav) | |
704 | KEY_FREESAV(&sav); | 708 | KEY_FREESAV(&sav); | |
705 | mutex_exit(softnet_lock); | 709 | mutex_exit(softnet_lock); | |
706 | splx(s); | 710 | splx(s); | |
707 | if (m != NULL) | 711 | if (m != NULL) | |
708 | m_freem(m); | 712 | m_freem(m); | |
709 | if (tc != NULL) | 713 | if (tc != NULL) | |
710 | free(tc, M_XDATA); | 714 | free(tc, M_XDATA); | |
711 | if (crp != NULL) | 715 | if (crp != NULL) | |
712 | crypto_freereq(crp); | 716 | crypto_freereq(crp); | |
713 | return error; | 717 | return error; | |
714 | } | 718 | } | |
715 | 719 | |||
716 | /* | 720 | /* | |
717 | * ESP output routine, called by ipsec[46]_process_packet(). | 721 | * ESP output routine, called by ipsec[46]_process_packet(). | |
718 | */ | 722 | */ | |
719 | static int | 723 | static int | |
720 | esp_output( | 724 | esp_output( | |
721 | struct mbuf *m, | 725 | struct mbuf *m, | |
722 | struct ipsecrequest *isr, | 726 | struct ipsecrequest *isr, | |
723 | struct mbuf **mp, | 727 | struct mbuf **mp, | |
724 | int skip, | 728 | int skip, | |
725 | int protoff | 729 | int protoff | |
726 | ) | 730 | ) | |
727 | { | 731 | { | |
728 | const struct enc_xform *espx; | 732 | const struct enc_xform *espx; | |
729 | const struct auth_hash *esph; | 733 | const struct auth_hash *esph; | |
730 | int hlen, rlen, plen, padding, blks, alen, i, roff; | 734 | int hlen, rlen, plen, padding, blks, alen, i, roff; | |
731 | struct mbuf *mo = NULL; | 735 | struct mbuf *mo = NULL; | |
732 | struct tdb_crypto *tc; | 736 | struct tdb_crypto *tc; | |
733 | const struct secasvar *sav; | 737 | const struct secasvar *sav; | |
734 | struct secasindex *saidx; | 738 | struct secasindex *saidx; | |
735 | unsigned char *pad; | 739 | unsigned char *pad; | |
736 | u_int8_t prot; | 740 | u_int8_t prot; | |
737 | int error, maxpacketsize; | 741 | int error, maxpacketsize; | |
738 | 742 | |||
739 | struct cryptodesc *crde = NULL, *crda = NULL; | 743 | struct cryptodesc *crde = NULL, *crda = NULL; | |
740 | struct cryptop *crp; | 744 | struct cryptop *crp; | |
741 | 745 | |||
742 | IPSEC_SPLASSERT_SOFTNET("esp_output"); | 746 | IPSEC_SPLASSERT_SOFTNET("esp_output"); | |
743 | 747 | |||
744 | sav = isr->sav; | 748 | sav = isr->sav; | |
745 | IPSEC_ASSERT(sav != NULL, ("esp_output: null SA")); | 749 | IPSEC_ASSERT(sav != NULL, ("esp_output: null SA")); | |
746 | esph = sav->tdb_authalgxform; | 750 | esph = sav->tdb_authalgxform; | |
747 | espx = sav->tdb_encalgxform; | 751 | espx = sav->tdb_encalgxform; | |
748 | IPSEC_ASSERT(espx != NULL, ("esp_output: null encoding xform")); | 752 | IPSEC_ASSERT(espx != NULL, ("esp_output: null encoding xform")); | |
749 | 753 | |||
750 | if (sav->flags & SADB_X_EXT_OLD) | 754 | if (sav->flags & SADB_X_EXT_OLD) | |
751 | hlen = sizeof (struct esp) + sav->ivlen; | 755 | hlen = sizeof (struct esp) + sav->ivlen; | |
752 | else | 756 | else | |
753 | hlen = sizeof (struct newesp) + sav->ivlen; | 757 | hlen = sizeof (struct newesp) + sav->ivlen; | |
754 | 758 | |||
755 | rlen = m->m_pkthdr.len - skip; /* Raw payload length. */ | 759 | rlen = m->m_pkthdr.len - skip; /* Raw payload length. */ | |
756 | /* | 760 | /* | |
757 | * NB: The null encoding transform has a blocksize of 4 | 761 | * NB: The null encoding transform has a blocksize of 4 | |
758 | * so that headers are properly aligned. | 762 | * so that headers are properly aligned. | |
759 | */ | 763 | */ | |
760 | blks = espx->blocksize; /* IV blocksize */ | 764 | blks = espx->blocksize; /* IV blocksize */ | |
761 | 765 | |||
762 | /* XXX clamp padding length a la KAME??? */ | 766 | /* XXX clamp padding length a la KAME??? */ | |
763 | padding = ((blks - ((rlen + 2) % blks)) % blks) + 2; | 767 | padding = ((blks - ((rlen + 2) % blks)) % blks) + 2; | |
764 | plen = rlen + padding; /* Padded payload length. */ | 768 | plen = rlen + padding; /* Padded payload length. */ | |
765 | 769 | |||
766 | if (esph) | 770 | if (esph) | |
767 | alen = esph->authsize; | 771 | alen = esph->authsize; | |
768 | else | 772 | else | |
769 | alen = 0; | 773 | alen = 0; | |
770 | 774 | |||
771 | ESP_STATINC(ESP_STAT_OUTPUT); | 775 | ESP_STATINC(ESP_STAT_OUTPUT); | |
772 | 776 | |||
773 | saidx = &sav->sah->saidx; | 777 | saidx = &sav->sah->saidx; | |
774 | /* Check for maximum packet size violations. */ | 778 | /* Check for maximum packet size violations. */ | |
775 | switch (saidx->dst.sa.sa_family) { | 779 | switch (saidx->dst.sa.sa_family) { | |
776 | #ifdef INET | 780 | #ifdef INET | |
777 | case AF_INET: | 781 | case AF_INET: | |
778 | maxpacketsize = IP_MAXPACKET; | 782 | maxpacketsize = IP_MAXPACKET; | |
779 | break; | 783 | break; | |
780 | #endif /* INET */ | 784 | #endif /* INET */ | |
781 | #ifdef INET6 | 785 | #ifdef INET6 | |
782 | case AF_INET6: | 786 | case AF_INET6: | |
783 | maxpacketsize = IPV6_MAXPACKET; | 787 | maxpacketsize = IPV6_MAXPACKET; | |
784 | break; | 788 | break; | |
785 | #endif /* INET6 */ | 789 | #endif /* INET6 */ | |
786 | default: | 790 | default: | |
787 | DPRINTF(("esp_output: unknown/unsupported protocol " | 791 | DPRINTF(("esp_output: unknown/unsupported protocol " | |
788 | "family %d, SA %s/%08lx\n", | 792 | "family %d, SA %s/%08lx\n", | |
789 | saidx->dst.sa.sa_family, ipsec_address(&saidx->dst), | 793 | saidx->dst.sa.sa_family, ipsec_address(&saidx->dst), | |
790 | (u_long) ntohl(sav->spi))); | 794 | (u_long) ntohl(sav->spi))); | |
791 | ESP_STATINC(ESP_STAT_NOPF); | 795 | ESP_STATINC(ESP_STAT_NOPF); | |
792 | error = EPFNOSUPPORT; | 796 | error = EPFNOSUPPORT; | |
793 | goto bad; | 797 | goto bad; | |
794 | } | 798 | } | |
795 | if (skip + hlen + rlen + padding + alen > maxpacketsize) { | 799 | if (skip + hlen + rlen + padding + alen > maxpacketsize) { | |
796 | DPRINTF(("esp_output: packet in SA %s/%08lx got too big " | 800 | DPRINTF(("esp_output: packet in SA %s/%08lx got too big " | |
797 | "(len %u, max len %u)\n", | 801 | "(len %u, max len %u)\n", | |
798 | ipsec_address(&saidx->dst), (u_long) ntohl(sav->spi), | 802 | ipsec_address(&saidx->dst), (u_long) ntohl(sav->spi), | |
799 | skip + hlen + rlen + padding + alen, maxpacketsize)); | 803 | skip + hlen + rlen + padding + alen, maxpacketsize)); | |
800 | ESP_STATINC(ESP_STAT_TOOBIG); | 804 | ESP_STATINC(ESP_STAT_TOOBIG); | |
801 | error = EMSGSIZE; | 805 | error = EMSGSIZE; | |
802 | goto bad; | 806 | goto bad; | |
803 | } | 807 | } | |
804 | 808 | |||
805 | /* Update the counters. */ | 809 | /* Update the counters. */ | |
806 | ESP_STATADD(ESP_STAT_OBYTES, m->m_pkthdr.len - skip); | 810 | ESP_STATADD(ESP_STAT_OBYTES, m->m_pkthdr.len - skip); | |
807 | 811 | |||
808 | m = m_clone(m); | 812 | m = m_clone(m); | |
809 | if (m == NULL) { | 813 | if (m == NULL) { | |
810 | DPRINTF(("esp_output: cannot clone mbuf chain, SA %s/%08lx\n", | 814 | DPRINTF(("esp_output: cannot clone mbuf chain, SA %s/%08lx\n", | |
811 | ipsec_address(&saidx->dst), (u_long) ntohl(sav->spi))); | 815 | ipsec_address(&saidx->dst), (u_long) ntohl(sav->spi))); | |
812 | ESP_STATINC(ESP_STAT_HDROPS); | 816 | ESP_STATINC(ESP_STAT_HDROPS); | |
813 | error = ENOBUFS; | 817 | error = ENOBUFS; | |
814 | goto bad; | 818 | goto bad; | |
815 | } | 819 | } | |
816 | 820 | |||
817 | /* Inject ESP header. */ | 821 | /* Inject ESP header. */ | |
818 | mo = m_makespace(m, skip, hlen, &roff); | 822 | mo = m_makespace(m, skip, hlen, &roff); | |
819 | if (mo == NULL) { | 823 | if (mo == NULL) { | |
820 | DPRINTF(("esp_output: failed to inject %u byte ESP hdr for SA " | 824 | DPRINTF(("esp_output: failed to inject %u byte ESP hdr for SA " | |
821 | "%s/%08lx\n", | 825 | "%s/%08lx\n", | |
822 | hlen, ipsec_address(&saidx->dst), | 826 | hlen, ipsec_address(&saidx->dst), | |
823 | (u_long) ntohl(sav->spi))); | 827 | (u_long) ntohl(sav->spi))); | |
824 | ESP_STATINC(ESP_STAT_HDROPS); /* XXX diffs from openbsd */ | 828 | ESP_STATINC(ESP_STAT_HDROPS); /* XXX diffs from openbsd */ | |
825 | error = ENOBUFS; | 829 | error = ENOBUFS; | |
826 | goto bad; | 830 | goto bad; | |
827 | } | 831 | } | |
828 | 832 | |||
829 | /* Initialize ESP header. */ | 833 | /* Initialize ESP header. */ | |
830 | memcpy(mtod(mo, char *) + roff, &sav->spi, sizeof(u_int32_t)); | 834 | memcpy(mtod(mo, char *) + roff, &sav->spi, sizeof(u_int32_t)); | |
831 | if (sav->replay) { | 835 | if (sav->replay) { | |
832 | u_int32_t replay; | 836 | u_int32_t replay; | |
833 | 837 | |||
834 | #ifdef IPSEC_DEBUG | 838 | #ifdef IPSEC_DEBUG | |
835 | /* Emulate replay attack when ipsec_replay is TRUE. */ | 839 | /* Emulate replay attack when ipsec_replay is TRUE. */ | |
836 | if (!ipsec_replay) | 840 | if (!ipsec_replay) | |
837 | #endif | 841 | #endif | |
838 | sav->replay->count++; | 842 | sav->replay->count++; | |
839 | 843 | |||
840 | replay = htonl(sav->replay->count); | 844 | replay = htonl(sav->replay->count); | |
841 | bcopy(&replay, | 845 | bcopy(&replay, | |
842 | mtod(mo,char *) + roff + sizeof(u_int32_t), | 846 | mtod(mo,char *) + roff + sizeof(u_int32_t), | |
843 | sizeof(u_int32_t)); | 847 | sizeof(u_int32_t)); | |
844 | } | 848 | } | |
845 | 849 | |||
846 | /* | 850 | /* | |
847 | * Add padding -- better to do it ourselves than use the crypto engine, | 851 | * Add padding -- better to do it ourselves than use the crypto engine, | |
848 | * although if/when we support compression, we'd have to do that. | 852 | * although if/when we support compression, we'd have to do that. | |
849 | */ | 853 | */ | |
850 | pad = (u_char *) m_pad(m, padding + alen); | 854 | pad = (u_char *) m_pad(m, padding + alen); | |
851 | if (pad == NULL) { | 855 | if (pad == NULL) { | |
852 | DPRINTF(("esp_output: m_pad failed for SA %s/%08lx\n", | 856 | DPRINTF(("esp_output: m_pad failed for SA %s/%08lx\n", | |
853 | ipsec_address(&saidx->dst), (u_long) ntohl(sav->spi))); | 857 | ipsec_address(&saidx->dst), (u_long) ntohl(sav->spi))); | |
854 | m = NULL; /* NB: free'd by m_pad */ | 858 | m = NULL; /* NB: free'd by m_pad */ | |
855 | error = ENOBUFS; | 859 | error = ENOBUFS; | |
856 | goto bad; | 860 | goto bad; | |
857 | } | 861 | } | |
858 | 862 | |||
859 | /* | 863 | /* | |
860 | * Add padding: random, zero, or self-describing. | 864 | * Add padding: random, zero, or self-describing. | |
861 | * XXX catch unexpected setting | 865 | * XXX catch unexpected setting | |
862 | */ | 866 | */ | |
863 | switch (sav->flags & SADB_X_EXT_PMASK) { | 867 | switch (sav->flags & SADB_X_EXT_PMASK) { | |
864 | case SADB_X_EXT_PRAND: | 868 | case SADB_X_EXT_PRAND: | |
865 | (void) read_random(pad, padding - 2); | 869 | (void) read_random(pad, padding - 2); | |
866 | break; | 870 | break; | |
867 | case SADB_X_EXT_PZERO: | 871 | case SADB_X_EXT_PZERO: | |
868 | memset(pad, 0, padding - 2); | 872 | memset(pad, 0, padding - 2); | |
869 | break; | 873 | break; | |
870 | case SADB_X_EXT_PSEQ: | 874 | case SADB_X_EXT_PSEQ: | |
871 | for (i = 0; i < padding - 2; i++) | 875 | for (i = 0; i < padding - 2; i++) | |
872 | pad[i] = i+1; | 876 | pad[i] = i+1; | |
873 | break; | 877 | break; | |
874 | } | 878 | } | |
875 | 879 | |||
876 | /* Fix padding length and Next Protocol in padding itself. */ | 880 | /* Fix padding length and Next Protocol in padding itself. */ | |
877 | pad[padding - 2] = padding - 2; | 881 | pad[padding - 2] = padding - 2; | |
878 | m_copydata(m, protoff, sizeof(u_int8_t), pad + padding - 1); | 882 | m_copydata(m, protoff, sizeof(u_int8_t), pad + padding - 1); | |
879 | 883 | |||
880 | /* Fix Next Protocol in IPv4/IPv6 header. */ | 884 | /* Fix Next Protocol in IPv4/IPv6 header. */ | |
881 | prot = IPPROTO_ESP; | 885 | prot = IPPROTO_ESP; | |
882 | m_copyback(m, protoff, sizeof(u_int8_t), (u_char *) &prot); | 886 | m_copyback(m, protoff, sizeof(u_int8_t), (u_char *) &prot); | |
883 | 887 | |||
884 | /* Get crypto descriptors. */ | 888 | /* Get crypto descriptors. */ | |
885 | crp = crypto_getreq(esph && espx ? 2 : 1); | 889 | crp = crypto_getreq(esph && espx ? 2 : 1); | |
886 | if (crp == NULL) { | 890 | if (crp == NULL) { | |
887 | DPRINTF(("esp_output: failed to acquire crypto descriptors\n")); | 891 | DPRINTF(("esp_output: failed to acquire crypto descriptors\n")); | |
888 | ESP_STATINC(ESP_STAT_CRYPTO); | 892 | ESP_STATINC(ESP_STAT_CRYPTO); | |
889 | error = ENOBUFS; | 893 | error = ENOBUFS; | |
890 | goto bad; | 894 | goto bad; | |
891 | } | 895 | } | |
892 | 896 | |||
893 | if (espx) { | 897 | if (espx) { | |
894 | crde = crp->crp_desc; | 898 | crde = crp->crp_desc; | |
895 | crda = crde->crd_next; | 899 | crda = crde->crd_next; | |
896 | 900 | |||
897 | /* Encryption descriptor. */ | 901 | /* Encryption descriptor. */ | |
898 | crde->crd_skip = skip + hlen; | 902 | crde->crd_skip = skip + hlen; | |
899 | if (espx->type == CRYPTO_AES_GMAC) | 903 | if (espx->type == CRYPTO_AES_GMAC) | |
900 | crde->crd_len = 0; | 904 | crde->crd_len = 0; | |
901 | else | 905 | else | |
902 | crde->crd_len = m->m_pkthdr.len - (skip + hlen + alen); | 906 | crde->crd_len = m->m_pkthdr.len - (skip + hlen + alen); | |
903 | crde->crd_flags = CRD_F_ENCRYPT; | 907 | crde->crd_flags = CRD_F_ENCRYPT; | |
904 | crde->crd_inject = skip + hlen - sav->ivlen; | 908 | crde->crd_inject = skip + hlen - sav->ivlen; | |
905 | 909 | |||
906 | /* Encryption operation. */ | 910 | /* Encryption operation. */ | |
907 | crde->crd_alg = espx->type; | 911 | crde->crd_alg = espx->type; | |
908 | crde->crd_key = _KEYBUF(sav->key_enc); | 912 | crde->crd_key = _KEYBUF(sav->key_enc); | |
909 | crde->crd_klen = _KEYBITS(sav->key_enc); | 913 | crde->crd_klen = _KEYBITS(sav->key_enc); | |
910 | /* XXX Rounds ? */ | 914 | /* XXX Rounds ? */ | |
911 | } else | 915 | } else | |
912 | crda = crp->crp_desc; | 916 | crda = crp->crp_desc; | |
913 | 917 | |||
914 | /* IPsec-specific opaque crypto info. */ | 918 | /* IPsec-specific opaque crypto info. */ | |
915 | tc = (struct tdb_crypto *) malloc(sizeof(struct tdb_crypto), | 919 | tc = (struct tdb_crypto *) malloc(sizeof(struct tdb_crypto), | |
916 | M_XDATA, M_NOWAIT|M_ZERO); | 920 | M_XDATA, M_NOWAIT|M_ZERO); | |
917 | if (tc == NULL) { | 921 | if (tc == NULL) { | |
918 | crypto_freereq(crp); | 922 | crypto_freereq(crp); | |
919 | DPRINTF(("esp_output: failed to allocate tdb_crypto\n")); | 923 | DPRINTF(("esp_output: failed to allocate tdb_crypto\n")); | |
920 | ESP_STATINC(ESP_STAT_CRYPTO); | 924 | ESP_STATINC(ESP_STAT_CRYPTO); | |
921 | error = ENOBUFS; | 925 | error = ENOBUFS; | |
922 | goto bad; | 926 | goto bad; | |
923 | } | 927 | } | |
924 | 928 | |||
925 | /* Callback parameters */ | 929 | /* Callback parameters */ | |
926 | tc->tc_isr = isr; | 930 | tc->tc_isr = isr; | |
927 | tc->tc_spi = sav->spi; | 931 | tc->tc_spi = sav->spi; | |
928 | tc->tc_dst = saidx->dst; | 932 | tc->tc_dst = saidx->dst; | |
929 | tc->tc_proto = saidx->proto; | 933 | tc->tc_proto = saidx->proto; | |
930 | 934 | |||
931 | /* Crypto operation descriptor. */ | 935 | /* Crypto operation descriptor. */ | |
932 | crp->crp_ilen = m->m_pkthdr.len; /* Total input length. */ | 936 | crp->crp_ilen = m->m_pkthdr.len; /* Total input length. */ | |
933 | crp->crp_flags = CRYPTO_F_IMBUF; | 937 | crp->crp_flags = CRYPTO_F_IMBUF; | |
934 | crp->crp_buf = m; | 938 | crp->crp_buf = m; | |
935 | crp->crp_callback = esp_output_cb; | 939 | crp->crp_callback = esp_output_cb; | |
936 | crp->crp_opaque = tc; | 940 | crp->crp_opaque = tc; | |
937 | crp->crp_sid = sav->tdb_cryptoid; | 941 | crp->crp_sid = sav->tdb_cryptoid; | |
938 | 942 | |||
939 | if (esph) { | 943 | if (esph) { | |
940 | /* Authentication descriptor. */ | 944 | /* Authentication descriptor. */ | |
941 | crda->crd_skip = skip; | 945 | crda->crd_skip = skip; | |
942 | if (espx && espx->type == CRYPTO_AES_GCM_16) | 946 | if (espx && espx->type == CRYPTO_AES_GCM_16) | |
943 | crda->crd_len = hlen - sav->ivlen; | 947 | crda->crd_len = hlen - sav->ivlen; | |
944 | else | 948 | else | |
945 | crda->crd_len = m->m_pkthdr.len - (skip + alen); | 949 | crda->crd_len = m->m_pkthdr.len - (skip + alen); | |
946 | crda->crd_inject = m->m_pkthdr.len - alen; | 950 | crda->crd_inject = m->m_pkthdr.len - alen; | |
947 | 951 | |||
948 | /* Authentication operation. */ | 952 | /* Authentication operation. */ | |
949 | crda->crd_alg = esph->type; | 953 | crda->crd_alg = esph->type; | |
950 | if (espx && (espx->type == CRYPTO_AES_GCM_16 || | 954 | if (espx && (espx->type == CRYPTO_AES_GCM_16 || | |
951 | espx->type == CRYPTO_AES_GMAC)) { | 955 | espx->type == CRYPTO_AES_GMAC)) { | |
952 | crda->crd_key = _KEYBUF(sav->key_enc); | 956 | crda->crd_key = _KEYBUF(sav->key_enc); | |
953 | crda->crd_klen = _KEYBITS(sav->key_enc); | 957 | crda->crd_klen = _KEYBITS(sav->key_enc); | |
954 | } else { | 958 | } else { | |
955 | crda->crd_key = _KEYBUF(sav->key_auth); | 959 | crda->crd_key = _KEYBUF(sav->key_auth); | |
956 | crda->crd_klen = _KEYBITS(sav->key_auth); | 960 | crda->crd_klen = _KEYBITS(sav->key_auth); | |
957 | } | 961 | } | |
958 | } | 962 | } | |
959 | 963 | |||
960 | return crypto_dispatch(crp); | 964 | return crypto_dispatch(crp); | |
961 | bad: | 965 | bad: | |
962 | if (m) | 966 | if (m) | |
963 | m_freem(m); | 967 | m_freem(m); | |
964 | return (error); | 968 | return (error); | |
965 | } | 969 | } | |
966 | 970 | |||
967 | /* | 971 | /* | |
968 | * ESP output callback from the crypto driver. | 972 | * ESP output callback from the crypto driver. | |
969 | */ | 973 | */ | |
970 | static int | 974 | static int | |
971 | esp_output_cb(struct cryptop *crp) | 975 | esp_output_cb(struct cryptop *crp) | |
972 | { | 976 | { | |
973 | struct tdb_crypto *tc; | 977 | struct tdb_crypto *tc; | |
974 | struct ipsecrequest *isr; | 978 | struct ipsecrequest *isr; | |
975 | struct secasvar *sav; | 979 | struct secasvar *sav; | |
976 | struct mbuf *m; | 980 | struct mbuf *m; | |
977 | int s, err, error; | 981 | int s, err, error; | |
978 | 982 | |||
979 | tc = (struct tdb_crypto *) crp->crp_opaque; | 983 | tc = (struct tdb_crypto *) crp->crp_opaque; | |
980 | IPSEC_ASSERT(tc != NULL, ("esp_output_cb: null opaque data area!")); | 984 | IPSEC_ASSERT(tc != NULL, ("esp_output_cb: null opaque data area!")); | |
981 | m = (struct mbuf *) crp->crp_buf; | 985 | m = (struct mbuf *) crp->crp_buf; | |
982 | 986 | |||
983 | s = splsoftnet(); | 987 | s = splsoftnet(); | |
984 | mutex_enter(softnet_lock); | 988 | mutex_enter(softnet_lock); | |
985 | 989 | |||
986 | isr = tc->tc_isr; | 990 | isr = tc->tc_isr; | |
987 | sav = KEY_ALLOCSA(&tc->tc_dst, tc->tc_proto, tc->tc_spi, 0, 0); | 991 | sav = KEY_ALLOCSA(&tc->tc_dst, tc->tc_proto, tc->tc_spi, 0, 0); | |
988 | if (sav == NULL) { | 992 | if (sav == NULL) { | |
989 | ESP_STATINC(ESP_STAT_NOTDB); | 993 | ESP_STATINC(ESP_STAT_NOTDB); | |
990 | DPRINTF(("esp_output_cb: SA expired while in crypto " | 994 | DPRINTF(("esp_output_cb: SA expired while in crypto " | |
991 | "(SA %s/%08lx proto %u)\n", ipsec_address(&tc->tc_dst), | 995 | "(SA %s/%08lx proto %u)\n", ipsec_address(&tc->tc_dst), | |
992 | (u_long) ntohl(tc->tc_spi), tc->tc_proto)); | 996 | (u_long) ntohl(tc->tc_spi), tc->tc_proto)); | |
993 | error = ENOBUFS; /*XXX*/ | 997 | error = ENOBUFS; /*XXX*/ | |
994 | goto bad; | 998 | goto bad; | |
995 | } | 999 | } | |
996 | IPSEC_ASSERT(isr->sav == sav, | 1000 | IPSEC_ASSERT(isr->sav == sav, | |
997 | ("esp_output_cb: SA changed was %p now %p\n", isr->sav, sav)); | 1001 | ("esp_output_cb: SA changed was %p now %p\n", isr->sav, sav)); | |
998 | 1002 | |||
999 | /* Check for crypto errors. */ | 1003 | /* Check for crypto errors. */ | |
1000 | if (crp->crp_etype) { | 1004 | if (crp->crp_etype) { | |
1001 | /* Reset session ID. */ | 1005 | /* Reset session ID. */ | |
1002 | if (sav->tdb_cryptoid != 0) | 1006 | if (sav->tdb_cryptoid != 0) | |
1003 | sav->tdb_cryptoid = crp->crp_sid; | 1007 | sav->tdb_cryptoid = crp->crp_sid; | |
1004 | 1008 | |||
1005 | if (crp->crp_etype == EAGAIN) { | 1009 | if (crp->crp_etype == EAGAIN) { | |
1006 | KEY_FREESAV(&sav); | 1010 | KEY_FREESAV(&sav); | |
1007 | mutex_exit(softnet_lock); | 1011 | mutex_exit(softnet_lock); | |
1008 | splx(s); | 1012 | splx(s); | |
1009 | return crypto_dispatch(crp); | 1013 | return crypto_dispatch(crp); | |
1010 | } | 1014 | } | |
1011 | 1015 | |||
1012 | ESP_STATINC(ESP_STAT_NOXFORM); | 1016 | ESP_STATINC(ESP_STAT_NOXFORM); | |
1013 | DPRINTF(("esp_output_cb: crypto error %d\n", crp->crp_etype)); | 1017 | DPRINTF(("esp_output_cb: crypto error %d\n", crp->crp_etype)); | |
1014 | error = crp->crp_etype; | 1018 | error = crp->crp_etype; | |
1015 | goto bad; | 1019 | goto bad; | |
1016 | } | 1020 | } | |
1017 | 1021 | |||
1018 | /* Shouldn't happen... */ | 1022 | /* Shouldn't happen... */ | |
1019 | if (m == NULL) { | 1023 | if (m == NULL) { | |
1020 | ESP_STATINC(ESP_STAT_CRYPTO); | 1024 | ESP_STATINC(ESP_STAT_CRYPTO); | |
1021 | DPRINTF(("esp_output_cb: bogus returned buffer from crypto\n")); | 1025 | DPRINTF(("esp_output_cb: bogus returned buffer from crypto\n")); | |
1022 | error = EINVAL; | 1026 | error = EINVAL; | |
1023 | goto bad; | 1027 | goto bad; | |
1024 | } | 1028 | } | |
1025 | ESP_STATINC(ESP_STAT_HIST + sav->alg_enc); | 1029 | ESP_STATINC(ESP_STAT_HIST + sav->alg_enc); | |
1026 | if (sav->tdb_authalgxform != NULL) | 1030 | if (sav->tdb_authalgxform != NULL) | |
1027 | AH_STATINC(AH_STAT_HIST + sav->alg_auth); | 1031 | AH_STATINC(AH_STAT_HIST + sav->alg_auth); | |
1028 | 1032 | |||
1029 | /* Release crypto descriptors. */ | 1033 | /* Release crypto descriptors. */ | |
1030 | free(tc, M_XDATA); | 1034 | free(tc, M_XDATA); | |
1031 | crypto_freereq(crp); | 1035 | crypto_freereq(crp); | |
1032 | 1036 | |||
1033 | #ifdef IPSEC_DEBUG | 1037 | #ifdef IPSEC_DEBUG | |
1034 | /* Emulate man-in-the-middle attack when ipsec_integrity is TRUE. */ | 1038 | /* Emulate man-in-the-middle attack when ipsec_integrity is TRUE. */ | |
1035 | if (ipsec_integrity) { | 1039 | if (ipsec_integrity) { | |
1036 | static unsigned char ipseczeroes[AH_ALEN_MAX]; | 1040 | static unsigned char ipseczeroes[AH_ALEN_MAX]; | |
1037 | const struct auth_hash *esph; | 1041 | const struct auth_hash *esph; | |
1038 | 1042 | |||
1039 | /* | 1043 | /* | |
1040 | * Corrupt HMAC if we want to test integrity verification of | 1044 | * Corrupt HMAC if we want to test integrity verification of | |
1041 | * the other side. | 1045 | * the other side. | |
1042 | */ | 1046 | */ | |
1043 | esph = sav->tdb_authalgxform; | 1047 | esph = sav->tdb_authalgxform; | |
1044 | if (esph != NULL) { | 1048 | if (esph != NULL) { | |
1045 | m_copyback(m, m->m_pkthdr.len - esph->authsize, | 1049 | m_copyback(m, m->m_pkthdr.len - esph->authsize, | |
1046 | esph->authsize, ipseczeroes); | 1050 | esph->authsize, ipseczeroes); | |
1047 | } | 1051 | } | |
1048 | } | 1052 | } | |
1049 | #endif | 1053 | #endif | |
1050 | 1054 | |||
1051 | /* NB: m is reclaimed by ipsec_process_done. */ | 1055 | /* NB: m is reclaimed by ipsec_process_done. */ | |
1052 | err = ipsec_process_done(m, isr); | 1056 | err = ipsec_process_done(m, isr); | |
1053 | KEY_FREESAV(&sav); | 1057 | KEY_FREESAV(&sav); | |
1054 | mutex_exit(softnet_lock); | 1058 | mutex_exit(softnet_lock); | |
1055 | splx(s); | 1059 | splx(s); | |
1056 | return err; | 1060 | return err; | |
1057 | bad: | 1061 | bad: | |
1058 | if (sav) | 1062 | if (sav) | |
1059 | KEY_FREESAV(&sav); | 1063 | KEY_FREESAV(&sav); | |
1060 | mutex_exit(softnet_lock); | 1064 | mutex_exit(softnet_lock); | |
1061 | splx(s); | 1065 | splx(s); | |
1062 | if (m) | 1066 | if (m) | |
1063 | m_freem(m); | 1067 | m_freem(m); | |
1064 | free(tc, M_XDATA); | 1068 | free(tc, M_XDATA); | |
1065 | crypto_freereq(crp); | 1069 | crypto_freereq(crp); | |
1066 | return error; | 1070 | return error; | |
1067 | } | 1071 | } | |
1068 | 1072 | |||
1069 | static struct xformsw esp_xformsw = { | 1073 | static struct xformsw esp_xformsw = { | |
1070 | XF_ESP, XFT_CONF|XFT_AUTH, "IPsec ESP", | 1074 | XF_ESP, XFT_CONF|XFT_AUTH, "IPsec ESP", | |
1071 | esp_init, esp_zeroize, esp_input, | 1075 | esp_init, esp_zeroize, esp_input, | |
1072 | esp_output, | 1076 | esp_output, | |
1073 | NULL, | 1077 | NULL, | |
1074 | }; | 1078 | }; | |
1075 | 1079 | |||
1076 | INITFN void | 1080 | INITFN void | |
1077 | esp_attach(void) | 1081 | esp_attach(void) | |
1078 | { | 1082 | { | |
1079 | 1083 | |||
1080 | espstat_percpu = percpu_alloc(sizeof(uint64_t) * ESP_NSTATS); | 1084 | espstat_percpu = percpu_alloc(sizeof(uint64_t) * ESP_NSTATS); | |
1081 | 1085 | |||
1082 | #define MAXIV(xform) \ | 1086 | #define MAXIV(xform) \ | |
1083 | if (xform.ivsize > esp_max_ivlen) \ | 1087 | if (xform.ivsize > esp_max_ivlen) \ | |
1084 | esp_max_ivlen = xform.ivsize \ | 1088 | esp_max_ivlen = xform.ivsize \ | |
1085 | 1089 | |||
1086 | esp_max_ivlen = 0; | 1090 | esp_max_ivlen = 0; | |
1087 | MAXIV(enc_xform_des); /* SADB_EALG_DESCBC */ | 1091 | MAXIV(enc_xform_des); /* SADB_EALG_DESCBC */ | |
1088 | MAXIV(enc_xform_3des); /* SADB_EALG_3DESCBC */ | 1092 | MAXIV(enc_xform_3des); /* SADB_EALG_3DESCBC */ | |
1089 | MAXIV(enc_xform_rijndael128); /* SADB_X_EALG_AES */ | 1093 | MAXIV(enc_xform_rijndael128); /* SADB_X_EALG_AES */ | |
1090 | MAXIV(enc_xform_blf); /* SADB_X_EALG_BLOWFISHCBC */ | 1094 | MAXIV(enc_xform_blf); /* SADB_X_EALG_BLOWFISHCBC */ | |
1091 | MAXIV(enc_xform_cast5); /* SADB_X_EALG_CAST128CBC */ | 1095 | MAXIV(enc_xform_cast5); /* SADB_X_EALG_CAST128CBC */ | |
1092 | MAXIV(enc_xform_skipjack); /* SADB_X_EALG_SKIPJACK */ | 1096 | MAXIV(enc_xform_skipjack); /* SADB_X_EALG_SKIPJACK */ | |
1093 | MAXIV(enc_xform_camellia); /* SADB_X_EALG_CAMELLIACBC */ | 1097 | MAXIV(enc_xform_camellia); /* SADB_X_EALG_CAMELLIACBC */ | |
1094 | MAXIV(enc_xform_aes_ctr); /* SADB_X_EALG_AESCTR */ | 1098 | MAXIV(enc_xform_aes_ctr); /* SADB_X_EALG_AESCTR */ | |
1095 | MAXIV(enc_xform_null); /* SADB_EALG_NULL */ | 1099 | MAXIV(enc_xform_null); /* SADB_EALG_NULL */ | |
1096 | 1100 | |||
1097 | xform_register(&esp_xformsw); | 1101 | xform_register(&esp_xformsw); | |
1098 | #undef MAXIV | 1102 | #undef MAXIV | |
1099 | } | 1103 | } | |
1100 | #ifdef __FreeBSD__ | 1104 | #ifdef __FreeBSD__ | |
1101 | SYSINIT(esp_xform_init, SI_SUB_DRIVERS, SI_ORDER_FIRST, esp_attach, NULL) | 1105 | SYSINIT(esp_xform_init, SI_SUB_DRIVERS, SI_ORDER_FIRST, esp_attach, NULL) | |
1102 | #else | 1106 | #else | |
1103 | #endif | 1107 | #endif |
--- src/sys/netipsec/xform_ipip.c 2018/02/15 14:51:44 1.28.14.1
+++ src/sys/netipsec/xform_ipip.c 2018/03/13 17:18:12 1.28.14.2
@@ -1,779 +1,780 @@ | @@ -1,779 +1,780 @@ | |||
1 | /* $NetBSD: xform_ipip.c,v 1.28.14.1 2018/02/15 14:51:44 martin Exp $ */ | 1 | /* $NetBSD: xform_ipip.c,v 1.28.14.2 2018/03/13 17:18:12 snj Exp $ */ | |
2 | /* $FreeBSD: src/sys/netipsec/xform_ipip.c,v 1.3.2.1 2003/01/24 05:11:36 sam Exp $ */ | 2 | /* $FreeBSD: src/sys/netipsec/xform_ipip.c,v 1.3.2.1 2003/01/24 05:11:36 sam Exp $ */ | |
3 | /* $OpenBSD: ip_ipip.c,v 1.25 2002/06/10 18:04:55 itojun Exp $ */ | 3 | /* $OpenBSD: ip_ipip.c,v 1.25 2002/06/10 18:04:55 itojun Exp $ */ | |
4 | 4 | |||
5 | /* | 5 | /* | |
6 | * The authors of this code are John Ioannidis (ji@tla.org), | 6 | * The authors of this code are John Ioannidis (ji@tla.org), | |
7 | * Angelos D. Keromytis (kermit@csd.uch.gr) and | 7 | * Angelos D. Keromytis (kermit@csd.uch.gr) and | |
8 | * Niels Provos (provos@physnet.uni-hamburg.de). | 8 | * Niels Provos (provos@physnet.uni-hamburg.de). | |
9 | * | 9 | * | |
10 | * The original version of this code was written by John Ioannidis | 10 | * The original version of this code was written by John Ioannidis | |
11 | * for BSD/OS in Athens, Greece, in November 1995. | 11 | * for BSD/OS in Athens, Greece, in November 1995. | |
12 | * | 12 | * | |
13 | * Ported to OpenBSD and NetBSD, with additional transforms, in December 1996, | 13 | * Ported to OpenBSD and NetBSD, with additional transforms, in December 1996, | |
14 | * by Angelos D. Keromytis. | 14 | * by Angelos D. Keromytis. | |
15 | * | 15 | * | |
16 | * Additional transforms and features in 1997 and 1998 by Angelos D. Keromytis | 16 | * Additional transforms and features in 1997 and 1998 by Angelos D. Keromytis | |
17 | * and Niels Provos. | 17 | * and Niels Provos. | |
18 | * | 18 | * | |
19 | * Additional features in 1999 by Angelos D. Keromytis. | 19 | * Additional features in 1999 by Angelos D. Keromytis. | |
20 | * | 20 | * | |
21 | * Copyright (C) 1995, 1996, 1997, 1998, 1999 by John Ioannidis, | 21 | * Copyright (C) 1995, 1996, 1997, 1998, 1999 by John Ioannidis, | |
22 | * Angelos D. Keromytis and Niels Provos. | 22 | * Angelos D. Keromytis and Niels Provos. | |
23 | * Copyright (c) 2001, Angelos D. Keromytis. | 23 | * Copyright (c) 2001, Angelos D. Keromytis. | |
24 | * | 24 | * | |
25 | * Permission to use, copy, and modify this software with or without fee | 25 | * Permission to use, copy, and modify this software with or without fee | |
26 | * is hereby granted, provided that this entire notice is included in | 26 | * is hereby granted, provided that this entire notice is included in | |
27 | * all copies of any software which is or includes a copy or | 27 | * all copies of any software which is or includes a copy or | |
28 | * modification of this software. | 28 | * modification of this software. | |
29 | * You may use this code under the GNU public license if you so wish. Please | 29 | * You may use this code under the GNU public license if you so wish. Please | |
30 | * contribute changes back to the authors under this freer than GPL license | 30 | * contribute changes back to the authors under this freer than GPL license | |
31 | * so that we may further the use of strong encryption without limitations to | 31 | * so that we may further the use of strong encryption without limitations to | |
32 | * all. | 32 | * all. | |
33 | * | 33 | * | |
34 | * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR | 34 | * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR | |
35 | * IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY | 35 | * IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY | |
36 | * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE | 36 | * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE | |
37 | * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR | 37 | * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR | |
38 | * PURPOSE. | 38 | * PURPOSE. | |
39 | */ | 39 | */ | |
40 | 40 | |||
41 | #include <sys/cdefs.h> | 41 | #include <sys/cdefs.h> | |
42 | __KERNEL_RCSID(0, "$NetBSD: xform_ipip.c,v 1.28.14.1 2018/02/15 14:51:44 martin Exp $"); | 42 | __KERNEL_RCSID(0, "$NetBSD: xform_ipip.c,v 1.28.14.2 2018/03/13 17:18:12 snj Exp $"); | |
43 | 43 | |||
44 | /* | 44 | /* | |
45 | * IP-inside-IP processing | 45 | * IP-inside-IP processing | |
46 | */ | 46 | */ | |
47 | #include "opt_inet.h" | 47 | #include "opt_inet.h" | |
48 | #ifdef __FreeBSD__ | 48 | #ifdef __FreeBSD__ | |
49 | #include "opt_inet6.h" | 49 | #include "opt_inet6.h" | |
50 | #include "opt_random_ip_id.h" | 50 | #include "opt_random_ip_id.h" | |
51 | #endif /* __FreeBSD__ */ | 51 | #endif /* __FreeBSD__ */ | |
52 | 52 | |||
53 | 53 | |||
54 | #include <sys/param.h> | 54 | #include <sys/param.h> | |
55 | #include <sys/systm.h> | 55 | #include <sys/systm.h> | |
56 | #include <sys/mbuf.h> | 56 | #include <sys/mbuf.h> | |
57 | #include <sys/socket.h> | 57 | #include <sys/socket.h> | |
58 | #include <sys/kernel.h> | 58 | #include <sys/kernel.h> | |
59 | #include <sys/protosw.h> | 59 | #include <sys/protosw.h> | |
60 | #include <sys/sysctl.h> | 60 | #include <sys/sysctl.h> | |
61 | 61 | |||
62 | #include <net/if.h> | 62 | #include <net/if.h> | |
63 | #include <net/route.h> | 63 | #include <net/route.h> | |
64 | #include <net/netisr.h> | 64 | #include <net/netisr.h> | |
65 | 65 | |||
66 | #include <netinet/in.h> | 66 | #include <netinet/in.h> | |
67 | #include <netinet/in_systm.h> | 67 | #include <netinet/in_systm.h> | |
68 | #include <netinet/in_var.h> | 68 | #include <netinet/in_var.h> | |
69 | #include <netinet/ip.h> | 69 | #include <netinet/ip.h> | |
70 | #include <netinet/ip_ecn.h> | 70 | #include <netinet/ip_ecn.h> | |
71 | #include <netinet/ip_var.h> | 71 | #include <netinet/ip_var.h> | |
72 | #include <netinet/ip_encap.h> | 72 | #include <netinet/ip_encap.h> | |
73 | #ifdef __FreeBSD__ | 73 | #ifdef __FreeBSD__ | |
74 | #include <netinet/ipprotosw.h> | 74 | #include <netinet/ipprotosw.h> | |
75 | #endif | 75 | #endif | |
76 | 76 | |||
77 | #include <netipsec/ipsec.h> | 77 | #include <netipsec/ipsec.h> | |
78 | #include <netipsec/ipsec_private.h> | 78 | #include <netipsec/ipsec_private.h> | |
79 | #include <netipsec/xform.h> | 79 | #include <netipsec/xform.h> | |
80 | 80 | |||
81 | #include <netipsec/ipip_var.h> | 81 | #include <netipsec/ipip_var.h> | |
82 | 82 | |||
83 | #ifdef MROUTING | 83 | #ifdef MROUTING | |
84 | #include <netinet/ip_mroute.h> | 84 | #include <netinet/ip_mroute.h> | |
85 | #endif | 85 | #endif | |
86 | 86 | |||
87 | #ifdef INET6 | 87 | #ifdef INET6 | |
88 | #include <netinet/ip6.h> | 88 | #include <netinet/ip6.h> | |
89 | #include <netipsec/ipsec6.h> | 89 | #include <netipsec/ipsec6.h> | |
90 | # ifdef __FreeBSD__ | 90 | # ifdef __FreeBSD__ | |
91 | # include <netinet6/ip6_ecn.h> | 91 | # include <netinet6/ip6_ecn.h> | |
92 | # endif | 92 | # endif | |
93 | #include <netinet6/in6_var.h> | 93 | #include <netinet6/in6_var.h> | |
94 | #include <netinet6/ip6protosw.h> | 94 | #include <netinet6/ip6protosw.h> | |
95 | #endif | 95 | #endif | |
96 | 96 | |||
97 | #include <netipsec/key.h> | 97 | #include <netipsec/key.h> | |
98 | #include <netipsec/key_debug.h> | 98 | #include <netipsec/key_debug.h> | |
99 | #include <netipsec/ipsec_osdep.h> | 99 | #include <netipsec/ipsec_osdep.h> | |
100 | 100 | |||
101 | #ifdef __FreeBSD__ | 101 | #ifdef __FreeBSD__ | |
102 | typedef void pr_in_input_t (struct mbuf *, int, int); /* XXX FIX THIS */ | 102 | typedef void pr_in_input_t (struct mbuf *, int, int); /* XXX FIX THIS */ | |
103 | #else | 103 | #else | |
104 | typedef void pr_in_input_t (struct mbuf *m, ...); | 104 | typedef void pr_in_input_t (struct mbuf *m, ...); | |
105 | #endif | 105 | #endif | |
106 | 106 | |||
107 | /* | 107 | /* | |
108 | * We can control the acceptance of IP4 packets by altering the sysctl | 108 | * We can control the acceptance of IP4 packets by altering the sysctl | |
109 | * net.inet.ipip.allow value. Zero means drop them, all else is acceptance. | 109 | * net.inet.ipip.allow value. Zero means drop them, all else is acceptance. | |
110 | */ | 110 | */ | |
111 | int ipip_allow = 0; | 111 | int ipip_allow = 0; | |
112 | 112 | |||
113 | percpu_t *ipipstat_percpu; | 113 | percpu_t *ipipstat_percpu; | |
114 | 114 | |||
115 | #ifdef SYSCTL_DECL | 115 | #ifdef SYSCTL_DECL | |
116 | SYSCTL_DECL(_net_inet_ipip); | 116 | SYSCTL_DECL(_net_inet_ipip); | |
117 | 117 | |||
118 | SYSCTL_INT(_net_inet_ipip, OID_AUTO, | 118 | SYSCTL_INT(_net_inet_ipip, OID_AUTO, | |
119 | ipip_allow, CTLFLAG_RW, &ipip_allow, 0, ""); | 119 | ipip_allow, CTLFLAG_RW, &ipip_allow, 0, ""); | |
120 | SYSCTL_STRUCT(_net_inet_ipip, IPSECCTL_STATS, | 120 | SYSCTL_STRUCT(_net_inet_ipip, IPSECCTL_STATS, | |
121 | stats, CTLFLAG_RD, &ipipstat, ipipstat, ""); | 121 | stats, CTLFLAG_RD, &ipipstat, ipipstat, ""); | |
122 | 122 | |||
123 | #endif | 123 | #endif | |
124 | 124 | |||
125 | #ifdef __FreeBSD__ | 125 | #ifdef __FreeBSD__ | |
126 | static | 126 | static | |
127 | #endif | 127 | #endif | |
128 | void ipe4_attach(void); | 128 | void ipe4_attach(void); | |
129 | 129 | |||
130 | 130 | |||
131 | /* XXX IPCOMP */ | 131 | /* XXX IPCOMP */ | |
132 | #define M_IPSEC (M_AUTHIPHDR|M_AUTHIPDGM|M_DECRYPTED) | 132 | #define M_IPSEC (M_AUTHIPHDR|M_AUTHIPDGM|M_DECRYPTED) | |
133 | 133 | |||
134 | static void _ipip_input(struct mbuf *m, int iphlen, struct ifnet *gifp); | 134 | static void _ipip_input(struct mbuf *m, int iphlen, struct ifnet *gifp); | |
135 | 135 | |||
136 | #ifdef INET6 | 136 | #ifdef INET6 | |
137 | /* | 137 | /* | |
138 | * Really only a wrapper for ipip_input(), for use with IPv6. | 138 | * Really only a wrapper for ipip_input(), for use with IPv6. | |
139 | */ | 139 | */ | |
140 | int | 140 | int | |
141 | ip4_input6(struct mbuf **m, int *offp, int proto) | 141 | ip4_input6(struct mbuf **m, int *offp, int proto) | |
142 | { | 142 | { | |
143 | #if 0 | 143 | #if 0 | |
144 | /* If we do not accept IP-in-IP explicitly, drop. */ | 144 | /* If we do not accept IP-in-IP explicitly, drop. */ | |
145 | if (!ipip_allow && ((*m)->m_flags & M_IPSEC) == 0) { | 145 | if (!ipip_allow && ((*m)->m_flags & M_IPSEC) == 0) { | |
146 | DPRINTF(("ip4_input6: dropped due to policy\n")); | 146 | DPRINTF(("ip4_input6: dropped due to policy\n")); | |
147 | IPIP_STATINC(IPIP_STAT_PDROPS); | 147 | IPIP_STATINC(IPIP_STAT_PDROPS); | |
148 | m_freem(*m); | 148 | m_freem(*m); | |
149 | return IPPROTO_DONE; | 149 | return IPPROTO_DONE; | |
150 | } | 150 | } | |
151 | #endif | 151 | #endif | |
152 | _ipip_input(*m, *offp, NULL); | 152 | _ipip_input(*m, *offp, NULL); | |
153 | return IPPROTO_DONE; | 153 | return IPPROTO_DONE; | |
154 | } | 154 | } | |
155 | #endif /* INET6 */ | 155 | #endif /* INET6 */ | |
156 | 156 | |||
157 | #ifdef INET | 157 | #ifdef INET | |
158 | /* | 158 | /* | |
159 | * Really only a wrapper for ipip_input(), for use with IPv4. | 159 | * Really only a wrapper for ipip_input(), for use with IPv4. | |
160 | */ | 160 | */ | |
161 | void | 161 | void | |
162 | ip4_input(struct mbuf *m, ...) | 162 | ip4_input(struct mbuf *m, ...) | |
163 | { | 163 | { | |
164 | va_list ap; | 164 | va_list ap; | |
165 | int iphlen; | 165 | int iphlen; | |
166 | 166 | |||
167 | #if 0 | 167 | #if 0 | |
168 | /* If we do not accept IP-in-IP explicitly, drop. */ | 168 | /* If we do not accept IP-in-IP explicitly, drop. */ | |
169 | if (!ipip_allow && (m->m_flags & M_IPSEC) == 0) { | 169 | if (!ipip_allow && (m->m_flags & M_IPSEC) == 0) { | |
170 | DPRINTF(("ip4_input: dropped due to policy\n")); | 170 | DPRINTF(("ip4_input: dropped due to policy\n")); | |
171 | IPIP_STATINC(IPIP_STAT_PDROPS); | 171 | IPIP_STATINC(IPIP_STAT_PDROPS); | |
172 | m_freem(m); | 172 | m_freem(m); | |
173 | return; | 173 | return; | |
174 | } | 174 | } | |
175 | #endif | 175 | #endif | |
176 | va_start(ap, m); | 176 | va_start(ap, m); | |
177 | iphlen = va_arg(ap, int); | 177 | iphlen = va_arg(ap, int); | |
178 | va_end(ap); | 178 | va_end(ap); | |
179 | 179 | |||
180 | _ipip_input(m, iphlen, NULL); | 180 | _ipip_input(m, iphlen, NULL); | |
181 | } | 181 | } | |
182 | #endif /* INET */ | 182 | #endif /* INET */ | |
183 | 183 | |||
184 | /* | 184 | /* | |
185 | * ipip_input gets called when we receive an IP{46} encapsulated packet, | 185 | * ipip_input gets called when we receive an IP{46} encapsulated packet, | |
186 | * either because we got it at a real interface, or because AH or ESP | 186 | * either because we got it at a real interface, or because AH or ESP | |
187 | * were being used in tunnel mode (in which case the rcvif element will | 187 | * were being used in tunnel mode (in which case the rcvif element will | |
188 | * contain the address of the encX interface associated with the tunnel. | 188 | * contain the address of the encX interface associated with the tunnel. | |
189 | */ | 189 | */ | |
190 | 190 | |||
191 | static void | 191 | static void | |
192 | _ipip_input(struct mbuf *m, int iphlen, struct ifnet *gifp) | 192 | _ipip_input(struct mbuf *m, int iphlen, struct ifnet *gifp) | |
193 | { | 193 | { | |
194 | register struct sockaddr_in *sin; | 194 | register struct sockaddr_in *sin; | |
195 | register struct ifnet *ifp; | 195 | register struct ifnet *ifp; | |
196 | register struct ifaddr *ifa; | 196 | register struct ifaddr *ifa; | |
197 | struct ifqueue *ifq = NULL; | 197 | struct ifqueue *ifq = NULL; | |
198 | struct ip *ipo; | 198 | struct ip *ipo; | |
199 | #ifdef INET6 | 199 | #ifdef INET6 | |
200 | register struct sockaddr_in6 *sin6; | 200 | register struct sockaddr_in6 *sin6; | |
201 | struct ip6_hdr *ip6 = NULL; | 201 | struct ip6_hdr *ip6 = NULL; | |
202 | u_int8_t itos; | 202 | u_int8_t itos; | |
203 | #endif | 203 | #endif | |
204 | int isr; | 204 | int isr; | |
205 | u_int8_t otos; | 205 | u_int8_t otos; | |
206 | u_int8_t v; | 206 | u_int8_t v; | |
207 | int hlen; | 207 | int hlen; | |
208 | 208 | |||
209 | IPIP_STATINC(IPIP_STAT_IPACKETS); | 209 | IPIP_STATINC(IPIP_STAT_IPACKETS); | |
210 | 210 | |||
211 | m_copydata(m, 0, 1, &v); | 211 | m_copydata(m, 0, 1, &v); | |
212 | 212 | |||
213 | switch (v >> 4) { | 213 | switch (v >> 4) { | |
214 | #ifdef INET | 214 | #ifdef INET | |
215 | case 4: | 215 | case 4: | |
216 | hlen = sizeof(struct ip); | 216 | hlen = sizeof(struct ip); | |
217 | break; | 217 | break; | |
218 | #endif /* INET */ | 218 | #endif /* INET */ | |
219 | #ifdef INET6 | 219 | #ifdef INET6 | |
220 | case 6: | 220 | case 6: | |
221 | hlen = sizeof(struct ip6_hdr); | 221 | hlen = sizeof(struct ip6_hdr); | |
222 | break; | 222 | break; | |
223 | #endif | 223 | #endif | |
224 | default: | 224 | default: | |
225 | DPRINTF(("_ipip_input: bad protocol version 0x%x (%u) " | 225 | DPRINTF(("_ipip_input: bad protocol version 0x%x (%u) " | |
226 | "for outer header\n", v, v>>4)); | 226 | "for outer header\n", v, v>>4)); | |
227 | IPIP_STATINC(IPIP_STAT_FAMILY); | 227 | IPIP_STATINC(IPIP_STAT_FAMILY); | |
228 | m_freem(m); | 228 | m_freem(m); | |
229 | return /* EAFNOSUPPORT */; | 229 | return /* EAFNOSUPPORT */; | |
230 | } | 230 | } | |
231 | 231 | |||
232 | /* Bring the IP header in the first mbuf, if not there already */ | 232 | /* Bring the IP header in the first mbuf, if not there already */ | |
233 | if (m->m_len < hlen) { | 233 | if (m->m_len < hlen) { | |
234 | if ((m = m_pullup(m, hlen)) == NULL) { | 234 | if ((m = m_pullup(m, hlen)) == NULL) { | |
235 | DPRINTF(("ipip_input: m_pullup (1) failed\n")); | 235 | DPRINTF(("ipip_input: m_pullup (1) failed\n")); | |
236 | IPIP_STATINC(IPIP_STAT_HDROPS); | 236 | IPIP_STATINC(IPIP_STAT_HDROPS); | |
237 | return; | 237 | return; | |
238 | } | 238 | } | |
239 | } | 239 | } | |
240 | 240 | |||
241 | ipo = mtod(m, struct ip *); | 241 | ipo = mtod(m, struct ip *); | |
242 | 242 | |||
243 | #ifdef MROUTING | 243 | #ifdef MROUTING | |
244 | if (ipo->ip_v == IPVERSION && ipo->ip_p == IPPROTO_IPV4) { | 244 | if (ipo->ip_v == IPVERSION && ipo->ip_p == IPPROTO_IPV4) { | |
245 | if (IN_MULTICAST(((struct ip *)((char *) ipo + iphlen))->ip_dst.s_addr)) { | 245 | if (IN_MULTICAST(((struct ip *)((char *) ipo + iphlen))->ip_dst.s_addr)) { | |
246 | ipip_mroute_input (m, iphlen); | 246 | ipip_mroute_input (m, iphlen); | |
247 | return; | 247 | return; | |
248 | } | 248 | } | |
249 | } | 249 | } | |
250 | #endif /* MROUTING */ | 250 | #endif /* MROUTING */ | |
251 | 251 | |||
252 | /* Keep outer ecn field. */ | 252 | /* Keep outer ecn field. */ | |
253 | switch (v >> 4) { | 253 | switch (v >> 4) { | |
254 | #ifdef INET | 254 | #ifdef INET | |
255 | case 4: | 255 | case 4: | |
256 | otos = ipo->ip_tos; | 256 | otos = ipo->ip_tos; | |
257 | break; | 257 | break; | |
258 | #endif /* INET */ | 258 | #endif /* INET */ | |
259 | #ifdef INET6 | 259 | #ifdef INET6 | |
260 | case 6: | 260 | case 6: | |
261 | otos = (ntohl(mtod(m, struct ip6_hdr *)->ip6_flow) >> 20) & 0xff; | 261 | otos = (ntohl(mtod(m, struct ip6_hdr *)->ip6_flow) >> 20) & 0xff; | |
262 | break; | 262 | break; | |
263 | #endif | 263 | #endif | |
264 | default: | 264 | default: | |
265 | panic("ipip_input: unknown ip version %u (outer)", v>>4); | 265 | panic("ipip_input: unknown ip version %u (outer)", v>>4); | |
266 | } | 266 | } | |
267 | 267 | |||
268 | /* Remove outer IP header */ | 268 | /* Remove outer IP header */ | |
269 | m_adj(m, iphlen); | 269 | m_adj(m, iphlen); | |
270 | 270 | |||
271 | /* Sanity check */ | 271 | /* Sanity check */ | |
272 | if (m->m_pkthdr.len < sizeof(struct ip)) { | 272 | if (m->m_pkthdr.len < sizeof(struct ip)) { | |
273 | IPIP_STATINC(IPIP_STAT_HDROPS); | 273 | IPIP_STATINC(IPIP_STAT_HDROPS); | |
274 | m_freem(m); | 274 | m_freem(m); | |
275 | return; | 275 | return; | |
276 | } | 276 | } | |
277 | 277 | |||
278 | m_copydata(m, 0, 1, &v); | 278 | m_copydata(m, 0, 1, &v); | |
279 | 279 | |||
280 | switch (v >> 4) { | 280 | switch (v >> 4) { | |
281 | #ifdef INET | 281 | #ifdef INET | |
282 | case 4: | 282 | case 4: | |
283 | hlen = sizeof(struct ip); | 283 | hlen = sizeof(struct ip); | |
284 | break; | 284 | break; | |
285 | #endif /* INET */ | 285 | #endif /* INET */ | |
286 | 286 | |||
287 | #ifdef INET6 | 287 | #ifdef INET6 | |
288 | case 6: | 288 | case 6: | |
289 | hlen = sizeof(struct ip6_hdr); | 289 | hlen = sizeof(struct ip6_hdr); | |
290 | break; | 290 | break; | |
291 | #endif | 291 | #endif | |
292 | default: | 292 | default: | |
293 | DPRINTF(("_ipip_input: bad protocol version 0x%x (%u) " | 293 | DPRINTF(("_ipip_input: bad protocol version 0x%x (%u) " | |
294 | "for inner header\n", v, v>>4)); | 294 | "for inner header\n", v, v>>4)); | |
295 | IPIP_STATINC(IPIP_STAT_FAMILY); | 295 | IPIP_STATINC(IPIP_STAT_FAMILY); | |
296 | m_freem(m); | 296 | m_freem(m); | |
297 | return; /* EAFNOSUPPORT */ | 297 | return; /* EAFNOSUPPORT */ | |
298 | } | 298 | } | |
299 | 299 | |||
300 | /* | 300 | /* | |
301 | * Bring the inner IP header in the first mbuf, if not there already. | 301 | * Bring the inner IP header in the first mbuf, if not there already. | |
302 | */ | 302 | */ | |
303 | if (m->m_len < hlen) { | 303 | if (m->m_len < hlen) { | |
304 | if ((m = m_pullup(m, hlen)) == NULL) { | 304 | if ((m = m_pullup(m, hlen)) == NULL) { | |
305 | DPRINTF(("ipip_input: m_pullup (2) failed\n")); | 305 | DPRINTF(("ipip_input: m_pullup (2) failed\n")); | |
306 | IPIP_STATINC(IPIP_STAT_HDROPS); | 306 | IPIP_STATINC(IPIP_STAT_HDROPS); | |
307 | return; | 307 | return; | |
308 | } | 308 | } | |
309 | } | 309 | } | |
310 | 310 | |||
311 | /* | 311 | /* | |
312 | * RFC 1853 specifies that the inner TTL should not be touched on | 312 | * RFC 1853 specifies that the inner TTL should not be touched on | |
313 | * decapsulation. There's no reason this comment should be here, but | 313 | * decapsulation. There's no reason this comment should be here, but | |
314 | * this is as good as any a position. | 314 | * this is as good as any a position. | |
315 | */ | 315 | */ | |
316 | 316 | |||
317 | /* Some sanity checks in the inner IP header */ | 317 | /* Some sanity checks in the inner IP header */ | |
318 | switch (v >> 4) { | 318 | switch (v >> 4) { | |
319 | #ifdef INET | 319 | #ifdef INET | |
320 | case 4: | 320 | case 4: | |
321 | ipo = mtod(m, struct ip *); | 321 | ipo = mtod(m, struct ip *); | |
322 | ip_ecn_egress(ip4_ipsec_ecn, &otos, &ipo->ip_tos); | 322 | ip_ecn_egress(ip4_ipsec_ecn, &otos, &ipo->ip_tos); | |
323 | break; | 323 | break; | |
324 | #endif /* INET */ | 324 | #endif /* INET */ | |
325 | #ifdef INET6 | 325 | #ifdef INET6 | |
326 | case 6: | 326 | case 6: | |
327 | ip6 = (struct ip6_hdr *) ipo; | 327 | ipo = NULL; | |
328 | ip6 = mtod(m, struct ip6_hdr *); | |||
328 | itos = (ntohl(ip6->ip6_flow) >> 20) & 0xff; | 329 | itos = (ntohl(ip6->ip6_flow) >> 20) & 0xff; | |
329 | ip_ecn_egress(ip6_ipsec_ecn, &otos, &itos); | 330 | ip_ecn_egress(ip6_ipsec_ecn, &otos, &itos); | |
330 | ip6->ip6_flow &= ~htonl(0xff << 20); | 331 | ip6->ip6_flow &= ~htonl(0xff << 20); | |
331 | ip6->ip6_flow |= htonl((u_int32_t) itos << 20); | 332 | ip6->ip6_flow |= htonl((u_int32_t) itos << 20); | |
332 | break; | 333 | break; | |
333 | #endif | 334 | #endif | |
334 | default: | 335 | default: | |
335 | panic("ipip_input: unknown ip version %u (inner)", v>>4); | 336 | panic("ipip_input: unknown ip version %u (inner)", v>>4); | |
336 | } | 337 | } | |
337 | 338 | |||
338 | /* Check for local address spoofing. */ | 339 | /* Check for local address spoofing. */ | |
339 | if ((m->m_pkthdr.rcvif == NULL || | 340 | if ((m->m_pkthdr.rcvif == NULL || | |
340 | !(m->m_pkthdr.rcvif->if_flags & IFF_LOOPBACK)) && | 341 | !(m->m_pkthdr.rcvif->if_flags & IFF_LOOPBACK)) && | |
341 | ipip_allow != 2) { | 342 | ipip_allow != 2) { | |
342 | IFNET_FOREACH(ifp) { | 343 | IFNET_FOREACH(ifp) { | |
343 | IFADDR_FOREACH(ifa, ifp) { | 344 | IFADDR_FOREACH(ifa, ifp) { | |
344 | #ifdef INET | 345 | #ifdef INET | |
345 | if (ipo) { | 346 | if (ipo) { | |
346 | if (ifa->ifa_addr->sa_family != | 347 | if (ifa->ifa_addr->sa_family != | |
347 | AF_INET) | 348 | AF_INET) | |
348 | continue; | 349 | continue; | |
349 | 350 | |||
350 | sin = (struct sockaddr_in *) ifa->ifa_addr; | 351 | sin = (struct sockaddr_in *) ifa->ifa_addr; | |
351 | 352 | |||
352 | if (sin->sin_addr.s_addr == | 353 | if (sin->sin_addr.s_addr == | |
353 | ipo->ip_src.s_addr) { | 354 | ipo->ip_src.s_addr) { | |
354 | IPIP_STATINC(IPIP_STAT_SPOOF); | 355 | IPIP_STATINC(IPIP_STAT_SPOOF); | |
355 | m_freem(m); | 356 | m_freem(m); | |
356 | return; | 357 | return; | |
357 | } | 358 | } | |
358 | } | 359 | } | |
359 | #endif /* INET */ | 360 | #endif /* INET */ | |
360 | 361 | |||
361 | #ifdef INET6 | 362 | #ifdef INET6 | |
362 | if (ip6) { | 363 | if (ip6) { | |
363 | if (ifa->ifa_addr->sa_family != | 364 | if (ifa->ifa_addr->sa_family != | |
364 | AF_INET6) | 365 | AF_INET6) | |
365 | continue; | 366 | continue; | |
366 | 367 | |||
367 | sin6 = (struct sockaddr_in6 *) ifa->ifa_addr; | 368 | sin6 = (struct sockaddr_in6 *) ifa->ifa_addr; | |
368 | 369 | |||
369 | if (IN6_ARE_ADDR_EQUAL(&sin6->sin6_addr, &ip6->ip6_src)) { | 370 | if (IN6_ARE_ADDR_EQUAL(&sin6->sin6_addr, &ip6->ip6_src)) { | |
370 | IPIP_STATINC(IPIP_STAT_SPOOF); | 371 | IPIP_STATINC(IPIP_STAT_SPOOF); | |
371 | m_freem(m); | 372 | m_freem(m); | |
372 | return; | 373 | return; | |
373 | } | 374 | } | |
374 | 375 | |||
375 | } | 376 | } | |
376 | #endif /* INET6 */ | 377 | #endif /* INET6 */ | |
377 | } | 378 | } | |
378 | } | 379 | } | |
379 | } | 380 | } | |
380 | 381 | |||
381 | /* Statistics */ | 382 | /* Statistics */ | |
382 | IPIP_STATADD(IPIP_STAT_IBYTES, m->m_pkthdr.len - iphlen); | 383 | IPIP_STATADD(IPIP_STAT_IBYTES, m->m_pkthdr.len - iphlen); | |
383 | 384 | |||
384 | /* | 385 | /* | |
385 | * Interface pointer stays the same; if no IPsec processing has | 386 | * Interface pointer stays the same; if no IPsec processing has | |
386 | * been done (or will be done), this will point to a normal | 387 | * been done (or will be done), this will point to a normal | |
387 | * interface. Otherwise, it'll point to an enc interface, which | 388 | * interface. Otherwise, it'll point to an enc interface, which | |
388 | * will allow a packet filter to distinguish between secure and | 389 | * will allow a packet filter to distinguish between secure and | |
389 | * untrusted packets. | 390 | * untrusted packets. | |
390 | */ | 391 | */ | |
391 | 392 | |||
392 | switch (v >> 4) { | 393 | switch (v >> 4) { | |
393 | #ifdef INET | 394 | #ifdef INET | |
394 | case 4: | 395 | case 4: | |
395 | ifq = &ipintrq; | 396 | ifq = &ipintrq; | |
396 | isr = NETISR_IP; | 397 | isr = NETISR_IP; | |
397 | break; | 398 | break; | |
398 | #endif | 399 | #endif | |
399 | #ifdef INET6 | 400 | #ifdef INET6 | |
400 | case 6: | 401 | case 6: | |
401 | ifq = &ip6intrq; | 402 | ifq = &ip6intrq; | |
402 | isr = NETISR_IPV6; | 403 | isr = NETISR_IPV6; | |
403 | break; | 404 | break; | |
404 | #endif | 405 | #endif | |
405 | default: | 406 | default: | |
406 | panic("ipip_input: should never reach here"); | 407 | panic("ipip_input: should never reach here"); | |
407 | } | 408 | } | |
408 | 409 | |||
409 | if (!IF_HANDOFF(ifq, m, NULL)) { | 410 | if (!IF_HANDOFF(ifq, m, NULL)) { | |
410 | IPIP_STATINC(IPIP_STAT_QFULL); | 411 | IPIP_STATINC(IPIP_STAT_QFULL); | |
411 | 412 | |||
412 | DPRINTF(("ipip_input: packet dropped because of full queue\n")); | 413 | DPRINTF(("ipip_input: packet dropped because of full queue\n")); | |
413 | } else { | 414 | } else { | |
414 | schednetisr(isr); | 415 | schednetisr(isr); | |
415 | } | 416 | } | |
416 | } | 417 | } | |
417 | 418 | |||
418 | int | 419 | int | |
419 | ipip_output( | 420 | ipip_output( | |
420 | struct mbuf *m, | 421 | struct mbuf *m, | |
421 | struct ipsecrequest *isr, | 422 | struct ipsecrequest *isr, | |
422 | struct mbuf **mp, | 423 | struct mbuf **mp, | |
423 | int skip, | 424 | int skip, | |
424 | int protoff | 425 | int protoff | |
425 | ) | 426 | ) | |
426 | { | 427 | { | |
427 | const struct secasvar *sav; | 428 | const struct secasvar *sav; | |
428 | u_int8_t tp, otos; | 429 | u_int8_t tp, otos; | |
429 | struct secasindex *saidx; | 430 | struct secasindex *saidx; | |
430 | int error; | 431 | int error; | |
431 | #ifdef INET | 432 | #ifdef INET | |
432 | u_int8_t itos; | 433 | u_int8_t itos; | |
433 | struct ip *ipo; | 434 | struct ip *ipo; | |
434 | #endif /* INET */ | 435 | #endif /* INET */ | |
435 | #ifdef INET6 | 436 | #ifdef INET6 | |
436 | struct ip6_hdr *ip6, *ip6o; | 437 | struct ip6_hdr *ip6, *ip6o; | |
437 | #endif /* INET6 */ | 438 | #endif /* INET6 */ | |
438 | 439 | |||
439 | IPSEC_SPLASSERT_SOFTNET("ipip_output"); | 440 | IPSEC_SPLASSERT_SOFTNET("ipip_output"); | |
440 | 441 | |||
441 | sav = isr->sav; | 442 | sav = isr->sav; | |
442 | IPSEC_ASSERT(sav != NULL, ("ipip_output: null SA")); | 443 | IPSEC_ASSERT(sav != NULL, ("ipip_output: null SA")); | |
443 | IPSEC_ASSERT(sav->sah != NULL, ("ipip_output: null SAH")); | 444 | IPSEC_ASSERT(sav->sah != NULL, ("ipip_output: null SAH")); | |
444 | 445 | |||
445 | /* XXX Deal with empty TDB source/destination addresses. */ | 446 | /* XXX Deal with empty TDB source/destination addresses. */ | |
446 | 447 | |||
447 | m_copydata(m, 0, 1, &tp); | 448 | m_copydata(m, 0, 1, &tp); | |
448 | tp = (tp >> 4) & 0xff; /* Get the IP version number. */ | 449 | tp = (tp >> 4) & 0xff; /* Get the IP version number. */ | |
449 | 450 | |||
450 | saidx = &sav->sah->saidx; | 451 | saidx = &sav->sah->saidx; | |
451 | switch (saidx->dst.sa.sa_family) { | 452 | switch (saidx->dst.sa.sa_family) { | |
452 | #ifdef INET | 453 | #ifdef INET | |
453 | case AF_INET: | 454 | case AF_INET: | |
454 | if (saidx->src.sa.sa_family != AF_INET || | 455 | if (saidx->src.sa.sa_family != AF_INET || | |
455 | saidx->src.sin.sin_addr.s_addr == INADDR_ANY || | 456 | saidx->src.sin.sin_addr.s_addr == INADDR_ANY || | |
456 | saidx->dst.sin.sin_addr.s_addr == INADDR_ANY) { | 457 | saidx->dst.sin.sin_addr.s_addr == INADDR_ANY) { | |
457 | DPRINTF(("ipip_output: unspecified tunnel endpoint " | 458 | DPRINTF(("ipip_output: unspecified tunnel endpoint " | |
458 | "address in SA %s/%08lx\n", | 459 | "address in SA %s/%08lx\n", | |
459 | ipsec_address(&saidx->dst), | 460 | ipsec_address(&saidx->dst), | |
460 | (u_long) ntohl(sav->spi))); | 461 | (u_long) ntohl(sav->spi))); | |
461 | IPIP_STATINC(IPIP_STAT_UNSPEC); | 462 | IPIP_STATINC(IPIP_STAT_UNSPEC); | |
462 | error = EINVAL; | 463 | error = EINVAL; | |
463 | goto bad; | 464 | goto bad; | |
464 | } | 465 | } | |
465 | 466 | |||
466 | M_PREPEND(m, sizeof(struct ip), M_DONTWAIT); | 467 | M_PREPEND(m, sizeof(struct ip), M_DONTWAIT); | |
467 | if (m == 0) { | 468 | if (m == 0) { | |
468 | DPRINTF(("ipip_output: M_PREPEND failed\n")); | 469 | DPRINTF(("ipip_output: M_PREPEND failed\n")); | |
469 | IPIP_STATINC(IPIP_STAT_HDROPS); | 470 | IPIP_STATINC(IPIP_STAT_HDROPS); | |
470 | error = ENOBUFS; | 471 | error = ENOBUFS; | |
471 | goto bad; | 472 | goto bad; | |
472 | } | 473 | } | |
473 | 474 | |||
474 | ipo = mtod(m, struct ip *); | 475 | ipo = mtod(m, struct ip *); | |
475 | 476 | |||
476 | ipo->ip_v = IPVERSION; | 477 | ipo->ip_v = IPVERSION; | |
477 | ipo->ip_hl = 5; | 478 | ipo->ip_hl = 5; | |
478 | ipo->ip_len = htons(m->m_pkthdr.len); | 479 | ipo->ip_len = htons(m->m_pkthdr.len); | |
479 | ipo->ip_ttl = ip_defttl; | 480 | ipo->ip_ttl = ip_defttl; | |
480 | ipo->ip_sum = 0; | 481 | ipo->ip_sum = 0; | |
481 | ipo->ip_src = saidx->src.sin.sin_addr; | 482 | ipo->ip_src = saidx->src.sin.sin_addr; | |
482 | ipo->ip_dst = saidx->dst.sin.sin_addr; | 483 | ipo->ip_dst = saidx->dst.sin.sin_addr; | |
483 | 484 | |||
484 | #if defined(__NetBSD__) | 485 | #if defined(__NetBSD__) | |
485 | ipo->ip_id = ip_newid(NULL); | 486 | ipo->ip_id = ip_newid(NULL); | |
486 | #elif defined(RANDOM_IP_ID) | 487 | #elif defined(RANDOM_IP_ID) | |
487 | ipo->ip_id = ip_randomid(); | 488 | ipo->ip_id = ip_randomid(); | |
488 | #else | 489 | #else | |
489 | ipo->ip_id = htons(ip_id++); | 490 | ipo->ip_id = htons(ip_id++); | |
490 | #endif | 491 | #endif | |
491 | 492 | |||
492 | /* If the inner protocol is IP... */ | 493 | /* If the inner protocol is IP... */ | |
493 | if (tp == IPVERSION) { | 494 | if (tp == IPVERSION) { | |
494 | /* Save ECN notification */ | 495 | /* Save ECN notification */ | |
495 | m_copydata(m, sizeof(struct ip) + | 496 | m_copydata(m, sizeof(struct ip) + | |
496 | offsetof(struct ip, ip_tos), | 497 | offsetof(struct ip, ip_tos), | |
497 | sizeof(u_int8_t), &itos); | 498 | sizeof(u_int8_t), &itos); | |
498 | 499 | |||
499 | ipo->ip_p = IPPROTO_IPIP; | 500 | ipo->ip_p = IPPROTO_IPIP; | |
500 | 501 | |||
501 | /* | 502 | /* | |
502 | * We should be keeping tunnel soft-state and | 503 | * We should be keeping tunnel soft-state and | |
503 | * send back ICMPs if needed. | 504 | * send back ICMPs if needed. | |
504 | */ | 505 | */ | |
505 | m_copydata(m, sizeof(struct ip) + | 506 | m_copydata(m, sizeof(struct ip) + | |
506 | offsetof(struct ip, ip_off), | 507 | offsetof(struct ip, ip_off), | |
507 | sizeof(u_int16_t), &ipo->ip_off); | 508 | sizeof(u_int16_t), &ipo->ip_off); | |
508 | ipo->ip_off &= ~ IP_OFF_CONVERT(IP_DF | IP_MF | IP_OFFMASK); | 509 | ipo->ip_off &= ~ IP_OFF_CONVERT(IP_DF | IP_MF | IP_OFFMASK); | |
509 | } | 510 | } | |
510 | #ifdef INET6 | 511 | #ifdef INET6 | |
511 | else if (tp == (IPV6_VERSION >> 4)) { | 512 | else if (tp == (IPV6_VERSION >> 4)) { | |
512 | u_int32_t itos32; | 513 | u_int32_t itos32; | |
513 | 514 | |||
514 | /* Save ECN notification. */ | 515 | /* Save ECN notification. */ | |
515 | m_copydata(m, sizeof(struct ip) + | 516 | m_copydata(m, sizeof(struct ip) + | |
516 | offsetof(struct ip6_hdr, ip6_flow), | 517 | offsetof(struct ip6_hdr, ip6_flow), | |
517 | sizeof(u_int32_t), &itos32); | 518 | sizeof(u_int32_t), &itos32); | |
518 | itos = ntohl(itos32) >> 20; | 519 | itos = ntohl(itos32) >> 20; | |
519 | ipo->ip_p = IPPROTO_IPV6; | 520 | ipo->ip_p = IPPROTO_IPV6; | |
520 | ipo->ip_off = 0; | 521 | ipo->ip_off = 0; | |
521 | } | 522 | } | |
522 | #endif /* INET6 */ | 523 | #endif /* INET6 */ | |
523 | else { | 524 | else { | |
524 | goto nofamily; | 525 | goto nofamily; | |
525 | } | 526 | } | |
526 | 527 | |||
527 | otos = 0; | 528 | otos = 0; | |
528 | ip_ecn_ingress(ECN_ALLOWED, &otos, &itos); | 529 | ip_ecn_ingress(ECN_ALLOWED, &otos, &itos); | |
529 | ipo->ip_tos = otos; | 530 | ipo->ip_tos = otos; | |
530 | break; | 531 | break; | |
531 | #endif /* INET */ | 532 | #endif /* INET */ | |
532 | 533 | |||
533 | #ifdef INET6 | 534 | #ifdef INET6 | |
534 | case AF_INET6: | 535 | case AF_INET6: | |
535 | if (IN6_IS_ADDR_UNSPECIFIED(&saidx->dst.sin6.sin6_addr) || | 536 | if (IN6_IS_ADDR_UNSPECIFIED(&saidx->dst.sin6.sin6_addr) || | |
536 | saidx->src.sa.sa_family != AF_INET6 || | 537 | saidx->src.sa.sa_family != AF_INET6 || | |
537 | IN6_IS_ADDR_UNSPECIFIED(&saidx->src.sin6.sin6_addr)) { | 538 | IN6_IS_ADDR_UNSPECIFIED(&saidx->src.sin6.sin6_addr)) { | |
538 | DPRINTF(("ipip_output: unspecified tunnel endpoint " | 539 | DPRINTF(("ipip_output: unspecified tunnel endpoint " | |
539 | "address in SA %s/%08lx\n", | 540 | "address in SA %s/%08lx\n", | |
540 | ipsec_address(&saidx->dst), | 541 | ipsec_address(&saidx->dst), | |
541 | (u_long) ntohl(sav->spi))); | 542 | (u_long) ntohl(sav->spi))); | |
542 | IPIP_STATINC(IPIP_STAT_UNSPEC); | 543 | IPIP_STATINC(IPIP_STAT_UNSPEC); | |
543 | error = ENOBUFS; | 544 | error = ENOBUFS; | |
544 | goto bad; | 545 | goto bad; | |
545 | } | 546 | } | |
546 | 547 | |||
547 | if (tp == (IPV6_VERSION >> 4)) { | 548 | if (tp == (IPV6_VERSION >> 4)) { | |
548 | /* scoped address handling */ | 549 | /* scoped address handling */ | |
549 | ip6 = mtod(m, struct ip6_hdr *); | 550 | ip6 = mtod(m, struct ip6_hdr *); | |
550 | if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_src)) | 551 | if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_src)) | |
551 | ip6->ip6_src.s6_addr16[1] = 0; | 552 | ip6->ip6_src.s6_addr16[1] = 0; | |
552 | if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_dst)) | 553 | if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_dst)) | |
553 | ip6->ip6_dst.s6_addr16[1] = 0; | 554 | ip6->ip6_dst.s6_addr16[1] = 0; | |
554 | } | 555 | } | |
555 | 556 | |||
556 | M_PREPEND(m, sizeof(struct ip6_hdr), M_DONTWAIT); | 557 | M_PREPEND(m, sizeof(struct ip6_hdr), M_DONTWAIT); | |
557 | if (m == 0) { | 558 | if (m == 0) { | |
558 | DPRINTF(("ipip_output: M_PREPEND failed\n")); | 559 | DPRINTF(("ipip_output: M_PREPEND failed\n")); | |
559 | IPIP_STATINC(IPIP_STAT_HDROPS); | 560 | IPIP_STATINC(IPIP_STAT_HDROPS); | |
560 | error = ENOBUFS; | 561 | error = ENOBUFS; | |
561 | goto bad; | 562 | goto bad; | |
562 | } | 563 | } | |
563 | 564 | |||
564 | /* Initialize IPv6 header */ | 565 | /* Initialize IPv6 header */ | |
565 | ip6o = mtod(m, struct ip6_hdr *); | 566 | ip6o = mtod(m, struct ip6_hdr *); | |
566 | ip6o->ip6_flow = 0; | 567 | ip6o->ip6_flow = 0; | |
567 | ip6o->ip6_vfc &= ~IPV6_VERSION_MASK; | 568 | ip6o->ip6_vfc &= ~IPV6_VERSION_MASK; | |
568 | ip6o->ip6_vfc |= IPV6_VERSION; | 569 | ip6o->ip6_vfc |= IPV6_VERSION; | |
569 | ip6o->ip6_plen = htons(m->m_pkthdr.len - sizeof(*ip6o)); | 570 | ip6o->ip6_plen = htons(m->m_pkthdr.len - sizeof(*ip6o)); | |
570 | ip6o->ip6_hlim = ip_defttl; | 571 | ip6o->ip6_hlim = ip_defttl; | |
571 | ip6o->ip6_dst = saidx->dst.sin6.sin6_addr; | 572 | ip6o->ip6_dst = saidx->dst.sin6.sin6_addr; | |
572 | ip6o->ip6_src = saidx->src.sin6.sin6_addr; | 573 | ip6o->ip6_src = saidx->src.sin6.sin6_addr; | |
573 | if (IN6_IS_SCOPE_LINKLOCAL(&ip6o->ip6_dst)) | 574 | if (IN6_IS_SCOPE_LINKLOCAL(&ip6o->ip6_dst)) | |
574 | ip6o->ip6_dst.s6_addr16[1] = htons(saidx->dst.sin6.sin6_scope_id); | 575 | ip6o->ip6_dst.s6_addr16[1] = htons(saidx->dst.sin6.sin6_scope_id); | |
575 | if (IN6_IS_SCOPE_LINKLOCAL(&ip6o->ip6_src)) | 576 | if (IN6_IS_SCOPE_LINKLOCAL(&ip6o->ip6_src)) | |
576 | ip6o->ip6_src.s6_addr16[1] = htons(saidx->src.sin6.sin6_scope_id); | 577 | ip6o->ip6_src.s6_addr16[1] = htons(saidx->src.sin6.sin6_scope_id); | |
577 | 578 | |||
578 | #ifdef INET | 579 | #ifdef INET | |
579 | if (tp == IPVERSION) { | 580 | if (tp == IPVERSION) { | |
580 | /* Save ECN notification */ | 581 | /* Save ECN notification */ | |
581 | m_copydata(m, sizeof(struct ip6_hdr) + | 582 | m_copydata(m, sizeof(struct ip6_hdr) + | |
582 | offsetof(struct ip, ip_tos), sizeof(u_int8_t), | 583 | offsetof(struct ip, ip_tos), sizeof(u_int8_t), | |
583 | &itos); | 584 | &itos); | |
584 | 585 | |||
585 | /* This is really IPVERSION. */ | 586 | /* This is really IPVERSION. */ | |
586 | ip6o->ip6_nxt = IPPROTO_IPIP; | 587 | ip6o->ip6_nxt = IPPROTO_IPIP; | |
587 | } else | 588 | } else | |
588 | #endif /* INET */ | 589 | #endif /* INET */ | |
589 | if (tp == (IPV6_VERSION >> 4)) { | 590 | if (tp == (IPV6_VERSION >> 4)) { | |
590 | u_int32_t itos32; | 591 | u_int32_t itos32; | |
591 | 592 | |||
592 | /* Save ECN notification. */ | 593 | /* Save ECN notification. */ | |
593 | m_copydata(m, sizeof(struct ip6_hdr) + | 594 | m_copydata(m, sizeof(struct ip6_hdr) + | |
594 | offsetof(struct ip6_hdr, ip6_flow), | 595 | offsetof(struct ip6_hdr, ip6_flow), | |
595 | sizeof(u_int32_t), &itos32); | 596 | sizeof(u_int32_t), &itos32); | |
596 | itos = ntohl(itos32) >> 20; | 597 | itos = ntohl(itos32) >> 20; | |
597 | 598 | |||
598 | ip6o->ip6_nxt = IPPROTO_IPV6; | 599 | ip6o->ip6_nxt = IPPROTO_IPV6; | |
599 | } else { | 600 | } else { | |
600 | goto nofamily; | 601 | goto nofamily; | |
601 | } | 602 | } | |
602 | 603 | |||
603 | otos = 0; | 604 | otos = 0; | |
604 | ip_ecn_ingress(ECN_ALLOWED, &otos, &itos); | 605 | ip_ecn_ingress(ECN_ALLOWED, &otos, &itos); | |
605 | ip6o->ip6_flow |= htonl((u_int32_t) otos << 20); | 606 | ip6o->ip6_flow |= htonl((u_int32_t) otos << 20); | |
606 | break; | 607 | break; | |
607 | #endif /* INET6 */ | 608 | #endif /* INET6 */ | |
608 | 609 | |||
609 | default: | 610 | default: | |
610 | nofamily: | 611 | nofamily: | |
611 | DPRINTF(("ipip_output: unsupported protocol family %u\n", | 612 | DPRINTF(("ipip_output: unsupported protocol family %u\n", | |
612 | saidx->dst.sa.sa_family)); | 613 | saidx->dst.sa.sa_family)); | |
613 | IPIP_STATINC(IPIP_STAT_FAMILY); | 614 | IPIP_STATINC(IPIP_STAT_FAMILY); | |
614 | error = EAFNOSUPPORT; /* XXX diffs from openbsd */ | 615 | error = EAFNOSUPPORT; /* XXX diffs from openbsd */ | |
615 | goto bad; | 616 | goto bad; | |
616 | } | 617 | } | |
617 | 618 | |||
618 | IPIP_STATINC(IPIP_STAT_OPACKETS); | 619 | IPIP_STATINC(IPIP_STAT_OPACKETS); | |
619 | *mp = m; | 620 | *mp = m; | |
620 | 621 | |||
621 | #ifdef INET | 622 | #ifdef INET | |
622 | if (saidx->dst.sa.sa_family == AF_INET) { | 623 | if (saidx->dst.sa.sa_family == AF_INET) { | |
623 | #if 0 | 624 | #if 0 | |
624 | if (sav->tdb_xform->xf_type == XF_IP4) | 625 | if (sav->tdb_xform->xf_type == XF_IP4) | |
625 | tdb->tdb_cur_bytes += | 626 | tdb->tdb_cur_bytes += | |
626 | m->m_pkthdr.len - sizeof(struct ip); | 627 | m->m_pkthdr.len - sizeof(struct ip); | |
627 | #endif | 628 | #endif | |
628 | IPIP_STATADD(IPIP_STAT_OBYTES, | 629 | IPIP_STATADD(IPIP_STAT_OBYTES, | |
629 | m->m_pkthdr.len - sizeof(struct ip)); | 630 | m->m_pkthdr.len - sizeof(struct ip)); | |
630 | } | 631 | } | |
631 | #endif /* INET */ | 632 | #endif /* INET */ | |
632 | 633 | |||
633 | #ifdef INET6 | 634 | #ifdef INET6 | |
634 | if (saidx->dst.sa.sa_family == AF_INET6) { | 635 | if (saidx->dst.sa.sa_family == AF_INET6) { | |
635 | #if 0 | 636 | #if 0 | |
636 | if (sav->tdb_xform->xf_type == XF_IP4) | 637 | if (sav->tdb_xform->xf_type == XF_IP4) | |
637 | tdb->tdb_cur_bytes += | 638 | tdb->tdb_cur_bytes += | |
638 | m->m_pkthdr.len - sizeof(struct ip6_hdr); | 639 | m->m_pkthdr.len - sizeof(struct ip6_hdr); | |
639 | #endif | 640 | #endif | |
640 | IPIP_STATADD(IPIP_STAT_OBYTES, | 641 | IPIP_STATADD(IPIP_STAT_OBYTES, | |
641 | m->m_pkthdr.len - sizeof(struct ip6_hdr)); | 642 | m->m_pkthdr.len - sizeof(struct ip6_hdr)); | |
642 | } | 643 | } | |
643 | #endif /* INET6 */ | 644 | #endif /* INET6 */ | |
644 | 645 | |||
645 | return 0; | 646 | return 0; | |
646 | bad: | 647 | bad: | |
647 | if (m) | 648 | if (m) | |
648 | m_freem(m); | 649 | m_freem(m); | |
649 | *mp = NULL; | 650 | *mp = NULL; | |
650 | return (error); | 651 | return (error); | |
651 | } | 652 | } | |
652 | 653 | |||
653 | #ifdef FAST_IPSEC | 654 | #ifdef FAST_IPSEC | |
654 | static int | 655 | static int | |
655 | ipe4_init(struct secasvar *sav, const struct xformsw *xsp) | 656 | ipe4_init(struct secasvar *sav, const struct xformsw *xsp) | |
656 | { | 657 | { | |
657 | sav->tdb_xform = xsp; | 658 | sav->tdb_xform = xsp; | |
658 | return 0; | 659 | return 0; | |
659 | } | 660 | } | |
660 | 661 | |||
661 | static int | 662 | static int | |
662 | ipe4_zeroize(struct secasvar *sav) | 663 | ipe4_zeroize(struct secasvar *sav) | |
663 | { | 664 | { | |
664 | sav->tdb_xform = NULL; | 665 | sav->tdb_xform = NULL; | |
665 | return 0; | 666 | return 0; | |
666 | } | 667 | } | |
667 | 668 | |||
668 | static int | 669 | static int | |
669 | ipe4_input( | 670 | ipe4_input( | |
670 | struct mbuf *m, | 671 | struct mbuf *m, | |
671 | const struct secasvar *sav, | 672 | const struct secasvar *sav, | |
672 | int skip, | 673 | int skip, | |
673 | int protoff | 674 | int protoff | |
674 | ) | 675 | ) | |
675 | { | 676 | { | |
676 | /* This is a rather serious mistake, so no conditional printing. */ | 677 | /* This is a rather serious mistake, so no conditional printing. */ | |
677 | printf("ipe4_input: should never be called\n"); | 678 | printf("ipe4_input: should never be called\n"); | |
678 | if (m) | 679 | if (m) | |
679 | m_freem(m); | 680 | m_freem(m); | |
680 | return EOPNOTSUPP; | 681 | return EOPNOTSUPP; | |
681 | } | 682 | } | |
682 | 683 | |||
683 | static struct xformsw ipe4_xformsw = { | 684 | static struct xformsw ipe4_xformsw = { | |
684 | XF_IP4, 0, "IPv4 Simple Encapsulation", | 685 | XF_IP4, 0, "IPv4 Simple Encapsulation", | |
685 | ipe4_init, ipe4_zeroize, ipe4_input, ipip_output, | 686 | ipe4_init, ipe4_zeroize, ipe4_input, ipip_output, | |
686 | NULL, | 687 | NULL, | |
687 | }; | 688 | }; | |
688 | 689 | |||
689 | #ifdef INET | 690 | #ifdef INET | |
690 | PR_WRAP_CTLOUTPUT(rip_ctloutput) | 691 | PR_WRAP_CTLOUTPUT(rip_ctloutput) | |
691 | PR_WRAP_USRREQ(rip_usrreq) | 692 | PR_WRAP_USRREQ(rip_usrreq) | |
692 | #define rip_ctloutput rip_ctloutput_wrapper | 693 | #define rip_ctloutput rip_ctloutput_wrapper | |
693 | #define rip_usrreq rip_usrreq_wrapper | 694 | #define rip_usrreq rip_usrreq_wrapper | |
694 | 695 | |||
695 | extern struct domain inetdomain; | 696 | extern struct domain inetdomain; | |
696 | static struct ipprotosw ipe4_protosw = { | 697 | static struct ipprotosw ipe4_protosw = { | |
697 | .pr_type = SOCK_RAW, | 698 | .pr_type = SOCK_RAW, | |
698 | .pr_domain = &inetdomain, | 699 | .pr_domain = &inetdomain, | |
699 | .pr_protocol = IPPROTO_IPV4, | 700 | .pr_protocol = IPPROTO_IPV4, | |
700 | .pr_flags = PR_ATOMIC|PR_ADDR|PR_LASTHDR, | 701 | .pr_flags = PR_ATOMIC|PR_ADDR|PR_LASTHDR, | |
701 | .pr_input = ip4_input, | 702 | .pr_input = ip4_input, | |
702 | .pr_output = 0, | 703 | .pr_output = 0, | |
703 | .pr_ctlinput = 0, | 704 | .pr_ctlinput = 0, | |
704 | .pr_ctloutput = rip_ctloutput, | 705 | .pr_ctloutput = rip_ctloutput, | |
705 | .pr_usrreq = rip_usrreq, | 706 | .pr_usrreq = rip_usrreq, | |
706 | .pr_init = 0, | 707 | .pr_init = 0, | |
707 | .pr_fasttimo = 0, | 708 | .pr_fasttimo = 0, | |
708 | .pr_slowtimo = 0, | 709 | .pr_slowtimo = 0, | |
709 | .pr_drain = 0, | 710 | .pr_drain = 0, | |
710 | }; | 711 | }; | |
711 | #endif | 712 | #endif | |
712 | #ifdef INET6 | 713 | #ifdef INET6 | |
713 | PR_WRAP_CTLOUTPUT(rip6_ctloutput) | 714 | PR_WRAP_CTLOUTPUT(rip6_ctloutput) | |
714 | PR_WRAP_USRREQ(rip6_usrreq) | 715 | PR_WRAP_USRREQ(rip6_usrreq) | |
715 | #define rip6_ctloutput rip6_ctloutput_wrapper | 716 | #define rip6_ctloutput rip6_ctloutput_wrapper | |
716 | #define rip6_usrreq rip6_usrreq_wrapper | 717 | #define rip6_usrreq rip6_usrreq_wrapper | |
717 | 718 | |||
718 | extern struct domain inet6domain; | 719 | extern struct domain inet6domain; | |
719 | static struct ip6protosw ipe4_protosw6 = { | 720 | static struct ip6protosw ipe4_protosw6 = { | |
720 | .pr_type = SOCK_RAW, | 721 | .pr_type = SOCK_RAW, | |
721 | .pr_domain = &inet6domain, | 722 | .pr_domain = &inet6domain, | |
722 | .pr_protocol = IPPROTO_IPV6, | 723 | .pr_protocol = IPPROTO_IPV6, | |
723 | .pr_flags = PR_ATOMIC|PR_ADDR|PR_LASTHDR, | 724 | .pr_flags = PR_ATOMIC|PR_ADDR|PR_LASTHDR, | |
724 | .pr_input = ip4_input6, | 725 | .pr_input = ip4_input6, | |
725 | .pr_output = 0, | 726 | .pr_output = 0, | |
726 | .pr_ctlinput = 0, | 727 | .pr_ctlinput = 0, | |
727 | .pr_ctloutput = rip6_ctloutput, | 728 | .pr_ctloutput = rip6_ctloutput, | |
728 | .pr_usrreq = rip6_usrreq, | 729 | .pr_usrreq = rip6_usrreq, | |
729 | .pr_init = 0, | 730 | .pr_init = 0, | |
730 | .pr_fasttimo = 0, | 731 | .pr_fasttimo = 0, | |
731 | .pr_slowtimo = 0, | 732 | .pr_slowtimo = 0, | |
732 | .pr_drain = 0, | 733 | .pr_drain = 0, | |
733 | }; | 734 | }; | |
734 | #endif | 735 | #endif | |
735 | 736 | |||
736 | #endif /* FAST_IPSEC */ | 737 | #endif /* FAST_IPSEC */ | |
737 | 738 | |||
738 | /* | 739 | /* | |
739 | * Check the encapsulated packet to see if we want it | 740 | * Check the encapsulated packet to see if we want it | |
740 | */ | 741 | */ | |
741 | static int | 742 | static int | |
742 | ipe4_encapcheck(struct mbuf *m, | 743 | ipe4_encapcheck(struct mbuf *m, | |
743 | int off, | 744 | int off, | |
744 | int proto, | 745 | int proto, | |
745 | void *arg | 746 | void *arg | |
746 | ) | 747 | ) | |
747 | { | 748 | { | |
748 | /* | 749 | /* | |
749 | * Only take packets coming from IPSEC tunnels; the rest | 750 | * Only take packets coming from IPSEC tunnels; the rest | |
750 | * must be handled by the gif tunnel code. Note that we | 751 | * must be handled by the gif tunnel code. Note that we | |
751 | * also return a minimum priority when we want the packet | 752 | * also return a minimum priority when we want the packet | |
752 | * so any explicit gif tunnels take precedence. | 753 | * so any explicit gif tunnels take precedence. | |
753 | */ | 754 | */ | |
754 | return ((m->m_flags & M_IPSEC) != 0 ? 1 : 0); | 755 | return ((m->m_flags & M_IPSEC) != 0 ? 1 : 0); | |
755 | } | 756 | } | |
756 | 757 | |||
757 | INITFN void | 758 | INITFN void | |
758 | ipe4_attach(void) | 759 | ipe4_attach(void) | |
759 | { | 760 | { | |
760 | 761 | |||
761 | ipipstat_percpu = percpu_alloc(sizeof(uint64_t) * IPIP_NSTATS); | 762 | ipipstat_percpu = percpu_alloc(sizeof(uint64_t) * IPIP_NSTATS); | |
762 | 763 | |||
763 | xform_register(&ipe4_xformsw); | 764 | xform_register(&ipe4_xformsw); | |
764 | /* attach to encapsulation framework */ | 765 | /* attach to encapsulation framework */ | |
765 | /* XXX save return cookie for detach on module remove */ | 766 | /* XXX save return cookie for detach on module remove */ | |
766 | #ifdef INET | 767 | #ifdef INET | |
767 | (void) encap_attach_func(AF_INET, -1, | 768 | (void) encap_attach_func(AF_INET, -1, | |
768 | ipe4_encapcheck, (struct protosw*) &ipe4_protosw, NULL); | 769 | ipe4_encapcheck, (struct protosw*) &ipe4_protosw, NULL); | |
769 | #endif | 770 | #endif | |
770 | #ifdef INET6 | 771 | #ifdef INET6 | |
771 | (void) encap_attach_func(AF_INET6, -1, | 772 | (void) encap_attach_func(AF_INET6, -1, | |
772 | ipe4_encapcheck, (struct protosw*) &ipe4_protosw6, NULL); | 773 | ipe4_encapcheck, (struct protosw*) &ipe4_protosw6, NULL); | |
773 | #endif | 774 | #endif | |
774 | } | 775 | } | |
775 | 776 | |||
776 | #ifdef SYSINIT | 777 | #ifdef SYSINIT | |
777 | SYSINIT(ipe4_xform_init, SI_SUB_PROTO_DOMAIN, SI_ORDER_MIDDLE, ipe4_attach, NULL); | 778 | SYSINIT(ipe4_xform_init, SI_SUB_PROTO_DOMAIN, SI_ORDER_MIDDLE, ipe4_attach, NULL); | |
778 | #endif | 779 | #endif | |
779 | 780 |