Skip to content

Commit 7a7513a

Browse files
dhowellskuba-moo
authored andcommitted
rxrpc: rxgk: Implement connection rekeying
Implement rekeying of connections with the RxGK security class. This involves regenerating the keys with a different key number as part of the input data after a certain amount of time or a certain amount of bytes encrypted. Rekeying may be triggered by either end. The LSW of the key number is inserted into the security-specific field in the RX header, and we try and expand it to 32-bits to make it last longer. Signed-off-by: David Howells <[email protected]> cc: Marc Dionne <[email protected]> cc: Herbert Xu <[email protected]> cc: Chuck Lever <[email protected]> cc: Simon Horman <[email protected]> cc: [email protected] Link: https://patch.msgid.link/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
1 parent 9d1d2b5 commit 7a7513a

File tree

4 files changed

+181
-7
lines changed

4 files changed

+181
-7
lines changed

include/trace/events/rxrpc.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2725,6 +2725,30 @@ TRACE_EVENT(rxrpc_rack_timer,
27252725
ktime_to_us(__entry->delay))
27262726
);
27272727

2728+
TRACE_EVENT(rxrpc_rxgk_rekey,
2729+
TP_PROTO(struct rxrpc_connection *conn,
2730+
unsigned int current_key, unsigned int requested_key),
2731+
2732+
TP_ARGS(conn, current_key, requested_key),
2733+
2734+
TP_STRUCT__entry(
2735+
__field(unsigned int, conn)
2736+
__field(unsigned int, current_key)
2737+
__field(unsigned int, requested_key)
2738+
),
2739+
2740+
TP_fast_assign(
2741+
__entry->conn = conn->debug_id;
2742+
__entry->current_key = current_key;
2743+
__entry->requested_key = requested_key;
2744+
),
2745+
2746+
TP_printk("C=%08x cur=%x req=%x",
2747+
__entry->conn,
2748+
__entry->current_key,
2749+
__entry->requested_key)
2750+
);
2751+
27282752
#undef EM
27292753
#undef E_
27302754

net/rxrpc/ar-internal.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -565,13 +565,16 @@ struct rxrpc_connection {
565565
u32 nonce; /* response re-use preventer */
566566
} rxkad;
567567
struct {
568-
struct rxgk_context *keys[1];
568+
struct rxgk_context *keys[4]; /* (Re-)keying buffer */
569569
u64 start_time; /* The start time for TK derivation */
570570
u8 nonce[20]; /* Response re-use preventer */
571571
u32 enctype; /* Kerberos 5 encoding type */
572+
u32 key_number; /* Current key number */
572573
} rxgk;
573574
};
575+
rwlock_t security_use_lock; /* Security use/modification lock */
574576
struct sk_buff *tx_response; /* Response packet to be transmitted */
577+
575578
unsigned long flags;
576579
unsigned long events;
577580
unsigned long idle_timestamp; /* Time at which last became idle */

net/rxrpc/conn_object.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ struct rxrpc_connection *rxrpc_alloc_connection(struct rxrpc_net *rxnet,
7373
skb_queue_head_init(&conn->rx_queue);
7474
conn->rxnet = rxnet;
7575
conn->security = &rxrpc_no_security;
76+
rwlock_init(&conn->security_use_lock);
7677
spin_lock_init(&conn->state_lock);
7778
conn->debug_id = atomic_inc_return(&rxrpc_debug_id);
7879
conn->idle_timestamp = jiffies;

net/rxrpc/rxgk.c

Lines changed: 152 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -76,11 +76,155 @@ static void rxgk_describe_server_key(const struct key *key, struct seq_file *m)
7676
seq_printf(m, ": %s", krb5->name);
7777
}
7878

