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 }
217