1*7f2fe78bSCy Schubert /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ 2*7f2fe78bSCy Schubert /* plugins/preauth/spake/groups.h - SPAKE group interfaces */ 3*7f2fe78bSCy Schubert /* 4*7f2fe78bSCy Schubert * Copyright (C) 2015 by the Massachusetts Institute of Technology. 5*7f2fe78bSCy Schubert * All rights reserved. 6*7f2fe78bSCy Schubert * 7*7f2fe78bSCy Schubert * Redistribution and use in source and binary forms, with or without 8*7f2fe78bSCy Schubert * modification, are permitted provided that the following conditions 9*7f2fe78bSCy Schubert * are met: 10*7f2fe78bSCy Schubert * 11*7f2fe78bSCy Schubert * * Redistributions of source code must retain the above copyright 12*7f2fe78bSCy Schubert * notice, this list of conditions and the following disclaimer. 13*7f2fe78bSCy Schubert * 14*7f2fe78bSCy Schubert * * Redistributions in binary form must reproduce the above copyright 15*7f2fe78bSCy Schubert * notice, this list of conditions and the following disclaimer in 16*7f2fe78bSCy Schubert * the documentation and/or other materials provided with the 17*7f2fe78bSCy Schubert * distribution. 18*7f2fe78bSCy Schubert * 19*7f2fe78bSCy Schubert * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20*7f2fe78bSCy Schubert * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21*7f2fe78bSCy Schubert * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 22*7f2fe78bSCy Schubert * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 23*7f2fe78bSCy Schubert * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 24*7f2fe78bSCy Schubert * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 25*7f2fe78bSCy Schubert * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26*7f2fe78bSCy Schubert * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27*7f2fe78bSCy Schubert * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 28*7f2fe78bSCy Schubert * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29*7f2fe78bSCy Schubert * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 30*7f2fe78bSCy Schubert * OF THE POSSIBILITY OF SUCH DAMAGE. 31*7f2fe78bSCy Schubert */ 32*7f2fe78bSCy Schubert 33*7f2fe78bSCy Schubert #ifndef GROUPS_H 34*7f2fe78bSCy Schubert #define GROUPS_H 35*7f2fe78bSCy Schubert 36*7f2fe78bSCy Schubert #include "k5-int.h" 37*7f2fe78bSCy Schubert #include "iana.h" 38*7f2fe78bSCy Schubert 39*7f2fe78bSCy Schubert typedef struct groupstate_st groupstate; 40*7f2fe78bSCy Schubert typedef struct groupdata_st groupdata; 41*7f2fe78bSCy Schubert typedef struct groupdef_st groupdef; 42*7f2fe78bSCy Schubert 43*7f2fe78bSCy Schubert struct groupdef_st { 44*7f2fe78bSCy Schubert const spake_iana *reg; 45*7f2fe78bSCy Schubert 46*7f2fe78bSCy Schubert /* 47*7f2fe78bSCy Schubert * Optional: create a per-group data object to allow more efficient keygen 48*7f2fe78bSCy Schubert * and result computations. Saving a reference to gdef is okay; its 49*7f2fe78bSCy Schubert * lifetime will always be longer than the resulting object. 50*7f2fe78bSCy Schubert */ 51*7f2fe78bSCy Schubert krb5_error_code (*init)(krb5_context context, const groupdef *gdef, 52*7f2fe78bSCy Schubert groupdata **gdata_out); 53*7f2fe78bSCy Schubert 54*7f2fe78bSCy Schubert /* Optional: release a group data object. */ 55*7f2fe78bSCy Schubert void (*fini)(groupdata *gdata); 56*7f2fe78bSCy Schubert 57*7f2fe78bSCy Schubert /* 58*7f2fe78bSCy Schubert * Mandatory: generate a random private scalar (x or y) and a public 59*7f2fe78bSCy Schubert * element (T or S), using wbytes for the w value. If use_m is true, use 60*7f2fe78bSCy Schubert * the M element (generating T); otherwise use the N element (generating 61*7f2fe78bSCy Schubert * S). wbytes and priv_out have length reg->mult_len; pub_out has length 62*7f2fe78bSCy Schubert * reg->elem_len. priv_out and pub_out are caller-allocated. 63*7f2fe78bSCy Schubert */ 64*7f2fe78bSCy Schubert krb5_error_code (*keygen)(krb5_context context, groupdata *gdata, 65*7f2fe78bSCy Schubert const uint8_t *wbytes, krb5_boolean use_m, 66*7f2fe78bSCy Schubert uint8_t *priv_out, uint8_t *pub_out); 67*7f2fe78bSCy Schubert 68*7f2fe78bSCy Schubert /* 69*7f2fe78bSCy Schubert * Mandatory: compute K given a private scalar (x or y) and the other 70*7f2fe78bSCy Schubert * party's public element (S or T), using wbytes for the w value. If use_m 71*7f2fe78bSCy Schubert * is true, use the M element (computing K from y and T); otherwise use the 72*7f2fe78bSCy Schubert * N element (computing K from x and S). wbytes and ourpriv have length 73*7f2fe78bSCy Schubert * reg->mult_len; theirpub and elem_out have length reg->elem_len. 74*7f2fe78bSCy Schubert * elem_out is caller-allocated. 75*7f2fe78bSCy Schubert */ 76*7f2fe78bSCy Schubert krb5_error_code (*result)(krb5_context context, groupdata *gdata, 77*7f2fe78bSCy Schubert const uint8_t *wbytes, const uint8_t *ourpriv, 78*7f2fe78bSCy Schubert const uint8_t *theirpub, krb5_boolean use_m, 79*7f2fe78bSCy Schubert uint8_t *elem_out); 80*7f2fe78bSCy Schubert 81*7f2fe78bSCy Schubert /* 82*7f2fe78bSCy Schubert * Mandatory: compute the group's specified hash function over datas (with 83*7f2fe78bSCy Schubert * ndata elements), placing the result in result_out. result_out is 84*7f2fe78bSCy Schubert * caller-allocated with length reg->hash_len. 85*7f2fe78bSCy Schubert */ 86*7f2fe78bSCy Schubert krb5_error_code (*hash)(krb5_context context, groupdata *gdata, 87*7f2fe78bSCy Schubert const krb5_data *datas, size_t ndata, 88*7f2fe78bSCy Schubert uint8_t *result_out); 89*7f2fe78bSCy Schubert }; 90*7f2fe78bSCy Schubert 91*7f2fe78bSCy Schubert /* Initialize an object which holds group configuration and pre-computation 92*7f2fe78bSCy Schubert * state for each group. is_kdc is true for KDCs, false for clients. */ 93*7f2fe78bSCy Schubert krb5_error_code group_init_state(krb5_context context, krb5_boolean is_kdc, 94*7f2fe78bSCy Schubert groupstate **out); 95*7f2fe78bSCy Schubert 96*7f2fe78bSCy Schubert /* Release resources held by gstate. */ 97*7f2fe78bSCy Schubert void group_free_state(groupstate *gstate); 98*7f2fe78bSCy Schubert 99*7f2fe78bSCy Schubert /* Return true if group is permitted by configuration. */ 100*7f2fe78bSCy Schubert krb5_boolean group_is_permitted(groupstate *gstate, int32_t group); 101*7f2fe78bSCy Schubert 102*7f2fe78bSCy Schubert /* Set *list_out and *count_out to the list of groups permitted by 103*7f2fe78bSCy Schubert * configuration. */ 104*7f2fe78bSCy Schubert void group_get_permitted(groupstate *gstate, int32_t **list_out, 105*7f2fe78bSCy Schubert int32_t *count_out); 106*7f2fe78bSCy Schubert 107*7f2fe78bSCy Schubert /* Return the KDC optimistic challenge group if one is configured. Valid for 108*7f2fe78bSCy Schubert * KDC groupstate objects only. */ 109*7f2fe78bSCy Schubert krb5_int32 group_optimistic_challenge(groupstate *gstate); 110*7f2fe78bSCy Schubert 111*7f2fe78bSCy Schubert /* Set *len_out to the multiplier length for group. */ 112*7f2fe78bSCy Schubert krb5_error_code group_mult_len(int32_t group, size_t *len_out); 113*7f2fe78bSCy Schubert 114*7f2fe78bSCy Schubert /* 115*7f2fe78bSCy Schubert * Generate a SPAKE private scalar (x or y) and public element (T or S), given 116*7f2fe78bSCy Schubert * an input multiplier wbytes. Use constant M if gstate is a KDC groupstate 117*7f2fe78bSCy Schubert * object, N if it is a client object. Allocate storage and place the results 118*7f2fe78bSCy Schubert * in *priv_out and *pub_out. 119*7f2fe78bSCy Schubert */ 120*7f2fe78bSCy Schubert krb5_error_code group_keygen(krb5_context context, groupstate *gstate, 121*7f2fe78bSCy Schubert int32_t group, const krb5_data *wbytes, 122*7f2fe78bSCy Schubert krb5_data *priv_out, krb5_data *pub_out); 123*7f2fe78bSCy Schubert 124*7f2fe78bSCy Schubert /* 125*7f2fe78bSCy Schubert * Compute the SPAKE result K from our private scalar (x or y) and their public 126*7f2fe78bSCy Schubert * key (S or T), deriving the input scalar w from ikey. Use the other party's 127*7f2fe78bSCy Schubert * constant, N if gstate is a KDC groupstate object or M if it is a client 128*7f2fe78bSCy Schubert * object. Allocate storage and place the result in *spakeresult_out. 129*7f2fe78bSCy Schubert */ 130*7f2fe78bSCy Schubert krb5_error_code group_result(krb5_context context, groupstate *gstate, 131*7f2fe78bSCy Schubert int32_t group, const krb5_data *wbytes, 132*7f2fe78bSCy Schubert const krb5_data *ourpriv, 133*7f2fe78bSCy Schubert const krb5_data *theirpub, 134*7f2fe78bSCy Schubert krb5_data *spakeresult_out); 135*7f2fe78bSCy Schubert 136*7f2fe78bSCy Schubert /* Set *result_out to the hash output length for group. */ 137*7f2fe78bSCy Schubert krb5_error_code group_hash_len(int32_t group, size_t *result_out); 138*7f2fe78bSCy Schubert 139*7f2fe78bSCy Schubert /* 140*7f2fe78bSCy Schubert * Compute the group's specified hash function over dlist (with ndata 141*7f2fe78bSCy Schubert * elements). result_out is caller-allocated with enough bytes for the hash 142*7f2fe78bSCy Schubert * output as given by group_hash_len(). 143*7f2fe78bSCy Schubert */ 144*7f2fe78bSCy Schubert krb5_error_code group_hash(krb5_context context, groupstate *gstate, 145*7f2fe78bSCy Schubert int32_t group, const krb5_data *dlist, size_t ndata, 146*7f2fe78bSCy Schubert uint8_t *result_out); 147*7f2fe78bSCy Schubert 148*7f2fe78bSCy Schubert #endif /* GROUPS_H */ 149