18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-or-later */
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * CIPSO - Commercial IP Security Option
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * This is an implementation of the CIPSO 2.2 protocol as specified in
68c2ecf20Sopenharmony_ci * draft-ietf-cipso-ipsecurity-01.txt with additional tag types as found in
78c2ecf20Sopenharmony_ci * FIPS-188, copies of both documents can be found in the Documentation
88c2ecf20Sopenharmony_ci * directory.  While CIPSO never became a full IETF RFC standard many vendors
98c2ecf20Sopenharmony_ci * have chosen to adopt the protocol and over the years it has become a
108c2ecf20Sopenharmony_ci * de-facto standard for labeled networking.
118c2ecf20Sopenharmony_ci *
128c2ecf20Sopenharmony_ci * Author: Paul Moore <paul@paul-moore.com>
138c2ecf20Sopenharmony_ci */
148c2ecf20Sopenharmony_ci
158c2ecf20Sopenharmony_ci/*
168c2ecf20Sopenharmony_ci * (c) Copyright Hewlett-Packard Development Company, L.P., 2006
178c2ecf20Sopenharmony_ci */
188c2ecf20Sopenharmony_ci
198c2ecf20Sopenharmony_ci#ifndef _CIPSO_IPV4_H
208c2ecf20Sopenharmony_ci#define _CIPSO_IPV4_H
218c2ecf20Sopenharmony_ci
228c2ecf20Sopenharmony_ci#include <linux/types.h>
238c2ecf20Sopenharmony_ci#include <linux/rcupdate.h>
248c2ecf20Sopenharmony_ci#include <linux/list.h>
258c2ecf20Sopenharmony_ci#include <linux/net.h>
268c2ecf20Sopenharmony_ci#include <linux/skbuff.h>
278c2ecf20Sopenharmony_ci#include <net/netlabel.h>
288c2ecf20Sopenharmony_ci#include <net/request_sock.h>
298c2ecf20Sopenharmony_ci#include <linux/atomic.h>
308c2ecf20Sopenharmony_ci#include <linux/refcount.h>
318c2ecf20Sopenharmony_ci#include <asm/unaligned.h>
328c2ecf20Sopenharmony_ci
338c2ecf20Sopenharmony_ci/* known doi values */
348c2ecf20Sopenharmony_ci#define CIPSO_V4_DOI_UNKNOWN          0x00000000
358c2ecf20Sopenharmony_ci
368c2ecf20Sopenharmony_ci/* standard tag types */
378c2ecf20Sopenharmony_ci#define CIPSO_V4_TAG_INVALID          0
388c2ecf20Sopenharmony_ci#define CIPSO_V4_TAG_RBITMAP          1
398c2ecf20Sopenharmony_ci#define CIPSO_V4_TAG_ENUM             2
408c2ecf20Sopenharmony_ci#define CIPSO_V4_TAG_RANGE            5
418c2ecf20Sopenharmony_ci#define CIPSO_V4_TAG_PBITMAP          6
428c2ecf20Sopenharmony_ci#define CIPSO_V4_TAG_FREEFORM         7
438c2ecf20Sopenharmony_ci
448c2ecf20Sopenharmony_ci/* non-standard tag types (tags > 127) */
458c2ecf20Sopenharmony_ci#define CIPSO_V4_TAG_LOCAL            128
468c2ecf20Sopenharmony_ci
478c2ecf20Sopenharmony_ci/* doi mapping types */
488c2ecf20Sopenharmony_ci#define CIPSO_V4_MAP_UNKNOWN          0
498c2ecf20Sopenharmony_ci#define CIPSO_V4_MAP_TRANS            1
508c2ecf20Sopenharmony_ci#define CIPSO_V4_MAP_PASS             2
518c2ecf20Sopenharmony_ci#define CIPSO_V4_MAP_LOCAL            3
528c2ecf20Sopenharmony_ci
538c2ecf20Sopenharmony_ci/* limits */
548c2ecf20Sopenharmony_ci#define CIPSO_V4_MAX_REM_LVLS         255
558c2ecf20Sopenharmony_ci#define CIPSO_V4_INV_LVL              0x80000000
568c2ecf20Sopenharmony_ci#define CIPSO_V4_MAX_LOC_LVLS         (CIPSO_V4_INV_LVL - 1)
578c2ecf20Sopenharmony_ci#define CIPSO_V4_MAX_REM_CATS         65534
588c2ecf20Sopenharmony_ci#define CIPSO_V4_INV_CAT              0x80000000
598c2ecf20Sopenharmony_ci#define CIPSO_V4_MAX_LOC_CATS         (CIPSO_V4_INV_CAT - 1)
608c2ecf20Sopenharmony_ci
618c2ecf20Sopenharmony_ci/*
628c2ecf20Sopenharmony_ci * CIPSO DOI definitions
638c2ecf20Sopenharmony_ci */
648c2ecf20Sopenharmony_ci
658c2ecf20Sopenharmony_ci/* DOI definition struct */
668c2ecf20Sopenharmony_ci#define CIPSO_V4_TAG_MAXCNT           5
678c2ecf20Sopenharmony_cistruct cipso_v4_doi {
688c2ecf20Sopenharmony_ci	u32 doi;
698c2ecf20Sopenharmony_ci	u32 type;
708c2ecf20Sopenharmony_ci	union {
718c2ecf20Sopenharmony_ci		struct cipso_v4_std_map_tbl *std;
728c2ecf20Sopenharmony_ci	} map;
738c2ecf20Sopenharmony_ci	u8 tags[CIPSO_V4_TAG_MAXCNT];
748c2ecf20Sopenharmony_ci
758c2ecf20Sopenharmony_ci	refcount_t refcount;
768c2ecf20Sopenharmony_ci	struct list_head list;
778c2ecf20Sopenharmony_ci	struct rcu_head rcu;
788c2ecf20Sopenharmony_ci};
798c2ecf20Sopenharmony_ci
808c2ecf20Sopenharmony_ci/* Standard CIPSO mapping table */
818c2ecf20Sopenharmony_ci/* NOTE: the highest order bit (i.e. 0x80000000) is an 'invalid' flag, if the
828c2ecf20Sopenharmony_ci *       bit is set then consider that value as unspecified, meaning the
838c2ecf20Sopenharmony_ci *       mapping for that particular level/category is invalid */
848c2ecf20Sopenharmony_cistruct cipso_v4_std_map_tbl {
858c2ecf20Sopenharmony_ci	struct {
868c2ecf20Sopenharmony_ci		u32 *cipso;
878c2ecf20Sopenharmony_ci		u32 *local;
888c2ecf20Sopenharmony_ci		u32 cipso_size;
898c2ecf20Sopenharmony_ci		u32 local_size;
908c2ecf20Sopenharmony_ci	} lvl;
918c2ecf20Sopenharmony_ci	struct {
928c2ecf20Sopenharmony_ci		u32 *cipso;
938c2ecf20Sopenharmony_ci		u32 *local;
948c2ecf20Sopenharmony_ci		u32 cipso_size;
958c2ecf20Sopenharmony_ci		u32 local_size;
968c2ecf20Sopenharmony_ci	} cat;
978c2ecf20Sopenharmony_ci};
988c2ecf20Sopenharmony_ci
998c2ecf20Sopenharmony_ci/*
1008c2ecf20Sopenharmony_ci * Sysctl Variables
1018c2ecf20Sopenharmony_ci */
1028c2ecf20Sopenharmony_ci
1038c2ecf20Sopenharmony_ci#ifdef CONFIG_NETLABEL
1048c2ecf20Sopenharmony_ciextern int cipso_v4_cache_enabled;
1058c2ecf20Sopenharmony_ciextern int cipso_v4_cache_bucketsize;
1068c2ecf20Sopenharmony_ciextern int cipso_v4_rbm_optfmt;
1078c2ecf20Sopenharmony_ciextern int cipso_v4_rbm_strictvalid;
1088c2ecf20Sopenharmony_ci#endif
1098c2ecf20Sopenharmony_ci
1108c2ecf20Sopenharmony_ci/*
1118c2ecf20Sopenharmony_ci * DOI List Functions
1128c2ecf20Sopenharmony_ci */
1138c2ecf20Sopenharmony_ci
1148c2ecf20Sopenharmony_ci#ifdef CONFIG_NETLABEL
1158c2ecf20Sopenharmony_ciint cipso_v4_doi_add(struct cipso_v4_doi *doi_def,
1168c2ecf20Sopenharmony_ci		     struct netlbl_audit *audit_info);
1178c2ecf20Sopenharmony_civoid cipso_v4_doi_free(struct cipso_v4_doi *doi_def);
1188c2ecf20Sopenharmony_ciint cipso_v4_doi_remove(u32 doi, struct netlbl_audit *audit_info);
1198c2ecf20Sopenharmony_cistruct cipso_v4_doi *cipso_v4_doi_getdef(u32 doi);
1208c2ecf20Sopenharmony_civoid cipso_v4_doi_putdef(struct cipso_v4_doi *doi_def);
1218c2ecf20Sopenharmony_ciint cipso_v4_doi_walk(u32 *skip_cnt,
1228c2ecf20Sopenharmony_ci		     int (*callback) (struct cipso_v4_doi *doi_def, void *arg),
1238c2ecf20Sopenharmony_ci	             void *cb_arg);
1248c2ecf20Sopenharmony_ci#else
1258c2ecf20Sopenharmony_cistatic inline int cipso_v4_doi_add(struct cipso_v4_doi *doi_def,
1268c2ecf20Sopenharmony_ci				   struct netlbl_audit *audit_info)
1278c2ecf20Sopenharmony_ci{
1288c2ecf20Sopenharmony_ci	return -ENOSYS;
1298c2ecf20Sopenharmony_ci}
1308c2ecf20Sopenharmony_ci
1318c2ecf20Sopenharmony_cistatic inline void cipso_v4_doi_free(struct cipso_v4_doi *doi_def)
1328c2ecf20Sopenharmony_ci{
1338c2ecf20Sopenharmony_ci	return;
1348c2ecf20Sopenharmony_ci}
1358c2ecf20Sopenharmony_ci
1368c2ecf20Sopenharmony_cistatic inline int cipso_v4_doi_remove(u32 doi,
1378c2ecf20Sopenharmony_ci				      struct netlbl_audit *audit_info)
1388c2ecf20Sopenharmony_ci{
1398c2ecf20Sopenharmony_ci	return 0;
1408c2ecf20Sopenharmony_ci}
1418c2ecf20Sopenharmony_ci
1428c2ecf20Sopenharmony_cistatic inline struct cipso_v4_doi *cipso_v4_doi_getdef(u32 doi)
1438c2ecf20Sopenharmony_ci{
1448c2ecf20Sopenharmony_ci	return NULL;
1458c2ecf20Sopenharmony_ci}
1468c2ecf20Sopenharmony_ci
1478c2ecf20Sopenharmony_cistatic inline int cipso_v4_doi_walk(u32 *skip_cnt,
1488c2ecf20Sopenharmony_ci		     int (*callback) (struct cipso_v4_doi *doi_def, void *arg),
1498c2ecf20Sopenharmony_ci		     void *cb_arg)
1508c2ecf20Sopenharmony_ci{
1518c2ecf20Sopenharmony_ci	return 0;
1528c2ecf20Sopenharmony_ci}
1538c2ecf20Sopenharmony_ci#endif /* CONFIG_NETLABEL */
1548c2ecf20Sopenharmony_ci
1558c2ecf20Sopenharmony_ci/*
1568c2ecf20Sopenharmony_ci * Label Mapping Cache Functions
1578c2ecf20Sopenharmony_ci */
1588c2ecf20Sopenharmony_ci
1598c2ecf20Sopenharmony_ci#ifdef CONFIG_NETLABEL
1608c2ecf20Sopenharmony_civoid cipso_v4_cache_invalidate(void);
1618c2ecf20Sopenharmony_ciint cipso_v4_cache_add(const unsigned char *cipso_ptr,
1628c2ecf20Sopenharmony_ci		       const struct netlbl_lsm_secattr *secattr);
1638c2ecf20Sopenharmony_ci#else
1648c2ecf20Sopenharmony_cistatic inline void cipso_v4_cache_invalidate(void)
1658c2ecf20Sopenharmony_ci{
1668c2ecf20Sopenharmony_ci	return;
1678c2ecf20Sopenharmony_ci}
1688c2ecf20Sopenharmony_ci
1698c2ecf20Sopenharmony_cistatic inline int cipso_v4_cache_add(const unsigned char *cipso_ptr,
1708c2ecf20Sopenharmony_ci				     const struct netlbl_lsm_secattr *secattr)
1718c2ecf20Sopenharmony_ci{
1728c2ecf20Sopenharmony_ci	return 0;
1738c2ecf20Sopenharmony_ci}
1748c2ecf20Sopenharmony_ci#endif /* CONFIG_NETLABEL */
1758c2ecf20Sopenharmony_ci
1768c2ecf20Sopenharmony_ci/*
1778c2ecf20Sopenharmony_ci * Protocol Handling Functions
1788c2ecf20Sopenharmony_ci */
1798c2ecf20Sopenharmony_ci
1808c2ecf20Sopenharmony_ci#ifdef CONFIG_NETLABEL
1818c2ecf20Sopenharmony_civoid cipso_v4_error(struct sk_buff *skb, int error, u32 gateway);
1828c2ecf20Sopenharmony_ciint cipso_v4_getattr(const unsigned char *cipso,
1838c2ecf20Sopenharmony_ci		     struct netlbl_lsm_secattr *secattr);
1848c2ecf20Sopenharmony_ciint cipso_v4_sock_setattr(struct sock *sk,
1858c2ecf20Sopenharmony_ci			  const struct cipso_v4_doi *doi_def,
1868c2ecf20Sopenharmony_ci			  const struct netlbl_lsm_secattr *secattr);
1878c2ecf20Sopenharmony_civoid cipso_v4_sock_delattr(struct sock *sk);
1888c2ecf20Sopenharmony_ciint cipso_v4_sock_getattr(struct sock *sk, struct netlbl_lsm_secattr *secattr);
1898c2ecf20Sopenharmony_ciint cipso_v4_req_setattr(struct request_sock *req,
1908c2ecf20Sopenharmony_ci			 const struct cipso_v4_doi *doi_def,
1918c2ecf20Sopenharmony_ci			 const struct netlbl_lsm_secattr *secattr);
1928c2ecf20Sopenharmony_civoid cipso_v4_req_delattr(struct request_sock *req);
1938c2ecf20Sopenharmony_ciint cipso_v4_skbuff_setattr(struct sk_buff *skb,
1948c2ecf20Sopenharmony_ci			    const struct cipso_v4_doi *doi_def,
1958c2ecf20Sopenharmony_ci			    const struct netlbl_lsm_secattr *secattr);
1968c2ecf20Sopenharmony_ciint cipso_v4_skbuff_delattr(struct sk_buff *skb);
1978c2ecf20Sopenharmony_ciint cipso_v4_skbuff_getattr(const struct sk_buff *skb,
1988c2ecf20Sopenharmony_ci			    struct netlbl_lsm_secattr *secattr);
1998c2ecf20Sopenharmony_ciunsigned char *cipso_v4_optptr(const struct sk_buff *skb);
2008c2ecf20Sopenharmony_ciint cipso_v4_validate(const struct sk_buff *skb, unsigned char **option);
2018c2ecf20Sopenharmony_ci#else
2028c2ecf20Sopenharmony_cistatic inline void cipso_v4_error(struct sk_buff *skb,
2038c2ecf20Sopenharmony_ci				  int error,
2048c2ecf20Sopenharmony_ci				  u32 gateway)
2058c2ecf20Sopenharmony_ci{
2068c2ecf20Sopenharmony_ci	return;
2078c2ecf20Sopenharmony_ci}
2088c2ecf20Sopenharmony_ci
2098c2ecf20Sopenharmony_cistatic inline int cipso_v4_getattr(const unsigned char *cipso,
2108c2ecf20Sopenharmony_ci				   struct netlbl_lsm_secattr *secattr)
2118c2ecf20Sopenharmony_ci{
2128c2ecf20Sopenharmony_ci	return -ENOSYS;
2138c2ecf20Sopenharmony_ci}
2148c2ecf20Sopenharmony_ci
2158c2ecf20Sopenharmony_cistatic inline int cipso_v4_sock_setattr(struct sock *sk,
2168c2ecf20Sopenharmony_ci				      const struct cipso_v4_doi *doi_def,
2178c2ecf20Sopenharmony_ci				      const struct netlbl_lsm_secattr *secattr)
2188c2ecf20Sopenharmony_ci{
2198c2ecf20Sopenharmony_ci	return -ENOSYS;
2208c2ecf20Sopenharmony_ci}
2218c2ecf20Sopenharmony_ci
2228c2ecf20Sopenharmony_cistatic inline void cipso_v4_sock_delattr(struct sock *sk)
2238c2ecf20Sopenharmony_ci{
2248c2ecf20Sopenharmony_ci}
2258c2ecf20Sopenharmony_ci
2268c2ecf20Sopenharmony_cistatic inline int cipso_v4_sock_getattr(struct sock *sk,
2278c2ecf20Sopenharmony_ci					struct netlbl_lsm_secattr *secattr)
2288c2ecf20Sopenharmony_ci{
2298c2ecf20Sopenharmony_ci	return -ENOSYS;
2308c2ecf20Sopenharmony_ci}
2318c2ecf20Sopenharmony_ci
2328c2ecf20Sopenharmony_cistatic inline int cipso_v4_req_setattr(struct request_sock *req,
2338c2ecf20Sopenharmony_ci				       const struct cipso_v4_doi *doi_def,
2348c2ecf20Sopenharmony_ci				       const struct netlbl_lsm_secattr *secattr)
2358c2ecf20Sopenharmony_ci{
2368c2ecf20Sopenharmony_ci	return -ENOSYS;
2378c2ecf20Sopenharmony_ci}
2388c2ecf20Sopenharmony_ci
2398c2ecf20Sopenharmony_cistatic inline void cipso_v4_req_delattr(struct request_sock *req)
2408c2ecf20Sopenharmony_ci{
2418c2ecf20Sopenharmony_ci	return;
2428c2ecf20Sopenharmony_ci}
2438c2ecf20Sopenharmony_ci
2448c2ecf20Sopenharmony_cistatic inline int cipso_v4_skbuff_setattr(struct sk_buff *skb,
2458c2ecf20Sopenharmony_ci				      const struct cipso_v4_doi *doi_def,
2468c2ecf20Sopenharmony_ci				      const struct netlbl_lsm_secattr *secattr)
2478c2ecf20Sopenharmony_ci{
2488c2ecf20Sopenharmony_ci	return -ENOSYS;
2498c2ecf20Sopenharmony_ci}
2508c2ecf20Sopenharmony_ci
2518c2ecf20Sopenharmony_cistatic inline int cipso_v4_skbuff_delattr(struct sk_buff *skb)
2528c2ecf20Sopenharmony_ci{
2538c2ecf20Sopenharmony_ci	return -ENOSYS;
2548c2ecf20Sopenharmony_ci}
2558c2ecf20Sopenharmony_ci
2568c2ecf20Sopenharmony_cistatic inline int cipso_v4_skbuff_getattr(const struct sk_buff *skb,
2578c2ecf20Sopenharmony_ci					  struct netlbl_lsm_secattr *secattr)
2588c2ecf20Sopenharmony_ci{
2598c2ecf20Sopenharmony_ci	return -ENOSYS;
2608c2ecf20Sopenharmony_ci}
2618c2ecf20Sopenharmony_ci
2628c2ecf20Sopenharmony_cistatic inline unsigned char *cipso_v4_optptr(const struct sk_buff *skb)
2638c2ecf20Sopenharmony_ci{
2648c2ecf20Sopenharmony_ci	return NULL;
2658c2ecf20Sopenharmony_ci}
2668c2ecf20Sopenharmony_ci
2678c2ecf20Sopenharmony_cistatic inline int cipso_v4_validate(const struct sk_buff *skb,
2688c2ecf20Sopenharmony_ci				    unsigned char **option)
2698c2ecf20Sopenharmony_ci{
2708c2ecf20Sopenharmony_ci	unsigned char *opt = *option;
2718c2ecf20Sopenharmony_ci	unsigned char err_offset = 0;
2728c2ecf20Sopenharmony_ci	u8 opt_len = opt[1];
2738c2ecf20Sopenharmony_ci	u8 opt_iter;
2748c2ecf20Sopenharmony_ci	u8 tag_len;
2758c2ecf20Sopenharmony_ci
2768c2ecf20Sopenharmony_ci	if (opt_len < 8) {
2778c2ecf20Sopenharmony_ci		err_offset = 1;
2788c2ecf20Sopenharmony_ci		goto out;
2798c2ecf20Sopenharmony_ci	}
2808c2ecf20Sopenharmony_ci
2818c2ecf20Sopenharmony_ci	if (get_unaligned_be32(&opt[2]) == 0) {
2828c2ecf20Sopenharmony_ci		err_offset = 2;
2838c2ecf20Sopenharmony_ci		goto out;
2848c2ecf20Sopenharmony_ci	}
2858c2ecf20Sopenharmony_ci
2868c2ecf20Sopenharmony_ci	for (opt_iter = 6; opt_iter < opt_len;) {
2878c2ecf20Sopenharmony_ci		if (opt_iter + 1 == opt_len) {
2888c2ecf20Sopenharmony_ci			err_offset = opt_iter;
2898c2ecf20Sopenharmony_ci			goto out;
2908c2ecf20Sopenharmony_ci		}
2918c2ecf20Sopenharmony_ci		tag_len = opt[opt_iter + 1];
2928c2ecf20Sopenharmony_ci		if ((tag_len == 0) || (tag_len > (opt_len - opt_iter))) {
2938c2ecf20Sopenharmony_ci			err_offset = opt_iter + 1;
2948c2ecf20Sopenharmony_ci			goto out;
2958c2ecf20Sopenharmony_ci		}
2968c2ecf20Sopenharmony_ci		opt_iter += tag_len;
2978c2ecf20Sopenharmony_ci	}
2988c2ecf20Sopenharmony_ci
2998c2ecf20Sopenharmony_ciout:
3008c2ecf20Sopenharmony_ci	*option = opt + err_offset;
3018c2ecf20Sopenharmony_ci	return err_offset;
3028c2ecf20Sopenharmony_ci
3038c2ecf20Sopenharmony_ci}
3048c2ecf20Sopenharmony_ci#endif /* CONFIG_NETLABEL */
3058c2ecf20Sopenharmony_ci
3068c2ecf20Sopenharmony_ci#endif /* _CIPSO_IPV4_H */
307