gss_aeap.c revision 226031
11573Srgrimes/*
21573Srgrimes * AEAD support
31573Srgrimes */
41573Srgrimes
51573Srgrimes#include "mech_locl.h"
61573Srgrimes
71573Srgrimes/**
81573Srgrimes * Encrypts or sign the data.
91573Srgrimes *
101573Srgrimes * This is a more complicated version of gss_wrap(), it allows the
111573Srgrimes * caller to use AEAD data (signed header/trailer) and allow greater
121573Srgrimes * controll over where the encrypted data is placed.
131573Srgrimes *
141573Srgrimes * The maximum packet size is gss_context_stream_sizes.max_msg_size.
151573Srgrimes *
16148834Sstefanf * The caller needs provide the folloing buffers when using in conf_req_flag=1 mode:
171573Srgrimes *
181573Srgrimes * - HEADER (of size gss_context_stream_sizes.header)
191573Srgrimes *   { DATA or SIGN_ONLY } (optional, zero or more)
201573Srgrimes *   PADDING (of size gss_context_stream_sizes.blocksize, if zero padding is zero, can be omitted)
211573Srgrimes *   TRAILER (of size gss_context_stream_sizes.trailer)
221573Srgrimes *
231573Srgrimes * - on DCE-RPC mode, the caller can skip PADDING and TRAILER if the
241573Srgrimes *   DATA elements is padded to a block bountry and header is of at
251573Srgrimes *   least size gss_context_stream_sizes.header + gss_context_stream_sizes.trailer.
261573Srgrimes *
271573Srgrimes * HEADER, PADDING, TRAILER will be shrunken to the size required to transmit any of them too large.
281573Srgrimes *
291573Srgrimes * To generate gss_wrap() compatible packets, use: HEADER | DATA | PADDING | TRAILER
301573Srgrimes *
311573Srgrimes * When used in conf_req_flag=0,
321573Srgrimes *
33148834Sstefanf * - HEADER (of size gss_context_stream_sizes.header)
3484260Sobrien *   { DATA or SIGN_ONLY } (optional, zero or more)
351573Srgrimes *   PADDING (of size gss_context_stream_sizes.blocksize, if zero padding is zero, can be omitted)
361573Srgrimes *   TRAILER (of size gss_context_stream_sizes.trailer)
371573Srgrimes *
381573Srgrimes *
391573Srgrimes * The input sizes of HEADER, PADDING and TRAILER can be fetched using gss_wrap_iov_length() or
401573Srgrimes * gss_context_query_attributes().
4184260Sobrien *
421573Srgrimes * @ingroup gssapi
431573Srgrimes */
441573Srgrimes
4584260Sobrien
461573SrgrimesGSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
471573Srgrimesgss_wrap_iov(OM_uint32 * minor_status,
4884260Sobrien	     gss_ctx_id_t  context_handle,
4984260Sobrien	     int conf_req_flag,
5084260Sobrien	     gss_qop_t qop_req,
5184260Sobrien	     int * conf_state,
5284260Sobrien	     gss_iov_buffer_desc *iov,
5384260Sobrien	     int iov_count)
5484260Sobrien{
551573Srgrimes	struct _gss_context *ctx = (struct _gss_context *) context_handle;
561573Srgrimes	gssapi_mech_interface m;
5784260Sobrien
5884260Sobrien	if (minor_status)
5984260Sobrien	    *minor_status = 0;
601573Srgrimes	if (conf_state)
611573Srgrimes	    *conf_state = 0;
621573Srgrimes	if (ctx == NULL)
631573Srgrimes	    return GSS_S_NO_CONTEXT;
641573Srgrimes	if (iov == NULL && iov_count != 0)
65148834Sstefanf	    return GSS_S_CALL_INACCESSIBLE_READ;
6684260Sobrien
6784260Sobrien	m = ctx->gc_mech;
68278411Sbapt
691573Srgrimes	if (m->gm_wrap_iov == NULL)
7084260Sobrien	    return GSS_S_UNAVAILABLE;
7184260Sobrien
7284260Sobrien	return (m->gm_wrap_iov)(minor_status, ctx->gc_ctx,
7384260Sobrien				conf_req_flag, qop_req, conf_state,
74148834Sstefanf				iov, iov_count);
7584260Sobrien}
761573Srgrimes
771573Srgrimes/**
78 * Decrypt or verifies the signature on the data.
79 *
80 *
81 * @ingroup gssapi
82 */
83
84GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
85gss_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
127GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
128gss_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
165GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
166gss_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
197gss_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
200GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
201gss_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}
217