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