17c478bd9Sstevel@tonic-gate /*
2*159d09a2SMark Phalan  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
37c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
47c478bd9Sstevel@tonic-gate  */
57c478bd9Sstevel@tonic-gate 
67c478bd9Sstevel@tonic-gate 
77c478bd9Sstevel@tonic-gate /*
8*159d09a2SMark Phalan   * Copyright2001 by the Massachusetts Institute of Technology.
97c478bd9Sstevel@tonic-gate  * Copyright 1993 by OpenVision Technologies, Inc.
107c478bd9Sstevel@tonic-gate  *
117c478bd9Sstevel@tonic-gate  * Permission to use, copy, modify, distribute, and sell this software
127c478bd9Sstevel@tonic-gate  * and its documentation for any purpose is hereby granted without fee,
137c478bd9Sstevel@tonic-gate  * provided that the above copyright notice appears in all copies and
147c478bd9Sstevel@tonic-gate  * that both that copyright notice and this permission notice appear in
157c478bd9Sstevel@tonic-gate  * supporting documentation, and that the name of OpenVision not be used
167c478bd9Sstevel@tonic-gate  * in advertising or publicity pertaining to distribution of the software
177c478bd9Sstevel@tonic-gate  * without specific, written prior permission. OpenVision makes no
187c478bd9Sstevel@tonic-gate  * representations about the suitability of this software for any
197c478bd9Sstevel@tonic-gate  * purpose.  It is provided "as is" without express or implied warranty.
207c478bd9Sstevel@tonic-gate  *
217c478bd9Sstevel@tonic-gate  * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
227c478bd9Sstevel@tonic-gate  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
237c478bd9Sstevel@tonic-gate  * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
247c478bd9Sstevel@tonic-gate  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
257c478bd9Sstevel@tonic-gate  * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
267c478bd9Sstevel@tonic-gate  * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
277c478bd9Sstevel@tonic-gate  * PERFORMANCE OF THIS SOFTWARE.
287c478bd9Sstevel@tonic-gate  */
297c478bd9Sstevel@tonic-gate 
307c478bd9Sstevel@tonic-gate /*
317c478bd9Sstevel@tonic-gate  * Copyright (C) 1998 by the FundsXpress, INC.
327c478bd9Sstevel@tonic-gate  *
337c478bd9Sstevel@tonic-gate  * All rights reserved.
347c478bd9Sstevel@tonic-gate  *
357c478bd9Sstevel@tonic-gate  * Export of this software from the United States of America may require
367c478bd9Sstevel@tonic-gate  * a specific license from the United States Government.  It is the
377c478bd9Sstevel@tonic-gate  * responsibility of any person or organization contemplating export to
387c478bd9Sstevel@tonic-gate  * obtain such a license before exporting.
397c478bd9Sstevel@tonic-gate  *
407c478bd9Sstevel@tonic-gate  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
417c478bd9Sstevel@tonic-gate  * distribute this software and its documentation for any purpose and
427c478bd9Sstevel@tonic-gate  * without fee is hereby granted, provided that the above copyright
437c478bd9Sstevel@tonic-gate  * notice appear in all copies and that both that copyright notice and
447c478bd9Sstevel@tonic-gate  * this permission notice appear in supporting documentation, and that
457c478bd9Sstevel@tonic-gate  * the name of FundsXpress. not be used in advertising or publicity pertaining
467c478bd9Sstevel@tonic-gate  * to distribution of the software without specific, written prior
477c478bd9Sstevel@tonic-gate  * permission.  FundsXpress makes no representations about the suitability of
487c478bd9Sstevel@tonic-gate  * this software for any purpose.  It is provided "as is" without express
497c478bd9Sstevel@tonic-gate  * or implied warranty.
507c478bd9Sstevel@tonic-gate  *
517c478bd9Sstevel@tonic-gate  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
527c478bd9Sstevel@tonic-gate  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
537c478bd9Sstevel@tonic-gate  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
547c478bd9Sstevel@tonic-gate  */
557c478bd9Sstevel@tonic-gate 
567c478bd9Sstevel@tonic-gate /* Solaris Kerberos:  order is important here.  include gssapiP_krb5.h
577c478bd9Sstevel@tonic-gate  * before all others, otherwise we get a LINT error from MALLOC macro
587c478bd9Sstevel@tonic-gate  * being redefined in mechglueP.h */
597c478bd9Sstevel@tonic-gate #include <gssapiP_krb5.h>
607c478bd9Sstevel@tonic-gate #include <k5-int.h>
617c478bd9Sstevel@tonic-gate 
627c478bd9Sstevel@tonic-gate /* Solaris Kerberos defines memory management macros in <krb5.h> */
637c478bd9Sstevel@tonic-gate /* #include <memory.h> */
647c478bd9Sstevel@tonic-gate 
657c478bd9Sstevel@tonic-gate /*
667c478bd9Sstevel@tonic-gate  * $Id: util_crypt.c,v 1.11.6.3 2000/06/03 06:09:45 tlyu Exp $
677c478bd9Sstevel@tonic-gate  */
687c478bd9Sstevel@tonic-gate 
697c478bd9Sstevel@tonic-gate int
707c478bd9Sstevel@tonic-gate kg_confounder_size(context, key)
717c478bd9Sstevel@tonic-gate      krb5_context context;
727c478bd9Sstevel@tonic-gate      krb5_keyblock *key;
737c478bd9Sstevel@tonic-gate {
74*159d09a2SMark Phalan    krb5_error_code code;
757c478bd9Sstevel@tonic-gate    size_t blocksize;
767c478bd9Sstevel@tonic-gate    /* We special case rc4*/
777c478bd9Sstevel@tonic-gate    if (key->enctype == ENCTYPE_ARCFOUR_HMAC)
78*159d09a2SMark Phalan      return 8;
79*159d09a2SMark Phalan    code = krb5_c_block_size(context, key->enctype, &blocksize);
80*159d09a2SMark Phalan    if (code)
817c478bd9Sstevel@tonic-gate       return(-1); /* XXX */
827c478bd9Sstevel@tonic-gate 
837c478bd9Sstevel@tonic-gate    return(blocksize);
847c478bd9Sstevel@tonic-gate }
857c478bd9Sstevel@tonic-gate 
867c478bd9Sstevel@tonic-gate krb5_error_code
877c478bd9Sstevel@tonic-gate kg_make_confounder(context, key, buf)
887c478bd9Sstevel@tonic-gate      krb5_context context;
897c478bd9Sstevel@tonic-gate      krb5_keyblock *key;
907c478bd9Sstevel@tonic-gate      unsigned char *buf;
917c478bd9Sstevel@tonic-gate {
927c478bd9Sstevel@tonic-gate    krb5_error_code code;
937c478bd9Sstevel@tonic-gate    size_t blocksize;
94*159d09a2SMark Phalan    krb5_data lrandom;
957c478bd9Sstevel@tonic-gate 
96*159d09a2SMark Phalan    code = krb5_c_block_size(context, key->enctype, &blocksize);
97*159d09a2SMark Phalan    if (code)
987c478bd9Sstevel@tonic-gate        return(code);
997c478bd9Sstevel@tonic-gate 
100*159d09a2SMark Phalan    lrandom.length = blocksize;
101*159d09a2SMark Phalan    lrandom.data = (char *) buf;
1027c478bd9Sstevel@tonic-gate 
103*159d09a2SMark Phalan    return(krb5_c_random_make_octets(context, &lrandom));
1047c478bd9Sstevel@tonic-gate }
1057c478bd9Sstevel@tonic-gate 
1067c478bd9Sstevel@tonic-gate int
1077c478bd9Sstevel@tonic-gate kg_encrypt_size(context, key, n)
1087c478bd9Sstevel@tonic-gate      krb5_context context;
1097c478bd9Sstevel@tonic-gate      krb5_keyblock *key;
1107c478bd9Sstevel@tonic-gate      int n;
1117c478bd9Sstevel@tonic-gate {
1127c478bd9Sstevel@tonic-gate    size_t enclen;
1137c478bd9Sstevel@tonic-gate 
1147c478bd9Sstevel@tonic-gate    if (krb5_c_encrypt_length(context, key->enctype, n, &enclen) != 0)
1157c478bd9Sstevel@tonic-gate       return(-1); /* XXX */
1167c478bd9Sstevel@tonic-gate 
1177c478bd9Sstevel@tonic-gate    return(enclen);
1187c478bd9Sstevel@tonic-gate }
1197c478bd9Sstevel@tonic-gate 
1207c478bd9Sstevel@tonic-gate krb5_error_code
1217c478bd9Sstevel@tonic-gate kg_encrypt(context, key, usage, iv, in, out, length)
1227c478bd9Sstevel@tonic-gate      krb5_context context;
1237c478bd9Sstevel@tonic-gate      krb5_keyblock *key;
1247c478bd9Sstevel@tonic-gate      int usage;
1257c478bd9Sstevel@tonic-gate      krb5_pointer iv;
126*159d09a2SMark Phalan      krb5_const_pointer in;
1277c478bd9Sstevel@tonic-gate      krb5_pointer out;
128ab9b2e15Sgtb      unsigned int length;
1297c478bd9Sstevel@tonic-gate {
1307c478bd9Sstevel@tonic-gate    krb5_error_code code;
1317c478bd9Sstevel@tonic-gate    size_t blocksize;
1327c478bd9Sstevel@tonic-gate    krb5_data ivd, *pivd, inputd;
1337c478bd9Sstevel@tonic-gate    krb5_enc_data outputd;
1347c478bd9Sstevel@tonic-gate 
1357c478bd9Sstevel@tonic-gate    KRB5_LOG0(KRB5_INFO, "kg_encrypt() start.");
1367c478bd9Sstevel@tonic-gate 
1377c478bd9Sstevel@tonic-gate    if (iv) {
138*159d09a2SMark Phalan        code = krb5_c_block_size(context, key->enctype, &blocksize);
139*159d09a2SMark Phalan        if (code)
1407c478bd9Sstevel@tonic-gate 	   return(code);
1417c478bd9Sstevel@tonic-gate 
1427c478bd9Sstevel@tonic-gate        ivd.length = blocksize;
1437c478bd9Sstevel@tonic-gate        ivd.data = MALLOC(ivd.length);
1447c478bd9Sstevel@tonic-gate        if (ivd.data == NULL)
1457c478bd9Sstevel@tonic-gate 	   return ENOMEM;
1467c478bd9Sstevel@tonic-gate        (void) memcpy(ivd.data, iv, ivd.length);
1477c478bd9Sstevel@tonic-gate        pivd = &ivd;
1487c478bd9Sstevel@tonic-gate    } else {
1497c478bd9Sstevel@tonic-gate        pivd = NULL;
1507c478bd9Sstevel@tonic-gate    }
1517c478bd9Sstevel@tonic-gate 
1527c478bd9Sstevel@tonic-gate    inputd.length = length;
153*159d09a2SMark Phalan    inputd.data = (char *)in; /* Solaris Kerberos */
1547c478bd9Sstevel@tonic-gate 
1557c478bd9Sstevel@tonic-gate    outputd.ciphertext.length = length;
1567c478bd9Sstevel@tonic-gate    outputd.ciphertext.data = out;
1577c478bd9Sstevel@tonic-gate 
1587c478bd9Sstevel@tonic-gate    code = krb5_c_encrypt(context, key, usage, pivd, &inputd, &outputd);
1597c478bd9Sstevel@tonic-gate    if (pivd != NULL)
1607c478bd9Sstevel@tonic-gate        krb5_free_data_contents(context, pivd);
1617c478bd9Sstevel@tonic-gate 
1627c478bd9Sstevel@tonic-gate    KRB5_LOG(KRB5_INFO, "kg_encrypt() end. code = %d", code);
1637c478bd9Sstevel@tonic-gate    return code;
1647c478bd9Sstevel@tonic-gate }
1657c478bd9Sstevel@tonic-gate 
1667c478bd9Sstevel@tonic-gate /* length is the length of the cleartext. */
1677c478bd9Sstevel@tonic-gate 
1687c478bd9Sstevel@tonic-gate krb5_error_code
1697c478bd9Sstevel@tonic-gate kg_decrypt(context, key, usage, iv, in, out, length)
1707c478bd9Sstevel@tonic-gate      krb5_context context;
1717c478bd9Sstevel@tonic-gate      krb5_keyblock *key;
1727c478bd9Sstevel@tonic-gate      int usage;
1737c478bd9Sstevel@tonic-gate      krb5_pointer iv;
174*159d09a2SMark Phalan      krb5_const_pointer in;
1757c478bd9Sstevel@tonic-gate      krb5_pointer out;
176ab9b2e15Sgtb      unsigned int length;
1777c478bd9Sstevel@tonic-gate {
1787c478bd9Sstevel@tonic-gate    krb5_error_code code;
1797c478bd9Sstevel@tonic-gate    size_t blocksize;
1807c478bd9Sstevel@tonic-gate    krb5_data ivd, *pivd, outputd;
1817c478bd9Sstevel@tonic-gate    krb5_enc_data inputd;
1827c478bd9Sstevel@tonic-gate    KRB5_LOG0(KRB5_INFO, "kg_decrypt() start.");
1837c478bd9Sstevel@tonic-gate 
1847c478bd9Sstevel@tonic-gate    if (iv) {
185*159d09a2SMark Phalan        code = krb5_c_block_size(context, key->enctype, &blocksize);
186*159d09a2SMark Phalan        if (code)
1877c478bd9Sstevel@tonic-gate 	   return(code);
1887c478bd9Sstevel@tonic-gate 
1897c478bd9Sstevel@tonic-gate        ivd.length = blocksize;
1907c478bd9Sstevel@tonic-gate        ivd.data = MALLOC(ivd.length);
1917c478bd9Sstevel@tonic-gate        if (ivd.data == NULL)
1927c478bd9Sstevel@tonic-gate 	   return ENOMEM;
1937c478bd9Sstevel@tonic-gate        (void) memcpy(ivd.data, iv, ivd.length);
1947c478bd9Sstevel@tonic-gate        pivd = &ivd;
1957c478bd9Sstevel@tonic-gate    } else {
1967c478bd9Sstevel@tonic-gate        pivd = NULL;
1977c478bd9Sstevel@tonic-gate    }
1987c478bd9Sstevel@tonic-gate 
1997c478bd9Sstevel@tonic-gate    inputd.enctype = ENCTYPE_UNKNOWN;
2007c478bd9Sstevel@tonic-gate    inputd.ciphertext.length = length;
201*159d09a2SMark Phalan    inputd.ciphertext.data = (char *)in; /* Solaris Kerberos */
2027c478bd9Sstevel@tonic-gate 
2037c478bd9Sstevel@tonic-gate    outputd.length = length;
2047c478bd9Sstevel@tonic-gate    outputd.data = out;
2057c478bd9Sstevel@tonic-gate 
2067c478bd9Sstevel@tonic-gate    code = krb5_c_decrypt(context, key, usage, pivd, &inputd, &outputd);
2077c478bd9Sstevel@tonic-gate    if (pivd != NULL)
2087c478bd9Sstevel@tonic-gate        krb5_free_data_contents(context, pivd);
2097c478bd9Sstevel@tonic-gate 
2107c478bd9Sstevel@tonic-gate    KRB5_LOG(KRB5_INFO, "kg_decrypt() end. code = %d", code);
2117c478bd9Sstevel@tonic-gate    return code;
2127c478bd9Sstevel@tonic-gate }
2137c478bd9Sstevel@tonic-gate 
2147c478bd9Sstevel@tonic-gate krb5_error_code
2157c478bd9Sstevel@tonic-gate kg_arcfour_docrypt (krb5_context context,
2167c478bd9Sstevel@tonic-gate 		const krb5_keyblock *longterm_key , int ms_usage,
2177c478bd9Sstevel@tonic-gate 		const unsigned char *kd_data, size_t kd_data_len,
2187c478bd9Sstevel@tonic-gate 		const unsigned char *input_buf, size_t input_len,
2197c478bd9Sstevel@tonic-gate 		unsigned char *output_buf)
2207c478bd9Sstevel@tonic-gate {
2217c478bd9Sstevel@tonic-gate   krb5_error_code code;
2227c478bd9Sstevel@tonic-gate   krb5_data input, output;
2237c478bd9Sstevel@tonic-gate   krb5_keyblock seq_enc_key, usage_key;
2247c478bd9Sstevel@tonic-gate   unsigned char t[4];
2257c478bd9Sstevel@tonic-gate 
2267c478bd9Sstevel@tonic-gate   KRB5_LOG0(KRB5_INFO, "kg_arcfour_docrypt() start");
2277c478bd9Sstevel@tonic-gate 
2287c478bd9Sstevel@tonic-gate   bzero(&usage_key, sizeof(krb5_keyblock));
2297c478bd9Sstevel@tonic-gate   bzero(&seq_enc_key, sizeof(krb5_keyblock));
2307c478bd9Sstevel@tonic-gate 
2317c478bd9Sstevel@tonic-gate   usage_key.length = longterm_key->length;
2327c478bd9Sstevel@tonic-gate   usage_key.contents = MALLOC(usage_key.length);
2337c478bd9Sstevel@tonic-gate   usage_key.enctype = longterm_key->enctype;
2347c478bd9Sstevel@tonic-gate   usage_key.dk_list = NULL;
2357c478bd9Sstevel@tonic-gate #ifdef _KERNEL
2367c478bd9Sstevel@tonic-gate 
2377c478bd9Sstevel@tonic-gate   usage_key.kef_mt  = longterm_key->kef_mt;
2387c478bd9Sstevel@tonic-gate   code = init_key_kef(longterm_key->kef_mt, &usage_key);
2397c478bd9Sstevel@tonic-gate   if (code)
2407c478bd9Sstevel@tonic-gate 	return (code);
2417c478bd9Sstevel@tonic-gate #endif /* _KERNEL */
2427c478bd9Sstevel@tonic-gate   if (usage_key.contents == NULL)
2437c478bd9Sstevel@tonic-gate     return (ENOMEM);
2447c478bd9Sstevel@tonic-gate   seq_enc_key.length = longterm_key->length;
2457c478bd9Sstevel@tonic-gate   seq_enc_key.contents = MALLOC(seq_enc_key.length);
2467c478bd9Sstevel@tonic-gate   seq_enc_key.enctype = longterm_key->enctype;
2477c478bd9Sstevel@tonic-gate   seq_enc_key.dk_list = NULL;
2487c478bd9Sstevel@tonic-gate #ifdef _KERNEL
2497c478bd9Sstevel@tonic-gate   seq_enc_key.kef_mt  = longterm_key->kef_mt;
2507c478bd9Sstevel@tonic-gate   code = init_key_kef(longterm_key->kef_mt, &seq_enc_key);
2517c478bd9Sstevel@tonic-gate   if (code)
2527c478bd9Sstevel@tonic-gate 	return (code);
2537c478bd9Sstevel@tonic-gate #endif /* _KERNEL */
2547c478bd9Sstevel@tonic-gate   if (seq_enc_key.contents == NULL) {
2557c478bd9Sstevel@tonic-gate     FREE ((void *) usage_key.contents, usage_key.length);
2567c478bd9Sstevel@tonic-gate     return (ENOMEM);
2577c478bd9Sstevel@tonic-gate   }
2587c478bd9Sstevel@tonic-gate 
2597c478bd9Sstevel@tonic-gate   t[0] = ms_usage &0xff;
2607c478bd9Sstevel@tonic-gate   t[1] = (ms_usage>>8) & 0xff;
2617c478bd9Sstevel@tonic-gate   t[2] = (ms_usage>>16) & 0xff;
2627c478bd9Sstevel@tonic-gate   t[3] = (ms_usage>>24) & 0xff;
2637c478bd9Sstevel@tonic-gate   input.data = (void *) &t;
2647c478bd9Sstevel@tonic-gate   input.length = 4;
2657c478bd9Sstevel@tonic-gate   output.data = (void *) usage_key.contents;
2667c478bd9Sstevel@tonic-gate   output.length = usage_key.length;
2677c478bd9Sstevel@tonic-gate #ifdef _KERNEL
2687c478bd9Sstevel@tonic-gate   code = krb5_hmac(context, longterm_key, &input, &output);
2697c478bd9Sstevel@tonic-gate #else
2707c478bd9Sstevel@tonic-gate   code = krb5_hmac(context, &krb5int_hash_md5,
2717c478bd9Sstevel@tonic-gate 		longterm_key, 1, &input, &output);
2727c478bd9Sstevel@tonic-gate #endif /* _KERNEL */
2737c478bd9Sstevel@tonic-gate   if (code)
2747c478bd9Sstevel@tonic-gate     goto cleanup_arcfour;
275*159d09a2SMark Phalan 
2767c478bd9Sstevel@tonic-gate   input.data = ( void *) kd_data;
2777c478bd9Sstevel@tonic-gate   input.length = kd_data_len;
2787c478bd9Sstevel@tonic-gate   output.data = (void *) seq_enc_key.contents;
2797c478bd9Sstevel@tonic-gate #ifdef _KERNEL
2807c478bd9Sstevel@tonic-gate   code = krb5_hmac(context, &usage_key, &input, &output);
2817c478bd9Sstevel@tonic-gate #else
2827c478bd9Sstevel@tonic-gate   code = krb5_hmac(context, &krb5int_hash_md5,
2837c478bd9Sstevel@tonic-gate 		&usage_key, 1, &input, &output);
2847c478bd9Sstevel@tonic-gate #endif /* _KERNEL */
2857c478bd9Sstevel@tonic-gate 
2867c478bd9Sstevel@tonic-gate   if (code)
2877c478bd9Sstevel@tonic-gate     goto cleanup_arcfour;
2887c478bd9Sstevel@tonic-gate   input.data = ( void * ) input_buf;
2897c478bd9Sstevel@tonic-gate   input.length = input_len;
290*159d09a2SMark Phalan   output.data = (void * ) output_buf;
2917c478bd9Sstevel@tonic-gate   output.length = input_len;
2927c478bd9Sstevel@tonic-gate 
2937c478bd9Sstevel@tonic-gate   /*
2947c478bd9Sstevel@tonic-gate    * Call the arcfour encryption method directly here, we cannot
2957c478bd9Sstevel@tonic-gate    * use the standard "krb5_c_encrypt" interface because we just
2967c478bd9Sstevel@tonic-gate    * want the arcfour algorithm applied and not the additional MD5-HMAC
2977c478bd9Sstevel@tonic-gate    * which are applied when using the standard interface.
2987c478bd9Sstevel@tonic-gate    */
2997c478bd9Sstevel@tonic-gate   code = krb5int_enc_arcfour.encrypt(context, &seq_enc_key, 0, &input, &output);
3007c478bd9Sstevel@tonic-gate 
3017c478bd9Sstevel@tonic-gate  cleanup_arcfour:
3027c478bd9Sstevel@tonic-gate   bzero ((void *) seq_enc_key.contents, seq_enc_key.length);
3037c478bd9Sstevel@tonic-gate   bzero ((void *) usage_key.contents, usage_key.length);
3047c478bd9Sstevel@tonic-gate   FREE ((void *) usage_key.contents, usage_key.length);
3057c478bd9Sstevel@tonic-gate   FREE ((void *) seq_enc_key.contents, seq_enc_key.length);
3067c478bd9Sstevel@tonic-gate 
3077c478bd9Sstevel@tonic-gate   KRB5_LOG(KRB5_INFO, "kg_arcfour_docrypt() end code = %d", code);
3087c478bd9Sstevel@tonic-gate   return (code);
3097c478bd9Sstevel@tonic-gate }
310*159d09a2SMark Phalan 
311