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 * lib/kdb/kdb_cpw.c
87c478bd9Sstevel@tonic-gate *
97c478bd9Sstevel@tonic-gate * Copyright 1995 by the Massachusetts Institute of Technology.
107c478bd9Sstevel@tonic-gate * All Rights Reserved.
117c478bd9Sstevel@tonic-gate *
127c478bd9Sstevel@tonic-gate * Export of this software from the United States of America may
137c478bd9Sstevel@tonic-gate * require a specific license from the United States Government.
147c478bd9Sstevel@tonic-gate * It is the responsibility of any person or organization contemplating
157c478bd9Sstevel@tonic-gate * export to obtain such a license before exporting.
167c478bd9Sstevel@tonic-gate *
177c478bd9Sstevel@tonic-gate * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
187c478bd9Sstevel@tonic-gate * distribute this software and its documentation for any purpose and
197c478bd9Sstevel@tonic-gate * without fee is hereby granted, provided that the above copyright
207c478bd9Sstevel@tonic-gate * notice appear in all copies and that both that copyright notice and
217c478bd9Sstevel@tonic-gate * this permission notice appear in supporting documentation, and that
227c478bd9Sstevel@tonic-gate * the name of M.I.T. not be used in advertising or publicity pertaining
237c478bd9Sstevel@tonic-gate * to distribution of the software without specific, written prior
247c478bd9Sstevel@tonic-gate * permission. Furthermore if you modify this software you must label
257c478bd9Sstevel@tonic-gate * your software as modified software and not distribute it in such a
267c478bd9Sstevel@tonic-gate * fashion that it might be confused with the original M.I.T. software.
277c478bd9Sstevel@tonic-gate * M.I.T. makes no representations about the suitability of
287c478bd9Sstevel@tonic-gate * this software for any purpose. It is provided "as is" without express
297c478bd9Sstevel@tonic-gate * or implied warranty.
307c478bd9Sstevel@tonic-gate *
317c478bd9Sstevel@tonic-gate */
327c478bd9Sstevel@tonic-gate
337c478bd9Sstevel@tonic-gate /*
347c478bd9Sstevel@tonic-gate * Copyright (C) 1998 by the FundsXpress, INC.
357c478bd9Sstevel@tonic-gate *
367c478bd9Sstevel@tonic-gate * All rights reserved.
377c478bd9Sstevel@tonic-gate *
387c478bd9Sstevel@tonic-gate * Export of this software from the United States of America may require
397c478bd9Sstevel@tonic-gate * a specific license from the United States Government. It is the
407c478bd9Sstevel@tonic-gate * responsibility of any person or organization contemplating export to
417c478bd9Sstevel@tonic-gate * obtain such a license before exporting.
427c478bd9Sstevel@tonic-gate *
437c478bd9Sstevel@tonic-gate * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
447c478bd9Sstevel@tonic-gate * distribute this software and its documentation for any purpose and
457c478bd9Sstevel@tonic-gate * without fee is hereby granted, provided that the above copyright
467c478bd9Sstevel@tonic-gate * notice appear in all copies and that both that copyright notice and
477c478bd9Sstevel@tonic-gate * this permission notice appear in supporting documentation, and that
487c478bd9Sstevel@tonic-gate * the name of FundsXpress. not be used in advertising or publicity pertaining
497c478bd9Sstevel@tonic-gate * to distribution of the software without specific, written prior
507c478bd9Sstevel@tonic-gate * permission. FundsXpress makes no representations about the suitability of
517c478bd9Sstevel@tonic-gate * this software for any purpose. It is provided "as is" without express
527c478bd9Sstevel@tonic-gate * or implied warranty.
537c478bd9Sstevel@tonic-gate *
547c478bd9Sstevel@tonic-gate * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
557c478bd9Sstevel@tonic-gate * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
567c478bd9Sstevel@tonic-gate * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
577c478bd9Sstevel@tonic-gate */
587c478bd9Sstevel@tonic-gate
597c478bd9Sstevel@tonic-gate #include "k5-int.h"
60*159d09a2SMark Phalan #include "kdb.h"
617c478bd9Sstevel@tonic-gate #include <stdio.h>
627c478bd9Sstevel@tonic-gate #include <errno.h>
637c478bd9Sstevel@tonic-gate
647c478bd9Sstevel@tonic-gate static int
get_key_data_kvno(context,count,data)657c478bd9Sstevel@tonic-gate get_key_data_kvno(context, count, data)
667c478bd9Sstevel@tonic-gate krb5_context context;
677c478bd9Sstevel@tonic-gate int count;
687c478bd9Sstevel@tonic-gate krb5_key_data * data;
697c478bd9Sstevel@tonic-gate {
707c478bd9Sstevel@tonic-gate int i, kvno;
717c478bd9Sstevel@tonic-gate /* Find last key version number */
727c478bd9Sstevel@tonic-gate for (kvno = i = 0; i < count; i++) {
737c478bd9Sstevel@tonic-gate if (kvno < data[i].key_data_kvno) {
747c478bd9Sstevel@tonic-gate kvno = data[i].key_data_kvno;
757c478bd9Sstevel@tonic-gate }
767c478bd9Sstevel@tonic-gate }
777c478bd9Sstevel@tonic-gate return(kvno);
787c478bd9Sstevel@tonic-gate }
797c478bd9Sstevel@tonic-gate
807c478bd9Sstevel@tonic-gate static void
cleanup_key_data(context,count,data)817c478bd9Sstevel@tonic-gate cleanup_key_data(context, count, data)
827c478bd9Sstevel@tonic-gate krb5_context context;
837c478bd9Sstevel@tonic-gate int count;
847c478bd9Sstevel@tonic-gate krb5_key_data * data;
857c478bd9Sstevel@tonic-gate {
867c478bd9Sstevel@tonic-gate int i, j;
877c478bd9Sstevel@tonic-gate
8856a424ccSmp153739 /* If data is NULL, count is always 0 */
8956a424ccSmp153739 if (data == NULL) return;
9056a424ccSmp153739
917c478bd9Sstevel@tonic-gate for (i = 0; i < count; i++) {
927c478bd9Sstevel@tonic-gate for (j = 0; j < data[i].key_data_ver; j++) {
937c478bd9Sstevel@tonic-gate if (data[i].key_data_length[j]) {
94*159d09a2SMark Phalan krb5_db_free(context, data[i].key_data_contents[j]);
957c478bd9Sstevel@tonic-gate }
967c478bd9Sstevel@tonic-gate }
977c478bd9Sstevel@tonic-gate }
98*159d09a2SMark Phalan krb5_db_free(context, data);
997c478bd9Sstevel@tonic-gate }
1007c478bd9Sstevel@tonic-gate
1017c478bd9Sstevel@tonic-gate static krb5_error_code
add_key_rnd(context,master_key,ks_tuple,ks_tuple_count,db_entry,kvno)1027c478bd9Sstevel@tonic-gate add_key_rnd(context, master_key, ks_tuple, ks_tuple_count, db_entry, kvno)
1037c478bd9Sstevel@tonic-gate krb5_context context;
1047c478bd9Sstevel@tonic-gate krb5_keyblock * master_key;
1057c478bd9Sstevel@tonic-gate krb5_key_salt_tuple * ks_tuple;
1067c478bd9Sstevel@tonic-gate int ks_tuple_count;
1077c478bd9Sstevel@tonic-gate krb5_db_entry * db_entry;
1087c478bd9Sstevel@tonic-gate int kvno;
1097c478bd9Sstevel@tonic-gate {
1107c478bd9Sstevel@tonic-gate krb5_principal krbtgt_princ;
1117c478bd9Sstevel@tonic-gate krb5_keyblock key;
1127c478bd9Sstevel@tonic-gate krb5_db_entry krbtgt_entry;
1137c478bd9Sstevel@tonic-gate krb5_boolean more;
114*159d09a2SMark Phalan int max_kvno, one, i, j, k;
1157c478bd9Sstevel@tonic-gate krb5_error_code retval;
116*159d09a2SMark Phalan krb5_key_data tmp_key_data;
117*159d09a2SMark Phalan krb5_key_data *tptr;
118*159d09a2SMark Phalan
119*159d09a2SMark Phalan memset( &tmp_key_data, 0, sizeof(tmp_key_data));
120*159d09a2SMark Phalan
1217c478bd9Sstevel@tonic-gate
1227c478bd9Sstevel@tonic-gate retval = krb5_build_principal_ext(context, &krbtgt_princ,
1237c478bd9Sstevel@tonic-gate db_entry->princ->realm.length,
1247c478bd9Sstevel@tonic-gate db_entry->princ->realm.data,
1257c478bd9Sstevel@tonic-gate KRB5_TGS_NAME_SIZE,
1267c478bd9Sstevel@tonic-gate KRB5_TGS_NAME,
1277c478bd9Sstevel@tonic-gate db_entry->princ->realm.length,
1287c478bd9Sstevel@tonic-gate db_entry->princ->realm.data,
1297c478bd9Sstevel@tonic-gate 0);
1307c478bd9Sstevel@tonic-gate if (retval)
1317c478bd9Sstevel@tonic-gate return retval;
1327c478bd9Sstevel@tonic-gate
1337c478bd9Sstevel@tonic-gate /* Get tgt from database */
1347c478bd9Sstevel@tonic-gate retval = krb5_db_get_principal(context, krbtgt_princ, &krbtgt_entry,
1357c478bd9Sstevel@tonic-gate &one, &more);
1367c478bd9Sstevel@tonic-gate krb5_free_principal(context, krbtgt_princ); /* don't need it anymore */
1377c478bd9Sstevel@tonic-gate if (retval)
1387c478bd9Sstevel@tonic-gate return(retval);
1397c478bd9Sstevel@tonic-gate if ((one > 1) || (more)) {
1407c478bd9Sstevel@tonic-gate krb5_db_free_principal(context, &krbtgt_entry, one);
1417c478bd9Sstevel@tonic-gate return KRB5KDC_ERR_PRINCIPAL_NOT_UNIQUE;
1427c478bd9Sstevel@tonic-gate }
1437c478bd9Sstevel@tonic-gate if (!one)
1447c478bd9Sstevel@tonic-gate return KRB5_KDB_NOENTRY;
1457c478bd9Sstevel@tonic-gate
1467c478bd9Sstevel@tonic-gate /* Get max kvno */
1477c478bd9Sstevel@tonic-gate for (max_kvno = j = 0; j < krbtgt_entry.n_key_data; j++) {
1487c478bd9Sstevel@tonic-gate if (max_kvno < krbtgt_entry.key_data[j].key_data_kvno) {
1497c478bd9Sstevel@tonic-gate max_kvno = krbtgt_entry.key_data[j].key_data_kvno;
1507c478bd9Sstevel@tonic-gate }
1517c478bd9Sstevel@tonic-gate }
1527c478bd9Sstevel@tonic-gate
1537c478bd9Sstevel@tonic-gate for (i = 0; i < ks_tuple_count; i++) {
1547c478bd9Sstevel@tonic-gate krb5_boolean similar;
1557c478bd9Sstevel@tonic-gate
1567c478bd9Sstevel@tonic-gate similar = 0;
1577c478bd9Sstevel@tonic-gate
1587c478bd9Sstevel@tonic-gate /*
1597c478bd9Sstevel@tonic-gate * We could use krb5_keysalt_iterate to replace this loop, or use
1607c478bd9Sstevel@tonic-gate * krb5_keysalt_is_present for the loop below, but we want to avoid
1617c478bd9Sstevel@tonic-gate * circular library dependencies.
1627c478bd9Sstevel@tonic-gate */
1637c478bd9Sstevel@tonic-gate for (j = 0; j < i; j++) {
1647c478bd9Sstevel@tonic-gate if ((retval = krb5_c_enctype_compare(context,
1657c478bd9Sstevel@tonic-gate ks_tuple[i].ks_enctype,
1667c478bd9Sstevel@tonic-gate ks_tuple[j].ks_enctype,
1677c478bd9Sstevel@tonic-gate &similar)))
1687c478bd9Sstevel@tonic-gate return(retval);
1697c478bd9Sstevel@tonic-gate
1707c478bd9Sstevel@tonic-gate if (similar)
1717c478bd9Sstevel@tonic-gate break;
1727c478bd9Sstevel@tonic-gate }
1737c478bd9Sstevel@tonic-gate
1747c478bd9Sstevel@tonic-gate if (similar)
1757c478bd9Sstevel@tonic-gate continue;
1767c478bd9Sstevel@tonic-gate
17756a424ccSmp153739 if ((retval = krb5_dbe_create_key_data(context, db_entry)))
1787c478bd9Sstevel@tonic-gate goto add_key_rnd_err;
1797c478bd9Sstevel@tonic-gate
1807c478bd9Sstevel@tonic-gate /* there used to be code here to extract the old key, and derive
1817c478bd9Sstevel@tonic-gate a new key from it. Now that there's a unified prng, that isn't
1827c478bd9Sstevel@tonic-gate necessary. */
1837c478bd9Sstevel@tonic-gate
1847c478bd9Sstevel@tonic-gate /* make new key */
1857c478bd9Sstevel@tonic-gate if ((retval = krb5_c_make_random_key(context, ks_tuple[i].ks_enctype,
1867c478bd9Sstevel@tonic-gate &key)))
1877c478bd9Sstevel@tonic-gate goto add_key_rnd_err;
1887c478bd9Sstevel@tonic-gate
189*159d09a2SMark Phalan
190*159d09a2SMark Phalan /* db library will free this. Since, its a so, it could actually be using different memory management
191*159d09a2SMark Phalan function. So, its better if the memory is allocated by the db's malloc. So, a temporary memory is used
192*159d09a2SMark Phalan here which will later be copied to the db_entry */
1937c478bd9Sstevel@tonic-gate retval = krb5_dbekd_encrypt_key_data(context, master_key,
1947c478bd9Sstevel@tonic-gate &key, NULL, kvno,
195*159d09a2SMark Phalan &tmp_key_data);
1967c478bd9Sstevel@tonic-gate
1977c478bd9Sstevel@tonic-gate krb5_free_keyblock_contents(context, &key);
1987c478bd9Sstevel@tonic-gate if( retval )
1997c478bd9Sstevel@tonic-gate goto add_key_rnd_err;
200*159d09a2SMark Phalan
201*159d09a2SMark Phalan tptr = &db_entry->key_data[db_entry->n_key_data-1];
202*159d09a2SMark Phalan
203*159d09a2SMark Phalan tptr->key_data_ver = tmp_key_data.key_data_ver;
204*159d09a2SMark Phalan tptr->key_data_kvno = tmp_key_data.key_data_kvno;
205*159d09a2SMark Phalan
206*159d09a2SMark Phalan for( k = 0; k < tmp_key_data.key_data_ver; k++ )
207*159d09a2SMark Phalan {
208*159d09a2SMark Phalan tptr->key_data_type[k] = tmp_key_data.key_data_type[k];
209*159d09a2SMark Phalan tptr->key_data_length[k] = tmp_key_data.key_data_length[k];
210*159d09a2SMark Phalan if( tmp_key_data.key_data_contents[k] )
211*159d09a2SMark Phalan {
212*159d09a2SMark Phalan tptr->key_data_contents[k] = krb5_db_alloc(context, NULL, tmp_key_data.key_data_length[k]);
213*159d09a2SMark Phalan if( tptr->key_data_contents[k] == NULL )
214*159d09a2SMark Phalan {
215*159d09a2SMark Phalan cleanup_key_data(context, db_entry->n_key_data, db_entry->key_data);
216*159d09a2SMark Phalan db_entry->key_data = NULL;
217*159d09a2SMark Phalan db_entry->n_key_data = 0;
218*159d09a2SMark Phalan retval = ENOMEM;
219*159d09a2SMark Phalan goto add_key_rnd_err;
220*159d09a2SMark Phalan }
221*159d09a2SMark Phalan memcpy( tptr->key_data_contents[k], tmp_key_data.key_data_contents[k], tmp_key_data.key_data_length[k]);
222*159d09a2SMark Phalan
223*159d09a2SMark Phalan memset( tmp_key_data.key_data_contents[k], 0, tmp_key_data.key_data_length[k]);
224*159d09a2SMark Phalan free( tmp_key_data.key_data_contents[k] );
225*159d09a2SMark Phalan tmp_key_data.key_data_contents[k] = NULL;
226*159d09a2SMark Phalan }
227*159d09a2SMark Phalan }
228*159d09a2SMark Phalan
2297c478bd9Sstevel@tonic-gate }
2307c478bd9Sstevel@tonic-gate
2317c478bd9Sstevel@tonic-gate add_key_rnd_err:
2327c478bd9Sstevel@tonic-gate krb5_db_free_principal(context, &krbtgt_entry, one);
2337c478bd9Sstevel@tonic-gate
234*159d09a2SMark Phalan for( i = 0; i < tmp_key_data.key_data_ver; i++ )
235*159d09a2SMark Phalan {
236*159d09a2SMark Phalan if( tmp_key_data.key_data_contents[i] )
237*159d09a2SMark Phalan {
238*159d09a2SMark Phalan memset( tmp_key_data.key_data_contents[i], 0, tmp_key_data.key_data_length[i]);
239*159d09a2SMark Phalan free( tmp_key_data.key_data_contents[i] );
240*159d09a2SMark Phalan }
241*159d09a2SMark Phalan }
2427c478bd9Sstevel@tonic-gate return(retval);
2437c478bd9Sstevel@tonic-gate }
2447c478bd9Sstevel@tonic-gate
2457c478bd9Sstevel@tonic-gate /*
2467c478bd9Sstevel@tonic-gate * Change random key for a krb5_db_entry
2477c478bd9Sstevel@tonic-gate * Assumes the max kvno
2487c478bd9Sstevel@tonic-gate *
2497c478bd9Sstevel@tonic-gate * As a side effect all old keys are nuked if keepold is false.
2507c478bd9Sstevel@tonic-gate */
2517c478bd9Sstevel@tonic-gate krb5_error_code
krb5_dbe_crk(context,master_key,ks_tuple,ks_tuple_count,keepold,db_entry)2527c478bd9Sstevel@tonic-gate krb5_dbe_crk(context, master_key, ks_tuple, ks_tuple_count, keepold, db_entry)
2537c478bd9Sstevel@tonic-gate krb5_context context;
2547c478bd9Sstevel@tonic-gate krb5_keyblock * master_key;
2557c478bd9Sstevel@tonic-gate krb5_key_salt_tuple * ks_tuple;
2567c478bd9Sstevel@tonic-gate int ks_tuple_count;
2577c478bd9Sstevel@tonic-gate krb5_boolean keepold;
2587c478bd9Sstevel@tonic-gate krb5_db_entry * db_entry;
2597c478bd9Sstevel@tonic-gate {
2607c478bd9Sstevel@tonic-gate int key_data_count;
2617c478bd9Sstevel@tonic-gate int n_new_key_data;
2627c478bd9Sstevel@tonic-gate krb5_key_data * key_data;
2637c478bd9Sstevel@tonic-gate krb5_error_code retval;
2647c478bd9Sstevel@tonic-gate int kvno;
2657c478bd9Sstevel@tonic-gate int i;
2667c478bd9Sstevel@tonic-gate
2677c478bd9Sstevel@tonic-gate /* First save the old keydata */
2687c478bd9Sstevel@tonic-gate kvno = get_key_data_kvno(context, db_entry->n_key_data, db_entry->key_data);
2697c478bd9Sstevel@tonic-gate key_data_count = db_entry->n_key_data;
2707c478bd9Sstevel@tonic-gate key_data = db_entry->key_data;
2717c478bd9Sstevel@tonic-gate db_entry->key_data = NULL;
2727c478bd9Sstevel@tonic-gate db_entry->n_key_data = 0;
2737c478bd9Sstevel@tonic-gate
2747c478bd9Sstevel@tonic-gate /* increment the kvno */
2757c478bd9Sstevel@tonic-gate kvno++;
2767c478bd9Sstevel@tonic-gate
2777c478bd9Sstevel@tonic-gate retval = add_key_rnd(context, master_key, ks_tuple,
2787c478bd9Sstevel@tonic-gate ks_tuple_count, db_entry, kvno);
2797c478bd9Sstevel@tonic-gate if (retval) {
2807c478bd9Sstevel@tonic-gate cleanup_key_data(context, db_entry->n_key_data, db_entry->key_data);
2817c478bd9Sstevel@tonic-gate db_entry->n_key_data = key_data_count;
2827c478bd9Sstevel@tonic-gate db_entry->key_data = key_data;
2837c478bd9Sstevel@tonic-gate } else if (keepold) {
2847c478bd9Sstevel@tonic-gate n_new_key_data = db_entry->n_key_data;
2857c478bd9Sstevel@tonic-gate for (i = 0; i < key_data_count; i++) {
2867c478bd9Sstevel@tonic-gate retval = krb5_dbe_create_key_data(context, db_entry);
2877c478bd9Sstevel@tonic-gate if (retval) {
2887c478bd9Sstevel@tonic-gate cleanup_key_data(context, db_entry->n_key_data,
2897c478bd9Sstevel@tonic-gate db_entry->key_data);
2907c478bd9Sstevel@tonic-gate break;
2917c478bd9Sstevel@tonic-gate }
2927c478bd9Sstevel@tonic-gate db_entry->key_data[i+n_new_key_data] = key_data[i];
2937c478bd9Sstevel@tonic-gate memset(&key_data[i], 0, sizeof(krb5_key_data));
2947c478bd9Sstevel@tonic-gate }
295*159d09a2SMark Phalan krb5_db_free(context, key_data); /* we moved the cotents to new memory. But, the original block which contained the data */
2967c478bd9Sstevel@tonic-gate } else {
2977c478bd9Sstevel@tonic-gate cleanup_key_data(context, key_data_count, key_data);
2987c478bd9Sstevel@tonic-gate }
2997c478bd9Sstevel@tonic-gate return(retval);
3007c478bd9Sstevel@tonic-gate }
3017c478bd9Sstevel@tonic-gate
3027c478bd9Sstevel@tonic-gate /*
3037c478bd9Sstevel@tonic-gate * Add random key for a krb5_db_entry
3047c478bd9Sstevel@tonic-gate * Assumes the max kvno
3057c478bd9Sstevel@tonic-gate *
3067c478bd9Sstevel@tonic-gate * As a side effect all old keys older than the max kvno are nuked.
3077c478bd9Sstevel@tonic-gate */
3087c478bd9Sstevel@tonic-gate krb5_error_code
krb5_dbe_ark(context,master_key,ks_tuple,ks_tuple_count,db_entry)3097c478bd9Sstevel@tonic-gate krb5_dbe_ark(context, master_key, ks_tuple, ks_tuple_count, db_entry)
3107c478bd9Sstevel@tonic-gate krb5_context context;
3117c478bd9Sstevel@tonic-gate krb5_keyblock * master_key;
3127c478bd9Sstevel@tonic-gate krb5_key_salt_tuple * ks_tuple;
3137c478bd9Sstevel@tonic-gate int ks_tuple_count;
3147c478bd9Sstevel@tonic-gate krb5_db_entry * db_entry;
3157c478bd9Sstevel@tonic-gate {
3167c478bd9Sstevel@tonic-gate int key_data_count;
3177c478bd9Sstevel@tonic-gate krb5_key_data * key_data;
3187c478bd9Sstevel@tonic-gate krb5_error_code retval;
3197c478bd9Sstevel@tonic-gate int kvno;
3207c478bd9Sstevel@tonic-gate int i;
3217c478bd9Sstevel@tonic-gate
3227c478bd9Sstevel@tonic-gate /* First save the old keydata */
3237c478bd9Sstevel@tonic-gate kvno = get_key_data_kvno(context, db_entry->n_key_data, db_entry->key_data);
3247c478bd9Sstevel@tonic-gate key_data_count = db_entry->n_key_data;
3257c478bd9Sstevel@tonic-gate key_data = db_entry->key_data;
3267c478bd9Sstevel@tonic-gate db_entry->key_data = NULL;
3277c478bd9Sstevel@tonic-gate db_entry->n_key_data = 0;
3287c478bd9Sstevel@tonic-gate
3297c478bd9Sstevel@tonic-gate /* increment the kvno */
3307c478bd9Sstevel@tonic-gate kvno++;
3317c478bd9Sstevel@tonic-gate
33256a424ccSmp153739 if ((retval = add_key_rnd(context, master_key, ks_tuple,
33356a424ccSmp153739 ks_tuple_count, db_entry, kvno))) {
3347c478bd9Sstevel@tonic-gate cleanup_key_data(context, db_entry->n_key_data, db_entry->key_data);
3357c478bd9Sstevel@tonic-gate db_entry->n_key_data = key_data_count;
3367c478bd9Sstevel@tonic-gate db_entry->key_data = key_data;
3377c478bd9Sstevel@tonic-gate } else {
3387c478bd9Sstevel@tonic-gate /* Copy keys with key_data_kvno == kvno - 1 ( = old kvno ) */
3397c478bd9Sstevel@tonic-gate for (i = 0; i < key_data_count; i++) {
3407c478bd9Sstevel@tonic-gate if (key_data[i].key_data_kvno == (kvno - 1)) {
34156a424ccSmp153739 if ((retval = krb5_dbe_create_key_data(context, db_entry))) {
3427c478bd9Sstevel@tonic-gate cleanup_key_data(context, db_entry->n_key_data,
3437c478bd9Sstevel@tonic-gate db_entry->key_data);
3447c478bd9Sstevel@tonic-gate break;
3457c478bd9Sstevel@tonic-gate }
3467c478bd9Sstevel@tonic-gate /* We should decrypt/re-encrypt the data to use the same mkvno*/
3477c478bd9Sstevel@tonic-gate db_entry->key_data[db_entry->n_key_data - 1] = key_data[i];
3487c478bd9Sstevel@tonic-gate memset(&key_data[i], 0, sizeof(krb5_key_data));
3497c478bd9Sstevel@tonic-gate }
3507c478bd9Sstevel@tonic-gate }
3517c478bd9Sstevel@tonic-gate cleanup_key_data(context, key_data_count, key_data);
3527c478bd9Sstevel@tonic-gate }
3537c478bd9Sstevel@tonic-gate return(retval);
3547c478bd9Sstevel@tonic-gate }
3557c478bd9Sstevel@tonic-gate
3567c478bd9Sstevel@tonic-gate /*
3577c478bd9Sstevel@tonic-gate * Add key_data for a krb5_db_entry
3587c478bd9Sstevel@tonic-gate * If passwd is NULL the assumes that the caller wants a random password.
3597c478bd9Sstevel@tonic-gate */
3607c478bd9Sstevel@tonic-gate static krb5_error_code
add_key_pwd(context,master_key,ks_tuple,ks_tuple_count,passwd,db_entry,kvno)3617c478bd9Sstevel@tonic-gate add_key_pwd(context, master_key, ks_tuple, ks_tuple_count, passwd,
3627c478bd9Sstevel@tonic-gate db_entry, kvno)
3637c478bd9Sstevel@tonic-gate krb5_context context;
3647c478bd9Sstevel@tonic-gate krb5_keyblock * master_key;
3657c478bd9Sstevel@tonic-gate krb5_key_salt_tuple * ks_tuple;
3667c478bd9Sstevel@tonic-gate int ks_tuple_count;
3677c478bd9Sstevel@tonic-gate char * passwd;
3687c478bd9Sstevel@tonic-gate krb5_db_entry * db_entry;
3697c478bd9Sstevel@tonic-gate int kvno;
3707c478bd9Sstevel@tonic-gate {
3717c478bd9Sstevel@tonic-gate krb5_error_code retval;
3727c478bd9Sstevel@tonic-gate krb5_keysalt key_salt;
3737c478bd9Sstevel@tonic-gate krb5_keyblock key;
3747c478bd9Sstevel@tonic-gate krb5_data pwd;
375*159d09a2SMark Phalan int i, j, k;
376*159d09a2SMark Phalan krb5_key_data tmp_key_data;
377*159d09a2SMark Phalan krb5_key_data *tptr;
378*159d09a2SMark Phalan
379*159d09a2SMark Phalan memset( &tmp_key_data, 0, sizeof(tmp_key_data));
3807c478bd9Sstevel@tonic-gate
3817c478bd9Sstevel@tonic-gate retval = 0;
38256a424ccSmp153739
3837c478bd9Sstevel@tonic-gate for (i = 0; i < ks_tuple_count; i++) {
3847c478bd9Sstevel@tonic-gate krb5_boolean similar;
3857c478bd9Sstevel@tonic-gate
3867c478bd9Sstevel@tonic-gate similar = 0;
3877c478bd9Sstevel@tonic-gate
3887c478bd9Sstevel@tonic-gate /*
3897c478bd9Sstevel@tonic-gate * We could use krb5_keysalt_iterate to replace this loop, or use
3907c478bd9Sstevel@tonic-gate * krb5_keysalt_is_present for the loop below, but we want to avoid
3917c478bd9Sstevel@tonic-gate * circular library dependencies.
3927c478bd9Sstevel@tonic-gate */
3937c478bd9Sstevel@tonic-gate for (j = 0; j < i; j++) {
3947c478bd9Sstevel@tonic-gate if ((retval = krb5_c_enctype_compare(context,
3957c478bd9Sstevel@tonic-gate ks_tuple[i].ks_enctype,
3967c478bd9Sstevel@tonic-gate ks_tuple[j].ks_enctype,
3977c478bd9Sstevel@tonic-gate &similar)))
3987c478bd9Sstevel@tonic-gate return(retval);
3997c478bd9Sstevel@tonic-gate
4007c478bd9Sstevel@tonic-gate if (similar &&
4017c478bd9Sstevel@tonic-gate (ks_tuple[j].ks_salttype == ks_tuple[i].ks_salttype))
4027c478bd9Sstevel@tonic-gate break;
4037c478bd9Sstevel@tonic-gate }
4047c478bd9Sstevel@tonic-gate
4057c478bd9Sstevel@tonic-gate if (j < i)
4067c478bd9Sstevel@tonic-gate continue;
4077c478bd9Sstevel@tonic-gate
40856a424ccSmp153739 if ((retval = krb5_dbe_create_key_data(context, db_entry)))
4097c478bd9Sstevel@tonic-gate return(retval);
4107c478bd9Sstevel@tonic-gate
4117c478bd9Sstevel@tonic-gate /* Convert password string to key using appropriate salt */
4127c478bd9Sstevel@tonic-gate switch (key_salt.type = ks_tuple[i].ks_salttype) {
4137c478bd9Sstevel@tonic-gate case KRB5_KDB_SALTTYPE_ONLYREALM: {
4147c478bd9Sstevel@tonic-gate krb5_data * saltdata;
41556a424ccSmp153739 if ((retval = krb5_copy_data(context, krb5_princ_realm(context,
41656a424ccSmp153739 db_entry->princ), &saltdata)))
4177c478bd9Sstevel@tonic-gate return(retval);
4187c478bd9Sstevel@tonic-gate
4197c478bd9Sstevel@tonic-gate key_salt.data = *saltdata;
4207c478bd9Sstevel@tonic-gate krb5_xfree(saltdata);
4217c478bd9Sstevel@tonic-gate }
4227c478bd9Sstevel@tonic-gate break;
4237c478bd9Sstevel@tonic-gate case KRB5_KDB_SALTTYPE_NOREALM:
42456a424ccSmp153739 if ((retval=krb5_principal2salt_norealm(context, db_entry->princ,
42556a424ccSmp153739 &key_salt.data)))
4267c478bd9Sstevel@tonic-gate return(retval);
4277c478bd9Sstevel@tonic-gate break;
4287c478bd9Sstevel@tonic-gate case KRB5_KDB_SALTTYPE_NORMAL:
42956a424ccSmp153739 if ((retval = krb5_principal2salt(context, db_entry->princ,
43056a424ccSmp153739 &key_salt.data)))
4317c478bd9Sstevel@tonic-gate return(retval);
4327c478bd9Sstevel@tonic-gate break;
4337c478bd9Sstevel@tonic-gate case KRB5_KDB_SALTTYPE_V4:
4347c478bd9Sstevel@tonic-gate key_salt.data.length = 0;
4357c478bd9Sstevel@tonic-gate key_salt.data.data = 0;
4367c478bd9Sstevel@tonic-gate break;
4377c478bd9Sstevel@tonic-gate case KRB5_KDB_SALTTYPE_AFS3: {
4387c478bd9Sstevel@tonic-gate #if 0
4397c478bd9Sstevel@tonic-gate krb5_data * saltdata;
4407c478bd9Sstevel@tonic-gate if (retval = krb5_copy_data(context, krb5_princ_realm(context,
4417c478bd9Sstevel@tonic-gate db_entry->princ), &saltdata))
4427c478bd9Sstevel@tonic-gate return(retval);
4437c478bd9Sstevel@tonic-gate
4447c478bd9Sstevel@tonic-gate key_salt.data = *saltdata;
44556a424ccSmp153739 key_salt.data.length = SALT_TYPE_AFS_LENGTH; /*length actually used below...*/
4467c478bd9Sstevel@tonic-gate krb5_xfree(saltdata);
4477c478bd9Sstevel@tonic-gate #else
4487c478bd9Sstevel@tonic-gate /* Why do we do this? Well, the afs_mit_string_to_key needs to
4497c478bd9Sstevel@tonic-gate use strlen, and the realm is not NULL terminated.... */
45056a424ccSmp153739 unsigned int slen =
45156a424ccSmp153739 (*krb5_princ_realm(context,db_entry->princ)).length;
4527c478bd9Sstevel@tonic-gate if(!(key_salt.data.data = (char *) malloc(slen+1)))
4537c478bd9Sstevel@tonic-gate return ENOMEM;
4547c478bd9Sstevel@tonic-gate key_salt.data.data[slen] = 0;
4557c478bd9Sstevel@tonic-gate memcpy((char *)key_salt.data.data,
4567c478bd9Sstevel@tonic-gate (char *)(*krb5_princ_realm(context,db_entry->princ)).data,
4577c478bd9Sstevel@tonic-gate slen);
45856a424ccSmp153739 key_salt.data.length = SALT_TYPE_AFS_LENGTH; /*length actually used below...*/
4597c478bd9Sstevel@tonic-gate #endif
4607c478bd9Sstevel@tonic-gate
4617c478bd9Sstevel@tonic-gate }
4627c478bd9Sstevel@tonic-gate break;
4637c478bd9Sstevel@tonic-gate default:
4647c478bd9Sstevel@tonic-gate return(KRB5_KDB_BAD_SALTTYPE);
4657c478bd9Sstevel@tonic-gate }
4667c478bd9Sstevel@tonic-gate
4677c478bd9Sstevel@tonic-gate pwd.data = passwd;
4687c478bd9Sstevel@tonic-gate pwd.length = strlen(passwd);
4697c478bd9Sstevel@tonic-gate
470*159d09a2SMark Phalan /* Solaris Kerberos */
4717c478bd9Sstevel@tonic-gate memset(&key, 0, sizeof (krb5_keyblock));
4727c478bd9Sstevel@tonic-gate
473*159d09a2SMark Phalan /* AFS string to key will happen here */
4747c478bd9Sstevel@tonic-gate if ((retval = krb5_c_string_to_key(context, ks_tuple[i].ks_enctype,
4757c478bd9Sstevel@tonic-gate &pwd, &key_salt.data, &key))) {
4767c478bd9Sstevel@tonic-gate if (key_salt.data.data)
4777c478bd9Sstevel@tonic-gate free(key_salt.data.data);
4787c478bd9Sstevel@tonic-gate return(retval);
4797c478bd9Sstevel@tonic-gate }
4807c478bd9Sstevel@tonic-gate
48156a424ccSmp153739 if (key_salt.data.length == SALT_TYPE_AFS_LENGTH)
4827c478bd9Sstevel@tonic-gate key_salt.data.length =
4837c478bd9Sstevel@tonic-gate krb5_princ_realm(context, db_entry->princ)->length;
4847c478bd9Sstevel@tonic-gate
485*159d09a2SMark Phalan /* memory allocation to be done by db. So, use temporary block and later copy
486*159d09a2SMark Phalan it to the memory allocated by db */
487*159d09a2SMark Phalan retval = krb5_dbekd_encrypt_key_data(context, master_key, &key,
4887c478bd9Sstevel@tonic-gate (const krb5_keysalt *)&key_salt,
489*159d09a2SMark Phalan kvno, &tmp_key_data);
4907c478bd9Sstevel@tonic-gate if (key_salt.data.data)
4917c478bd9Sstevel@tonic-gate free(key_salt.data.data);
4927c478bd9Sstevel@tonic-gate
493*159d09a2SMark Phalan /* Solaris Kerberos */
4947c478bd9Sstevel@tonic-gate krb5_free_keyblock_contents(context, &key);
4957c478bd9Sstevel@tonic-gate
496*159d09a2SMark Phalan if( retval )
497*159d09a2SMark Phalan return retval;
498*159d09a2SMark Phalan
499*159d09a2SMark Phalan tptr = &db_entry->key_data[db_entry->n_key_data-1];
500*159d09a2SMark Phalan
501*159d09a2SMark Phalan tptr->key_data_ver = tmp_key_data.key_data_ver;
502*159d09a2SMark Phalan tptr->key_data_kvno = tmp_key_data.key_data_kvno;
503*159d09a2SMark Phalan
504*159d09a2SMark Phalan for( k = 0; k < tmp_key_data.key_data_ver; k++ )
505*159d09a2SMark Phalan {
506*159d09a2SMark Phalan tptr->key_data_type[k] = tmp_key_data.key_data_type[k];
507*159d09a2SMark Phalan tptr->key_data_length[k] = tmp_key_data.key_data_length[k];
508*159d09a2SMark Phalan if( tmp_key_data.key_data_contents[k] )
509*159d09a2SMark Phalan {
510*159d09a2SMark Phalan tptr->key_data_contents[k] = krb5_db_alloc(context, NULL, tmp_key_data.key_data_length[k]);
511*159d09a2SMark Phalan if( tptr->key_data_contents[k] == NULL )
512*159d09a2SMark Phalan {
513*159d09a2SMark Phalan cleanup_key_data(context, db_entry->n_key_data, db_entry->key_data);
514*159d09a2SMark Phalan db_entry->key_data = NULL;
515*159d09a2SMark Phalan db_entry->n_key_data = 0;
516*159d09a2SMark Phalan retval = ENOMEM;
517*159d09a2SMark Phalan goto add_key_pwd_err;
5187c478bd9Sstevel@tonic-gate }
519*159d09a2SMark Phalan memcpy( tptr->key_data_contents[k], tmp_key_data.key_data_contents[k], tmp_key_data.key_data_length[k]);
520*159d09a2SMark Phalan
521*159d09a2SMark Phalan memset( tmp_key_data.key_data_contents[k], 0, tmp_key_data.key_data_length[k]);
522*159d09a2SMark Phalan free( tmp_key_data.key_data_contents[k] );
523*159d09a2SMark Phalan tmp_key_data.key_data_contents[k] = NULL;
524*159d09a2SMark Phalan }
525*159d09a2SMark Phalan }
526*159d09a2SMark Phalan }
527*159d09a2SMark Phalan add_key_pwd_err:
528*159d09a2SMark Phalan for( i = 0; i < tmp_key_data.key_data_ver; i++ )
529*159d09a2SMark Phalan {
530*159d09a2SMark Phalan if( tmp_key_data.key_data_contents[i] )
531*159d09a2SMark Phalan {
532*159d09a2SMark Phalan memset( tmp_key_data.key_data_contents[i], 0, tmp_key_data.key_data_length[i]);
533*159d09a2SMark Phalan free( tmp_key_data.key_data_contents[i] );
534*159d09a2SMark Phalan }
535*159d09a2SMark Phalan }
536*159d09a2SMark Phalan
5377c478bd9Sstevel@tonic-gate return(retval);
5387c478bd9Sstevel@tonic-gate }
5397c478bd9Sstevel@tonic-gate
5407c478bd9Sstevel@tonic-gate /*
5417c478bd9Sstevel@tonic-gate * Change password for a krb5_db_entry
5427c478bd9Sstevel@tonic-gate * Assumes the max kvno
5437c478bd9Sstevel@tonic-gate *
5447c478bd9Sstevel@tonic-gate * As a side effect all old keys are nuked if keepold is false.
5457c478bd9Sstevel@tonic-gate */
5467c478bd9Sstevel@tonic-gate krb5_error_code
krb5_dbe_def_cpw(context,master_key,ks_tuple,ks_tuple_count,passwd,new_kvno,keepold,db_entry)54754925bf6Swillf krb5_dbe_def_cpw(context, master_key, ks_tuple, ks_tuple_count, passwd,
5487c478bd9Sstevel@tonic-gate new_kvno, keepold, db_entry)
5497c478bd9Sstevel@tonic-gate krb5_context context;
5507c478bd9Sstevel@tonic-gate krb5_keyblock * master_key;
5517c478bd9Sstevel@tonic-gate krb5_key_salt_tuple * ks_tuple;
5527c478bd9Sstevel@tonic-gate int ks_tuple_count;
5537c478bd9Sstevel@tonic-gate char * passwd;
5547c478bd9Sstevel@tonic-gate int new_kvno;
5557c478bd9Sstevel@tonic-gate krb5_boolean keepold;
5567c478bd9Sstevel@tonic-gate krb5_db_entry * db_entry;
5577c478bd9Sstevel@tonic-gate {
5587c478bd9Sstevel@tonic-gate int key_data_count;
5597c478bd9Sstevel@tonic-gate int n_new_key_data;
5607c478bd9Sstevel@tonic-gate krb5_key_data * key_data;
5617c478bd9Sstevel@tonic-gate krb5_error_code retval;
5627c478bd9Sstevel@tonic-gate int old_kvno;
5637c478bd9Sstevel@tonic-gate int i;
5647c478bd9Sstevel@tonic-gate
5657c478bd9Sstevel@tonic-gate /* First save the old keydata */
5667c478bd9Sstevel@tonic-gate old_kvno = get_key_data_kvno(context, db_entry->n_key_data,
5677c478bd9Sstevel@tonic-gate db_entry->key_data);
5687c478bd9Sstevel@tonic-gate key_data_count = db_entry->n_key_data;
5697c478bd9Sstevel@tonic-gate key_data = db_entry->key_data;
5707c478bd9Sstevel@tonic-gate db_entry->key_data = NULL;
5717c478bd9Sstevel@tonic-gate db_entry->n_key_data = 0;
5727c478bd9Sstevel@tonic-gate
5737c478bd9Sstevel@tonic-gate /* increment the kvno. if the requested kvno is too small,
5747c478bd9Sstevel@tonic-gate increment the old kvno */
5757c478bd9Sstevel@tonic-gate if (new_kvno < old_kvno+1)
5767c478bd9Sstevel@tonic-gate new_kvno = old_kvno+1;
5777c478bd9Sstevel@tonic-gate
5787c478bd9Sstevel@tonic-gate retval = add_key_pwd(context, master_key, ks_tuple, ks_tuple_count,
5797c478bd9Sstevel@tonic-gate passwd, db_entry, new_kvno);
5807c478bd9Sstevel@tonic-gate if (retval) {
5817c478bd9Sstevel@tonic-gate cleanup_key_data(context, db_entry->n_key_data, db_entry->key_data);
5827c478bd9Sstevel@tonic-gate db_entry->n_key_data = key_data_count;
5837c478bd9Sstevel@tonic-gate db_entry->key_data = key_data;
5847c478bd9Sstevel@tonic-gate } else if (keepold) {
5857c478bd9Sstevel@tonic-gate n_new_key_data = db_entry->n_key_data;
5867c478bd9Sstevel@tonic-gate for (i = 0; i < key_data_count; i++) {
5877c478bd9Sstevel@tonic-gate retval = krb5_dbe_create_key_data(context, db_entry);
5887c478bd9Sstevel@tonic-gate if (retval) {
5897c478bd9Sstevel@tonic-gate cleanup_key_data(context, db_entry->n_key_data,
5907c478bd9Sstevel@tonic-gate db_entry->key_data);
5917c478bd9Sstevel@tonic-gate break;
5927c478bd9Sstevel@tonic-gate }
5937c478bd9Sstevel@tonic-gate db_entry->key_data[i+n_new_key_data] = key_data[i];
5947c478bd9Sstevel@tonic-gate memset(&key_data[i], 0, sizeof(krb5_key_data));
5957c478bd9Sstevel@tonic-gate }
59654925bf6Swillf krb5_db_free( context, key_data );
5977c478bd9Sstevel@tonic-gate } else {
5987c478bd9Sstevel@tonic-gate cleanup_key_data(context, key_data_count, key_data);
5997c478bd9Sstevel@tonic-gate }
6007c478bd9Sstevel@tonic-gate return(retval);
6017c478bd9Sstevel@tonic-gate }
6027c478bd9Sstevel@tonic-gate
6037c478bd9Sstevel@tonic-gate /*
6047c478bd9Sstevel@tonic-gate * Add password for a krb5_db_entry
6057c478bd9Sstevel@tonic-gate * Assumes the max kvno
6067c478bd9Sstevel@tonic-gate *
6077c478bd9Sstevel@tonic-gate * As a side effect all old keys older than the max kvno are nuked.
6087c478bd9Sstevel@tonic-gate */
6097c478bd9Sstevel@tonic-gate krb5_error_code
krb5_dbe_apw(context,master_key,ks_tuple,ks_tuple_count,passwd,db_entry)6107c478bd9Sstevel@tonic-gate krb5_dbe_apw(context, master_key, ks_tuple, ks_tuple_count, passwd, db_entry)
6117c478bd9Sstevel@tonic-gate krb5_context context;
6127c478bd9Sstevel@tonic-gate krb5_keyblock * master_key;
6137c478bd9Sstevel@tonic-gate krb5_key_salt_tuple * ks_tuple;
6147c478bd9Sstevel@tonic-gate int ks_tuple_count;
6157c478bd9Sstevel@tonic-gate char * passwd;
6167c478bd9Sstevel@tonic-gate krb5_db_entry * db_entry;
6177c478bd9Sstevel@tonic-gate {
6187c478bd9Sstevel@tonic-gate int key_data_count;
6197c478bd9Sstevel@tonic-gate krb5_key_data * key_data;
6207c478bd9Sstevel@tonic-gate krb5_error_code retval;
6217c478bd9Sstevel@tonic-gate int old_kvno, new_kvno;
6227c478bd9Sstevel@tonic-gate int i;
6237c478bd9Sstevel@tonic-gate
6247c478bd9Sstevel@tonic-gate /* First save the old keydata */
6257c478bd9Sstevel@tonic-gate old_kvno = get_key_data_kvno(context, db_entry->n_key_data,
6267c478bd9Sstevel@tonic-gate db_entry->key_data);
6277c478bd9Sstevel@tonic-gate key_data_count = db_entry->n_key_data;
6287c478bd9Sstevel@tonic-gate key_data = db_entry->key_data;
6297c478bd9Sstevel@tonic-gate db_entry->key_data = NULL;
6307c478bd9Sstevel@tonic-gate db_entry->n_key_data = 0;
6317c478bd9Sstevel@tonic-gate
6327c478bd9Sstevel@tonic-gate /* increment the kvno */
6337c478bd9Sstevel@tonic-gate new_kvno = old_kvno+1;
6347c478bd9Sstevel@tonic-gate
63556a424ccSmp153739 if ((retval = add_key_pwd(context, master_key, ks_tuple, ks_tuple_count,
63656a424ccSmp153739 passwd, db_entry, new_kvno))) {
6377c478bd9Sstevel@tonic-gate cleanup_key_data(context, db_entry->n_key_data, db_entry->key_data);
6387c478bd9Sstevel@tonic-gate db_entry->n_key_data = key_data_count;
6397c478bd9Sstevel@tonic-gate db_entry->key_data = key_data;
6407c478bd9Sstevel@tonic-gate } else {
6417c478bd9Sstevel@tonic-gate /* Copy keys with key_data_kvno == old_kvno */
6427c478bd9Sstevel@tonic-gate for (i = 0; i < key_data_count; i++) {
6437c478bd9Sstevel@tonic-gate if (key_data[i].key_data_kvno == old_kvno) {
64456a424ccSmp153739 if ((retval = krb5_dbe_create_key_data(context, db_entry))) {
6457c478bd9Sstevel@tonic-gate cleanup_key_data(context, db_entry->n_key_data,
6467c478bd9Sstevel@tonic-gate db_entry->key_data);
6477c478bd9Sstevel@tonic-gate break;
6487c478bd9Sstevel@tonic-gate }
6497c478bd9Sstevel@tonic-gate /* We should decrypt/re-encrypt the data to use the same mkvno*/
6507c478bd9Sstevel@tonic-gate db_entry->key_data[db_entry->n_key_data - 1] = key_data[i];
6517c478bd9Sstevel@tonic-gate memset(&key_data[i], 0, sizeof(krb5_key_data));
6527c478bd9Sstevel@tonic-gate }
6537c478bd9Sstevel@tonic-gate }
6547c478bd9Sstevel@tonic-gate cleanup_key_data(context, key_data_count, key_data);
6557c478bd9Sstevel@tonic-gate }
6567c478bd9Sstevel@tonic-gate return(retval);
6577c478bd9Sstevel@tonic-gate }
658*159d09a2SMark Phalan
659*159d09a2SMark Phalan
660