xref: /illumos-gate/usr/src/uts/common/gssapi/mechs/krb5/mech/util_crypt.c (revision ab9b2e153c3a9a2b1141fefa87925b1a9beb1236)
17c478bd9Sstevel@tonic-gate /*
2*ab9b2e15Sgtb  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
37c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
47c478bd9Sstevel@tonic-gate  */
57c478bd9Sstevel@tonic-gate 
67c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
77c478bd9Sstevel@tonic-gate 
87c478bd9Sstevel@tonic-gate /*
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 {
747c478bd9Sstevel@tonic-gate    size_t blocksize;
757c478bd9Sstevel@tonic-gate    /* We special case rc4*/
767c478bd9Sstevel@tonic-gate    if (key->enctype == ENCTYPE_ARCFOUR_HMAC)
777c478bd9Sstevel@tonic-gate 	return 8;
787c478bd9Sstevel@tonic-gate    if (krb5_c_block_size(context, key->enctype, &blocksize) != 0)
797c478bd9Sstevel@tonic-gate       return(-1); /* XXX */
807c478bd9Sstevel@tonic-gate 
817c478bd9Sstevel@tonic-gate    return(blocksize);
827c478bd9Sstevel@tonic-gate }
837c478bd9Sstevel@tonic-gate 
847c478bd9Sstevel@tonic-gate krb5_error_code
857c478bd9Sstevel@tonic-gate kg_make_confounder(context, key, buf)
867c478bd9Sstevel@tonic-gate      krb5_context context;
877c478bd9Sstevel@tonic-gate      krb5_keyblock *key;
887c478bd9Sstevel@tonic-gate      unsigned char *buf;
897c478bd9Sstevel@tonic-gate {
907c478bd9Sstevel@tonic-gate    krb5_error_code code;
917c478bd9Sstevel@tonic-gate    size_t blocksize;
927c478bd9Sstevel@tonic-gate    krb5_data random;
937c478bd9Sstevel@tonic-gate 
947c478bd9Sstevel@tonic-gate    if (code = krb5_c_block_size(context, key->enctype, &blocksize))
957c478bd9Sstevel@tonic-gate        return(code);
967c478bd9Sstevel@tonic-gate 
977c478bd9Sstevel@tonic-gate    random.length = blocksize;
987c478bd9Sstevel@tonic-gate    random.data = (char *) buf;
997c478bd9Sstevel@tonic-gate 
1007c478bd9Sstevel@tonic-gate    return(krb5_c_random_make_octets(context, &random));
1017c478bd9Sstevel@tonic-gate }
1027c478bd9Sstevel@tonic-gate 
1037c478bd9Sstevel@tonic-gate int
1047c478bd9Sstevel@tonic-gate kg_encrypt_size(context, key, n)
1057c478bd9Sstevel@tonic-gate      krb5_context context;
1067c478bd9Sstevel@tonic-gate      krb5_keyblock *key;
1077c478bd9Sstevel@tonic-gate      int n;
1087c478bd9Sstevel@tonic-gate {
1097c478bd9Sstevel@tonic-gate    size_t enclen;
1107c478bd9Sstevel@tonic-gate 
1117c478bd9Sstevel@tonic-gate    if (krb5_c_encrypt_length(context, key->enctype, n, &enclen) != 0)
1127c478bd9Sstevel@tonic-gate       return(-1); /* XXX */
1137c478bd9Sstevel@tonic-gate 
1147c478bd9Sstevel@tonic-gate    return(enclen);
1157c478bd9Sstevel@tonic-gate }
1167c478bd9Sstevel@tonic-gate 
1177c478bd9Sstevel@tonic-gate krb5_error_code
1187c478bd9Sstevel@tonic-gate kg_encrypt(context, key, usage, iv, in, out, length)
1197c478bd9Sstevel@tonic-gate      krb5_context context;
1207c478bd9Sstevel@tonic-gate      krb5_keyblock *key;
1217c478bd9Sstevel@tonic-gate      int usage;
1227c478bd9Sstevel@tonic-gate      krb5_pointer iv;
1237c478bd9Sstevel@tonic-gate      krb5_pointer in;
1247c478bd9Sstevel@tonic-gate      krb5_pointer out;
125*ab9b2e15Sgtb      unsigned int length;
1267c478bd9Sstevel@tonic-gate {
1277c478bd9Sstevel@tonic-gate    krb5_error_code code;
1287c478bd9Sstevel@tonic-gate    size_t blocksize;
1297c478bd9Sstevel@tonic-gate    krb5_data ivd, *pivd, inputd;
1307c478bd9Sstevel@tonic-gate    krb5_enc_data outputd;
1317c478bd9Sstevel@tonic-gate 
1327c478bd9Sstevel@tonic-gate    KRB5_LOG0(KRB5_INFO, "kg_encrypt() start.");
1337c478bd9Sstevel@tonic-gate 
1347c478bd9Sstevel@tonic-gate    if (iv) {
1357c478bd9Sstevel@tonic-gate        if (code = krb5_c_block_size(context, key->enctype, &blocksize))
1367c478bd9Sstevel@tonic-gate 	   return(code);
1377c478bd9Sstevel@tonic-gate 
1387c478bd9Sstevel@tonic-gate        ivd.length = blocksize;
1397c478bd9Sstevel@tonic-gate        ivd.data = MALLOC(ivd.length);
1407c478bd9Sstevel@tonic-gate        if (ivd.data == NULL)
1417c478bd9Sstevel@tonic-gate 	   return ENOMEM;
1427c478bd9Sstevel@tonic-gate        (void) memcpy(ivd.data, iv, ivd.length);
1437c478bd9Sstevel@tonic-gate        pivd = &ivd;
1447c478bd9Sstevel@tonic-gate    } else {
1457c478bd9Sstevel@tonic-gate        pivd = NULL;
1467c478bd9Sstevel@tonic-gate    }
1477c478bd9Sstevel@tonic-gate 
1487c478bd9Sstevel@tonic-gate    inputd.length = length;
1497c478bd9Sstevel@tonic-gate    inputd.data = in;
1507c478bd9Sstevel@tonic-gate 
1517c478bd9Sstevel@tonic-gate    outputd.ciphertext.length = length;
1527c478bd9Sstevel@tonic-gate    outputd.ciphertext.data = out;
1537c478bd9Sstevel@tonic-gate 
1547c478bd9Sstevel@tonic-gate    code = krb5_c_encrypt(context, key, usage, pivd, &inputd, &outputd);
1557c478bd9Sstevel@tonic-gate    if (pivd != NULL)
1567c478bd9Sstevel@tonic-gate        krb5_free_data_contents(context, pivd);
1577c478bd9Sstevel@tonic-gate 
1587c478bd9Sstevel@tonic-gate    KRB5_LOG(KRB5_INFO, "kg_encrypt() end. code = %d", code);
1597c478bd9Sstevel@tonic-gate    return code;
1607c478bd9Sstevel@tonic-gate }
1617c478bd9Sstevel@tonic-gate 
1627c478bd9Sstevel@tonic-gate /* length is the length of the cleartext. */
1637c478bd9Sstevel@tonic-gate 
1647c478bd9Sstevel@tonic-gate krb5_error_code
1657c478bd9Sstevel@tonic-gate kg_decrypt(context, key, usage, iv, in, out, length)
1667c478bd9Sstevel@tonic-gate      krb5_context context;
1677c478bd9Sstevel@tonic-gate      krb5_keyblock *key;
1687c478bd9Sstevel@tonic-gate      int usage;
1697c478bd9Sstevel@tonic-gate      krb5_pointer iv;
1707c478bd9Sstevel@tonic-gate      krb5_pointer in;
1717c478bd9Sstevel@tonic-gate      krb5_pointer out;
172*ab9b2e15Sgtb      unsigned int length;
1737c478bd9Sstevel@tonic-gate {
1747c478bd9Sstevel@tonic-gate    krb5_error_code code;
1757c478bd9Sstevel@tonic-gate    size_t blocksize;
1767c478bd9Sstevel@tonic-gate    krb5_data ivd, *pivd, outputd;
1777c478bd9Sstevel@tonic-gate    krb5_enc_data inputd;
1787c478bd9Sstevel@tonic-gate    KRB5_LOG0(KRB5_INFO, "kg_decrypt() start.");
1797c478bd9Sstevel@tonic-gate 
1807c478bd9Sstevel@tonic-gate    if (iv) {
1817c478bd9Sstevel@tonic-gate        if (code = krb5_c_block_size(context, key->enctype, &blocksize))
1827c478bd9Sstevel@tonic-gate 	   return(code);
1837c478bd9Sstevel@tonic-gate 
1847c478bd9Sstevel@tonic-gate        ivd.length = blocksize;
1857c478bd9Sstevel@tonic-gate        ivd.data = MALLOC(ivd.length);
1867c478bd9Sstevel@tonic-gate        if (ivd.data == NULL)
1877c478bd9Sstevel@tonic-gate 	   return ENOMEM;
1887c478bd9Sstevel@tonic-gate        (void) memcpy(ivd.data, iv, ivd.length);
1897c478bd9Sstevel@tonic-gate        pivd = &ivd;
1907c478bd9Sstevel@tonic-gate    } else {
1917c478bd9Sstevel@tonic-gate        pivd = NULL;
1927c478bd9Sstevel@tonic-gate    }
1937c478bd9Sstevel@tonic-gate 
1947c478bd9Sstevel@tonic-gate    inputd.enctype = ENCTYPE_UNKNOWN;
1957c478bd9Sstevel@tonic-gate    inputd.ciphertext.length = length;
1967c478bd9Sstevel@tonic-gate    inputd.ciphertext.data = in;
1977c478bd9Sstevel@tonic-gate 
1987c478bd9Sstevel@tonic-gate    outputd.length = length;
1997c478bd9Sstevel@tonic-gate    outputd.data = out;
2007c478bd9Sstevel@tonic-gate 
2017c478bd9Sstevel@tonic-gate    code = krb5_c_decrypt(context, key, usage, pivd, &inputd, &outputd);
2027c478bd9Sstevel@tonic-gate    if (pivd != NULL)
2037c478bd9Sstevel@tonic-gate        krb5_free_data_contents(context, pivd);
2047c478bd9Sstevel@tonic-gate 
2057c478bd9Sstevel@tonic-gate    KRB5_LOG(KRB5_INFO, "kg_decrypt() end. code = %d", code);
2067c478bd9Sstevel@tonic-gate    return code;
2077c478bd9Sstevel@tonic-gate }
2087c478bd9Sstevel@tonic-gate 
2097c478bd9Sstevel@tonic-gate krb5_error_code
2107c478bd9Sstevel@tonic-gate kg_arcfour_docrypt (krb5_context context,
2117c478bd9Sstevel@tonic-gate 		const krb5_keyblock *longterm_key , int ms_usage,
2127c478bd9Sstevel@tonic-gate 		const unsigned char *kd_data, size_t kd_data_len,
2137c478bd9Sstevel@tonic-gate 		const unsigned char *input_buf, size_t input_len,
2147c478bd9Sstevel@tonic-gate 		unsigned char *output_buf)
2157c478bd9Sstevel@tonic-gate {
2167c478bd9Sstevel@tonic-gate   krb5_error_code code;
2177c478bd9Sstevel@tonic-gate   krb5_data input, output;
2187c478bd9Sstevel@tonic-gate   krb5_keyblock seq_enc_key, usage_key;
2197c478bd9Sstevel@tonic-gate   unsigned char t[4];
2207c478bd9Sstevel@tonic-gate 
2217c478bd9Sstevel@tonic-gate   KRB5_LOG0(KRB5_INFO, "kg_arcfour_docrypt() start");
2227c478bd9Sstevel@tonic-gate 
2237c478bd9Sstevel@tonic-gate   bzero(&usage_key, sizeof(krb5_keyblock));
2247c478bd9Sstevel@tonic-gate   bzero(&seq_enc_key, sizeof(krb5_keyblock));
2257c478bd9Sstevel@tonic-gate 
2267c478bd9Sstevel@tonic-gate   usage_key.length = longterm_key->length;
2277c478bd9Sstevel@tonic-gate   usage_key.contents = MALLOC(usage_key.length);
2287c478bd9Sstevel@tonic-gate   usage_key.enctype = longterm_key->enctype;
2297c478bd9Sstevel@tonic-gate   usage_key.dk_list = NULL;
2307c478bd9Sstevel@tonic-gate #ifdef _KERNEL
2317c478bd9Sstevel@tonic-gate 
2327c478bd9Sstevel@tonic-gate   usage_key.kef_mt  = longterm_key->kef_mt;
2337c478bd9Sstevel@tonic-gate   code = init_key_kef(longterm_key->kef_mt, &usage_key);
2347c478bd9Sstevel@tonic-gate   if (code)
2357c478bd9Sstevel@tonic-gate 	return (code);
2367c478bd9Sstevel@tonic-gate #endif /* _KERNEL */
2377c478bd9Sstevel@tonic-gate   if (usage_key.contents == NULL)
2387c478bd9Sstevel@tonic-gate     return (ENOMEM);
2397c478bd9Sstevel@tonic-gate   seq_enc_key.length = longterm_key->length;
2407c478bd9Sstevel@tonic-gate   seq_enc_key.contents = MALLOC(seq_enc_key.length);
2417c478bd9Sstevel@tonic-gate   seq_enc_key.enctype = longterm_key->enctype;
2427c478bd9Sstevel@tonic-gate   seq_enc_key.dk_list = NULL;
2437c478bd9Sstevel@tonic-gate #ifdef _KERNEL
2447c478bd9Sstevel@tonic-gate   seq_enc_key.kef_mt  = longterm_key->kef_mt;
2457c478bd9Sstevel@tonic-gate   code = init_key_kef(longterm_key->kef_mt, &seq_enc_key);
2467c478bd9Sstevel@tonic-gate   if (code)
2477c478bd9Sstevel@tonic-gate 	return (code);
2487c478bd9Sstevel@tonic-gate #endif /* _KERNEL */
2497c478bd9Sstevel@tonic-gate   if (seq_enc_key.contents == NULL) {
2507c478bd9Sstevel@tonic-gate     FREE ((void *) usage_key.contents, usage_key.length);
2517c478bd9Sstevel@tonic-gate     return (ENOMEM);
2527c478bd9Sstevel@tonic-gate   }
2537c478bd9Sstevel@tonic-gate 
2547c478bd9Sstevel@tonic-gate   t[0] = ms_usage &0xff;
2557c478bd9Sstevel@tonic-gate   t[1] = (ms_usage>>8) & 0xff;
2567c478bd9Sstevel@tonic-gate   t[2] = (ms_usage>>16) & 0xff;
2577c478bd9Sstevel@tonic-gate   t[3] = (ms_usage>>24) & 0xff;
2587c478bd9Sstevel@tonic-gate   input.data = (void *) &t;
2597c478bd9Sstevel@tonic-gate   input.length = 4;
2607c478bd9Sstevel@tonic-gate   output.data = (void *) usage_key.contents;
2617c478bd9Sstevel@tonic-gate   output.length = usage_key.length;
2627c478bd9Sstevel@tonic-gate #ifdef _KERNEL
2637c478bd9Sstevel@tonic-gate   code = krb5_hmac(context, longterm_key, &input, &output);
2647c478bd9Sstevel@tonic-gate #else
2657c478bd9Sstevel@tonic-gate   code = krb5_hmac(context, &krb5int_hash_md5,
2667c478bd9Sstevel@tonic-gate 		longterm_key, 1, &input, &output);
2677c478bd9Sstevel@tonic-gate #endif /* _KERNEL */
2687c478bd9Sstevel@tonic-gate   if (code)
2697c478bd9Sstevel@tonic-gate     goto cleanup_arcfour;
2707c478bd9Sstevel@tonic-gate 
2717c478bd9Sstevel@tonic-gate   input.data = ( void *) kd_data;
2727c478bd9Sstevel@tonic-gate   input.length = kd_data_len;
2737c478bd9Sstevel@tonic-gate   output.data = (void *) seq_enc_key.contents;
2747c478bd9Sstevel@tonic-gate #ifdef _KERNEL
2757c478bd9Sstevel@tonic-gate   code = krb5_hmac(context, &usage_key, &input, &output);
2767c478bd9Sstevel@tonic-gate #else
2777c478bd9Sstevel@tonic-gate   code = krb5_hmac(context, &krb5int_hash_md5,
2787c478bd9Sstevel@tonic-gate 		&usage_key, 1, &input, &output);
2797c478bd9Sstevel@tonic-gate #endif /* _KERNEL */
2807c478bd9Sstevel@tonic-gate 
2817c478bd9Sstevel@tonic-gate   if (code)
2827c478bd9Sstevel@tonic-gate     goto cleanup_arcfour;
2837c478bd9Sstevel@tonic-gate 
2847c478bd9Sstevel@tonic-gate   input.data = ( void * ) input_buf;
2857c478bd9Sstevel@tonic-gate   input.length = input_len;
2867c478bd9Sstevel@tonic-gate 
2877c478bd9Sstevel@tonic-gate   output.data = (char *)output_buf;
2887c478bd9Sstevel@tonic-gate   output.length = input_len;
2897c478bd9Sstevel@tonic-gate 
2907c478bd9Sstevel@tonic-gate   /*
2917c478bd9Sstevel@tonic-gate    * Call the arcfour encryption method directly here, we cannot
2927c478bd9Sstevel@tonic-gate    * use the standard "krb5_c_encrypt" interface because we just
2937c478bd9Sstevel@tonic-gate    * want the arcfour algorithm applied and not the additional MD5-HMAC
2947c478bd9Sstevel@tonic-gate    * which are applied when using the standard interface.
2957c478bd9Sstevel@tonic-gate    */
2967c478bd9Sstevel@tonic-gate   code = krb5int_enc_arcfour.encrypt(context, &seq_enc_key, 0, &input, &output);
2977c478bd9Sstevel@tonic-gate 
2987c478bd9Sstevel@tonic-gate  cleanup_arcfour:
2997c478bd9Sstevel@tonic-gate   bzero ((void *) seq_enc_key.contents, seq_enc_key.length);
3007c478bd9Sstevel@tonic-gate   bzero ((void *) usage_key.contents, usage_key.length);
3017c478bd9Sstevel@tonic-gate   FREE ((void *) usage_key.contents, usage_key.length);
3027c478bd9Sstevel@tonic-gate   FREE ((void *) seq_enc_key.contents, seq_enc_key.length);
3037c478bd9Sstevel@tonic-gate 
3047c478bd9Sstevel@tonic-gate   KRB5_LOG(KRB5_INFO, "kg_arcfour_docrypt() end code = %d", code);
3057c478bd9Sstevel@tonic-gate   return (code);
3067c478bd9Sstevel@tonic-gate }
307