/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
/* plugins/preauth/spake/groups.h - SPAKE group interfaces */
/*
* Copyright (C) 2015 by the Massachusetts Institute of Technology.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef GROUPS_H
#define GROUPS_H
#include "k5-int.h"
#include "iana.h"
typedef struct groupstate_st groupstate;
typedef struct groupdata_st groupdata;
typedef struct groupdef_st groupdef;
struct groupdef_st {
const spake_iana *reg;
/*
* Optional: create a per-group data object to allow more efficient keygen
* and result computations. Saving a reference to gdef is okay; its
* lifetime will always be longer than the resulting object.
*/
krb5_error_code (*init)(krb5_context context, const groupdef *gdef,
groupdata **gdata_out);
/* Optional: release a group data object. */
void (*fini)(groupdata *gdata);
/*
* Mandatory: generate a random private scalar (x or y) and a public
* element (T or S), using wbytes for the w value. If use_m is true, use
* the M element (generating T); otherwise use the N element (generating
* S). wbytes and priv_out have length reg->mult_len; pub_out has length
* reg->elem_len. priv_out and pub_out are caller-allocated.
*/
krb5_error_code (*keygen)(krb5_context context, groupdata *gdata,
const uint8_t *wbytes, krb5_boolean use_m,
uint8_t *priv_out, uint8_t *pub_out);
/*
* Mandatory: compute K given a private scalar (x or y) and the other
* party's public element (S or T), using wbytes for the w value. If use_m
* is true, use the M element (computing K from y and T); otherwise use the
* N element (computing K from x and S). wbytes and ourpriv have length
* reg->mult_len; theirpub and elem_out have length reg->elem_len.
* elem_out is caller-allocated.
*/
krb5_error_code (*result)(krb5_context context, groupdata *gdata,
const uint8_t *wbytes, const uint8_t *ourpriv,
const uint8_t *theirpub, krb5_boolean use_m,
uint8_t *elem_out);
/*
* Mandatory: compute the group's specified hash function over datas (with
* ndata elements), placing the result in result_out. result_out is
* caller-allocated with length reg->hash_len.
*/
krb5_error_code (*hash)(krb5_context context, groupdata *gdata,
const krb5_data *datas, size_t ndata,
uint8_t *result_out);
};
/* Initialize an object which holds group configuration and pre-computation
* state for each group. is_kdc is true for KDCs, false for clients. */
krb5_error_code group_init_state(krb5_context context, krb5_boolean is_kdc,
groupstate **out);
/* Release resources held by gstate. */
void group_free_state(groupstate *gstate);
/* Return true if group is permitted by configuration. */
krb5_boolean group_is_permitted(groupstate *gstate, int32_t group);
/* Set *list_out and *count_out to the list of groups permitted by
* configuration. */
void group_get_permitted(groupstate *gstate, int32_t **list_out,
int32_t *count_out);
/* Return the KDC optimistic challenge group if one is configured. Valid for
* KDC groupstate objects only. */
krb5_int32 group_optimistic_challenge(groupstate *gstate);
/* Set *len_out to the multiplier length for group. */
krb5_error_code group_mult_len(int32_t group, size_t *len_out);
/*
* Generate a SPAKE private scalar (x or y) and public element (T or S), given
* an input multiplier wbytes. Use constant M if gstate is a KDC groupstate
* object, N if it is a client object. Allocate storage and place the results
* in *priv_out and *pub_out.
*/
krb5_error_code group_keygen(krb5_context context, groupstate *gstate,
int32_t group, const krb5_data *wbytes,
krb5_data *priv_out, krb5_data *pub_out);
/*
* Compute the SPAKE result K from our private scalar (x or y) and their public
* key (S or T), deriving the input scalar w from ikey. Use the other party's
* constant, N if gstate is a KDC groupstate object or M if it is a client
* object. Allocate storage and place the result in *spakeresult_out.
*/
krb5_error_code group_result(krb5_context context, groupstate *gstate,
int32_t group, const krb5_data *wbytes,
const krb5_data *ourpriv,
const krb5_data *theirpub,
krb5_data *spakeresult_out);
/* Set *result_out to the hash output length for group. */
krb5_error_code group_hash_len(int32_t group, size_t *result_out);
/*
* Compute the group's specified hash function over dlist (with ndata
* elements). result_out is caller-allocated with enough bytes for the hash
* output as given by group_hash_len().
*/
krb5_error_code group_hash(krb5_context context, groupstate *gstate,
int32_t group, const krb5_data *dlist, size_t ndata,
uint8_t *result_out);
#endif /* GROUPS_H */