From df23589d2cc0419d8e74b5f1b824512d95623d2e Mon Sep 17 00:00:00 2001 From: Ben Kaduk Date: Tue, 10 Dec 2013 17:47:42 -0500 Subject: [PATCH 1/1] Add rxgk_util.c A few helper routines for the security class implementation. Change-Id: I395802b6c3b2436df4b00906544fc797f3e12e9b Reviewed-on: https://gerrit.openafs.org/10937 Reviewed-by: Benjamin Kaduk Tested-by: BuildBot --- src/rxgk/Makefile.in | 2 +- src/rxgk/rxgk_private.h | 5 ++ src/rxgk/rxgk_util.c | 146 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 152 insertions(+), 1 deletion(-) create mode 100644 src/rxgk/rxgk_util.c diff --git a/src/rxgk/Makefile.in b/src/rxgk/Makefile.in index d2b9418..fa398b1 100644 --- a/src/rxgk/Makefile.in +++ b/src/rxgk/Makefile.in @@ -8,7 +8,7 @@ INCLS= ${TOP_INCDIR}/rx/rx.h ${TOP_INCDIR}/rx/rxgk.h ${TOP_INCDIR}/rx/rxgk_errs. LT_objs = rxgk_client.lo rxgk_server.lo rxgk_errs.lo rxgk_int.cs.lo \ rxgk_int.xdr.lo rxgk_int.ss.lo rxgk_procs.lo rxgk_token.lo \ - rxgk_packet.lo rxgk_crypto_rfc3961.lo + rxgk_util.lo rxgk_packet.lo rxgk_crypto_rfc3961.lo LT_deps = $(top_builddir)/src/opr/liboafs_opr.la \ $(top_builddir)/src/comerr/liboafs_comerr.la \ diff --git a/src/rxgk/rxgk_private.h b/src/rxgk/rxgk_private.h index 8015ab8..7e682ef 100644 --- a/src/rxgk/rxgk_private.h +++ b/src/rxgk/rxgk_private.h @@ -142,6 +142,11 @@ afs_int32 rxgk_extract_token(RXGK_Data *tc, RXGK_Token *out, rxgk_getkey_func getkey, void *rock) AFS_NONNULL((1,2,3)); +/* rxgk_util.c */ +afs_int32 rxgk_security_overhead(struct rx_connection *aconn, RXGK_Level level, + rxgk_key k0); +afs_int32 rxgk_key_number(afs_uint16 wire, afs_uint32 local, afs_uint32 *real); + /* rxgk_packet.c */ int rxgk_check_mic_packet(rxgk_key tk, afs_int32 keyusage, struct rx_connection *aconn, diff --git a/src/rxgk/rxgk_util.c b/src/rxgk/rxgk_util.c new file mode 100644 index 0000000..0596070 --- /dev/null +++ b/src/rxgk/rxgk_util.c @@ -0,0 +1,146 @@ +/* rxgk/rxgk_util.c - utility functions for RXGK use */ +/* + * Copyright (C) 2013, 2014 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file + * Utility functions for RXGK use. Compute the security overhead for a + * connection at a given security level, and helpers for maintaining key + * version numbers for connections. + */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#ifdef KERNEL +# include "afs/sysincludes.h" +# include "afsincludes.h" +#else +# include +#endif + +#include "rxgk_private.h" + +/** + * Set the security header and trailer sizes on a connection + * + * Set the security header and trailer sizes on aconn to be consistent + * with the space needed for packet handling at the given security level + * using the given key (only its enctype/checksum type are relevant). + * + * @param[out] aconn The connection being modified. + * @param[in] level The security level of the connection. + * @param[in] k0 The master key for the connection. + * @return rxgk error codes. + */ +afs_int32 +rxgk_security_overhead(struct rx_connection *aconn, RXGK_Level level, + rxgk_key k0) +{ + afs_int32 ret; + size_t mlen; + afs_uint32 elen; + + switch (level) { + case RXGK_LEVEL_CLEAR: + return 0; + case RXGK_LEVEL_AUTH: + ret = rxgk_mic_length(k0, &mlen); + if (ret != 0) + return ret; + rx_SetSecurityHeaderSize(aconn, mlen); + rx_SetSecurityMaxTrailerSize(aconn, 0); + return 0; + case RXGK_LEVEL_CRYPT: + ret = rxgk_cipher_expansion(k0, &elen); + if (ret != 0) + return ret; + rx_SetSecurityHeaderSize(aconn, sizeof(struct rxgk_header)); + rx_SetSecurityMaxTrailerSize(aconn, elen); + return 0; + default: + return RXGK_INCONSISTENCY; + } +} + +/** + * Compute the full 32-bit kvno of a connection + * + * Given the 16-bit wire kvno and the local state, return the actual kvno which + * should be used for key derivation. All values are in host byte order. + * Understanding how we derive a 32-bit kvno from a 16-bit value requires some + * explanation: + * + * After an rxgk conn is set up, our peer informs us of kvno changes by sending + * the lowest 16 bits of its kvno. The real kvno being used is a 32-bit value, + * but the peer cannot change the kvno arbitrarily; the protocol spec only + * allows a peer to change the kvno by incrementing or decrementing it by 1. So + * if we know the current 32-bit kvno ('local'), and we know the advertised + * lower 16 bits of the new kvno ('wire'), we can calculate the new 32-bit kvno + * ('*real'). + * + * @param[in] wire The 16-bit kvno from the received packet. + * @param[in] local The 32-bit kvno from the local connection state. + * @param[out] real The kvno to be used to process this packet. + * @return rxgk error codes. + */ +afs_int32 +rxgk_key_number(afs_uint16 wire, afs_uint32 local, afs_uint32 *real) +{ + afs_uint16 lres, diff; + + lres = local % (1u << 16); + diff = (afs_uint16)(wire - lres); + + if (diff == 0) { + *real = local; + } else if (diff == 1) { + /* Our peer is using a kvno 1 higher than 'local' */ + if (local == MAX_AFS_UINT32) + return RXGK_INCONSISTENCY; + *real = local + 1; + + } else if (diff == (afs_uint16)0xffffu) { + /* Our peer is using a kvno 1 lower than 'local' */ + if (local == 0) + return RXGK_INCONSISTENCY; + *real = local - 1; + + } else { + return RXGK_BADKEYNO; + } + return 0; +} -- 1.9.4