Skip to content

Commit

Permalink
gss_wrap/gss_unwrap_aead implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
lhoward committed Dec 17, 2015
1 parent f10b118 commit b388d9e
Show file tree
Hide file tree
Showing 5 changed files with 208 additions and 0 deletions.
7 changes: 7 additions & 0 deletions lib/gssapi/gssapi/gssapi.h
Expand Up @@ -934,6 +934,13 @@ gss_wrap_iov_length(OM_uint32 *, gss_ctx_id_t, int, gss_qop_t, int *,
GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
gss_release_iov_buffer(OM_uint32 *, gss_iov_buffer_desc *, int);

GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
gss_wrap_aead(OM_uint32 *, gss_ctx_id_t, int, gss_qop_t,
gss_buffer_t, gss_buffer_t, int *, gss_buffer_t);

GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
gss_unwrap_aead(OM_uint32 *, gss_ctx_id_t, gss_buffer_t,
gss_buffer_t, gss_buffer_t, int *, gss_qop_t *);

GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
gss_export_cred(OM_uint32 * /* minor_status */,
Expand Down
2 changes: 2 additions & 0 deletions lib/gssapi/libgssapi-exports.def
Expand Up @@ -94,11 +94,13 @@ EXPORTS
gss_test_oid_set_member
gss_unseal
gss_unwrap
gss_unwrap_aead
gss_unwrap_iov
gss_userok
gss_verify
gss_verify_mic
gss_wrap
gss_wrap_aead
gss_wrap_iov
gss_wrap_iov_length
gss_wrap_size_limit
Expand Down
118 changes: 118 additions & 0 deletions lib/gssapi/mech/gss_aeap.c
Expand Up @@ -214,3 +214,121 @@ gss_context_query_attributes(OM_uint32 *minor_status,

return GSS_S_FAILURE;
}

/*
* AEAD wrap API for a single piece of associated data, for compatibility
* with MIT and as specified by draft-howard-gssapi-aead-00.txt.
*
* @ingroup gssapi
*/
GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
gss_wrap_aead(OM_uint32 *minor_status,
gss_ctx_id_t context_handle,
int conf_req_flag,
gss_qop_t qop_req,
gss_buffer_t input_assoc_buffer,
gss_buffer_t input_payload_buffer,
int *conf_state,
gss_buffer_t output_message_buffer)
{
OM_uint32 major_status, tmp, flags = 0;
gss_iov_buffer_desc iov[5];
size_t i;
unsigned char *p;

memset(iov, 0, sizeof(iov));

iov[0].type = GSS_IOV_BUFFER_TYPE_HEADER;

iov[1].type = GSS_IOV_BUFFER_TYPE_SIGN_ONLY;
if (input_assoc_buffer)
iov[1].buffer = *input_assoc_buffer;

iov[2].type = GSS_IOV_BUFFER_TYPE_DATA;
if (input_payload_buffer)
iov[2].buffer.length = input_payload_buffer->length;

gss_inquire_context(minor_status, context_handle, NULL, NULL,
NULL, NULL, &flags, NULL, NULL);

/* krb5 mech rejects padding/trailer if DCE-style is set */
iov[3].type = (flags & GSS_C_DCE_STYLE) ? GSS_IOV_BUFFER_TYPE_EMPTY
: GSS_IOV_BUFFER_TYPE_PADDING;
iov[4].type = (flags & GSS_C_DCE_STYLE) ? GSS_IOV_BUFFER_TYPE_EMPTY
: GSS_IOV_BUFFER_TYPE_TRAILER;

major_status = gss_wrap_iov_length(minor_status, context_handle,
conf_req_flag, qop_req, conf_state,
iov, 5);
if (GSS_ERROR(major_status))
return major_status;

for (i = 0, output_message_buffer->length = 0; i < 5; i++) {
if (GSS_IOV_BUFFER_TYPE(iov[i].type) == GSS_IOV_BUFFER_TYPE_SIGN_ONLY)
continue;

output_message_buffer->length += iov[i].buffer.length;
}

output_message_buffer->value = malloc(output_message_buffer->length);
if (output_message_buffer->value == NULL) {
*minor_status = ENOMEM;
return GSS_S_FAILURE;
}

for (i = 0, p = output_message_buffer->value; i < 5; i++) {
if (GSS_IOV_BUFFER_TYPE(iov[i].type) == GSS_IOV_BUFFER_TYPE_SIGN_ONLY)
continue;
else if (GSS_IOV_BUFFER_TYPE(iov[i].type) == GSS_IOV_BUFFER_TYPE_DATA)
memcpy(p, input_payload_buffer->value, input_payload_buffer->length);

iov[i].buffer.value = p;
p += iov[i].buffer.length;
}

major_status = gss_wrap_iov(minor_status, context_handle, conf_req_flag,
qop_req, conf_state, iov, 5);
if (GSS_ERROR(major_status))
gss_release_buffer(&tmp, output_message_buffer);

return major_status;
}

/*
* AEAD unwrap for a single piece of associated data, for compatibility
* with MIT and as specified by draft-howard-gssapi-aead-00.txt.
*
* @ingroup gssapi
*/
GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
gss_unwrap_aead(OM_uint32 *minor_status,
gss_ctx_id_t context_handle,
gss_buffer_t input_message_buffer,
gss_buffer_t input_assoc_buffer,
gss_buffer_t output_payload_buffer,
int *conf_state,
gss_qop_t *qop_state)
{
OM_uint32 major_status, tmp;
gss_iov_buffer_desc iov[3];

memset(iov, 0, sizeof(iov));

iov[0].type = GSS_IOV_BUFFER_TYPE_STREAM;
iov[0].buffer = *input_message_buffer;

iov[1].type = GSS_IOV_BUFFER_TYPE_SIGN_ONLY;
if (input_assoc_buffer)
iov[1].buffer = *input_assoc_buffer;

iov[2].type = GSS_IOV_BUFFER_TYPE_DATA | GSS_IOV_BUFFER_FLAG_ALLOCATE;

major_status = gss_unwrap_iov(minor_status, context_handle, conf_state,
qop_state, iov, 3);
if (GSS_ERROR(major_status))
gss_release_iov_buffer(&tmp, &iov[2], 1);
else
*output_payload_buffer = iov[2].buffer;

return major_status;
}
79 changes: 79 additions & 0 deletions lib/gssapi/test_context.c
Expand Up @@ -51,6 +51,7 @@ static int mutual_auth_flag = 0;
static int dce_style_flag = 0;
static int wrapunwrap_flag = 0;
static int iov_flag = 0;
static int aead_flag = 0;
static int getverifymic_flag = 0;
static int deleg_flag = 0;
static int policy_deleg_flag = 0;
Expand Down Expand Up @@ -449,6 +450,60 @@ wrapunwrap_iov(gss_ctx_id_t cctx, gss_ctx_id_t sctx, int flags, gss_OID mechoid)
free(token.data);
}

static void
wrapunwrap_aead(gss_ctx_id_t cctx, gss_ctx_id_t sctx, int flags, gss_OID mechoid)
{
gss_buffer_desc token, assoc, message = GSS_C_EMPTY_BUFFER;
gss_buffer_desc output;
OM_uint32 min_stat, maj_stat;
gss_qop_t qop_state;
int conf_state, conf_state2;
char assoc_data[9] = "ABCheader";
char token_data[16] = "0123456789abcdef";

if (flags & USE_SIGN_ONLY) {
assoc.value = assoc_data;
assoc.length = 9;
} else {
assoc.value = NULL;
assoc.length = 0;
}

token.value = token_data;
token.length = 16;

maj_stat = gss_wrap_aead(&min_stat, cctx, dce_style_flag || flags & USE_CONF,
GSS_C_QOP_DEFAULT, &assoc, &token,
&conf_state, &message);
if (maj_stat != GSS_S_COMPLETE)
errx(1, "gss_wrap_aead failed");

if ((flags & (USE_SIGN_ONLY|FORCE_IOV)) == 0) {
maj_stat = gss_unwrap(&min_stat, sctx, &message,
&output, &conf_state2, &qop_state);

if (maj_stat != GSS_S_COMPLETE)
errx(1, "gss_unwrap from gss_wrap_aead failed: %s",
gssapi_err(maj_stat, min_stat, mechoid));
} else {
maj_stat = gss_unwrap_aead(&min_stat, sctx, &message, &assoc,
&output, &conf_state2, &qop_state);
if (maj_stat != GSS_S_COMPLETE)
errx(1, "gss_unwrap_aead failed: %x %s", flags,
gssapi_err(maj_stat, min_stat, mechoid));
}

if (output.length != token.length)
errx(1, "plaintext length wrong for aead");
else if (memcmp(output.value, token.value, token.length) != 0)
errx(1, "plaintext wrong for aead");
if (conf_state2 != conf_state)
errx(1, "conf state wrong for aead: %x", flags);

gss_release_buffer(&min_stat, &message);
gss_release_buffer(&min_stat, &output);
}

static void
getverifymic(gss_ctx_id_t cctx, gss_ctx_id_t sctx, gss_OID mechoid)
{
Expand Down Expand Up @@ -508,6 +563,7 @@ static struct getargs args[] = {
{"dce-style",0, arg_flag, &dce_style_flag, "dce-style", NULL },
{"wrapunwrap",0, arg_flag, &wrapunwrap_flag, "wrap/unwrap", NULL },
{"iov", 0, arg_flag, &iov_flag, "wrap/unwrap iov", NULL },
{"aead", 0, arg_flag, &aead_flag, "wrap/unwrap aead", NULL },
{"getverifymic",0, arg_flag, &getverifymic_flag,
"get and verify mic", NULL },
{"delegate",0, arg_flag, &deleg_flag, "delegate credential", NULL },
Expand Down Expand Up @@ -966,6 +1022,29 @@ main(int argc, char **argv)
wrapunwrap_iov(cctx, sctx, USE_CONF|USE_HEADER_ONLY|FORCE_IOV, actual_mech);
}

if (aead_flag) {
wrapunwrap_aead(cctx, sctx, 0, actual_mech);
wrapunwrap_aead(cctx, sctx, USE_CONF, actual_mech);

wrapunwrap_aead(cctx, sctx, FORCE_IOV, actual_mech);
wrapunwrap_aead(cctx, sctx, USE_CONF|FORCE_IOV, actual_mech);

wrapunwrap_aead(cctx, sctx, USE_SIGN_ONLY|FORCE_IOV, actual_mech);
wrapunwrap_aead(cctx, sctx, USE_CONF|USE_SIGN_ONLY|FORCE_IOV, actual_mech);

wrapunwrap_aead(cctx, sctx, 0, actual_mech);
wrapunwrap_aead(cctx, sctx, FORCE_IOV, actual_mech);

wrapunwrap_aead(cctx, sctx, USE_CONF, actual_mech);
wrapunwrap_aead(cctx, sctx, USE_CONF|FORCE_IOV, actual_mech);

wrapunwrap_aead(cctx, sctx, USE_SIGN_ONLY, actual_mech);
wrapunwrap_aead(cctx, sctx, USE_SIGN_ONLY|FORCE_IOV, actual_mech);

wrapunwrap_aead(cctx, sctx, USE_CONF|USE_SIGN_ONLY, actual_mech);
wrapunwrap_aead(cctx, sctx, USE_CONF|USE_SIGN_ONLY|FORCE_IOV, actual_mech);
}

if (getverifymic_flag) {
getverifymic(cctx, sctx, actual_mech);
getverifymic(cctx, sctx, actual_mech);
Expand Down
2 changes: 2 additions & 0 deletions lib/gssapi/version-script.map
Expand Up @@ -88,11 +88,13 @@ HEIMDAL_GSS_2.0 {
gss_test_oid_set_member;
gss_unseal;
gss_unwrap;
gss_unwrap_aead;
gss_unwrap_iov;
gss_userok;
gss_verify;
gss_verify_mic;
gss_wrap;
gss_wrap_aead;
gss_wrap_iov;
gss_wrap_iov_length;
gss_wrap_size_limit;
Expand Down

0 comments on commit b388d9e

Please sign in to comment.