17c478bd9Sstevel@tonic-gate /*
2159d09a2SMark 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 /*
87c478bd9Sstevel@tonic-gate  * lib/crypto/aes/aes_s2k.c
97c478bd9Sstevel@tonic-gate  *
107c478bd9Sstevel@tonic-gate  * Copyright 2003 by the Massachusetts Institute of Technology.
117c478bd9Sstevel@tonic-gate  * All Rights Reserved.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * Export of this software from the United States of America may
147c478bd9Sstevel@tonic-gate  *   require a specific license from the United States Government.
157c478bd9Sstevel@tonic-gate  *   It is the responsibility of any person or organization contemplating
167c478bd9Sstevel@tonic-gate  *   export to obtain such a license before exporting.
17*55fea89dSDan Cross  *
187c478bd9Sstevel@tonic-gate  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
197c478bd9Sstevel@tonic-gate  * distribute this software and its documentation for any purpose and
207c478bd9Sstevel@tonic-gate  * without fee is hereby granted, provided that the above copyright
217c478bd9Sstevel@tonic-gate  * notice appear in all copies and that both that copyright notice and
227c478bd9Sstevel@tonic-gate  * this permission notice appear in supporting documentation, and that
237c478bd9Sstevel@tonic-gate  * the name of M.I.T. not be used in advertising or publicity pertaining
247c478bd9Sstevel@tonic-gate  * to distribution of the software without specific, written prior
257c478bd9Sstevel@tonic-gate  * permission.  Furthermore if you modify this software you must label
267c478bd9Sstevel@tonic-gate  * your software as modified software and not distribute it in such a
277c478bd9Sstevel@tonic-gate  * fashion that it might be confused with the original M.I.T. software.
287c478bd9Sstevel@tonic-gate  * M.I.T. makes no representations about the suitability of
297c478bd9Sstevel@tonic-gate  * this software for any purpose.  It is provided "as is" without express
307c478bd9Sstevel@tonic-gate  * or implied warranty.
31*55fea89dSDan Cross  *
327c478bd9Sstevel@tonic-gate  *
337c478bd9Sstevel@tonic-gate  * krb5int_aes_string_to_key
347c478bd9Sstevel@tonic-gate  */
357c478bd9Sstevel@tonic-gate 
36159d09a2SMark Phalan #include "k5-int.h"
37159d09a2SMark Phalan #include "dk.h"
38159d09a2SMark Phalan #include "aes_s2k.h"
397c478bd9Sstevel@tonic-gate 
407c478bd9Sstevel@tonic-gate #define DEFAULT_ITERATION_COUNT		4096 /* was 0xb000L in earlier drafts */
417c478bd9Sstevel@tonic-gate #define MAX_ITERATION_COUNT		0x1000000L
427c478bd9Sstevel@tonic-gate 
437c478bd9Sstevel@tonic-gate krb5_error_code
krb5int_aes_string_to_key(krb5_context context,const struct krb5_enc_provider * enc,const krb5_data * string,const krb5_data * salt,const krb5_data * params,krb5_keyblock * key)447c478bd9Sstevel@tonic-gate krb5int_aes_string_to_key(krb5_context context,
45159d09a2SMark Phalan 			  const struct krb5_enc_provider *enc,
46159d09a2SMark Phalan 			  const krb5_data *string,
47159d09a2SMark Phalan 			  const krb5_data *salt,
48159d09a2SMark Phalan 			  const krb5_data *params,
49159d09a2SMark Phalan 			  krb5_keyblock *key)
507c478bd9Sstevel@tonic-gate {
517c478bd9Sstevel@tonic-gate     unsigned long iter_count;
527c478bd9Sstevel@tonic-gate     krb5_data out;
537c478bd9Sstevel@tonic-gate     static const krb5_data usage = { KV5M_DATA, 8, "kerberos" };
547c478bd9Sstevel@tonic-gate     krb5_error_code err;
55159d09a2SMark Phalan     /* Solaris Kerberos */
567c478bd9Sstevel@tonic-gate     krb5_keyblock *inkey = NULL;
577c478bd9Sstevel@tonic-gate 
587c478bd9Sstevel@tonic-gate     if (params) {
597c478bd9Sstevel@tonic-gate 	unsigned char *p = (unsigned char *) params->data;
607c478bd9Sstevel@tonic-gate 	if (params->length != 4)
617c478bd9Sstevel@tonic-gate 	    return KRB5_ERR_BAD_S2K_PARAMS;
62159d09a2SMark Phalan 	/* The first two need casts in case 'int' is 16 bits.  */
63159d09a2SMark Phalan 	iter_count = (((unsigned long)p[0] << 24)
64159d09a2SMark Phalan 		      | ((unsigned long)p[1] << 16)
65159d09a2SMark Phalan 		      | (p[2] <<  8)
66159d09a2SMark Phalan 		      | (p[3]));
677c478bd9Sstevel@tonic-gate 	if (iter_count == 0) {
687c478bd9Sstevel@tonic-gate 	/*
697c478bd9Sstevel@tonic-gate 	    iter_count = (1L << 16) << 16;
707c478bd9Sstevel@tonic-gate 	    if (((iter_count >> 16) >> 16) != 1)
717c478bd9Sstevel@tonic-gate 		return KRB5_ERR_BAD_S2K_PARAMS;
727c478bd9Sstevel@tonic-gate 	*/
737c478bd9Sstevel@tonic-gate 	    iter_count = DEFAULT_ITERATION_COUNT;
747c478bd9Sstevel@tonic-gate 	}
757c478bd9Sstevel@tonic-gate     } else
767c478bd9Sstevel@tonic-gate 	iter_count = DEFAULT_ITERATION_COUNT;
777c478bd9Sstevel@tonic-gate 
787c478bd9Sstevel@tonic-gate     /* This is not a protocol specification constraint; this is an
797c478bd9Sstevel@tonic-gate        implementation limit, which should eventually be controlled by
807c478bd9Sstevel@tonic-gate        a config file.  */
817c478bd9Sstevel@tonic-gate     if (iter_count >= MAX_ITERATION_COUNT)
827c478bd9Sstevel@tonic-gate 	return KRB5_ERR_BAD_S2K_PARAMS;
837c478bd9Sstevel@tonic-gate 
847c478bd9Sstevel@tonic-gate     /*
857c478bd9Sstevel@tonic-gate      * Dense key space, no parity bits or anything, so take a shortcut
867c478bd9Sstevel@tonic-gate      * and use the key contents buffer for the generated bytes.
877c478bd9Sstevel@tonic-gate      */
88159d09a2SMark Phalan     /* Solaris Kerberos */
897c478bd9Sstevel@tonic-gate     if (key->length != 16 && key->length != 32)
907c478bd9Sstevel@tonic-gate 	return KRB5_CRYPTO_INTERNAL;
917c478bd9Sstevel@tonic-gate     out.data = (char *) key->contents;
927c478bd9Sstevel@tonic-gate     out.length = key->length;
93159d09a2SMark Phalan     /* Solaris Kerberos */
947c478bd9Sstevel@tonic-gate     err = krb5int_pbkdf2_hmac_sha1 (context, &out, iter_count, key->enctype,
957c478bd9Sstevel@tonic-gate 		string, salt);
967c478bd9Sstevel@tonic-gate     if (err) {
977c478bd9Sstevel@tonic-gate 	memset(out.data, 0, out.length);
987c478bd9Sstevel@tonic-gate 	return err;
997c478bd9Sstevel@tonic-gate     }
1007c478bd9Sstevel@tonic-gate 
1017c478bd9Sstevel@tonic-gate     /*
102*55fea89dSDan Cross      * Solaris Kerberos:
1037c478bd9Sstevel@tonic-gate      * The derive key operation below will not work correctly
1047c478bd9Sstevel@tonic-gate      * if the input and output key pointers are to the same
1057c478bd9Sstevel@tonic-gate      * data.  This is because the key object handle (PKCS#11)
1067c478bd9Sstevel@tonic-gate      * gets out-of-sync with the original key when the contents
1077c478bd9Sstevel@tonic-gate      * are modified.  We copy the original key here for use
1087c478bd9Sstevel@tonic-gate      * below in the derive_key step, then we free this key
1097c478bd9Sstevel@tonic-gate      * before exiting.
1107c478bd9Sstevel@tonic-gate      */
1117c478bd9Sstevel@tonic-gate     err  = krb5_copy_keyblock(context, key, &inkey);
1127c478bd9Sstevel@tonic-gate     if (err) {
1137c478bd9Sstevel@tonic-gate 	memset(out.data, 0, out.length);
1147c478bd9Sstevel@tonic-gate 	return err;
1157c478bd9Sstevel@tonic-gate     }
1167c478bd9Sstevel@tonic-gate 
1177c478bd9Sstevel@tonic-gate     err = krb5_derive_key (context, enc, inkey, key, &usage);
1187c478bd9Sstevel@tonic-gate     if (err) {
1197c478bd9Sstevel@tonic-gate 	memset(out.data, 0, out.length);
1207c478bd9Sstevel@tonic-gate     }
1217c478bd9Sstevel@tonic-gate     krb5_free_keyblock(context, inkey);
1227c478bd9Sstevel@tonic-gate 
1237c478bd9Sstevel@tonic-gate     return (err);
1247c478bd9Sstevel@tonic-gate }
125