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