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