xref: /freebsd/sys/netipsec/xform_tcp.c (revision c398230b64aea809cb7c5cea8db580af7097920c)
155d2c71bSBruce M Simpson /*	$FreeBSD$ */
255d2c71bSBruce M Simpson 
3c398230bSWarner Losh /*-
455d2c71bSBruce M Simpson  * Copyright (c) 2003 Bruce M. Simpson <bms@spc.org>
555d2c71bSBruce M Simpson  *
655d2c71bSBruce M Simpson  * Redistribution and use in source and binary forms, with or without
755d2c71bSBruce M Simpson  * modification, are permitted provided that the following conditions
855d2c71bSBruce M Simpson  * are met:
955d2c71bSBruce M Simpson  *
1055d2c71bSBruce M Simpson  * 1. Redistributions of source code must retain the above copyright
1155d2c71bSBruce M Simpson  *   notice, this list of conditions and the following disclaimer.
1255d2c71bSBruce M Simpson  * 2. Redistributions in binary form must reproduce the above copyright
1355d2c71bSBruce M Simpson  *   notice, this list of conditions and the following disclaimer in the
1455d2c71bSBruce M Simpson  *   documentation and/or other materials provided with the distribution.
1555d2c71bSBruce M Simpson  * 3. The name of the author may not be used to endorse or promote products
1655d2c71bSBruce M Simpson  *   derived from this software without specific prior written permission.
1755d2c71bSBruce M Simpson  *
1855d2c71bSBruce M Simpson  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
1955d2c71bSBruce M Simpson  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
2055d2c71bSBruce M Simpson  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
2155d2c71bSBruce M Simpson  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
2255d2c71bSBruce M Simpson  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
2355d2c71bSBruce M Simpson  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2455d2c71bSBruce M Simpson  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2555d2c71bSBruce M Simpson  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2655d2c71bSBruce M Simpson  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
2755d2c71bSBruce M Simpson  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2855d2c71bSBruce M Simpson  */
2955d2c71bSBruce M Simpson 
3055d2c71bSBruce M Simpson /* TCP MD5 Signature Option (RFC2385) */
3155d2c71bSBruce M Simpson #include "opt_inet.h"
3255d2c71bSBruce M Simpson #include "opt_inet6.h"
3355d2c71bSBruce M Simpson 
3455d2c71bSBruce M Simpson #include <sys/param.h>
3555d2c71bSBruce M Simpson #include <sys/systm.h>
3655d2c71bSBruce M Simpson #include <sys/mbuf.h>
3755d2c71bSBruce M Simpson #include <sys/lock.h>
3855d2c71bSBruce M Simpson #include <sys/socket.h>
3955d2c71bSBruce M Simpson #include <sys/kernel.h>
4055d2c71bSBruce M Simpson #include <sys/protosw.h>
4155d2c71bSBruce M Simpson #include <sys/sysctl.h>
4255d2c71bSBruce M Simpson 
4355d2c71bSBruce M Simpson #include <netinet/in.h>
4455d2c71bSBruce M Simpson #include <netinet/in_systm.h>
4555d2c71bSBruce M Simpson #include <netinet/ip.h>
4655d2c71bSBruce M Simpson #include <netinet/ip_var.h>
4755d2c71bSBruce M Simpson #include <netinet/tcp.h>
4855d2c71bSBruce M Simpson #include <netinet/tcp_var.h>
4955d2c71bSBruce M Simpson 
5055d2c71bSBruce M Simpson #include <net/route.h>
5155d2c71bSBruce M Simpson #include <netipsec/ipsec.h>
5255d2c71bSBruce M Simpson #include <netipsec/xform.h>
5355d2c71bSBruce M Simpson 
5455d2c71bSBruce M Simpson #ifdef INET6
5555d2c71bSBruce M Simpson #include <netinet/ip6.h>
5655d2c71bSBruce M Simpson #include <netipsec/ipsec6.h>
5755d2c71bSBruce M Simpson #endif
5855d2c71bSBruce M Simpson 
5955d2c71bSBruce M Simpson #include <netipsec/key.h>
6055d2c71bSBruce M Simpson #include <netipsec/key_debug.h>
6155d2c71bSBruce M Simpson 
6255d2c71bSBruce M Simpson /*
6355d2c71bSBruce M Simpson  * Initialize a TCP-MD5 SA. Called when the SA is being set up.
6455d2c71bSBruce M Simpson  *
6555d2c71bSBruce M Simpson  * We don't need to set up the tdb prefixed fields, as we don't use the
6655d2c71bSBruce M Simpson  * opencrypto code; we just perform a key length check.
6755d2c71bSBruce M Simpson  *
6855d2c71bSBruce M Simpson  * XXX: Currently we only allow a single 'magic' SPI to be used.
6955d2c71bSBruce M Simpson  *
7055d2c71bSBruce M Simpson  * This allows per-host granularity without affecting the userland
7155d2c71bSBruce M Simpson  * interface, which is a simple socket option toggle switch,
7255d2c71bSBruce M Simpson  * TCP_SIGNATURE_ENABLE.
7355d2c71bSBruce M Simpson  *
7455d2c71bSBruce M Simpson  * To allow per-service granularity requires that we have a means
7555d2c71bSBruce M Simpson  * of mapping port to SPI. The mandated way of doing this is to
7655d2c71bSBruce M Simpson  * use SPD entries to specify packet flows which get the TCP-MD5
7755d2c71bSBruce M Simpson  * treatment, however the code to do this is currently unstable
7855d2c71bSBruce M Simpson  * and unsuitable for production use.
7955d2c71bSBruce M Simpson  *
8055d2c71bSBruce M Simpson  * Therefore we use this compromise in the meantime.
8155d2c71bSBruce M Simpson  */
8255d2c71bSBruce M Simpson static int
8355d2c71bSBruce M Simpson tcpsignature_init(struct secasvar *sav, struct xformsw *xsp)
8455d2c71bSBruce M Simpson {
8555d2c71bSBruce M Simpson 	int keylen;
8655d2c71bSBruce M Simpson 
8755d2c71bSBruce M Simpson 	if (sav->spi != htonl(TCP_SIG_SPI)) {
8855d2c71bSBruce M Simpson 		DPRINTF(("%s: SPI must be TCP_SIG_SPI (0x1000)\n",
893a2366dcSBruce M Simpson 		    __func__));
9055d2c71bSBruce M Simpson 		return (EINVAL);
9155d2c71bSBruce M Simpson 	}
9255d2c71bSBruce M Simpson 	if (sav->alg_auth != SADB_X_AALG_TCP_MD5) {
9355d2c71bSBruce M Simpson 		DPRINTF(("%s: unsupported authentication algorithm %u\n",
9455d2c71bSBruce M Simpson 		    __func__, sav->alg_auth));
9555d2c71bSBruce M Simpson 		return (EINVAL);
9655d2c71bSBruce M Simpson 	}
9755d2c71bSBruce M Simpson 	if (sav->key_auth == NULL) {
9855d2c71bSBruce M Simpson 		DPRINTF(("%s: no authentication key present\n", __func__));
9955d2c71bSBruce M Simpson 		return (EINVAL);
10055d2c71bSBruce M Simpson 	}
10155d2c71bSBruce M Simpson 	keylen = _KEYLEN(sav->key_auth);
10255d2c71bSBruce M Simpson 	if ((keylen < TCP_KEYLEN_MIN) || (keylen > TCP_KEYLEN_MAX)) {
10355d2c71bSBruce M Simpson 		DPRINTF(("%s: invalid key length %u\n", __func__, keylen));
10455d2c71bSBruce M Simpson 		return (EINVAL);
10555d2c71bSBruce M Simpson 	}
10655d2c71bSBruce M Simpson 
10755d2c71bSBruce M Simpson 	return (0);
10855d2c71bSBruce M Simpson }
10955d2c71bSBruce M Simpson 
11055d2c71bSBruce M Simpson /*
11155d2c71bSBruce M Simpson  * Paranoia.
11255d2c71bSBruce M Simpson  *
11355d2c71bSBruce M Simpson  * Called when the SA is deleted.
11455d2c71bSBruce M Simpson  */
11555d2c71bSBruce M Simpson static int
11655d2c71bSBruce M Simpson tcpsignature_zeroize(struct secasvar *sav)
11755d2c71bSBruce M Simpson {
11855d2c71bSBruce M Simpson 
11955d2c71bSBruce M Simpson 	if (sav->key_auth)
12055d2c71bSBruce M Simpson 		bzero(_KEYBUF(sav->key_auth), _KEYLEN(sav->key_auth));
12155d2c71bSBruce M Simpson 
12255d2c71bSBruce M Simpson 	sav->tdb_cryptoid = 0;
12355d2c71bSBruce M Simpson 	sav->tdb_authalgxform = NULL;
12455d2c71bSBruce M Simpson 	sav->tdb_xform = NULL;
12555d2c71bSBruce M Simpson 
12655d2c71bSBruce M Simpson 	return (0);
12755d2c71bSBruce M Simpson }
12855d2c71bSBruce M Simpson 
12955d2c71bSBruce M Simpson /*
13055d2c71bSBruce M Simpson  * Verify that an input packet passes authentication.
13155d2c71bSBruce M Simpson  * Called from the ipsec layer.
13255d2c71bSBruce M Simpson  * We do this from within tcp itself, so this routine is just a stub.
13355d2c71bSBruce M Simpson  */
13455d2c71bSBruce M Simpson static int
13555d2c71bSBruce M Simpson tcpsignature_input(struct mbuf *m, struct secasvar *sav, int skip,
13655d2c71bSBruce M Simpson     int protoff)
13755d2c71bSBruce M Simpson {
13855d2c71bSBruce M Simpson 
13955d2c71bSBruce M Simpson 	return (0);
14055d2c71bSBruce M Simpson }
14155d2c71bSBruce M Simpson 
14255d2c71bSBruce M Simpson /*
14355d2c71bSBruce M Simpson  * Prepend the authentication header.
14455d2c71bSBruce M Simpson  * Called from the ipsec layer.
14555d2c71bSBruce M Simpson  * We do this from within tcp itself, so this routine is just a stub.
14655d2c71bSBruce M Simpson  */
14755d2c71bSBruce M Simpson static int
14855d2c71bSBruce M Simpson tcpsignature_output(struct mbuf *m, struct ipsecrequest *isr,
14955d2c71bSBruce M Simpson     struct mbuf **mp, int skip, int protoff)
15055d2c71bSBruce M Simpson {
15155d2c71bSBruce M Simpson 
15255d2c71bSBruce M Simpson 	return (EINVAL);
15355d2c71bSBruce M Simpson }
15455d2c71bSBruce M Simpson 
15555d2c71bSBruce M Simpson static struct xformsw tcpsignature_xformsw = {
15655d2c71bSBruce M Simpson 	XF_TCPSIGNATURE,	XFT_AUTH,		"TCPMD5",
15755d2c71bSBruce M Simpson 	tcpsignature_init,	tcpsignature_zeroize,
15855d2c71bSBruce M Simpson 	tcpsignature_input,	tcpsignature_output
15955d2c71bSBruce M Simpson };
16055d2c71bSBruce M Simpson 
16155d2c71bSBruce M Simpson static void
16255d2c71bSBruce M Simpson tcpsignature_attach(void)
16355d2c71bSBruce M Simpson {
16455d2c71bSBruce M Simpson 
16555d2c71bSBruce M Simpson 	xform_register(&tcpsignature_xformsw);
16655d2c71bSBruce M Simpson }
16755d2c71bSBruce M Simpson 
16855d2c71bSBruce M Simpson SYSINIT(tcpsignature_xform_init, SI_SUB_DRIVERS, SI_ORDER_FIRST,
16955d2c71bSBruce M Simpson     tcpsignature_attach, NULL)
170