aboutsummaryrefslogtreecommitdiffstats
path: root/docs/hazmat/primitives/symmetric-encryption.rst
Commit message (Collapse)AuthorAgeFilesLines
...
| * Merge pull request #325 from public/unsupported-cipher-messagesAlex Gaynor2013-12-221-1/+1
| |\ | | | | | | UnsupportedAlgorithm error messages for Ciphers
| | * UnsupportedAlgorithm error messages for CiphersAlex Stapleton2013-12-221-1/+1
| | |
| * | a few more doc changes to gcm tag infoPaul Kehrer2013-12-211-2/+3
| | |
| * | prose updates for GCM tagPaul Kehrer2013-12-211-4/+6
| | |
| * | doc updatesPaul Kehrer2013-12-211-2/+5
| | |
| * | add note regarding not truncating tagsPaul Kehrer2013-12-211-0/+5
| |/
* / Link from symmetric encryption to fernetAlex Gaynor2013-12-201-1/+1
|/
* Merge pull request #308 from alex/rename-bindingsDonald Stufft2013-12-151-4/+4
|\ | | | | Renamed bindings to backends
| * Renamed bindings to backendsAlex Gaynor2013-12-131-4/+4
| |
* | Need to include the importsAlex Gaynor2013-12-131-0/+2
| |
* | Prefer executable code examplesAlex Gaynor2013-12-131-2/+2
|/
* Always show where a baackend comes form in the docsAlex Gaynor2013-12-131-5/+6
|
* Merge pull request #285 from reaperhulk/fix-282Alex Gaynor2013-12-061-2/+2
|\ | | | | raise ValueErrors when supplying/not supplying tags for GCM
| * update docs to explain tag requirements and valueerrorPaul Kehrer2013-12-061-2/+2
| |
* | Don't show so much stuffAlex Gaynor2013-12-041-1/+1
| |
* | Be more specific about when you can trust authentication on GCMAlex Gaynor2013-12-041-3/+4
|/
* link to NIST GCM PDF where NIST recommends 96-bit IV for perf with GCMPaul Kehrer2013-12-031-5/+7
| | | | | Clarify that 96-bit IV is only recommended in performance critical situations...otherwise feel free to use something longer.
* remove AEADDecryptionContext references from GCM docsPaul Kehrer2013-12-031-12/+5
|
* improve language for gcm docsPaul Kehrer2013-12-031-5/+5
|
* attempt to document the new interfaces for AEADPaul Kehrer2013-11-291-6/+20
|
* explicit backend fix for gcm docsPaul Kehrer2013-11-291-2/+2
|
* begin adding warnings to GCM modePaul Kehrer2013-11-291-0/+6
|
* document tag param for GCM objectPaul Kehrer2013-11-291-0/+3
|
* raise TypeError if you attempt to get the tag attribute on a decryptPaul Kehrer2013-11-291-0/+1
| | | | | * To support this the _AEADCipherContext in base.py now needs to be aware of whether it is encrypting/decrypting
* rename add_data to authenticate_additional_data for clarity (hopefully)Paul Kehrer2013-11-291-8/+8
|
* gcm doc fixes (per review from alex)Paul Kehrer2013-11-291-3/+4
|
* gcm doc improvementsPaul Kehrer2013-11-291-2/+6
|
* gcm doc fixesPaul Kehrer2013-11-291-2/+2
|
* GCM supportPaul Kehrer2013-11-291-0/+48
|
* Learn how to spell a wordAlex Gaynor2013-11-271-1/+1
|
* Merge pull request #227 from dreid/explicit-backend-in-hazmatAlex Gaynor2013-11-261-5/+18
|\ | | | | Explicit backend
| * Document all the parameters including cross references to specific providers ↵David Reid2013-11-201-2/+12
| | | | | | | | where appropriate.
| * Use backend as keyword argument everywhere.David Reid2013-11-201-2/+2
| |
| * Fix doctests.David Reid2013-11-201-1/+1
| |
| * Add a default_backend and start updating docs.David Reid2013-11-201-3/+6
| |
* | Change teh exceptionAlex Gaynor2013-11-221-7/+3
| |
* | Documentation!Alex Gaynor2013-11-221-0/+16
|/
* Another twoAlex Gaynor2013-11-151-1/+1
|
* Fixed some spelling mistakesAlex Gaynor2013-11-151-4/+4
|
* Also mention finalizeAlex Gaynor2013-11-131-1/+1
|
* Use AlreadyFinalized for symmetric ciphersAlex Gaynor2013-11-131-0/+5
|
* Merge pull request #214 from reaperhulk/arc4-supportDavid Reid2013-11-091-0/+21
|\ | | | | ARC4 Support
| * update docs to include arc4 examplePaul Kehrer2013-11-091-0/+11
| |
| * Merge branch 'master' into arc4-supportPaul Kehrer2013-11-081-3/+26
| |\ | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | * master: Typo Be really explicit about what's good and bad Mention return types. Consistently use e.g. Module documentation. Single space. Add a new Mode interface to document mode.name and start on some prose docs for interfaces. Proper name for the iv thing. Actually note the properties for cipher modes types on their ABCs. Conflicts: docs/hazmat/primitives/symmetric-encryption.rst
| * | ARC4 supportPaul Kehrer2013-11-071-0/+10
| | |
* | | Be more and more explicit about how to do things correctlyAlex Gaynor2013-11-081-6/+17
| |/ |/|
* | Merge pull request #231 from dreid/mode-interface-propertiesAlex Gaynor2013-11-071-0/+3
|\ \ | | | | | | [WIP] Document mode interfaces.
| * | Add a new Mode interface to document mode.name and start on some prose docs ↵David Reid2013-11-071-0/+3
| |/ | | | | | | for interfaces.
* | TypoAlex Gaynor2013-11-071-1/+1
| |
* | Be really explicit about what's good and badAlex Gaynor2013-11-071-3/+23
|/
Literal.String.Backtick */ .highlight .sc { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Char */ .highlight .dl { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Delimiter */ .highlight .sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */ .highlight .s2 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Double */ .highlight .se { color: #0044dd; background-color: #fff0f0 } /* Literal.String.Escape */ .highlight .sh { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Heredoc */ .highlight .si { color: #3333bb; background-color: #fff0f0 } /* Literal.String.Interpol */ .highlight .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.String.Other */ .highlight .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */ .highlight .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */ .highlight .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */ .highlight .bp { color: #003388 } /* Name.Builtin.Pseudo */ .highlight .fm { color: #0066bb; font-weight: bold } /* Name.Function.Magic */ .highlight .vc { color: #336699 } /* Name.Variable.Class */ .highlight .vg { color: #dd7700 } /* Name.Variable.Global */ .highlight .vi { color: #3333bb } /* Name.Variable.Instance */ .highlight .vm { color: #336699 } /* Name.Variable.Magic */ .highlight .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long */
/*
 * swconfig.c: Switch configuration API
 *
 * Copyright (C) 2008 Felix Fietkau <nbd@openwrt.org>
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 */

#include <linux/types.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/list.h>
#include <linux/if.h>
#include <linux/if_ether.h>
#include <linux/capability.h>
#include <linux/skbuff.h>
#include <linux/switch.h>

//#define DEBUG 1
#ifdef DEBUG
#define DPRINTF(format, ...) printk("%s: " format, __func__, ##__VA_ARGS__)
#else
#define DPRINTF(...) do {} while(0)
#endif

MODULE_AUTHOR("Felix Fietkau <nbd@openwrt.org>");
MODULE_LICENSE("GPL");

static int swdev_id = 0;
static struct list_head swdevs;
static spinlock_t swdevs_lock = SPIN_LOCK_UNLOCKED;
struct swconfig_callback;

struct swconfig_callback
{
	struct sk_buff *msg;
	struct genlmsghdr *hdr;
	struct genl_info *info;
	int cmd;

	/* callback for filling in the message data */
	int (*fill)(struct swconfig_callback *cb, void *arg);

	/* callback for closing the message before sending it */
	int (*close)(struct swconfig_callback *cb, void *arg);

	struct nlattr *nest[4];
	int args[4];
};

/* defaults */

static int
swconfig_get_vlan_ports(struct switch_dev *dev, const struct switch_attr *attr, struct switch_val *val)
{
	int ret;
	if (val->port_vlan >= dev->vlans)
		return -EINVAL;

	if (!dev->get_vlan_ports)
		return -EOPNOTSUPP;

	ret = dev->get_vlan_ports(dev, val);
	return ret;
}

static int
swconfig_set_vlan_ports(struct switch_dev *dev, const struct switch_attr *attr, struct switch_val *val)
{
	struct switch_port *ports = val->value.ports;
	int i;

	if (val->port_vlan >= dev->vlans)
		return -EINVAL;

	/* validate ports */
	if (val->len > dev->ports)
		return -EINVAL;

	if (!dev->set_vlan_ports)
		return -EOPNOTSUPP;

	for (i = 0; i < val->len; i++) {
		if (ports[i].id >= dev->ports)
			return -EINVAL;

		if (dev->set_port_pvid && !(ports[i].flags & SWITCH_PORT_FLAG_TAGGED))
			dev->set_port_pvid(dev, ports[i].id, val->port_vlan);
	}

	return dev->set_vlan_ports(dev, val);
}

static int
swconfig_set_pvid(struct switch_dev *dev, const struct switch_attr *attr, struct switch_val *val)
{
	if (val->port_vlan >= dev->ports)
		return -EINVAL;

	if (!dev->set_port_pvid)
		return -EOPNOTSUPP;

	return dev->set_port_pvid(dev, val->port_vlan, val->value.i);
}

static int
swconfig_get_pvid(struct switch_dev *dev, const struct switch_attr *attr, struct switch_val *val)
{
	if (val->port_vlan >= dev->ports)
		return -EINVAL;

	if (!dev->get_port_pvid)
		return -EOPNOTSUPP;

	return dev->get_port_pvid(dev, val->port_vlan, &val->value.i);
}

static int
swconfig_apply_config(struct switch_dev *dev, const struct switch_attr *attr, struct switch_val *val)
{
	/* don't complain if not supported by the switch driver */
	if (!dev->apply_config)
		return 0;

	return dev->apply_config(dev);
}

static int
swconfig_reset_switch(struct switch_dev *dev, const struct switch_attr *attr, struct switch_val *val)
{
	/* don't complain if not supported by the switch driver */
	if (!dev->reset_switch)
		return 0;

	return dev->reset_switch(dev);
}

enum global_defaults {
	GLOBAL_APPLY,
	GLOBAL_RESET,
};

enum vlan_defaults {
	VLAN_PORTS,
};

enum port_defaults {
	PORT_PVID,
};

static struct switch_attr default_global[] = {
	[GLOBAL_APPLY] = {
		.type = SWITCH_TYPE_NOVAL,
		.name = "apply",
		.description = "Activate changes in the hardware",
		.set = swconfig_apply_config,
	},
	[GLOBAL_RESET] = {
		.type = SWITCH_TYPE_NOVAL,
		.name = "reset",
		.description = "Reset the switch",
		.set = swconfig_reset_switch,
	}
};

static struct switch_attr default_port[] = {
	[PORT_PVID] = {
		.type = SWITCH_TYPE_INT,
		.name = "pvid",
		.description = "Primary VLAN ID",
		.set = swconfig_set_pvid,
		.get = swconfig_get_pvid,
	}
};

static struct switch_attr default_vlan[] = {
	[VLAN_PORTS] = {
		.type = SWITCH_TYPE_PORTS,
		.name = "ports",
		.description = "VLAN port mapping",
		.set = swconfig_set_vlan_ports,
		.get = swconfig_get_vlan_ports,
	},
};


static void swconfig_defaults_init(struct switch_dev *dev)
{
	dev->def_global = 0;
	dev->def_vlan = 0;
	dev->def_port = 0;

	if (dev->get_vlan_ports || dev->set_vlan_ports)
		set_bit(VLAN_PORTS, &dev->def_vlan);

	if (dev->get_port_pvid || dev->set_port_pvid)
		set_bit(PORT_PVID, &dev->def_port);

	/* always present, can be no-op */
	set_bit(GLOBAL_APPLY, &dev->def_global);
	set_bit(GLOBAL_RESET, &dev->def_global);
}


static struct genl_family switch_fam = {
	.id = GENL_ID_GENERATE,
	.name = "switch",
	.hdrsize = 0,
	.version = 1,
	.maxattr = SWITCH_ATTR_MAX,
};

static const struct nla_policy switch_policy[SWITCH_ATTR_MAX+1] = {
	[SWITCH_ATTR_ID] = { .type = NLA_U32 },
	[SWITCH_ATTR_OP_ID] = { .type = NLA_U32 },
	[SWITCH_ATTR_OP_PORT] = { .type = NLA_U32 },
	[SWITCH_ATTR_OP_VLAN] = { .type = NLA_U32 },
	[SWITCH_ATTR_OP_VALUE_INT] = { .type = NLA_U32 },
	[SWITCH_ATTR_OP_VALUE_STR] = { .type = NLA_NUL_STRING },
	[SWITCH_ATTR_OP_VALUE_PORTS] = { .type = NLA_NESTED },
	[SWITCH_ATTR_TYPE] = { .type = NLA_U32 },
};

static const struct nla_policy port_policy[SWITCH_PORT_ATTR_MAX+1] = {
	[SWITCH_PORT_ID] = { .type = NLA_U32 },
	[SWITCH_PORT_FLAG_TAGGED] = { .type = NLA_FLAG },
};

static inline void
swconfig_lock(void)
{
	spin_lock(&swdevs_lock);
}

static inline void
swconfig_unlock(void)
{
	spin_unlock(&swdevs_lock);
}

static struct switch_dev *
swconfig_get_dev(struct genl_info *info)
{
	struct switch_dev *dev = NULL;
	struct switch_dev *p;
	int id;

	if (!info->attrs[SWITCH_ATTR_ID])
		goto done;

	id = nla_get_u32(info->attrs[SWITCH_ATTR_ID]);
	swconfig_lock();
	list_for_each_entry(p, &swdevs, dev_list) {
		if (id != p->id)
			continue;

		dev = p;
		break;
	}
	if (dev)
		spin_lock(&dev->lock);
	else
		DPRINTF("device %d not found\n", id);
	swconfig_unlock();
done:
	return dev;
}

static inline void
swconfig_put_dev(struct switch_dev *dev)
{
	spin_unlock(&dev->lock);
}

static int
swconfig_dump_attr(struct swconfig_callback *cb, void *arg)
{
	struct switch_attr *op = arg;
	struct genl_info *info = cb->info;
	struct sk_buff *msg = cb->msg;
	int id = cb->args[0];
	void *hdr;

	hdr = genlmsg_put(msg, info->snd_pid, info->snd_seq, &switch_fam,
			NLM_F_MULTI, SWITCH_CMD_NEW_ATTR);
	if (IS_ERR(hdr))
		return -1;

	NLA_PUT_U32(msg, SWITCH_ATTR_OP_ID, id);
	NLA_PUT_U32(msg, SWITCH_ATTR_OP_TYPE, op->type);
	NLA_PUT_STRING(msg, SWITCH_ATTR_OP_NAME, op->name);
	if (op->description)
		NLA_PUT_STRING(msg, SWITCH_ATTR_OP_DESCRIPTION,
			op->description);

	return genlmsg_end(msg, hdr);
nla_put_failure:
	genlmsg_cancel(msg, hdr);
	return -EMSGSIZE;
}

/* spread multipart messages across multiple message buffers */
static int
swconfig_send_multipart(struct swconfig_callback *cb, void *arg)
{
	struct genl_info *info = cb->info;
	int restart = 0;
	int err;

	do {
		if (!cb->msg) {
			cb->msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
			if (cb->msg == NULL)
				goto error;
		}

		if (!(cb->fill(cb, arg) < 0))
			break;

		/* fill failed, check if this was already the second attempt */
		if (restart)
			goto error;

		/* try again in a new message, send the current one */
		restart = 1;
		if (cb->close) {
			if (cb->close(cb, arg) < 0)
				goto error;
		}
		err = genlmsg_unicast(cb->msg, info->snd_pid);
		cb->msg = NULL;
		if (err < 0)
			goto error;

	} while (restart);

	return 0;

error:
	if (cb->msg)
		nlmsg_free(cb->msg);
	return -1;
}

static int
swconfig_list_attrs(struct sk_buff *skb, struct genl_info *info)
{
	struct genlmsghdr *hdr = nlmsg_data(info->nlhdr);
	const struct switch_attrlist *alist;
	struct switch_dev *dev;
	struct swconfig_callback cb;
	int err = -EINVAL;
	int i;

	/* defaults */
	struct switch_attr *def_list;
	unsigned long *def_active;
	int n_def;

	dev = swconfig_get_dev(info);
	if (!dev)
		return -EINVAL;

	switch(hdr->cmd) {
	case SWITCH_CMD_LIST_GLOBAL:
		alist = &dev->attr_global;
		def_list = default_global;
		def_active = &dev->def_global;
		n_def = ARRAY_SIZE(default_global);
		break;
	case SWITCH_CMD_LIST_VLAN:
		alist = &dev->attr_vlan;
		def_list = default_vlan;
		def_active = &dev->def_vlan;
		n_def = ARRAY_SIZE(default_vlan);
		break;
	case SWITCH_CMD_LIST_PORT:
		alist = &dev->attr_port;
		def_list = default_port;
		def_active = &dev->def_port;
		n_def = ARRAY_SIZE(default_port);
		break;
	default:
		WARN_ON(1);
		goto out;
	}

	memset(&cb, 0, sizeof(cb));
	cb.info = info;
	cb.fill = swconfig_dump_attr;
	for (i = 0; i < alist->n_attr; i++) {
		if (alist->attr[i].disabled)
			continue;
		cb.args[0] = i;
		err = swconfig_send_multipart(&cb, (void *) &alist->attr[i]);
		if (err < 0)
			goto error;
	}

	/* defaults */
	for (i = 0; i < n_def; i++) {
		if (!test_bit(i, def_active))
			continue;
		cb.args[0] = SWITCH_ATTR_DEFAULTS_OFFSET + i;
		err = swconfig_send_multipart(&cb, (void *) &def_list[i]);
		if (err < 0)
			goto error;
	}
	swconfig_put_dev(dev);

	if (!cb.msg)
		return 0;

	return genlmsg_unicast(cb.msg, info->snd_pid);

error:
	if (cb.msg)
		nlmsg_free(cb.msg);
out:
	swconfig_put_dev(dev);
	return err;
}

static const struct switch_attr *
swconfig_lookup_attr(struct switch_dev *dev, struct genl_info *info,
		struct switch_val *val)
{
	struct genlmsghdr *hdr = nlmsg_data(info->nlhdr);
	const struct switch_attrlist *alist;
	const struct switch_attr *attr = NULL;
	int attr_id;

	/* defaults */
	struct switch_attr *def_list;
	unsigned long *def_active;
	int n_def;

	if (!info->attrs[SWITCH_ATTR_OP_ID])
		goto done;

	switch(hdr->cmd) {
	case SWITCH_CMD_SET_GLOBAL:
	case SWITCH_CMD_GET_GLOBAL:
		alist = &dev->attr_global;
		def_list = default_global;
		def_active = &dev->def_global;
		n_def = ARRAY_SIZE(default_global);
		break;
	case SWITCH_CMD_SET_VLAN:
	case SWITCH_CMD_GET_VLAN:
		alist = &dev->attr_vlan;
		def_list = default_vlan;
		def_active = &dev->def_vlan;
		n_def = ARRAY_SIZE(default_vlan);
		if (!info->attrs[SWITCH_ATTR_OP_VLAN])
			goto done;
		val->port_vlan = nla_get_u32(info->attrs[SWITCH_ATTR_OP_VLAN]);
		if (val->port_vlan >= dev->vlans)
			goto done;
		break;
	case SWITCH_CMD_SET_PORT:
	case SWITCH_CMD_GET_PORT:
		alist = &dev->attr_port;
		def_list = default_port;
		def_active = &dev->def_port;
		n_def = ARRAY_SIZE(default_port);
		if (!info->attrs[SWITCH_ATTR_OP_PORT])
			goto done;
		val->port_vlan = nla_get_u32(info->attrs[SWITCH_ATTR_OP_PORT]);
		if (val->port_vlan >= dev->ports)
			goto done;
		break;
	default:
		WARN_ON(1);
		goto done;
	}

	if (!alist)
		goto done;

	attr_id = nla_get_u32(info->attrs[SWITCH_ATTR_OP_ID]);
	if (attr_id >= SWITCH_ATTR_DEFAULTS_OFFSET) {
		attr_id -= SWITCH_ATTR_DEFAULTS_OFFSET;
		if (attr_id >= n_def)
			goto done;
		if (!test_bit(attr_id, def_active))