Add rxgk_util.c
[openafs.git] / src / rxgk / rxgk_util.c
1 /* rxgk/rxgk_util.c - utility functions for RXGK use */
2 /*
3  * Copyright (C) 2013, 2014 by the Massachusetts Institute of Technology.
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  * * Redistributions of source code must retain the above copyright
11  *   notice, this list of conditions and the following disclaimer.
12  *
13  * * Redistributions in binary form must reproduce the above copyright
14  *   notice, this list of conditions and the following disclaimer in
15  *   the documentation and/or other materials provided with the
16  *   distribution.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
21  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
22  * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
23  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
27  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
29  * OF THE POSSIBILITY OF SUCH DAMAGE.
30  */
31
32 /**
33  * @file
34  * Utility functions for RXGK use. Compute the security overhead for a
35  * connection at a given security level, and helpers for maintaining key
36  * version numbers for connections.
37  */
38
39 #include <afsconfig.h>
40 #include <afs/param.h>
41 #include <afs/stds.h>
42
43 #include <rx/rx.h>
44 #include <rx/rx_identity.h>
45 #include <rx/rxgk.h>
46 #include <rx/rx_packet.h>
47 #include <afs/rfc3961.h>
48 #ifdef KERNEL
49 # include "afs/sysincludes.h"
50 # include "afsincludes.h"
51 #else
52 # include <errno.h>
53 #endif
54
55 #include "rxgk_private.h"
56
57 /**
58  * Set the security header and trailer sizes on a connection
59  *
60  * Set the security header and trailer sizes on aconn to be consistent
61  * with the space needed for packet handling at the given security level
62  * using the given key (only its enctype/checksum type are relevant).
63  *
64  * @param[out] aconn    The connection being modified.
65  * @param[in] level     The security level of the connection.
66  * @param[in] k0        The master key for the connection.
67  * @return rxgk error codes.
68  */
69 afs_int32
70 rxgk_security_overhead(struct rx_connection *aconn, RXGK_Level level,
71                        rxgk_key k0)
72 {
73     afs_int32 ret;
74     size_t mlen;
75     afs_uint32 elen;
76
77     switch (level) {
78         case RXGK_LEVEL_CLEAR:
79             return 0;
80         case RXGK_LEVEL_AUTH:
81             ret = rxgk_mic_length(k0, &mlen);
82             if (ret != 0)
83                 return ret;
84             rx_SetSecurityHeaderSize(aconn, mlen);
85             rx_SetSecurityMaxTrailerSize(aconn, 0);
86             return 0;
87         case RXGK_LEVEL_CRYPT:
88             ret = rxgk_cipher_expansion(k0, &elen);
89             if (ret != 0)
90                 return ret;
91             rx_SetSecurityHeaderSize(aconn, sizeof(struct rxgk_header));
92             rx_SetSecurityMaxTrailerSize(aconn, elen);
93             return 0;
94         default:
95             return RXGK_INCONSISTENCY;
96     }
97 }
98
99 /**
100  * Compute the full 32-bit kvno of a connection
101  *
102  * Given the 16-bit wire kvno and the local state, return the actual kvno which
103  * should be used for key derivation. All values are in host byte order.
104  * Understanding how we derive a 32-bit kvno from a 16-bit value requires some
105  * explanation:
106  *
107  * After an rxgk conn is set up, our peer informs us of kvno changes by sending
108  * the lowest 16 bits of its kvno. The real kvno being used is a 32-bit value,
109  * but the peer cannot change the kvno arbitrarily; the protocol spec only
110  * allows a peer to change the kvno by incrementing or decrementing it by 1. So
111  * if we know the current 32-bit kvno ('local'), and we know the advertised
112  * lower 16 bits of the new kvno ('wire'), we can calculate the new 32-bit kvno
113  * ('*real').
114  *
115  * @param[in] wire      The 16-bit kvno from the received packet.
116  * @param[in] local     The 32-bit kvno from the local connection state.
117  * @param[out] real     The kvno to be used to process this packet.
118  * @return rxgk error codes.
119  */
120 afs_int32
121 rxgk_key_number(afs_uint16 wire, afs_uint32 local, afs_uint32 *real)
122 {
123     afs_uint16 lres, diff;
124
125     lres = local % (1u << 16);
126     diff = (afs_uint16)(wire - lres);
127
128     if (diff == 0) {
129         *real = local;
130     } else if (diff == 1) {
131         /* Our peer is using a kvno 1 higher than 'local' */
132         if (local == MAX_AFS_UINT32)
133             return RXGK_INCONSISTENCY;
134         *real = local + 1;
135
136     } else if (diff == (afs_uint16)0xffffu) {
137         /* Our peer is using a kvno 1 lower than 'local' */
138         if (local == 0)
139             return RXGK_INCONSISTENCY;
140         *real = local - 1;
141
142     } else {
143         return RXGK_BADKEYNO;
144     }
145     return 0;
146 }