1 | /*
|
---|
2 | * AEAD support
|
---|
3 | */
|
---|
4 |
|
---|
5 | #include "mech_locl.h"
|
---|
6 |
|
---|
7 | /**
|
---|
8 | * Encrypts or sign the data.
|
---|
9 | *
|
---|
10 | * This is a more complicated version of gss_wrap(), it allows the
|
---|
11 | * caller to use AEAD data (signed header/trailer) and allow greater
|
---|
12 | * controll over where the encrypted data is placed.
|
---|
13 | *
|
---|
14 | * The maximum packet size is gss_context_stream_sizes.max_msg_size.
|
---|
15 | *
|
---|
16 | * The caller needs provide the folloing buffers when using in conf_req_flag=1 mode:
|
---|
17 | *
|
---|
18 | * - HEADER (of size gss_context_stream_sizes.header)
|
---|
19 | * { DATA or SIGN_ONLY } (optional, zero or more)
|
---|
20 | * PADDING (of size gss_context_stream_sizes.blocksize, if zero padding is zero, can be omitted)
|
---|
21 | * TRAILER (of size gss_context_stream_sizes.trailer)
|
---|
22 | *
|
---|
23 | * - on DCE-RPC mode, the caller can skip PADDING and TRAILER if the
|
---|
24 | * DATA elements is padded to a block bountry and header is of at
|
---|
25 | * least size gss_context_stream_sizes.header + gss_context_stream_sizes.trailer.
|
---|
26 | *
|
---|
27 | * HEADER, PADDING, TRAILER will be shrunken to the size required to transmit any of them too large.
|
---|
28 | *
|
---|
29 | * To generate gss_wrap() compatible packets, use: HEADER | DATA | PADDING | TRAILER
|
---|
30 | *
|
---|
31 | * When used in conf_req_flag=0,
|
---|
32 | *
|
---|
33 | * - HEADER (of size gss_context_stream_sizes.header)
|
---|
34 | * { DATA or SIGN_ONLY } (optional, zero or more)
|
---|
35 | * PADDING (of size gss_context_stream_sizes.blocksize, if zero padding is zero, can be omitted)
|
---|
36 | * TRAILER (of size gss_context_stream_sizes.trailer)
|
---|
37 | *
|
---|
38 | *
|
---|
39 | * The input sizes of HEADER, PADDING and TRAILER can be fetched using gss_wrap_iov_length() or
|
---|
40 | * gss_context_query_attributes().
|
---|
41 | *
|
---|
42 | * @ingroup gssapi
|
---|
43 | */
|
---|
44 |
|
---|
45 |
|
---|
46 | GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
|
---|
47 | gss_wrap_iov(OM_uint32 * minor_status,
|
---|
48 | gss_ctx_id_t context_handle,
|
---|
49 | int conf_req_flag,
|
---|
50 | gss_qop_t qop_req,
|
---|
51 | int * conf_state,
|
---|
52 | gss_iov_buffer_desc *iov,
|
---|
53 | int iov_count)
|
---|
54 | {
|
---|
55 | struct _gss_context *ctx = (struct _gss_context *) context_handle;
|
---|
56 | gssapi_mech_interface m;
|
---|
57 |
|
---|
58 | if (minor_status)
|
---|
59 | *minor_status = 0;
|
---|
60 | if (conf_state)
|
---|
61 | *conf_state = 0;
|
---|
62 | if (ctx == NULL)
|
---|
63 | return GSS_S_NO_CONTEXT;
|
---|
64 | if (iov == NULL && iov_count != 0)
|
---|
65 | return GSS_S_CALL_INACCESSIBLE_READ;
|
---|
66 |
|
---|
67 | m = ctx->gc_mech;
|
---|
68 |
|
---|
69 | if (m->gm_wrap_iov == NULL)
|
---|
70 | return GSS_S_UNAVAILABLE;
|
---|
71 |
|
---|
72 | return (m->gm_wrap_iov)(minor_status, ctx->gc_ctx,
|
---|
73 | conf_req_flag, qop_req, conf_state,
|
---|
74 | iov, iov_count);
|
---|
75 | }
|
---|
76 |
|
---|
77 | /**
|
---|
78 | * Decrypt or verifies the signature on the data.
|
---|
79 | *
|
---|
80 | *
|
---|
81 | * @ingroup gssapi
|
---|
82 | */
|
---|
83 |
|
---|
84 | GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
|
---|
85 | gss_unwrap_iov(OM_uint32 *minor_status,
|
---|
86 | gss_ctx_id_t context_handle,
|
---|
87 | int *conf_state,
|
---|
88 | gss_qop_t *qop_state,
|
---|
89 | gss_iov_buffer_desc *iov,
|
---|
90 | int iov_count)
|
---|
91 | {
|
---|
92 | struct _gss_context *ctx = (struct _gss_context *) context_handle;
|
---|
93 | gssapi_mech_interface m;
|
---|
94 |
|
---|
95 | if (minor_status)
|
---|
96 | *minor_status = 0;
|
---|
97 | if (conf_state)
|
---|
98 | *conf_state = 0;
|
---|
99 | if (qop_state)
|
---|
100 | *qop_state = 0;
|
---|
101 | if (ctx == NULL)
|
---|
102 | return GSS_S_NO_CONTEXT;
|
---|
103 | if (iov == NULL && iov_count != 0)
|
---|
104 | return GSS_S_CALL_INACCESSIBLE_READ;
|
---|
105 |
|
---|
106 | m = ctx->gc_mech;
|
---|
107 |
|
---|
108 | if (m->gm_unwrap_iov == NULL)
|
---|
109 | return GSS_S_UNAVAILABLE;
|
---|
110 |
|
---|
111 | return (m->gm_unwrap_iov)(minor_status, ctx->gc_ctx,
|
---|
112 | conf_state, qop_state,
|
---|
113 | iov, iov_count);
|
---|
114 | }
|
---|
115 |
|
---|
116 | /**
|
---|
117 | * Update the length fields in iov buffer for the types:
|
---|
118 | * - GSS_IOV_BUFFER_TYPE_HEADER
|
---|
119 | * - GSS_IOV_BUFFER_TYPE_PADDING
|
---|
120 | * - GSS_IOV_BUFFER_TYPE_TRAILER
|
---|
121 | *
|
---|
122 | * Consider using gss_context_query_attributes() to fetch the data instead.
|
---|
123 | *
|
---|
124 | * @ingroup gssapi
|
---|
125 | */
|
---|
126 |
|
---|
127 | GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
|
---|
128 | gss_wrap_iov_length(OM_uint32 * minor_status,
|
---|
129 | gss_ctx_id_t context_handle,
|
---|
130 | int conf_req_flag,
|
---|
131 | gss_qop_t qop_req,
|
---|
132 | int *conf_state,
|
---|
133 | gss_iov_buffer_desc *iov,
|
---|
134 | int iov_count)
|
---|
135 | {
|
---|
136 | struct _gss_context *ctx = (struct _gss_context *) context_handle;
|
---|
137 | gssapi_mech_interface m;
|
---|
138 |
|
---|
139 | if (minor_status)
|
---|
140 | *minor_status = 0;
|
---|
141 | if (conf_state)
|
---|
142 | *conf_state = 0;
|
---|
143 | if (ctx == NULL)
|
---|
144 | return GSS_S_NO_CONTEXT;
|
---|
145 | if (iov == NULL && iov_count != 0)
|
---|
146 | return GSS_S_CALL_INACCESSIBLE_READ;
|
---|
147 |
|
---|
148 | m = ctx->gc_mech;
|
---|
149 |
|
---|
150 | if (m->gm_wrap_iov_length == NULL)
|
---|
151 | return GSS_S_UNAVAILABLE;
|
---|
152 |
|
---|
153 | return (m->gm_wrap_iov_length)(minor_status, ctx->gc_ctx,
|
---|
154 | conf_req_flag, qop_req, conf_state,
|
---|
155 | iov, iov_count);
|
---|
156 | }
|
---|
157 |
|
---|
158 | /**
|
---|
159 | * Free all buffer allocated by gss_wrap_iov() or gss_unwrap_iov() by
|
---|
160 | * looking at the GSS_IOV_BUFFER_FLAG_ALLOCATED flag.
|
---|
161 | *
|
---|
162 | * @ingroup gssapi
|
---|
163 | */
|
---|
164 |
|
---|
165 | GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
|
---|
166 | gss_release_iov_buffer(OM_uint32 *minor_status,
|
---|
167 | gss_iov_buffer_desc *iov,
|
---|
168 | int iov_count)
|
---|
169 | {
|
---|
170 | OM_uint32 junk;
|
---|
171 | int i;
|
---|
172 |
|
---|
173 | if (minor_status)
|
---|
174 | *minor_status = 0;
|
---|
175 | if (iov == NULL && iov_count != 0)
|
---|
176 | return GSS_S_CALL_INACCESSIBLE_READ;
|
---|
177 |
|
---|
178 | for (i = 0; i < iov_count; i++) {
|
---|
179 | if ((iov[i].type & GSS_IOV_BUFFER_FLAG_ALLOCATED) == 0)
|
---|
180 | continue;
|
---|
181 | gss_release_buffer(&junk, &iov[i].buffer);
|
---|
182 | iov[i].type &= ~GSS_IOV_BUFFER_FLAG_ALLOCATED;
|
---|
183 | }
|
---|
184 | return GSS_S_COMPLETE;
|
---|
185 | }
|
---|
186 |
|
---|
187 | /**
|
---|
188 | * Query the context for parameters.
|
---|
189 | *
|
---|
190 | * SSPI equivalent if this function is QueryContextAttributes.
|
---|
191 | *
|
---|
192 | * - GSS_C_ATTR_STREAM_SIZES data is a gss_context_stream_sizes.
|
---|
193 | *
|
---|
194 | * @ingroup gssapi
|
---|
195 | */
|
---|
196 |
|
---|
197 | gss_OID_desc GSSAPI_LIB_FUNCTION __gss_c_attr_stream_sizes_oid_desc =
|
---|
198 | {10, rk_UNCONST("\x2a\x86\x48\x86\xf7\x12\x01\x02\x01\x03")};
|
---|
199 |
|
---|
200 | GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
|
---|
201 | gss_context_query_attributes(OM_uint32 *minor_status,
|
---|
202 | const gss_ctx_id_t context_handle,
|
---|
203 | const gss_OID attribute,
|
---|
204 | void *data,
|
---|
205 | size_t len)
|
---|
206 | {
|
---|
207 | if (minor_status)
|
---|
208 | *minor_status = 0;
|
---|
209 |
|
---|
210 | if (gss_oid_equal(GSS_C_ATTR_STREAM_SIZES, attribute)) {
|
---|
211 | memset(data, 0, len);
|
---|
212 | return GSS_S_COMPLETE;
|
---|
213 | }
|
---|
214 |
|
---|
215 | return GSS_S_FAILURE;
|
---|
216 | }
|
---|