Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/crypto/krb5/src/lib/gssapi/generic/util_seqstate.c
39562 views
1
/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2
/* lib/gssapi/generic/util_seqstate.c - sequence number checking */
3
/*
4
* Copyright (C) 2014 by the Massachusetts Institute of Technology.
5
* All rights reserved.
6
*
7
* Redistribution and use in source and binary forms, with or without
8
* modification, are permitted provided that the following conditions
9
* are met:
10
*
11
* * Redistributions of source code must retain the above copyright
12
* notice, this list of conditions and the following disclaimer.
13
*
14
* * Redistributions in binary form must reproduce the above copyright
15
* notice, this list of conditions and the following disclaimer in
16
* the documentation and/or other materials provided with the
17
* distribution.
18
*
19
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
22
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
23
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
24
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
25
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
28
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
30
* OF THE POSSIBILITY OF SUCH DAMAGE.
31
*/
32
33
#include "gssapiP_generic.h"
34
#include <string.h>
35
36
struct g_seqnum_state_st {
37
/* Flags to indicate whether we are supposed to check for replays or
38
* enforce strict sequencing. */
39
int do_replay;
40
int do_sequence;
41
42
/* UINT32_MAX for 32-bit sequence numbers, UINT64_MAX for 64-bit. Mask
43
* against this after arithmetic to stay within the correct range. */
44
uint64_t seqmask;
45
46
/* The initial sequence number for this context. This value will be
47
* subtracted from all received sequence numbers to simplify wraparound. */
48
uint64_t base;
49
50
/* The expected next sequence number (one more than the highest previously
51
* seen sequence number), relative to base. */
52
uint64_t next;
53
54
/*
55
* A bitmap for the 64 sequence numbers prior to next. If the 1<<(i-1) bit
56
* is set, then we have seen seqnum next-i relative to base. The least
57
* significant bit is always set if we have received any sequence numbers,
58
* and indicates the highest sequence number we have seen (next-1). When
59
* we advance next, we shift recvmap to the left.
60
*/
61
uint64_t recvmap;
62
};
63
64
long
65
g_seqstate_init(g_seqnum_state *state_out, uint64_t seqnum, int do_replay,
66
int do_sequence, int wide)
67
{
68
g_seqnum_state state;
69
70
*state_out = NULL;
71
state = malloc(sizeof(*state));
72
if (state == NULL)
73
return ENOMEM;
74
state->do_replay = do_replay;
75
state->do_sequence = do_sequence;
76
state->seqmask = wide ? UINT64_MAX : UINT32_MAX;
77
state->base = seqnum;
78
state->next = state->recvmap = 0;
79
*state_out = state;
80
return 0;
81
}
82
83
OM_uint32
84
g_seqstate_check(g_seqnum_state state, uint64_t seqnum)
85
{
86
uint64_t rel_seqnum, offset, bit;
87
88
if (!state->do_replay && !state->do_sequence)
89
return GSS_S_COMPLETE;
90
91
/* Use the difference from the base seqnum, to simplify wraparound. */
92
rel_seqnum = (seqnum - state->base) & state->seqmask;
93
94
if (rel_seqnum >= state->next) {
95
/* seqnum is the expected sequence number or in the future. Update the
96
* received bitmap and expected next sequence number. */
97
offset = rel_seqnum - state->next;
98
state->recvmap = (state->recvmap << (offset + 1)) | 1;
99
state->next = (rel_seqnum + 1) & state->seqmask;
100
101
return (offset > 0 && state->do_sequence) ? GSS_S_GAP_TOKEN :
102
GSS_S_COMPLETE;
103
}
104
105
/* seqnum is in the past. Check if it's too old for replay detection. */
106
offset = state->next - rel_seqnum;
107
if (offset > 64)
108
return state->do_sequence ? GSS_S_UNSEQ_TOKEN : GSS_S_OLD_TOKEN;
109
110
/* Check for replay and mark as received. */
111
bit = (uint64_t)1 << (offset - 1);
112
if (state->do_replay && (state->recvmap & bit))
113
return GSS_S_DUPLICATE_TOKEN;
114
state->recvmap |= bit;
115
116
return state->do_sequence ? GSS_S_UNSEQ_TOKEN : GSS_S_COMPLETE;
117
}
118
119
void
120
g_seqstate_free(g_seqnum_state state)
121
{
122
free(state);
123
}
124
125
/*
126
* These support functions are for the serialization routines
127
*/
128
void
129
g_seqstate_size(g_seqnum_state state, size_t *sizep)
130
{
131
*sizep += sizeof(*state);
132
}
133
134
long
135
g_seqstate_externalize(g_seqnum_state state, unsigned char **buf,
136
size_t *lenremain)
137
{
138
if (*lenremain < sizeof(*state))
139
return ENOMEM;
140
memcpy(*buf, state, sizeof(*state));
141
*buf += sizeof(*state);
142
*lenremain -= sizeof(*state);
143
return 0;
144
}
145
146
long
147
g_seqstate_internalize(g_seqnum_state *state_out, unsigned char **buf,
148
size_t *lenremain)
149
{
150
g_seqnum_state state;
151
152
*state_out = NULL;
153
if (*lenremain < sizeof(*state))
154
return EINVAL;
155
state = malloc(sizeof(*state));
156
if (state == NULL)
157
return ENOMEM;
158
memcpy(state, *buf, sizeof(*state));
159
*buf += sizeof(*state);
160
*lenremain -= sizeof(*state);
161
*state_out = state;
162
return 0;
163
}
164
165