79+
/*
80+
* Handle rekeying the connection when we see our limits overrun or when the
81+
* far side decided to rekey.
82+
*
83+
* Returns a ref on the context if successful or -ESTALE if the key is out of
84+
* date.
85+
*/
86+
static struct rxgk_context *rxgk_rekey(struct rxrpc_connection *conn,
87+
const u16 *specific_key_number)
88+
{
89+
struct rxgk_context *gk, *dead = NULL;
90+
unsigned int key_number, current_key, mask = ARRAY_SIZE(conn->rxgk.keys) - 1;
91+
bool crank = false;
92+
93+
_enter("%d", specific_key_number ? *specific_key_number : -1);
94+
95+
mutex_lock(&conn->security_lock);
96+
97+
current_key = conn->rxgk.key_number;
98+
if (!specific_key_number) {
99+
key_number = current_key;
100+
} else {
101+
if (*specific_key_number == (u16)current_key)
102+
key_number = current_key;
103+
else if (*specific_key_number == (u16)(current_key - 1))
104+
key_number = current_key - 1;
105+
else if (*specific_key_number == (u16)(current_key + 1))
106+
goto crank_window;
107+
else
108+
goto bad_key;
109+
}
110+
111+
gk = conn->rxgk.keys[key_number & mask];
112+
if (!gk)
113+
goto generate_key;
114+
if (!specific_key_number &&
115+
test_bit(RXGK_TK_NEEDS_REKEY, &gk->flags))
116+
goto crank_window;
117+
118+
grab:
119+
refcount_inc(&gk->usage);
120+
mutex_unlock(&conn->security_lock);
121+
rxgk_put(dead);
122+
return gk;
123+
124+
crank_window:
125+
trace_rxrpc_rxgk_rekey(conn, current_key,
126+
specific_key_number ? *specific_key_number : -1);
127+
if (current_key == UINT_MAX)
128+
goto bad_key;
129+
if (current_key + 1 == UINT_MAX)
130+
set_bit(RXRPC_CONN_DONT_REUSE, &conn->flags);
131+
132+
key_number = current_key + 1;
133+
if (WARN_ON(conn->rxgk.keys[key_number & mask]))
134+
goto bad_key;
135+
crank = true;
136+
137+
generate_key:
138+
gk = conn->rxgk.keys[current_key & mask];
139+
gk = rxgk_generate_transport_key(conn, gk->key, key_number, GFP_NOFS);
140+
if (IS_ERR(gk)) {
141+
mutex_unlock(&conn->security_lock);
142+
return gk;
143+
}
144+
145+
write_lock(&conn->security_use_lock);
146+
if (crank) {
147+
current_key++;
148+
conn->rxgk.key_number = current_key;
149+
dead = conn->rxgk.keys[(current_key - 2) & mask];
150+
conn->rxgk.keys[(current_key - 2) & mask] = NULL;
151+
}
152+
conn->rxgk.keys[current_key & mask] = gk;
153+
write_unlock(&conn->security_use_lock);
154+
goto grab;
155+
156+
bad_key:
157+
mutex_unlock(&conn->security_lock);
158+
return ERR_PTR(-ESTALE);
159+
}
160+
161+
/*
162+
* Get the specified keying context.
163+
*
164+
* Returns a ref on the context if successful or -ESTALE if the key is out of
165+
* date.
166+
*/
79167
static struct rxgk_context *rxgk_get_key(struct rxrpc_connection *conn,
80-
u16 *specific_key_number)
168+
const u16 *specific_key_number)
81169
{
82-
refcount_inc(&conn->rxgk.keys[0]->usage);
83-
return conn->rxgk.keys[0];
170+
struct rxgk_context *gk;
171+
unsigned int key_number, current_key, mask = ARRAY_SIZE(conn->rxgk.keys) - 1;
172+
173+
_enter("{%u},%d",
174+
conn->rxgk.key_number, specific_key_number ? *specific_key_number : -1);
175+
176+
read_lock(&conn->security_use_lock);
177+
178+
current_key = conn->rxgk.key_number;
179+
if (!specific_key_number) {
180+
key_number = current_key;
181+
} else {
182+
/* Only the bottom 16 bits of the key number are exposed in the
183+
* header, so we try and keep the upper 16 bits in step. The
184+
* whole 32 bits are used to generate the TK.
185+
*/
186+
if (*specific_key_number == (u16)current_key)
187+
key_number = current_key;
188+
else if (*specific_key_number == (u16)(current_key - 1))
189+
key_number = current_key - 1;
190+
else if (*specific_key_number == (u16)(current_key + 1))
191+
goto rekey;
192+
else
193+
goto bad_key;
194+
}
195+
196+
gk = conn->rxgk.keys[key_number & mask];
197+
if (!gk)
198+
goto slow_path;
199+
if (!specific_key_number &&
200+
key_number < UINT_MAX) {
201+
if (time_after(jiffies, gk->expiry) ||
202+
gk->bytes_remaining < 0) {
203+
set_bit(RXGK_TK_NEEDS_REKEY, &gk->flags);
204+
goto slow_path;
205+
}
206+
207+
if (test_bit(RXGK_TK_NEEDS_REKEY, &gk->flags))
208+
goto slow_path;
209+
}
210+
211+
refcount_inc(&gk->usage);
212+
read_unlock(&conn->security_use_lock);
213+
return gk;
214+
215+
rekey:
216+
_debug("rekey");
217+
if (current_key == UINT_MAX)
218+
goto bad_key;
219+
gk = conn->rxgk.keys[current_key & mask];
220+
if (gk)
221+
set_bit(RXGK_TK_NEEDS_REKEY, &gk->flags);
222+
slow_path:
223+
read_unlock(&conn->security_use_lock);
224+
return rxgk_rekey(conn, specific_key_number);
225+
bad_key:
226+
read_unlock(&conn->security_use_lock);
227+
return ERR_PTR(-ESTALE);
84228
}
85229

86230
/*
@@ -92,7 +236,8 @@ static int rxgk_init_connection_security(struct rxrpc_connection *conn,
92236
struct rxgk_context *gk;
93237
int ret;
94238

95-
_enter("{%d},{%x}", conn->debug_id, key_serial(conn->key));
239+
_enter("{%d,%u},{%x}",
240+
conn->debug_id, conn->rxgk.key_number, key_serial(conn->key));
96241

97242
conn->security_ix = token->security_index;
98243
conn->security_level = token->rxgk->level;
@@ -102,11 +247,12 @@ static int rxgk_init_connection_security(struct rxrpc_connection *conn,
102247
do_div(conn->rxgk.start_time, 100);
103248
}
104249

105-
gk = rxgk_generate_transport_key(conn, token->rxgk, 0, GFP_NOFS);
250+
gk = rxgk_generate_transport_key(conn, token->rxgk, conn->rxgk.key_number,
251+
GFP_NOFS);
106252
if (IS_ERR(gk))
107253
return PTR_ERR(gk);
108254
conn->rxgk.enctype = gk->krb5->etype;
109-
conn->rxgk.keys[0] = gk;
255+
conn->rxgk.keys[gk->key_number & 3] = gk;
110256

111257
switch (conn->security_level) {
112258
case RXRPC_SECURITY_PLAIN:

0 commit comments

Comments
 (0)