gss: update SAnon for draft-howard-gss-sanon-13

draft-howard-gss-sanon-13 will move extended (RFC4757) flags from the NegoEx
metadata to an optional component of the initial context token
This commit is contained in:
Luke Howard
2020-04-27 14:52:10 +10:00
parent 55a553c56d
commit c785af8b62
6 changed files with 70 additions and 100 deletions

View File

@@ -48,8 +48,10 @@ _gss_sanon_accept_sec_context(OM_uint32 *minor,
OM_uint32 major, tmp;
sanon_ctx sc = (sanon_ctx)*context_handle;
gss_buffer_desc mech_input_token = GSS_C_EMPTY_BUFFER;
gss_buffer_desc initiator_pk = GSS_C_EMPTY_BUFFER;
gss_buffer_desc hok_mic = GSS_C_EMPTY_BUFFER;
gss_buffer_desc session_key = GSS_C_EMPTY_BUFFER;
OM_uint32 req_flags = 0;
if (output_token == GSS_C_NO_BUFFER) {
*minor = EINVAL;
@@ -62,7 +64,7 @@ _gss_sanon_accept_sec_context(OM_uint32 *minor,
if (input_token == GSS_C_NO_BUFFER) {
major = GSS_S_DEFECTIVE_TOKEN;
goto out;
} else if (sc != NULL && sc->rfc4121 != GSS_C_NO_CONTEXT) {
} else if (sc != NULL) {
major = GSS_S_BAD_STATUS;
goto out;
}
@@ -73,30 +75,50 @@ _gss_sanon_accept_sec_context(OM_uint32 *minor,
if (major != GSS_S_COMPLETE)
goto out;
sc = calloc(1, sizeof(*sc));
if (sc == NULL) {
sc = calloc(1, sizeof(*sc));
if (sc == NULL) {
*minor = ENOMEM;
major = GSS_S_FAILURE;
goto out;
}
*minor = ENOMEM;
major = GSS_S_FAILURE;
goto out;
}
/* initiator token can include optional 64-bit flags */
if (mech_input_token.length != crypto_scalarmult_curve25519_BYTES &&
mech_input_token.length != crypto_scalarmult_curve25519_BYTES + 8) {
*minor = 0;
major = GSS_S_DEFECTIVE_TOKEN;
goto out;
}
initiator_pk = mech_input_token;
initiator_pk.length = crypto_scalarmult_curve25519_BYTES;
/* compute public and secret keys */
major = _gss_sanon_curve25519_base(minor, sc);
if (major != GSS_S_COMPLETE)
goto out;
if (mech_input_token.length > crypto_scalarmult_curve25519_BYTES) {
/* extra flags */
uint8_t *p = (uint8_t *)mech_input_token.value + crypto_scalarmult_curve25519_BYTES;
uint32_t dummy;
_gss_mg_decode_be_uint32(p, &dummy); /* upper 32 bits presently unused */
_gss_mg_decode_be_uint32(&p[4], &req_flags);
}
req_flags &= SANON_PROTOCOL_FLAG_MASK; /* do not let initiator set any other flags */
/* compute shared secret */
major = _gss_sanon_curve25519(minor, sc, &mech_input_token,
major = _gss_sanon_curve25519(minor, sc, &initiator_pk, req_flags,
input_chan_bindings, &session_key);
if (major != GSS_S_COMPLETE)
goto out;
sc->flags |= GSS_C_REPLAY_FLAG | GSS_C_SEQUENCE_FLAG | GSS_C_CONF_FLAG |
req_flags |= GSS_C_REPLAY_FLAG | GSS_C_SEQUENCE_FLAG | GSS_C_CONF_FLAG |
GSS_C_INTEG_FLAG | GSS_C_ANON_FLAG | GSS_C_TRANS_FLAG;
major = _gss_sanon_import_rfc4121_context(minor, sc, &session_key);
major = _gss_sanon_import_rfc4121_context(minor, sc, req_flags, &session_key);
if (major != GSS_S_COMPLETE)
goto out;
@@ -124,7 +146,7 @@ _gss_sanon_accept_sec_context(OM_uint32 *minor,
if (src_name)
*src_name = _gss_sanon_anonymous_identity;
if (ret_flags)
*ret_flags = sc->flags;
*ret_flags = req_flags;
if (time_rec)
*time_rec = GSS_C_INDEFINITE;

View File

@@ -239,6 +239,7 @@ OM_uint32
_gss_sanon_curve25519(OM_uint32 *minor,
sanon_ctx sc,
gss_buffer_t pk,
OM_uint32 gss_flags,
const gss_channel_bindings_t input_chan_bindings,
gss_buffer_t session_key)
{
@@ -268,7 +269,7 @@ _gss_sanon_curve25519(OM_uint32 *minor,
kdf_label.length = sizeof("sanon-x25519") - 1;
ret = krb5_data_alloc(&kdf_context,
2 * crypto_scalarmult_curve25519_BYTES +
2 * crypto_scalarmult_curve25519_BYTES + 8 +
(input_chan_bindings ? input_chan_bindings->application_data.length : 0));
if (ret != 0) {
krb5_free_context(context);
@@ -285,11 +286,15 @@ _gss_sanon_curve25519(OM_uint32 *minor,
memcpy(p, pk->value, pk->length);
memcpy(&p[sizeof(sc->pk)], sc->pk, sizeof(sc->pk));
}
p += 2 * crypto_scalarmult_curve25519_BYTES;
_gss_mg_encode_be_uint32(0, p); /* upper 32 bits presently unused */
p += 4;
_gss_mg_encode_be_uint32(gss_flags, p);
p += 4;
if (input_chan_bindings != GSS_C_NO_CHANNEL_BINDINGS &&
input_chan_bindings->application_data.value != NULL) {
memcpy(&p[2 * crypto_scalarmult_curve25519_BYTES],
input_chan_bindings->application_data.value,
memcpy(p, input_chan_bindings->application_data.value,
input_chan_bindings->application_data.length);
}
@@ -318,9 +323,10 @@ _gss_sanon_curve25519(OM_uint32 *minor,
OM_uint32
_gss_sanon_import_rfc4121_context(OM_uint32 *minor,
sanon_ctx sc,
OM_uint32 gss_flags,
gss_const_buffer_t session_key)
{
return _gss_mg_import_rfc4121_context(minor, sc->is_initiator, sc->flags,
return _gss_mg_import_rfc4121_context(minor, sc->is_initiator, gss_flags,
KRB5_ENCTYPE_AES128_CTS_HMAC_SHA256_128,
session_key, &sc->rfc4121);
}

View File

@@ -99,12 +99,13 @@ _gss_sanon_init_sec_context(OM_uint32 *minor,
}
flags |= GSS_C_REPLAY_FLAG | GSS_C_SEQUENCE_FLAG | GSS_C_CONF_FLAG |
GSS_C_INTEG_FLAG | GSS_C_DCE_STYLE | GSS_C_IDENTIFY_FLAG |
GSS_C_EXTENDED_ERROR_FLAG; /* supported flags */
GSS_C_INTEG_FLAG | SANON_PROTOCOL_FLAG_MASK; /* supported flags */
flags &= req_flags;
flags |= GSS_C_ANON_FLAG; /* always set this flag */
if (sc == NULL) {
uint8_t pk_and_flags[crypto_scalarmult_curve25519_BYTES + 8];
if (input_token != GSS_C_NO_BUFFER && input_token->length != 0) {
major = GSS_S_DEFECTIVE_TOKEN;
goto out;
@@ -118,15 +119,23 @@ _gss_sanon_init_sec_context(OM_uint32 *minor,
}
sc->is_initiator = 1;
sc->flags = req_flags;
/* compute public and secret keys */
major = _gss_sanon_curve25519_base(minor, sc);
if (major != GSS_S_COMPLETE)
goto out;
mech_token.length = sizeof(sc->pk);
mech_token.value = sc->pk;
if (req_flags & SANON_PROTOCOL_FLAG_MASK) {
memcpy(pk_and_flags, sc->pk, sizeof(sc->pk));
_gss_mg_encode_be_uint32(0, &pk_and_flags[sizeof(sc->pk)]);
_gss_mg_encode_be_uint32(req_flags & SANON_PROTOCOL_FLAG_MASK,
&pk_and_flags[sizeof(sc->pk) + 4]);
mech_token.length = sizeof(pk_and_flags);
mech_token.value = pk_and_flags;
} else {
mech_token.length = sizeof(sc->pk);
mech_token.value = sc->pk;
}
/* send public key to acceptor */
major = gss_encapsulate_token(&mech_token,
@@ -154,14 +163,14 @@ _gss_sanon_init_sec_context(OM_uint32 *minor,
pk.value = input_token->value;
/* compute shared secret */
major = _gss_sanon_curve25519(minor, sc, &pk, input_chan_bindings, &session_key);
major = _gss_sanon_curve25519(minor, sc, &pk, flags & SANON_PROTOCOL_FLAG_MASK,
input_chan_bindings, &session_key);
if (major != GSS_S_COMPLETE)
goto out;
flags |= GSS_C_TRANS_FLAG;
sc->flags |= GSS_C_TRANS_FLAG;
major = _gss_sanon_import_rfc4121_context(minor, sc, &session_key);
major = _gss_sanon_import_rfc4121_context(minor, sc, flags, &session_key);
if (major != GSS_S_COMPLETE)
goto out;

View File

@@ -64,7 +64,8 @@ _gss_sanon_inquire_context(OM_uint32 *minor,
if (open_context)
*open_context = 0;
if (ctx_flags)
*ctx_flags = sc->flags;
*ctx_flags = GSS_C_REPLAY_FLAG | GSS_C_SEQUENCE_FLAG |
GSS_C_CONF_FLAG | GSS_C_INTEG_FLAG | GSS_C_ANON_FLAG;
} else {
major = gss_inquire_context(minor, sc->rfc4121, NULL, NULL, NULL,
NULL, ctx_flags, locally_initiated,

View File

@@ -97,19 +97,6 @@ _gss_sanon_inquire_negoex_key(OM_uint32 *minor,
return major;
}
static OM_uint32
make_flags_meta_data(OM_uint32 *minor,
OM_uint32 flags,
gss_buffer_t meta_data)
{
uint8_t data[4];
gss_buffer_desc buffer = { sizeof(data), data };
_gss_mg_encode_le_uint32(flags, data);
return _gss_copy_buffer(minor, &buffer, meta_data);
}
OM_uint32 GSSAPI_CALLCONV
_gssspi_sanon_query_meta_data(OM_uint32 *minor,
gss_const_OID mech_oid,
@@ -119,45 +106,13 @@ _gssspi_sanon_query_meta_data(OM_uint32 *minor,
OM_uint32 req_flags,
gss_buffer_t meta_data)
{
OM_uint32 major;
int local = (targ_name != GSS_C_NO_NAME);
int is_initiator = (targ_name != GSS_C_NO_NAME);
*minor = 0;
if (local) {
if (!_gss_sanon_available_p(cred_handle, targ_name, req_flags))
return GSS_S_UNAVAILABLE;
/*
* Obscure Windows interoperability hack: use metadata to convey
* RFC4757 extended flags from initiator to acceptor.
*/
req_flags &= (GSS_C_DCE_STYLE | GSS_C_IDENTIFY_FLAG | GSS_C_EXTENDED_ERROR_FLAG);
if (req_flags) {
major = make_flags_meta_data(minor, req_flags, meta_data);
if (major != GSS_S_COMPLETE)
return major;
}
}
return GSS_S_COMPLETE;
}
static OM_uint32
parse_flags_meta_data(OM_uint32 *minor,
gss_const_buffer_t meta_data,
OM_uint32 *flags)
{
*minor = 0;
*flags = 0;
if (meta_data->length == 0)
return GSS_S_COMPLETE;
if (meta_data->length < 4)
return GSS_S_DEFECTIVE_TOKEN;
_gss_mg_decode_le_uint32(meta_data->value, flags);
if (is_initiator &&
!_gss_sanon_available_p(cred_handle, targ_name, req_flags))
return GSS_S_UNAVAILABLE;
return GSS_S_COMPLETE;
}
@@ -171,30 +126,6 @@ _gssspi_sanon_exchange_meta_data(OM_uint32 *minor,
OM_uint32 req_flags,
gss_const_buffer_t meta_data)
{
sanon_ctx sc = (sanon_ctx)*context_handle;
int local = (targ_name != GSS_C_NO_NAME);
OM_uint32 major, init_flags;
*minor = 0;
if (local)
return GSS_S_COMPLETE;
if (sc == NULL) {
sc = calloc(1, sizeof(*sc));
if (sc == NULL) {
*minor = ENOMEM;
return GSS_S_FAILURE;
}
*context_handle = (gss_ctx_id_t)sc;
}
major = parse_flags_meta_data(minor, meta_data, &init_flags);
if (major != GSS_S_COMPLETE)
return major;
init_flags &= ~(GSS_C_DCE_STYLE | GSS_C_IDENTIFY_FLAG | GSS_C_EXTENDED_ERROR_FLAG);
sc->flags |= init_flags | req_flags;
return GSS_S_COMPLETE;
}

View File

@@ -48,11 +48,9 @@ typedef struct sanon_ctx_desc {
uint8_t sk[crypto_scalarmult_curve25519_BYTES];
/* X25519 ECDH public key */
uint8_t pk[crypto_scalarmult_curve25519_BYTES];
/* GSS_C_*_FLAG */
uint32_t flags;
/* krb5 context for message protection/PRF */
gss_ctx_id_t rfc4121;
int is_initiator;
int is_initiator : 1;
} *sanon_ctx;
extern gss_name_t _gss_sanon_anonymous_identity;
@@ -80,4 +78,7 @@ buffer_equal_p(gss_const_buffer_t b1, gss_const_buffer_t b2)
memcmp(b1->value, b2->value, b2->length) == 0;
}
/* flags that are valid to be sent from a SAnon initiator in the flags field */
#define SANON_PROTOCOL_FLAG_MASK ( GSS_C_DCE_STYLE | GSS_C_IDENTIFY_FLAG | GSS_C_EXTENDED_ERROR_FLAG )
#endif /* SANON_LOCL_H */