1c19800e8SDoug Rabson /* 2*ae771770SStanislav Sedov * Copyright (c) 2007 Kungliga Tekniska Högskolan 3c19800e8SDoug Rabson * (Royal Institute of Technology, Stockholm, Sweden). 4c19800e8SDoug Rabson * All rights reserved. 5c19800e8SDoug Rabson * 6c19800e8SDoug Rabson * Redistribution and use in source and binary forms, with or without 7c19800e8SDoug Rabson * modification, are permitted provided that the following conditions 8c19800e8SDoug Rabson * are met: 9c19800e8SDoug Rabson * 10c19800e8SDoug Rabson * 1. Redistributions of source code must retain the above copyright 11c19800e8SDoug Rabson * notice, this list of conditions and the following disclaimer. 12c19800e8SDoug Rabson * 13c19800e8SDoug Rabson * 2. Redistributions in binary form must reproduce the above copyright 14c19800e8SDoug Rabson * notice, this list of conditions and the following disclaimer in the 15c19800e8SDoug Rabson * documentation and/or other materials provided with the distribution. 16c19800e8SDoug Rabson * 17c19800e8SDoug Rabson * 3. Neither the name of the Institute nor the names of its contributors 18c19800e8SDoug Rabson * may be used to endorse or promote products derived from this software 19c19800e8SDoug Rabson * without specific prior written permission. 20c19800e8SDoug Rabson * 21c19800e8SDoug Rabson * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 22c19800e8SDoug Rabson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23c19800e8SDoug Rabson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24c19800e8SDoug Rabson * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 25c19800e8SDoug Rabson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26c19800e8SDoug Rabson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27c19800e8SDoug Rabson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28c19800e8SDoug Rabson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29c19800e8SDoug Rabson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30c19800e8SDoug Rabson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31c19800e8SDoug Rabson * SUCH DAMAGE. 32c19800e8SDoug Rabson */ 33c19800e8SDoug Rabson 34*ae771770SStanislav Sedov #include "gsskrb5_locl.h" 35c19800e8SDoug Rabson 36*ae771770SStanislav Sedov OM_uint32 GSSAPI_CALLCONV 37c19800e8SDoug Rabson _gsskrb5_pseudo_random(OM_uint32 *minor_status, 38c19800e8SDoug Rabson gss_ctx_id_t context_handle, 39c19800e8SDoug Rabson int prf_key, 40c19800e8SDoug Rabson const gss_buffer_t prf_in, 41c19800e8SDoug Rabson ssize_t desired_output_len, 42c19800e8SDoug Rabson gss_buffer_t prf_out) 43c19800e8SDoug Rabson { 44c19800e8SDoug Rabson gsskrb5_ctx ctx = (gsskrb5_ctx)context_handle; 45c19800e8SDoug Rabson krb5_context context; 46c19800e8SDoug Rabson krb5_error_code ret; 47c19800e8SDoug Rabson krb5_crypto crypto; 48c19800e8SDoug Rabson krb5_data input, output; 49c19800e8SDoug Rabson uint32_t num; 50*ae771770SStanislav Sedov OM_uint32 junk; 51c19800e8SDoug Rabson unsigned char *p; 52c19800e8SDoug Rabson krb5_keyblock *key = NULL; 53*ae771770SStanislav Sedov size_t dol; 54c19800e8SDoug Rabson 55c19800e8SDoug Rabson if (ctx == NULL) { 56c19800e8SDoug Rabson *minor_status = 0; 57c19800e8SDoug Rabson return GSS_S_NO_CONTEXT; 58c19800e8SDoug Rabson } 59c19800e8SDoug Rabson 60*ae771770SStanislav Sedov if (desired_output_len <= 0 || prf_in->length + 4 < prf_in->length) { 61c19800e8SDoug Rabson *minor_status = 0; 62c19800e8SDoug Rabson return GSS_S_FAILURE; 63c19800e8SDoug Rabson } 64*ae771770SStanislav Sedov dol = desired_output_len; 65c19800e8SDoug Rabson 66c19800e8SDoug Rabson GSSAPI_KRB5_INIT (&context); 67c19800e8SDoug Rabson 68c19800e8SDoug Rabson switch(prf_key) { 69c19800e8SDoug Rabson case GSS_C_PRF_KEY_FULL: 70c19800e8SDoug Rabson _gsskrb5i_get_acceptor_subkey(ctx, context, &key); 71c19800e8SDoug Rabson break; 72c19800e8SDoug Rabson case GSS_C_PRF_KEY_PARTIAL: 73c19800e8SDoug Rabson _gsskrb5i_get_initiator_subkey(ctx, context, &key); 74c19800e8SDoug Rabson break; 75c19800e8SDoug Rabson default: 76*ae771770SStanislav Sedov _gsskrb5_set_status(EINVAL, "unknown kerberos prf_key"); 77*ae771770SStanislav Sedov *minor_status = EINVAL; 78c19800e8SDoug Rabson return GSS_S_FAILURE; 79c19800e8SDoug Rabson } 80c19800e8SDoug Rabson 81c19800e8SDoug Rabson if (key == NULL) { 82*ae771770SStanislav Sedov _gsskrb5_set_status(EINVAL, "no prf_key found"); 83*ae771770SStanislav Sedov *minor_status = EINVAL; 84c19800e8SDoug Rabson return GSS_S_FAILURE; 85c19800e8SDoug Rabson } 86c19800e8SDoug Rabson 87c19800e8SDoug Rabson ret = krb5_crypto_init(context, key, 0, &crypto); 88c19800e8SDoug Rabson krb5_free_keyblock (context, key); 89c19800e8SDoug Rabson if (ret) { 90c19800e8SDoug Rabson *minor_status = ret; 91c19800e8SDoug Rabson return GSS_S_FAILURE; 92c19800e8SDoug Rabson } 93c19800e8SDoug Rabson 94*ae771770SStanislav Sedov prf_out->value = malloc(dol); 95c19800e8SDoug Rabson if (prf_out->value == NULL) { 96*ae771770SStanislav Sedov _gsskrb5_set_status(GSS_KRB5_S_KG_INPUT_TOO_LONG, "Out of memory"); 97c19800e8SDoug Rabson *minor_status = GSS_KRB5_S_KG_INPUT_TOO_LONG; 98c19800e8SDoug Rabson krb5_crypto_destroy(context, crypto); 99c19800e8SDoug Rabson return GSS_S_FAILURE; 100c19800e8SDoug Rabson } 101*ae771770SStanislav Sedov prf_out->length = dol; 102c19800e8SDoug Rabson 103c19800e8SDoug Rabson HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); 104c19800e8SDoug Rabson 105c19800e8SDoug Rabson input.length = prf_in->length + 4; 106c19800e8SDoug Rabson input.data = malloc(prf_in->length + 4); 107c19800e8SDoug Rabson if (input.data == NULL) { 108*ae771770SStanislav Sedov _gsskrb5_set_status(GSS_KRB5_S_KG_INPUT_TOO_LONG, "Out of memory"); 109c19800e8SDoug Rabson *minor_status = GSS_KRB5_S_KG_INPUT_TOO_LONG; 110c19800e8SDoug Rabson gss_release_buffer(&junk, prf_out); 111c19800e8SDoug Rabson krb5_crypto_destroy(context, crypto); 112c19800e8SDoug Rabson HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); 113c19800e8SDoug Rabson return GSS_S_FAILURE; 114c19800e8SDoug Rabson } 115*ae771770SStanislav Sedov memcpy(((uint8_t *)input.data) + 4, prf_in->value, prf_in->length); 116c19800e8SDoug Rabson 117c19800e8SDoug Rabson num = 0; 118c19800e8SDoug Rabson p = prf_out->value; 119*ae771770SStanislav Sedov while(dol > 0) { 120*ae771770SStanislav Sedov size_t tsize; 121*ae771770SStanislav Sedov 122c19800e8SDoug Rabson _gsskrb5_encode_om_uint32(num, input.data); 123*ae771770SStanislav Sedov 124c19800e8SDoug Rabson ret = krb5_crypto_prf(context, crypto, &input, &output); 125c19800e8SDoug Rabson if (ret) { 126c19800e8SDoug Rabson *minor_status = ret; 127c19800e8SDoug Rabson free(input.data); 128c19800e8SDoug Rabson gss_release_buffer(&junk, prf_out); 129c19800e8SDoug Rabson krb5_crypto_destroy(context, crypto); 130c19800e8SDoug Rabson HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); 131c19800e8SDoug Rabson return GSS_S_FAILURE; 132c19800e8SDoug Rabson } 133*ae771770SStanislav Sedov 134*ae771770SStanislav Sedov tsize = min(dol, output.length); 135*ae771770SStanislav Sedov memcpy(p, output.data, tsize); 136c19800e8SDoug Rabson p += output.length; 137*ae771770SStanislav Sedov dol -= tsize; 138c19800e8SDoug Rabson krb5_data_free(&output); 139c19800e8SDoug Rabson num++; 140c19800e8SDoug Rabson } 141*ae771770SStanislav Sedov free(input.data); 142c19800e8SDoug Rabson 143c19800e8SDoug Rabson krb5_crypto_destroy(context, crypto); 144c19800e8SDoug Rabson 145c19800e8SDoug Rabson HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); 146c19800e8SDoug Rabson 147c19800e8SDoug Rabson return GSS_S_COMPLETE; 148c19800e8SDoug Rabson } 149