1 /*
2  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
3  * Use is subject to license terms.
4  */
5 
6 
7 /*
8  * lib/crypto/aes/aes_s2k.c
9  *
10  * Copyright 2003 by the Massachusetts Institute of Technology.
11  * All Rights Reserved.
12  *
13  * Export of this software from the United States of America may
14  *   require a specific license from the United States Government.
15  *   It is the responsibility of any person or organization contemplating
16  *   export to obtain such a license before exporting.
17  *
18  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
19  * distribute this software and its documentation for any purpose and
20  * without fee is hereby granted, provided that the above copyright
21  * notice appear in all copies and that both that copyright notice and
22  * this permission notice appear in supporting documentation, and that
23  * the name of M.I.T. not be used in advertising or publicity pertaining
24  * to distribution of the software without specific, written prior
25  * permission.  Furthermore if you modify this software you must label
26  * your software as modified software and not distribute it in such a
27  * fashion that it might be confused with the original M.I.T. software.
28  * M.I.T. makes no representations about the suitability of
29  * this software for any purpose.  It is provided "as is" without express
30  * or implied warranty.
31  *
32  *
33  * krb5int_aes_string_to_key
34  */
35 
36 #include "k5-int.h"
37 #include "dk.h"
38 #include "aes_s2k.h"
39 
40 #define DEFAULT_ITERATION_COUNT		4096 /* was 0xb000L in earlier drafts */
41 #define MAX_ITERATION_COUNT		0x1000000L
42 
43 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)44 krb5int_aes_string_to_key(krb5_context context,
45 			  const struct krb5_enc_provider *enc,
46 			  const krb5_data *string,
47 			  const krb5_data *salt,
48 			  const krb5_data *params,
49 			  krb5_keyblock *key)
50 {
51     unsigned long iter_count;
52     krb5_data out;
53     static const krb5_data usage = { KV5M_DATA, 8, "kerberos" };
54     krb5_error_code err;
55     /* Solaris Kerberos */
56     krb5_keyblock *inkey = NULL;
57 
58     if (params) {
59 	unsigned char *p = (unsigned char *) params->data;
60 	if (params->length != 4)
61 	    return KRB5_ERR_BAD_S2K_PARAMS;
62 	/* The first two need casts in case 'int' is 16 bits.  */
63 	iter_count = (((unsigned long)p[0] << 24)
64 		      | ((unsigned long)p[1] << 16)
65 		      | (p[2] <<  8)
66 		      | (p[3]));
67 	if (iter_count == 0) {
68 	/*
69 	    iter_count = (1L << 16) << 16;
70 	    if (((iter_count >> 16) >> 16) != 1)
71 		return KRB5_ERR_BAD_S2K_PARAMS;
72 	*/
73 	    iter_count = DEFAULT_ITERATION_COUNT;
74 	}
75     } else
76 	iter_count = DEFAULT_ITERATION_COUNT;
77 
78     /* This is not a protocol specification constraint; this is an
79        implementation limit, which should eventually be controlled by
80        a config file.  */
81     if (iter_count >= MAX_ITERATION_COUNT)
82 	return KRB5_ERR_BAD_S2K_PARAMS;
83 
84     /*
85      * Dense key space, no parity bits or anything, so take a shortcut
86      * and use the key contents buffer for the generated bytes.
87      */
88     /* Solaris Kerberos */
89     if (key->length != 16 && key->length != 32)
90 	return KRB5_CRYPTO_INTERNAL;
91     out.data = (char *) key->contents;
92     out.length = key->length;
93     /* Solaris Kerberos */
94     err = krb5int_pbkdf2_hmac_sha1 (context, &out, iter_count, key->enctype,
95 		string, salt);
96     if (err) {
97 	memset(out.data, 0, out.length);
98 	return err;
99     }
100 
101     /*
102      * Solaris Kerberos:
103      * The derive key operation below will not work correctly
104      * if the input and output key pointers are to the same
105      * data.  This is because the key object handle (PKCS#11)
106      * gets out-of-sync with the original key when the contents
107      * are modified.  We copy the original key here for use
108      * below in the derive_key step, then we free this key
109      * before exiting.
110      */
111     err  = krb5_copy_keyblock(context, key, &inkey);
112     if (err) {
113 	memset(out.data, 0, out.length);
114 	return err;
115     }
116 
117     err = krb5_derive_key (context, enc, inkey, key, &usage);
118     if (err) {
119 	memset(out.data, 0, out.length);
120     }
121     krb5_free_keyblock(context, inkey);
122 
123     return (err);
124 }
125