17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate * CDDL HEADER START
37c478bd9Sstevel@tonic-gate *
47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
57c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only
67c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance
77c478bd9Sstevel@tonic-gate * with the License.
87c478bd9Sstevel@tonic-gate *
97c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
107c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
117c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
127c478bd9Sstevel@tonic-gate * and limitations under the License.
137c478bd9Sstevel@tonic-gate *
147c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
157c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
167c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
177c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
187c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
197c478bd9Sstevel@tonic-gate *
207c478bd9Sstevel@tonic-gate * CDDL HEADER END
217c478bd9Sstevel@tonic-gate */
227c478bd9Sstevel@tonic-gate /*
237c478bd9Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
247c478bd9Sstevel@tonic-gate * Use is subject to license terms.
25*48bbca81SDaniel Hoffman * Copyright (c) 2016 by Delphix. All rights reserved.
267c478bd9Sstevel@tonic-gate */
277c478bd9Sstevel@tonic-gate
287c478bd9Sstevel@tonic-gate #include <sys/note.h>
297c478bd9Sstevel@tonic-gate #include "dh_gssapi.h"
307c478bd9Sstevel@tonic-gate
317c478bd9Sstevel@tonic-gate /*
327c478bd9Sstevel@tonic-gate * This module contains the implementation of the gssapi context support
337c478bd9Sstevel@tonic-gate * routines for the Diffie-Hellman mechanism.
347c478bd9Sstevel@tonic-gate *
357c478bd9Sstevel@tonic-gate * The GSS routines that are supported by this module are:
367c478bd9Sstevel@tonic-gate * gss_context_time
377c478bd9Sstevel@tonic-gate * gss_delete_sec_context
387c478bd9Sstevel@tonic-gate * gss_inquire_context
397c478bd9Sstevel@tonic-gate * gss_wrap_size_limit
407c478bd9Sstevel@tonic-gate *
417c478bd9Sstevel@tonic-gate * The following routines are not supported for the Diffie-Hellman
427c478bd9Sstevel@tonic-gate * Mechanism at this time.
437c478bd9Sstevel@tonic-gate * gss_export_sec_context
447c478bd9Sstevel@tonic-gate * gss_import_sec_context
457c478bd9Sstevel@tonic-gate *
467c478bd9Sstevel@tonic-gate * The following routine is not supported since it is obsolete in version 2
477c478bd9Sstevel@tonic-gate * of the GSS-API.
487c478bd9Sstevel@tonic-gate * gss_process_context_token.
497c478bd9Sstevel@tonic-gate *
507c478bd9Sstevel@tonic-gate * Note that support for gss_init_sec_context and gss_accept_sec_context is
517c478bd9Sstevel@tonic-gate * found in context_establish.c
527c478bd9Sstevel@tonic-gate */
537c478bd9Sstevel@tonic-gate
547c478bd9Sstevel@tonic-gate OM_uint32
__dh_gss_context_time(void * ctx,OM_uint32 * minor,gss_ctx_id_t context,OM_uint32 * time_remaining)557c478bd9Sstevel@tonic-gate __dh_gss_context_time(void *ctx, /* Mechanism context (not used) */
567c478bd9Sstevel@tonic-gate OM_uint32 * minor, /* GSS minor status */
577c478bd9Sstevel@tonic-gate gss_ctx_id_t context, /* GSS context handle */
587c478bd9Sstevel@tonic-gate OM_uint32* time_remaining /* Time remaining */)
597c478bd9Sstevel@tonic-gate
607c478bd9Sstevel@tonic-gate {
617c478bd9Sstevel@tonic-gate _NOTE(ARGUNUSED(ctx))
627c478bd9Sstevel@tonic-gate /* Context is a dh context */
637c478bd9Sstevel@tonic-gate dh_gss_context_t cntx = (dh_gss_context_t)context;
647c478bd9Sstevel@tonic-gate time_t now = time(0);
657c478bd9Sstevel@tonic-gate
667c478bd9Sstevel@tonic-gate if (minor == 0)
677c478bd9Sstevel@tonic-gate return (GSS_S_CALL_INACCESSIBLE_WRITE);
687c478bd9Sstevel@tonic-gate
697c478bd9Sstevel@tonic-gate if (time_remaining == 0)
707c478bd9Sstevel@tonic-gate return (GSS_S_CALL_INACCESSIBLE_WRITE);
717c478bd9Sstevel@tonic-gate
727c478bd9Sstevel@tonic-gate /* Validate context */
737c478bd9Sstevel@tonic-gate if ((*minor = __dh_validate_context(cntx)) != DH_SUCCESS)
747c478bd9Sstevel@tonic-gate return (GSS_S_NO_CONTEXT);
757c478bd9Sstevel@tonic-gate
767c478bd9Sstevel@tonic-gate /* See if it is always valid */
777c478bd9Sstevel@tonic-gate if (cntx->expire == (time_t)GSS_C_INDEFINITE) {
787c478bd9Sstevel@tonic-gate *time_remaining = GSS_C_INDEFINITE;
797c478bd9Sstevel@tonic-gate return (GSS_S_COMPLETE);
807c478bd9Sstevel@tonic-gate }
817c478bd9Sstevel@tonic-gate
827c478bd9Sstevel@tonic-gate /* Calculate the remainning time */
837c478bd9Sstevel@tonic-gate *time_remaining = (now < cntx->expire) ? cntx->expire - now : 0;
847c478bd9Sstevel@tonic-gate
857c478bd9Sstevel@tonic-gate /* Return expired if there is no time left */
867c478bd9Sstevel@tonic-gate return (*time_remaining ? GSS_S_COMPLETE : GSS_S_CONTEXT_EXPIRED);
877c478bd9Sstevel@tonic-gate }
887c478bd9Sstevel@tonic-gate
897c478bd9Sstevel@tonic-gate /*
907c478bd9Sstevel@tonic-gate * Delete a Diffie-Hellman context that is pointed to by context.
917c478bd9Sstevel@tonic-gate * On a successfull return *context will be NULL.
927c478bd9Sstevel@tonic-gate */
937c478bd9Sstevel@tonic-gate
947c478bd9Sstevel@tonic-gate OM_uint32
__dh_gss_delete_sec_context(void * ctx,OM_uint32 * minor,gss_ctx_id_t * context,gss_buffer_t token)957c478bd9Sstevel@tonic-gate __dh_gss_delete_sec_context(void *ctx, /* Mechanism context */
967c478bd9Sstevel@tonic-gate OM_uint32 *minor, /* Mechanism status */
977c478bd9Sstevel@tonic-gate gss_ctx_id_t *context, /* GSS context */
987c478bd9Sstevel@tonic-gate gss_buffer_t token /* GSS token */)
997c478bd9Sstevel@tonic-gate {
1007c478bd9Sstevel@tonic-gate _NOTE(ARGUNUSED(ctx))
1017c478bd9Sstevel@tonic-gate
1027c478bd9Sstevel@tonic-gate dh_gss_context_t cntx;
1037c478bd9Sstevel@tonic-gate
1047c478bd9Sstevel@tonic-gate if (context == 0)
1057c478bd9Sstevel@tonic-gate return (GSS_S_CALL_INACCESSIBLE_READ |
1067c478bd9Sstevel@tonic-gate GSS_S_CALL_INACCESSIBLE_WRITE);
1077c478bd9Sstevel@tonic-gate
1087c478bd9Sstevel@tonic-gate /* context is a Diffie-Hellman context */
1097c478bd9Sstevel@tonic-gate cntx = (dh_gss_context_t)*context;
1107c478bd9Sstevel@tonic-gate
1117c478bd9Sstevel@tonic-gate if (minor == 0)
1127c478bd9Sstevel@tonic-gate return (GSS_S_CALL_INACCESSIBLE_WRITE);
1137c478bd9Sstevel@tonic-gate
1147c478bd9Sstevel@tonic-gate /*
1157c478bd9Sstevel@tonic-gate * If token then set the length to zero value to zero to indicate
1167c478bd9Sstevel@tonic-gate * We indicat a null token since we don't need to send a token to
1177c478bd9Sstevel@tonic-gate * the other side.
1187c478bd9Sstevel@tonic-gate */
1197c478bd9Sstevel@tonic-gate
1207c478bd9Sstevel@tonic-gate if (token) {
1217c478bd9Sstevel@tonic-gate token->length = 0;
1227c478bd9Sstevel@tonic-gate token->value = NULL;
1237c478bd9Sstevel@tonic-gate }
1247c478bd9Sstevel@tonic-gate
1257c478bd9Sstevel@tonic-gate /* Deleting a null context is OK */
1267c478bd9Sstevel@tonic-gate if (cntx == NULL)
1277c478bd9Sstevel@tonic-gate return (GSS_S_COMPLETE);
1287c478bd9Sstevel@tonic-gate
1297c478bd9Sstevel@tonic-gate /* Validate the context */
1307c478bd9Sstevel@tonic-gate if ((*minor = __dh_validate_context(cntx)) != DH_SUCCESS)
1317c478bd9Sstevel@tonic-gate return (GSS_S_NO_CONTEXT);
1327c478bd9Sstevel@tonic-gate
1337c478bd9Sstevel@tonic-gate /* Zero out the session keys! */
1347c478bd9Sstevel@tonic-gate memset(cntx->keys, 0, cntx->no_keys * sizeof (des_block));
1357c478bd9Sstevel@tonic-gate
1367c478bd9Sstevel@tonic-gate /* Unregister the context */
1377c478bd9Sstevel@tonic-gate *minor = __dh_remove_context(cntx);
1387c478bd9Sstevel@tonic-gate
1397c478bd9Sstevel@tonic-gate /* Free storage */
1407c478bd9Sstevel@tonic-gate __dh_destroy_seq_hist(cntx);
1417c478bd9Sstevel@tonic-gate free(cntx->remote);
1427c478bd9Sstevel@tonic-gate free(cntx->local);
1437c478bd9Sstevel@tonic-gate Free(cntx->keys);
1447c478bd9Sstevel@tonic-gate Free(cntx);
1457c478bd9Sstevel@tonic-gate
1467c478bd9Sstevel@tonic-gate /* Set context to NULL */
1477c478bd9Sstevel@tonic-gate *context = NULL;
1487c478bd9Sstevel@tonic-gate
1497c478bd9Sstevel@tonic-gate return (GSS_S_COMPLETE);
1507c478bd9Sstevel@tonic-gate }
1517c478bd9Sstevel@tonic-gate
1527c478bd9Sstevel@tonic-gate
1537c478bd9Sstevel@tonic-gate /*
1547c478bd9Sstevel@tonic-gate * Diffie-Hellman mechanism currently does not support exporting and importing
1557c478bd9Sstevel@tonic-gate * gss contexts.
1567c478bd9Sstevel@tonic-gate */
1577c478bd9Sstevel@tonic-gate
1587c478bd9Sstevel@tonic-gate OM_uint32
1597c478bd9Sstevel@tonic-gate /*ARGSUSED*/
__dh_gss_export_sec_context(void * ctx,OM_uint32 * minor,gss_ctx_id_t * context,gss_buffer_t token)1607c478bd9Sstevel@tonic-gate __dh_gss_export_sec_context(void *ctx, OM_uint32 *minor,
1617c478bd9Sstevel@tonic-gate gss_ctx_id_t *context, gss_buffer_t token)
1627c478bd9Sstevel@tonic-gate {
1637c478bd9Sstevel@tonic-gate return (GSS_S_UNAVAILABLE);
1647c478bd9Sstevel@tonic-gate }
1657c478bd9Sstevel@tonic-gate
1667c478bd9Sstevel@tonic-gate OM_uint32
1677c478bd9Sstevel@tonic-gate /*ARGSUSED*/
__dh_gss_import_sec_context(void * ctx,OM_uint32 * minor,gss_buffer_t token,gss_ctx_id_t * context)1687c478bd9Sstevel@tonic-gate __dh_gss_import_sec_context(void * ctx, OM_uint32 *minor,
1697c478bd9Sstevel@tonic-gate gss_buffer_t token, gss_ctx_id_t *context)
1707c478bd9Sstevel@tonic-gate {
1717c478bd9Sstevel@tonic-gate return (GSS_S_UNAVAILABLE);
1727c478bd9Sstevel@tonic-gate }
1737c478bd9Sstevel@tonic-gate
1747c478bd9Sstevel@tonic-gate /*
1757c478bd9Sstevel@tonic-gate * Get the state of a Diffie-Hellman context
1767c478bd9Sstevel@tonic-gate */
1777c478bd9Sstevel@tonic-gate
1787c478bd9Sstevel@tonic-gate OM_uint32
__dh_gss_inquire_context(void * ctx,OM_uint32 * minor,gss_ctx_id_t context,gss_name_t * initiator,gss_name_t * acceptor,OM_uint32 * time_rec,gss_OID * mech,OM_uint32 * flags_rec,int * local,int * open)1797c478bd9Sstevel@tonic-gate __dh_gss_inquire_context(void *ctx, /* Mechanism context */
1807c478bd9Sstevel@tonic-gate OM_uint32 *minor, /* Mechanism status */
1817c478bd9Sstevel@tonic-gate gss_ctx_id_t context, /* GSS context */
1827c478bd9Sstevel@tonic-gate gss_name_t *initiator, /* Name of initiator */
1837c478bd9Sstevel@tonic-gate gss_name_t *acceptor, /* Name of acceptor */
1847c478bd9Sstevel@tonic-gate OM_uint32 *time_rec, /* Amount of time left */
1857c478bd9Sstevel@tonic-gate gss_OID *mech, /* return OID of mechanism */
1867c478bd9Sstevel@tonic-gate OM_uint32 *flags_rec, /* flags set on context */
1877c478bd9Sstevel@tonic-gate int *local, /* True if we're the initiator */
1887c478bd9Sstevel@tonic-gate int *open /* True if the context is established */)
1897c478bd9Sstevel@tonic-gate {
1907c478bd9Sstevel@tonic-gate dh_gss_context_t cntx;
1917c478bd9Sstevel@tonic-gate OM_uint32 stat = GSS_S_COMPLETE;
1927c478bd9Sstevel@tonic-gate OM_uint32 t;
1937c478bd9Sstevel@tonic-gate
1947c478bd9Sstevel@tonic-gate /* context is a Diffie-Hellman */
1957c478bd9Sstevel@tonic-gate cntx = (dh_gss_context_t)context;
1967c478bd9Sstevel@tonic-gate
1977c478bd9Sstevel@tonic-gate /* Validate the context */
1987c478bd9Sstevel@tonic-gate if ((*minor = __dh_validate_context(cntx)) != DH_SUCCESS)
1997c478bd9Sstevel@tonic-gate return (GSS_S_NO_CONTEXT);
2007c478bd9Sstevel@tonic-gate
2017c478bd9Sstevel@tonic-gate /* If the caller wants the mechanism OID set *mech to if we can */
2027c478bd9Sstevel@tonic-gate if (mech) {
2037c478bd9Sstevel@tonic-gate if (ctx == 0) {
2047c478bd9Sstevel@tonic-gate *mech = GSS_C_NO_OID;
2057c478bd9Sstevel@tonic-gate return (GSS_S_CALL_INACCESSIBLE_READ);
2067c478bd9Sstevel@tonic-gate }
2077c478bd9Sstevel@tonic-gate else
2087c478bd9Sstevel@tonic-gate *mech = ((dh_context_t)ctx)->mech;
2097c478bd9Sstevel@tonic-gate }
2107c478bd9Sstevel@tonic-gate
2117c478bd9Sstevel@tonic-gate /* set t to be the time left on the context */
2127c478bd9Sstevel@tonic-gate if (cntx->expire == GSS_C_INDEFINITE)
2137c478bd9Sstevel@tonic-gate t = GSS_C_INDEFINITE;
2147c478bd9Sstevel@tonic-gate else {
2157c478bd9Sstevel@tonic-gate time_t now = time(0);
2167c478bd9Sstevel@tonic-gate t = now > cntx->expire ? 0 : (OM_uint32)(cntx->expire - now);
2177c478bd9Sstevel@tonic-gate }
2187c478bd9Sstevel@tonic-gate
2197c478bd9Sstevel@tonic-gate /* If the caller wants the initiator set *initiator to it. */
2207c478bd9Sstevel@tonic-gate if (initiator) {
2217c478bd9Sstevel@tonic-gate dh_principal p = cntx->initiate ? cntx->local : cntx->remote;
2227c478bd9Sstevel@tonic-gate *initiator = (gss_name_t)strdup(p);
2237c478bd9Sstevel@tonic-gate }
2247c478bd9Sstevel@tonic-gate
2257c478bd9Sstevel@tonic-gate /* If the callers wants the acceptor set *acceptor to it. */
2267c478bd9Sstevel@tonic-gate if (acceptor) {
2277c478bd9Sstevel@tonic-gate dh_principal p = cntx->initiate ? cntx->remote : cntx->local;
2287c478bd9Sstevel@tonic-gate *acceptor = (gss_name_t)strdup(p);
2297c478bd9Sstevel@tonic-gate }
2307c478bd9Sstevel@tonic-gate
2317c478bd9Sstevel@tonic-gate /* If the caller wants the time remaining set *time_rec to t */
2327c478bd9Sstevel@tonic-gate if (time_rec)
2337c478bd9Sstevel@tonic-gate *time_rec = t;
2347c478bd9Sstevel@tonic-gate
2357c478bd9Sstevel@tonic-gate
2367c478bd9Sstevel@tonic-gate /* Return the flags in flags_rec if set */
2377c478bd9Sstevel@tonic-gate if (flags_rec)
2387c478bd9Sstevel@tonic-gate *flags_rec = cntx->flags;
2397c478bd9Sstevel@tonic-gate
2407c478bd9Sstevel@tonic-gate /* ditto for local */
2417c478bd9Sstevel@tonic-gate if (local)
2427c478bd9Sstevel@tonic-gate *local = cntx->initiate;
2437c478bd9Sstevel@tonic-gate
2447c478bd9Sstevel@tonic-gate /* ditto for open */
2457c478bd9Sstevel@tonic-gate if (open)
2467c478bd9Sstevel@tonic-gate *open = (cntx->state == ESTABLISHED);
2477c478bd9Sstevel@tonic-gate
2487c478bd9Sstevel@tonic-gate
2497c478bd9Sstevel@tonic-gate /* return GSS_S_CONTEXT_EXPIRED if no time is left on the context */
2507c478bd9Sstevel@tonic-gate return ((t == 0 ? GSS_S_CONTEXT_EXPIRED : GSS_S_COMPLETE) | stat);
2517c478bd9Sstevel@tonic-gate }
2527c478bd9Sstevel@tonic-gate
2537c478bd9Sstevel@tonic-gate /*
2547c478bd9Sstevel@tonic-gate * __dh_gss_process_context_token.
2557c478bd9Sstevel@tonic-gate * This routine is not implemented. It is depricated in version 2.
2567c478bd9Sstevel@tonic-gate */
2577c478bd9Sstevel@tonic-gate
2587c478bd9Sstevel@tonic-gate OM_uint32
2597c478bd9Sstevel@tonic-gate /*ARGSUSED*/
__dh_gss_process_context_token(void * ctx,OM_uint32 * minor,gss_ctx_id_t context,gss_buffer_t token)2607c478bd9Sstevel@tonic-gate __dh_gss_process_context_token(void *ctx, OM_uint32 *minor,
2617c478bd9Sstevel@tonic-gate gss_ctx_id_t context, gss_buffer_t token)
2627c478bd9Sstevel@tonic-gate {
2637c478bd9Sstevel@tonic-gate return (GSS_S_UNAVAILABLE);
2647c478bd9Sstevel@tonic-gate }
2657c478bd9Sstevel@tonic-gate
2667c478bd9Sstevel@tonic-gate /*
2677c478bd9Sstevel@tonic-gate * This implements the gss_wrap_size_limit entry point for Diffie-Hellman
2687c478bd9Sstevel@tonic-gate * mechanism. See RFC 2078 for details. The idea here is for a context,
2697c478bd9Sstevel@tonic-gate * qop, whether confidentiality is specified, and an output size, return
2707c478bd9Sstevel@tonic-gate * the maximum input size that will fit in the given output size. Typically
2717c478bd9Sstevel@tonic-gate * the output size would be the MTU of the higher level protocol using the
2727c478bd9Sstevel@tonic-gate * GSS-API.
2737c478bd9Sstevel@tonic-gate */
2747c478bd9Sstevel@tonic-gate
2757c478bd9Sstevel@tonic-gate OM_uint32
__dh_gss_wrap_size_limit(void * ctx,OM_uint32 * minor,gss_ctx_id_t context,int conf_req,gss_qop_t qop_req,OM_uint32 output_size,OM_uint32 * input_size)2767c478bd9Sstevel@tonic-gate __dh_gss_wrap_size_limit(void *ctx, /* Mechanism context (not used) */
2777c478bd9Sstevel@tonic-gate OM_uint32 *minor, /* Mechanism status */
2787c478bd9Sstevel@tonic-gate gss_ctx_id_t context, /* GSS context handle */
2797c478bd9Sstevel@tonic-gate int conf_req, /* True if confidentiality is wanted */
2807c478bd9Sstevel@tonic-gate gss_qop_t qop_req, /* Requested QOP */
2817c478bd9Sstevel@tonic-gate OM_uint32 output_size, /* The maximum ouput size */
2827c478bd9Sstevel@tonic-gate OM_uint32 *input_size /* Input size returned */)
2837c478bd9Sstevel@tonic-gate {
2847c478bd9Sstevel@tonic-gate _NOTE(ARGUNUSED(ctx))
2857c478bd9Sstevel@tonic-gate OM_uint32 major, stat = GSS_S_COMPLETE;
2867c478bd9Sstevel@tonic-gate unsigned int msgsize, sigsize, pad = 1, size;
2877c478bd9Sstevel@tonic-gate dh_token_desc token;
2887c478bd9Sstevel@tonic-gate dh_wrap_t wrap = &token.ver.dh_version_u.body.dh_token_body_desc_u.seal;
2897c478bd9Sstevel@tonic-gate OM_uint32 left;
2907c478bd9Sstevel@tonic-gate
2917c478bd9Sstevel@tonic-gate if (input_size == 0)
2927c478bd9Sstevel@tonic-gate stat = GSS_S_CALL_INACCESSIBLE_WRITE;
2937c478bd9Sstevel@tonic-gate
2947c478bd9Sstevel@tonic-gate /* We check for valid unexpired context by calling gss_context_time. */
2957c478bd9Sstevel@tonic-gate if ((major = stat | __dh_gss_context_time(ctx, minor, context, &left))
2967c478bd9Sstevel@tonic-gate != GSS_S_COMPLETE)
2977c478bd9Sstevel@tonic-gate return (major | stat);
2987c478bd9Sstevel@tonic-gate
2997c478bd9Sstevel@tonic-gate /* Find the signature size for this qop. */
3007c478bd9Sstevel@tonic-gate if ((*minor = __get_sig_size(qop_req, &sigsize)) != DH_SUCCESS)
3017c478bd9Sstevel@tonic-gate return (GSS_S_BAD_QOP | stat);
3027c478bd9Sstevel@tonic-gate
303*48bbca81SDaniel Hoffman /* Just return if we can't give the caller what it asked for. */
3047c478bd9Sstevel@tonic-gate if (stat)
3057c478bd9Sstevel@tonic-gate return (stat);
3067c478bd9Sstevel@tonic-gate
3077c478bd9Sstevel@tonic-gate /*
3087c478bd9Sstevel@tonic-gate * If we requested confidentiality, get the cipher pad for the
3097c478bd9Sstevel@tonic-gate * requested qop. Since we can't support privacy the cipher pad
3107c478bd9Sstevel@tonic-gate * is always 1.
3117c478bd9Sstevel@tonic-gate */
3127c478bd9Sstevel@tonic-gate if (conf_req)
3137c478bd9Sstevel@tonic-gate pad = 1;
3147c478bd9Sstevel@tonic-gate
3157c478bd9Sstevel@tonic-gate /*
3167c478bd9Sstevel@tonic-gate * Set up an empty wrap token to calculate header and signature
3177c478bd9Sstevel@tonic-gate * overhead.
3187c478bd9Sstevel@tonic-gate */
3197c478bd9Sstevel@tonic-gate
3207c478bd9Sstevel@tonic-gate token.ver.verno = DH_PROTO_VERSION;
3217c478bd9Sstevel@tonic-gate token.ver.dh_version_u.body.type = DH_WRAP;
3227c478bd9Sstevel@tonic-gate wrap->mic.qop = qop_req;
3237c478bd9Sstevel@tonic-gate wrap->mic.seqnum = 0;
3247c478bd9Sstevel@tonic-gate wrap->mic.client_flag = 0;
3257c478bd9Sstevel@tonic-gate wrap->body.body_len = 0;
3267c478bd9Sstevel@tonic-gate wrap->body.body_val = 0;
3277c478bd9Sstevel@tonic-gate token.verifier.dh_signature_len = sigsize;
3287c478bd9Sstevel@tonic-gate token.verifier.dh_signature_val = 0;
3297c478bd9Sstevel@tonic-gate
3307c478bd9Sstevel@tonic-gate /* This is the size of an empy wrap token */
3317c478bd9Sstevel@tonic-gate size = xdr_sizeof((xdrproc_t)xdr_dh_token_desc, (void *)&token);
3327c478bd9Sstevel@tonic-gate
3337c478bd9Sstevel@tonic-gate /* This is the amount of space left to put our message. */
3347c478bd9Sstevel@tonic-gate msgsize = (output_size > size) ? output_size - size : 0;
3357c478bd9Sstevel@tonic-gate
3367c478bd9Sstevel@tonic-gate /* XDR needs to pad to a four byte boundry */
3377c478bd9Sstevel@tonic-gate msgsize = (msgsize / 4) * 4;
3387c478bd9Sstevel@tonic-gate
3397c478bd9Sstevel@tonic-gate /* We need to pad to pad bytes for encryption (=1 if conf_req = 0) */
3407c478bd9Sstevel@tonic-gate msgsize = (msgsize / pad) * pad;
3417c478bd9Sstevel@tonic-gate
3427c478bd9Sstevel@tonic-gate /*
3437c478bd9Sstevel@tonic-gate * The serialization of the inner message includes
3447c478bd9Sstevel@tonic-gate * the original length.
3457c478bd9Sstevel@tonic-gate */
3467c478bd9Sstevel@tonic-gate
3477c478bd9Sstevel@tonic-gate msgsize = (msgsize > sizeof (uint_t)) ? msgsize - sizeof (uint_t) : 0;
3487c478bd9Sstevel@tonic-gate
3497c478bd9Sstevel@tonic-gate /*
3507c478bd9Sstevel@tonic-gate * We now have the space for the inner wrap message, which is also
3517c478bd9Sstevel@tonic-gate * XDR encoded and is padded to a four byte boundry.
3527c478bd9Sstevel@tonic-gate */
3537c478bd9Sstevel@tonic-gate
3547c478bd9Sstevel@tonic-gate msgsize = (msgsize / 4) * 4;
3557c478bd9Sstevel@tonic-gate
3567c478bd9Sstevel@tonic-gate *input_size = msgsize;
3577c478bd9Sstevel@tonic-gate
3587c478bd9Sstevel@tonic-gate return (GSS_S_COMPLETE);
3597c478bd9Sstevel@tonic-gate }
360