1*afab4e30Schristos /* $NetBSD: decapsulate.c,v 1.3 2023/06/19 21:41:43 christos Exp $ */
2ca1c9b0cSelric
3ca1c9b0cSelric /*
4ca1c9b0cSelric * Copyright (c) 1997 - 2001 Kungliga Tekniska Högskolan
5ca1c9b0cSelric * (Royal Institute of Technology, Stockholm, Sweden).
6ca1c9b0cSelric * All rights reserved.
7ca1c9b0cSelric *
8ca1c9b0cSelric * Redistribution and use in source and binary forms, with or without
9ca1c9b0cSelric * modification, are permitted provided that the following conditions
10ca1c9b0cSelric * are met:
11ca1c9b0cSelric *
12ca1c9b0cSelric * 1. Redistributions of source code must retain the above copyright
13ca1c9b0cSelric * notice, this list of conditions and the following disclaimer.
14ca1c9b0cSelric *
15ca1c9b0cSelric * 2. Redistributions in binary form must reproduce the above copyright
16ca1c9b0cSelric * notice, this list of conditions and the following disclaimer in the
17ca1c9b0cSelric * documentation and/or other materials provided with the distribution.
18ca1c9b0cSelric *
19ca1c9b0cSelric * 3. Neither the name of the Institute nor the names of its contributors
20ca1c9b0cSelric * may be used to endorse or promote products derived from this software
21ca1c9b0cSelric * without specific prior written permission.
22ca1c9b0cSelric *
23ca1c9b0cSelric * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
24ca1c9b0cSelric * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25ca1c9b0cSelric * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26ca1c9b0cSelric * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
27ca1c9b0cSelric * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28ca1c9b0cSelric * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29ca1c9b0cSelric * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30ca1c9b0cSelric * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31ca1c9b0cSelric * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32ca1c9b0cSelric * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33ca1c9b0cSelric * SUCH DAMAGE.
34ca1c9b0cSelric */
35ca1c9b0cSelric
36ca1c9b0cSelric #include "gsskrb5_locl.h"
37ca1c9b0cSelric
38ca1c9b0cSelric /*
39ca1c9b0cSelric * return the length of the mechanism in token or -1
40ca1c9b0cSelric * (which implies that the token was bad - GSS_S_DEFECTIVE_TOKEN
41ca1c9b0cSelric */
42ca1c9b0cSelric
43ca1c9b0cSelric ssize_t
_gsskrb5_get_mech(const u_char * ptr,size_t total_len,const u_char ** mech_ret)44ca1c9b0cSelric _gsskrb5_get_mech (const u_char *ptr,
45ca1c9b0cSelric size_t total_len,
46ca1c9b0cSelric const u_char **mech_ret)
47ca1c9b0cSelric {
48ca1c9b0cSelric size_t len, len_len, mech_len, foo;
49ca1c9b0cSelric const u_char *p = ptr;
50ca1c9b0cSelric int e;
51ca1c9b0cSelric
52ca1c9b0cSelric if (total_len < 1)
53ca1c9b0cSelric return -1;
54ca1c9b0cSelric if (*p++ != 0x60)
55ca1c9b0cSelric return -1;
56ca1c9b0cSelric e = der_get_length (p, total_len - 1, &len, &len_len);
57ca1c9b0cSelric if (e || 1 + len_len + len != total_len)
58ca1c9b0cSelric return -1;
59*afab4e30Schristos if (total_len < 1 + len_len + 1)
60*afab4e30Schristos return -1;
61ca1c9b0cSelric p += len_len;
62ca1c9b0cSelric if (*p++ != 0x06)
63ca1c9b0cSelric return -1;
64ca1c9b0cSelric e = der_get_length (p, total_len - 1 - len_len - 1,
65ca1c9b0cSelric &mech_len, &foo);
66ca1c9b0cSelric if (e)
67ca1c9b0cSelric return -1;
68ca1c9b0cSelric p += foo;
69ca1c9b0cSelric *mech_ret = p;
70ca1c9b0cSelric return mech_len;
71ca1c9b0cSelric }
72ca1c9b0cSelric
73ca1c9b0cSelric OM_uint32
_gssapi_verify_mech_header(u_char ** str,size_t total_len,gss_OID mech)74ca1c9b0cSelric _gssapi_verify_mech_header(u_char **str,
75ca1c9b0cSelric size_t total_len,
76ca1c9b0cSelric gss_OID mech)
77ca1c9b0cSelric {
78ca1c9b0cSelric const u_char *p;
79ca1c9b0cSelric ssize_t mech_len;
80ca1c9b0cSelric
81ca1c9b0cSelric mech_len = _gsskrb5_get_mech (*str, total_len, &p);
82ca1c9b0cSelric if (mech_len < 0)
83ca1c9b0cSelric return GSS_S_DEFECTIVE_TOKEN;
84ca1c9b0cSelric
85ca1c9b0cSelric if (mech_len != mech->length)
86ca1c9b0cSelric return GSS_S_BAD_MECH;
87*afab4e30Schristos if (mech_len > total_len)
88*afab4e30Schristos return GSS_S_BAD_MECH;
89*afab4e30Schristos if (p - *str > total_len - mech_len)
90*afab4e30Schristos return GSS_S_BAD_MECH;
91ca1c9b0cSelric if (ct_memcmp(p,
92ca1c9b0cSelric mech->elements,
93ca1c9b0cSelric mech->length) != 0)
94ca1c9b0cSelric return GSS_S_BAD_MECH;
95ca1c9b0cSelric p += mech_len;
96ca1c9b0cSelric *str = rk_UNCONST(p);
97ca1c9b0cSelric return GSS_S_COMPLETE;
98ca1c9b0cSelric }
99ca1c9b0cSelric
100ca1c9b0cSelric OM_uint32
_gsskrb5_verify_header(u_char ** str,size_t total_len,const void * type,gss_OID oid)101ca1c9b0cSelric _gsskrb5_verify_header(u_char **str,
102ca1c9b0cSelric size_t total_len,
103ca1c9b0cSelric const void *type,
104ca1c9b0cSelric gss_OID oid)
105ca1c9b0cSelric {
106ca1c9b0cSelric OM_uint32 ret;
107ca1c9b0cSelric size_t len;
108ca1c9b0cSelric u_char *p = *str;
109ca1c9b0cSelric
110ca1c9b0cSelric ret = _gssapi_verify_mech_header(str, total_len, oid);
111ca1c9b0cSelric if (ret)
112ca1c9b0cSelric return ret;
113ca1c9b0cSelric
114ca1c9b0cSelric len = total_len - (*str - p);
115ca1c9b0cSelric
116ca1c9b0cSelric if (len < 2)
117ca1c9b0cSelric return GSS_S_DEFECTIVE_TOKEN;
118ca1c9b0cSelric
119ca1c9b0cSelric if (ct_memcmp (*str, type, 2) != 0)
120ca1c9b0cSelric return GSS_S_DEFECTIVE_TOKEN;
121ca1c9b0cSelric *str += 2;
122ca1c9b0cSelric
123ca1c9b0cSelric return 0;
124ca1c9b0cSelric }
125ca1c9b0cSelric
126ca1c9b0cSelric /*
127ca1c9b0cSelric * Remove the GSS-API wrapping from `in_token' giving `out_data.
128ca1c9b0cSelric * Does not copy data, so just free `in_token'.
129ca1c9b0cSelric */
130ca1c9b0cSelric
131ca1c9b0cSelric OM_uint32
_gssapi_decapsulate(OM_uint32 * minor_status,gss_buffer_t input_token_buffer,krb5_data * out_data,const gss_OID mech)132ca1c9b0cSelric _gssapi_decapsulate(
133ca1c9b0cSelric OM_uint32 *minor_status,
134ca1c9b0cSelric gss_buffer_t input_token_buffer,
135ca1c9b0cSelric krb5_data *out_data,
136ca1c9b0cSelric const gss_OID mech
137ca1c9b0cSelric )
138ca1c9b0cSelric {
139ca1c9b0cSelric u_char *p;
140ca1c9b0cSelric OM_uint32 ret;
141ca1c9b0cSelric
142ca1c9b0cSelric p = input_token_buffer->value;
143ca1c9b0cSelric ret = _gssapi_verify_mech_header(&p,
144ca1c9b0cSelric input_token_buffer->length,
145ca1c9b0cSelric mech);
146ca1c9b0cSelric if (ret) {
147ca1c9b0cSelric *minor_status = 0;
148ca1c9b0cSelric return ret;
149ca1c9b0cSelric }
150ca1c9b0cSelric
151ca1c9b0cSelric out_data->length = input_token_buffer->length -
152ca1c9b0cSelric (p - (u_char *)input_token_buffer->value);
153ca1c9b0cSelric out_data->data = p;
154ca1c9b0cSelric return GSS_S_COMPLETE;
155ca1c9b0cSelric }
156ca1c9b0cSelric
157ca1c9b0cSelric /*
158ca1c9b0cSelric * Remove the GSS-API wrapping from `in_token' giving `out_data.
159ca1c9b0cSelric * Does not copy data, so just free `in_token'.
160ca1c9b0cSelric */
161ca1c9b0cSelric
162ca1c9b0cSelric OM_uint32
_gsskrb5_decapsulate(OM_uint32 * minor_status,gss_buffer_t input_token_buffer,krb5_data * out_data,const void * type,gss_OID oid)163ca1c9b0cSelric _gsskrb5_decapsulate(OM_uint32 *minor_status,
164ca1c9b0cSelric gss_buffer_t input_token_buffer,
165ca1c9b0cSelric krb5_data *out_data,
166ca1c9b0cSelric const void *type,
167ca1c9b0cSelric gss_OID oid)
168ca1c9b0cSelric {
169ca1c9b0cSelric u_char *p;
170ca1c9b0cSelric OM_uint32 ret;
171ca1c9b0cSelric
172ca1c9b0cSelric p = input_token_buffer->value;
173ca1c9b0cSelric ret = _gsskrb5_verify_header(&p,
174ca1c9b0cSelric input_token_buffer->length,
175ca1c9b0cSelric type,
176ca1c9b0cSelric oid);
177ca1c9b0cSelric if (ret) {
178ca1c9b0cSelric *minor_status = 0;
179ca1c9b0cSelric return ret;
180ca1c9b0cSelric }
181ca1c9b0cSelric
182ca1c9b0cSelric out_data->length = input_token_buffer->length -
183ca1c9b0cSelric (p - (u_char *)input_token_buffer->value);
184ca1c9b0cSelric out_data->data = p;
185ca1c9b0cSelric return GSS_S_COMPLETE;
186ca1c9b0cSelric }
187ca1c9b0cSelric
188ca1c9b0cSelric /*
189ca1c9b0cSelric * Verify padding of a gss wrapped message and return its length.
190ca1c9b0cSelric */
191ca1c9b0cSelric
192ca1c9b0cSelric OM_uint32
_gssapi_verify_pad(gss_buffer_t wrapped_token,size_t datalen,size_t * padlen)193ca1c9b0cSelric _gssapi_verify_pad(gss_buffer_t wrapped_token,
194ca1c9b0cSelric size_t datalen,
195ca1c9b0cSelric size_t *padlen)
196ca1c9b0cSelric {
197ca1c9b0cSelric u_char *pad;
198ca1c9b0cSelric size_t padlength;
199ca1c9b0cSelric int i;
200ca1c9b0cSelric
201b9d004c6Schristos if (wrapped_token->length < 1)
202b9d004c6Schristos return GSS_S_BAD_MECH;
203b9d004c6Schristos
204*afab4e30Schristos pad = (u_char *)wrapped_token->value + wrapped_token->length;
205*afab4e30Schristos padlength = pad[-1];
206ca1c9b0cSelric
207ca1c9b0cSelric if (padlength > datalen)
208ca1c9b0cSelric return GSS_S_BAD_MECH;
209ca1c9b0cSelric
210*afab4e30Schristos for (i = padlength; i > 0 && *--pad == padlength; i--)
211ca1c9b0cSelric ;
212ca1c9b0cSelric if (i != 0)
213ca1c9b0cSelric return GSS_S_BAD_MIC;
214ca1c9b0cSelric
215ca1c9b0cSelric *padlen = padlength;
216ca1c9b0cSelric
217ca1c9b0cSelric return 0;
218ca1c9b0cSelric }
219