Commit d77fdda9 authored by Jon Grimm's avatar Jon Grimm

[SCTP] Use Crypto API

Rip out our own HMAC-SHA1 and replace with crypto API.  
Can now choose hmac-sha1, hmac-md5, or none with regards to what
HMAC to use for cookie echo verification.
parent 38d05e5b
......@@ -6,46 +6,42 @@
*
* This file is part of the SCTP kernel reference Implementation
*
* This file is part of the implementation of the add-IP extension,
* based on <draft-ietf-tsvwg-addip-sctp-02.txt> June 29, 2001,
* for the SCTP kernel reference Implementation.
*
* The SCTP reference implementation is free software;
* The SCTP reference implementation 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, or (at your option)
* any later version.
*
* the SCTP reference implementation is distributed in the hope that it
* will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
* The SCTP reference implementation is distributed in the hope that it
* will be useful, but WITHOUT ANY WARRANTY; without even the implied
* ************************
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU CC; see the file COPYING. If not, write to
* the Free Software Foundation, 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*
* Please send any bug reports or fixes you make to one of the following email
* addresses:
* Please send any bug reports or fixes you make to the
* email address(es):
* lksctp developers <lksctp-developers@lists.sourceforge.net>
*
* Or submit a bug report through the following website:
* http://www.sf.net/projects/lksctp
*
* La Monte H.P. Yarroll <piggy@acm.org>
* Karl Knutson <karl@athena.chicago.il.us>
* Randall Stewart <randall@stewart.chicago.il.us>
* Ken Morneau <kmorneau@cisco.com>
* Qiaobing Xie <qxie1@motorola.com>
* Xingang Guo <xingang.guo@intel.com>
* Sridhar Samudrala <samudrala@us.ibm.com>
* Daisy Chang <daisyc@us.ibm.com>
* Written or modified by:
* La Monte H.P. Yarroll <piggy@acm.org>
* Karl Knutson <karl@athena.chicago.il.us>
* Randall Stewart <randall@stewart.chicago.il.us>
* Ken Morneau <kmorneau@cisco.com>
* Qiaobing Xie <qxie1@motorola.com>
* Xingang Guo <xingang.guo@intel.com>
* Sridhar Samudrala <samudrala@us.ibm.com>
* Daisy Chang <daisyc@us.ibm.com>
*
* Any bugs reported given to us we will try to fix... any fixes shared will
* be incorporated into the next SCTP release.
*
* There are still LOTS of bugs in this code... I always run on the motto
* "it is a wonder any code ever works :)"
*
*
*/
#ifndef __sctp_constants_h__
......@@ -336,10 +332,18 @@ typedef enum {
#define SCTP_SIGNATURE_SIZE 20 /* size of a SLA-1 signature */
#define SCTP_COOKIE_MULTIPLE 64 /* Pad out our cookie to make our hash
#define SCTP_COOKIE_MULTIPLE 32 /* Pad out our cookie to make our hash
* functions simpler to write.
*/
#if defined (CONFIG_SCTP_HMAC_MD5)
#define SCTP_COOKIE_HMAC_ALG "md5"
#elif defined (CONFIG_SCTP_HMAC_SHA1)
#define SCTP_COOKIE_HMAC_ALG "sha1"
#else
#define SCTP_COOKIE_HMAC_ALG NULL
#endif
/* These return values describe the success or failure of a number of
* routines which form the lower interface to SCTP_outqueue.
*/
......
......@@ -178,12 +178,6 @@ extern void sctp_err_finish(struct sock *, struct sctp_endpoint *,
struct sctp_association *);
extern void sctp_icmp_frag_needed(struct sock *, struct sctp_association *,
struct sctp_transport *t, __u32 pmtu);
/*
* sctp/hashdriver.c
*/
extern void sctp_hash_digest(const char *secret, const int secret_len,
const char *text, const int text_len,
__u8 *digest);
/*
* Section: Macros, externs, and inlines
......
......@@ -283,8 +283,11 @@ struct sctp_opt {
/* PF_ family specific functions. */
struct sctp_pf *pf;
/* Access to HMAC transform. */
struct crypto_tfm *hmac;
/* What is our base endpointer? */
sctp_endpoint_t *ep;
struct sctp_endpoint *ep;
/* Various Socket Options. */
__u16 default_stream;
......@@ -1054,11 +1057,6 @@ struct sctp_endpoint {
/* Common substructure for endpoint and association. */
sctp_endpoint_common_t base;
/* These are the system-wide defaults and other stuff which is
* endpoint-independent.
*/
struct sctp_protocol *proto;
/* Associations: A list of current associations and mappings
* to the data consumers for each association. This
* may be in the form of a hash table or other
......@@ -1092,28 +1090,29 @@ struct sctp_endpoint {
};
/* Recover the outter endpoint structure. */
static inline sctp_endpoint_t *sctp_ep(sctp_endpoint_common_t *base)
static inline struct sctp_endpoint *sctp_ep(sctp_endpoint_common_t *base)
{
sctp_endpoint_t *ep;
struct sctp_endpoint *ep;
ep = container_of(base, sctp_endpoint_t, base);
ep = container_of(base, struct sctp_endpoint, base);
return ep;
}
/* These are function signatures for manipulating endpoints. */
sctp_endpoint_t *sctp_endpoint_new(struct sctp_protocol *, struct sock *, int);
sctp_endpoint_t *sctp_endpoint_init(struct sctp_endpoint *,
struct sctp_protocol *,
struct sock *, int gfp);
void sctp_endpoint_free(sctp_endpoint_t *);
void sctp_endpoint_put(sctp_endpoint_t *);
void sctp_endpoint_hold(sctp_endpoint_t *);
void sctp_endpoint_add_asoc(sctp_endpoint_t *, struct sctp_association *asoc);
struct sctp_association *sctp_endpoint_lookup_assoc(const sctp_endpoint_t *ep,
const union sctp_addr *paddr,
struct sctp_transport **);
int sctp_endpoint_is_peeled_off(sctp_endpoint_t *, const union sctp_addr *);
sctp_endpoint_t *sctp_endpoint_is_match(sctp_endpoint_t *,
struct sctp_endpoint *sctp_endpoint_new(struct sock *, int);
struct sctp_endpoint *sctp_endpoint_init(struct sctp_endpoint *,
struct sock *, int gfp);
void sctp_endpoint_free(struct sctp_endpoint *);
void sctp_endpoint_put(struct sctp_endpoint *);
void sctp_endpoint_hold(struct sctp_endpoint *);
void sctp_endpoint_add_asoc(struct sctp_endpoint *, struct sctp_association *);
struct sctp_association *sctp_endpoint_lookup_assoc(
const struct sctp_endpoint *ep,
const union sctp_addr *paddr,
struct sctp_transport **);
int sctp_endpoint_is_peeled_off(struct sctp_endpoint *,
const union sctp_addr *);
struct sctp_endpoint *sctp_endpoint_is_match(struct sctp_endpoint *,
const union sctp_addr *);
int sctp_has_association(const union sctp_addr *laddr,
const union sctp_addr *paddr);
......@@ -1126,8 +1125,8 @@ int sctp_process_init(struct sctp_association *, sctp_cid_t cid,
sctp_init_chunk_t *init, int gfp);
int sctp_process_param(struct sctp_association *, union sctp_params param,
const union sctp_addr *from, int gfp);
__u32 sctp_generate_tag(const sctp_endpoint_t *);
__u32 sctp_generate_tsn(const sctp_endpoint_t *);
__u32 sctp_generate_tag(const struct sctp_endpoint *);
__u32 sctp_generate_tsn(const struct sctp_endpoint *);
/* RFC2960
......@@ -1162,7 +1161,7 @@ struct sctp_association {
__u32 eyecatcher;
/* This is our parent endpoint. */
sctp_endpoint_t *ep;
struct sctp_endpoint *ep;
/* These are those association elements needed in the cookie. */
sctp_cookie_t c;
......@@ -1571,10 +1570,10 @@ static inline struct sctp_association *sctp_assoc(sctp_endpoint_common_t *base)
struct sctp_association *
sctp_association_new(const sctp_endpoint_t *, const struct sock *,
sctp_association_new(const struct sctp_endpoint *, const struct sock *,
sctp_scope_t scope, int gfp);
struct sctp_association *
sctp_association_init(struct sctp_association *, const sctp_endpoint_t *,
sctp_association_init(struct sctp_association *, const struct sctp_endpoint *,
const struct sock *, sctp_scope_t scope,
int gfp);
void sctp_association_free(struct sctp_association *);
......
......@@ -43,12 +43,12 @@ config SCTP_ADLER32
bool "SCTP: Use old checksum (Adler-32)"
depends on IP_SCTP
help
RCF2960 currently specifies the Adler-32 checksum algorithm for SCTP.
RCF2960 currently specifies the Adler-32 checksum algorithm for SCTP.
This has been deprecated and replaced by an algorithm now referred
to as crc32c.
If you say Y, this will use the Adler-32 algorithm, this might be useful
for interoperation with downlevel peers.
If you say Y, this will use the Adler-32 algorithm, this might be
useful for interoperation with downlevel peers.
If unsure, say N.
......@@ -58,19 +58,46 @@ config SCTP_DBG_MSG
help
If you say Y, this will enable verbose debugging messages.
If unsure, say N. However, if you are running into problems, use this
option to gather detailed trace information
If unsure, say N. However, if you are running into problems, use
this option to gather detailed trace information
config SCTP_DBG_OBJCNT
bool "SCTP: Debug object counts"
depends on IP_SCTP
help
If you say Y, this will enable debugging support for counting the types
of objects that are currently allocated. This is useful for identifying
memory leaks. If the /proc filesystem is enabled this debug information
can be viewed by 'cat /proc/net/sctp/sctp_dbg_objcnt'
If you say Y, this will enable debugging support for counting the
type of objects that are currently allocated. This is useful for
identifying memory leaks. If the /proc filesystem is enabled this
debug information can be viewed by
'cat /proc/net/sctp/sctp_dbg_objcnt'
If unsure, say N
endmenu
choice
prompt "SCTP: Cookie HMAC Algorithm"
help
HMAC algorithm to be used during association initialization. It
is strongly recommended to use HMAC-SHA1 or HMAC-MD5. See
configuration for Cryptographic API and enable those algorithms
to make usable by SCTP.
config SCTP_HMAC_NONE
bool "None"
help
Choosing this disables the use of an HMAC during association
establishment. It is advised to use either HMAC-MD5 or HMAC-SHA1.
config SCTP_HMAC_SHA1
bool "HMAC-SHA1" if CRYPTO_HMAC=y && CRYPTO_SHA1=y || CRYPTO_SHA1=m
help
Enable the use of HMAC-SHA1 during association establishment. It
is advised to use either HMAC-MD5 or HMAC-SHA1.
config SCTP_HMAC_MD5
bool "HMAC-MD5" if CRYPTO_HMAC=y && CRYPTO_MD5=y || CRYPTO_MD5=m
help
Enable the use of HMAC-MD5 during association establishment. It is
advised to use either HMAC-MD5 or HMAC-SHA1.
endchoice
endmenu
......@@ -9,8 +9,7 @@ sctp-y := sm_statetable.o sm_statefuns.o sm_sideeffect.o \
transport.o sm_make_chunk.o ulpevent.o \
inqueue.o outqueue.o ulpqueue.o command.o \
tsnmap.o bind_addr.o socket.o primitive.o \
output.o input.o hashdriver.o sla1.o \
debug.o ssnmap.o proc.o
output.o input.o debug.o ssnmap.o proc.o
ifeq ($(CONFIG_SCTP_ADLER32), y)
sctp-y += adler32.o
......
......@@ -96,6 +96,7 @@ sctp_association_t *sctp_association_init(sctp_association_t *asoc,
int priority)
{
struct sctp_opt *sp;
struct sctp_protocol *proto = sctp_get_protocol();
int i;
/* Retrieve the SCTP per socket area. */
......@@ -136,10 +137,10 @@ sctp_association_t *sctp_association_init(sctp_association_t *asoc,
asoc->frag_point = 0;
/* Initialize the default association max_retrans and RTO values. */
asoc->max_retrans = ep->proto->max_retrans_association;
asoc->rto_initial = ep->proto->rto_initial;
asoc->rto_max = ep->proto->rto_max;
asoc->rto_min = ep->proto->rto_min;
asoc->max_retrans = proto->max_retrans_association;
asoc->rto_initial = proto->rto_initial;
asoc->rto_max = proto->rto_max;
asoc->rto_min = proto->rto_min;
asoc->overall_error_threshold = 0;
asoc->overall_error_count = 0;
......@@ -147,7 +148,7 @@ sctp_association_t *sctp_association_init(sctp_association_t *asoc,
/* Initialize the maximum mumber of new data packets that can be sent
* in a burst.
*/
asoc->max_burst = ep->proto->max_burst;
asoc->max_burst = proto->max_burst;
/* Copy things from the endpoint. */
for (i = SCTP_EVENT_TIMEOUT_NONE; i < SCTP_NUM_TIMEOUT_TYPES; ++i) {
......
......@@ -54,27 +54,27 @@
#include <linux/slab.h>
#include <linux/in.h>
#include <linux/random.h> /* get_random_bytes() */
#include <linux/crypto.h>
#include <net/sock.h>
#include <net/ipv6.h>
#include <net/sctp/sctp.h>
#include <net/sctp/sm.h>
/* Forward declarations for internal helpers. */
static void sctp_endpoint_bh_rcv(sctp_endpoint_t *ep);
static void sctp_endpoint_bh_rcv(struct sctp_endpoint *ep);
/* Create a sctp_endpoint_t with all that boring stuff initialized.
/* Create a sctp_endpoint with all that boring stuff initialized.
* Returns NULL if there isn't enough memory.
*/
sctp_endpoint_t *sctp_endpoint_new(struct sctp_protocol *proto,
struct sock *sk, int priority)
struct sctp_endpoint *sctp_endpoint_new(struct sock *sk, int gfp)
{
sctp_endpoint_t *ep;
struct sctp_endpoint *ep;
/* Build a local endpoint. */
ep = t_new(sctp_endpoint_t, priority);
ep = t_new(struct sctp_endpoint, gfp);
if (!ep)
goto fail;
if (!sctp_endpoint_init(ep, proto, sk, priority))
if (!sctp_endpoint_init(ep, sk, gfp))
goto fail_init;
ep->base.malloced = 1;
SCTP_DBG_OBJCNT_INC(ep);
......@@ -89,12 +89,11 @@ sctp_endpoint_t *sctp_endpoint_new(struct sctp_protocol *proto,
/*
* Initialize the base fields of the endpoint structure.
*/
sctp_endpoint_t *sctp_endpoint_init(sctp_endpoint_t *ep,
struct sctp_protocol *proto,
struct sock *sk, int priority)
struct sctp_endpoint *sctp_endpoint_init(struct sctp_endpoint *ep,
struct sock *sk, int gfp)
{
struct sctp_opt *sp = sctp_sk(sk);
memset(ep, 0, sizeof(sctp_endpoint_t));
memset(ep, 0, sizeof(struct sctp_endpoint));
/* Initialize the base structure. */
/* What type of endpoint are we? */
......@@ -110,8 +109,7 @@ sctp_endpoint_t *sctp_endpoint_init(sctp_endpoint_t *ep,
/* Set its top-half handler */
sctp_inq_set_th_handler(&ep->base.inqueue,
(void (*)(void *))sctp_endpoint_bh_rcv,
ep);
(void (*)(void *))sctp_endpoint_bh_rcv, ep);
/* Initialize the bind addr area */
sctp_bind_addr_init(&ep->base.bind_addr, 0);
......@@ -121,21 +119,16 @@ sctp_endpoint_t *sctp_endpoint_init(sctp_endpoint_t *ep,
ep->base.sk = sk;
sock_hold(ep->base.sk);
/* This pointer is useful to access the default protocol parameter
* values.
*/
ep->proto = proto;
/* Create the lists of associations. */
INIT_LIST_HEAD(&ep->asocs);
/* Set up the base timeout information. */
ep->timeouts[SCTP_EVENT_TIMEOUT_NONE] = 0;
ep->timeouts[SCTP_EVENT_TIMEOUT_T1_COOKIE] =
ep->timeouts[SCTP_EVENT_TIMEOUT_T1_COOKIE] =
SCTP_DEFAULT_TIMEOUT_T1_COOKIE;
ep->timeouts[SCTP_EVENT_TIMEOUT_T1_INIT] =
ep->timeouts[SCTP_EVENT_TIMEOUT_T1_INIT] =
SCTP_DEFAULT_TIMEOUT_T1_INIT;
ep->timeouts[SCTP_EVENT_TIMEOUT_T2_SHUTDOWN] =
ep->timeouts[SCTP_EVENT_TIMEOUT_T2_SHUTDOWN] =
sp->rtoinfo.srto_initial;
ep->timeouts[SCTP_EVENT_TIMEOUT_T3_RTX] = 0;
......@@ -146,11 +139,11 @@ sctp_endpoint_t *sctp_endpoint_init(sctp_endpoint_t *ep,
ep->timeouts[SCTP_EVENT_TIMEOUT_T5_SHUTDOWN_GUARD]
= 5 * sp->rtoinfo.srto_max;
ep->timeouts[SCTP_EVENT_TIMEOUT_HEARTBEAT] =
ep->timeouts[SCTP_EVENT_TIMEOUT_HEARTBEAT] =
SCTP_DEFAULT_TIMEOUT_HEARTBEAT;
ep->timeouts[SCTP_EVENT_TIMEOUT_SACK] =
ep->timeouts[SCTP_EVENT_TIMEOUT_SACK] =
SCTP_DEFAULT_TIMEOUT_SACK;
ep->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE] =
ep->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE] =
sp->autoclose * HZ;
/* Set up the default send/receive buffer space. */
......@@ -175,7 +168,8 @@ sctp_endpoint_t *sctp_endpoint_init(sctp_endpoint_t *ep,
}
/* Add an association to an endpoint. */
void sctp_endpoint_add_asoc(sctp_endpoint_t *ep, sctp_association_t *asoc)
void sctp_endpoint_add_asoc(struct sctp_endpoint *ep,
struct sctp_association *asoc)
{
struct sock *sk = ep->base.sk;
......@@ -191,14 +185,14 @@ void sctp_endpoint_add_asoc(sctp_endpoint_t *ep, sctp_association_t *asoc)
/* Free the endpoint structure. Delay cleanup until
* all users have released their reference count on this structure.
*/
void sctp_endpoint_free(sctp_endpoint_t *ep)
void sctp_endpoint_free(struct sctp_endpoint *ep)
{
ep->base.dead = 1;
sctp_endpoint_put(ep);
}
/* Final destructor for endpoint. */
void sctp_endpoint_destroy(sctp_endpoint_t *ep)
void sctp_endpoint_destroy(struct sctp_endpoint *ep)
{
SCTP_ASSERT(ep->base.dead, "Endpoint is not dead", return);
......@@ -207,9 +201,12 @@ void sctp_endpoint_destroy(sctp_endpoint_t *ep)
/* Unlink this endpoint, so we can't find it again! */
sctp_unhash_endpoint(ep);
/* Cleanup the inqueue. */
sctp_inq_free(&ep->base.inqueue);
/* Free up the HMAC transform. */
if (sctp_sk(ep->base.sk)->hmac)
crypto_free_tfm(sctp_sk(ep->base.sk)->hmac);
/* Cleanup. */
sctp_inq_free(&ep->base.inqueue);
sctp_bind_addr_free(&ep->base.bind_addr);
/* Remove and free the port */
......@@ -228,7 +225,7 @@ void sctp_endpoint_destroy(sctp_endpoint_t *ep)
}
/* Hold a reference to an endpoint. */
void sctp_endpoint_hold(sctp_endpoint_t *ep)
void sctp_endpoint_hold(struct sctp_endpoint *ep)
{
atomic_inc(&ep->base.refcnt);
}
......@@ -236,17 +233,17 @@ void sctp_endpoint_hold(sctp_endpoint_t *ep)
/* Release a reference to an endpoint and clean up if there are
* no more references.
*/
void sctp_endpoint_put(sctp_endpoint_t *ep)
void sctp_endpoint_put(struct sctp_endpoint *ep)
{
if (atomic_dec_and_test(&ep->base.refcnt))
sctp_endpoint_destroy(ep);
}
/* Is this the endpoint we are looking for? */
sctp_endpoint_t *sctp_endpoint_is_match(sctp_endpoint_t *ep,
const union sctp_addr *laddr)
struct sctp_endpoint *sctp_endpoint_is_match(struct sctp_endpoint *ep,
const union sctp_addr *laddr)
{
sctp_endpoint_t *retval;
struct sctp_endpoint *retval;
sctp_read_lock(&ep->base.addr_lock);
if (ep->base.bind_addr.port == laddr->v4.sin_port) {
......@@ -268,19 +265,19 @@ sctp_endpoint_t *sctp_endpoint_is_match(sctp_endpoint_t *ep,
* We do a linear search of the associations for this endpoint.
* We return the matching transport address too.
*/
sctp_association_t *__sctp_endpoint_lookup_assoc(
const sctp_endpoint_t *endpoint,
struct sctp_association *__sctp_endpoint_lookup_assoc(
const struct sctp_endpoint *ep,
const union sctp_addr *paddr,
struct sctp_transport **transport)
{
int rport;
sctp_association_t *asoc;
struct sctp_association *asoc;
struct list_head *pos;
rport = paddr->v4.sin_port;
list_for_each(pos, &endpoint->asocs) {
asoc = list_entry(pos, sctp_association_t, asocs);
list_for_each(pos, &ep->asocs) {
asoc = list_entry(pos, struct sctp_association, asocs);
if (rport == asoc->peer.port) {
sctp_read_lock(&asoc->base.addr_lock);
*transport = sctp_assoc_lookup_paddr(asoc, paddr);
......@@ -296,12 +293,12 @@ sctp_association_t *__sctp_endpoint_lookup_assoc(
}
/* Lookup association on an endpoint based on a peer address. BH-safe. */
sctp_association_t *sctp_endpoint_lookup_assoc(
const sctp_endpoint_t *ep,
struct sctp_association *sctp_endpoint_lookup_assoc(
const struct sctp_endpoint *ep,
const union sctp_addr *paddr,
struct sctp_transport **transport)
{
sctp_association_t *asoc;
struct sctp_association *asoc;
sctp_local_bh_disable();
asoc = __sctp_endpoint_lookup_assoc(ep, paddr, transport);
......@@ -313,7 +310,7 @@ sctp_association_t *sctp_endpoint_lookup_assoc(
/* Look for any peeled off association from the endpoint that matches the
* given peer address.
*/
int sctp_endpoint_is_peeled_off(sctp_endpoint_t *ep,
int sctp_endpoint_is_peeled_off(struct sctp_endpoint *ep,
const union sctp_addr *paddr)
{
struct list_head *pos;
......@@ -337,9 +334,9 @@ int sctp_endpoint_is_peeled_off(sctp_endpoint_t *ep,
/* Do delayed input processing. This is scheduled by sctp_rcv().
* This may be called on BH or task time.
*/
static void sctp_endpoint_bh_rcv(sctp_endpoint_t *ep)
static void sctp_endpoint_bh_rcv(struct sctp_endpoint *ep)
{
sctp_association_t *asoc;
struct sctp_association *asoc;
struct sock *sk;
struct sctp_transport *transport;
sctp_chunk_t *chunk;
......@@ -355,7 +352,7 @@ static void sctp_endpoint_bh_rcv(sctp_endpoint_t *ep)
inqueue = &ep->base.inqueue;
sk = ep->base.sk;
while (NULL != (chunk = sctp_inq_pop(inqueue))) {
while (NULL != (chunk = sctp_inq_pop(inqueue))) {
subtype.chunk = chunk->chunk_hdr->type;
/* We might have grown an association since last we
......
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment