1 /*
2  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
3  * Use is subject to license terms.
4  */
5 
6 /*
7  * lib/crypto/pbkdf2.c
8  *
9  * Copyright 2002 by the Massachusetts Institute of Technology.
10  * All Rights Reserved.
11  *
12  * Export of this software from the United States of America may
13  *   require a specific license from the United States Government.
14  *   It is the responsibility of any person or organization contemplating
15  *   export to obtain such a license before exporting.
16  *
17  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
18  * distribute this software and its documentation for any purpose and
19  * without fee is hereby granted, provided that the above copyright
20  * notice appear in all copies and that both that copyright notice and
21  * this permission notice appear in supporting documentation, and that
22  * the name of M.I.T. not be used in advertising or publicity pertaining
23  * to distribution of the software without specific, written prior
24  * permission.  Furthermore if you modify this software you must label
25  * your software as modified software and not distribute it in such a
26  * fashion that it might be confused with the original M.I.T. software.
27  * M.I.T. makes no representations about the suitability of
28  * this software for any purpose.  It is provided "as is" without express
29  * or implied warranty.
30  *
31  *
32  * Implementation of PBKDF2 from RFC 2898.
33  * Not currently used; likely to be used when we get around to AES support.
34  */
35 
36 #ifndef _KERNEL
37 
38 #include <ctype.h>
39 #include "k5-int.h"
40 #include "hash_provider.h"
41 
42 /*
43  * Solaris Kerberos:
44  * MIT code ripped out, use PBKDF2 algorithm from PKCS#11
45  * provider.
46  */
47 krb5_error_code
krb5int_pbkdf2_hmac_sha1(krb5_context context,const krb5_data * out,unsigned long count,krb5_enctype enctype,const krb5_data * pass,const krb5_data * salt)48 krb5int_pbkdf2_hmac_sha1(
49 	krb5_context context,
50 	const krb5_data *out,
51 	unsigned long count,
52 	krb5_enctype enctype,
53 	const krb5_data *pass, const krb5_data *salt)
54 {
55 	krb5_error_code ret = 0;
56 	CK_RV rv;
57 	CK_PKCS5_PBKD2_PARAMS params;
58 	CK_MECHANISM mechanism;
59 	CK_OBJECT_CLASS class = CKO_SECRET_KEY;
60 	CK_ATTRIBUTE tmpl[3];
61 	CK_KEY_TYPE	keytype;
62 	CK_OBJECT_HANDLE hKey;
63 	int attrs = 0;
64 	CK_ULONG outlen, passlen;
65 
66 	mechanism.mechanism = CKM_PKCS5_PBKD2;
67 	mechanism.pParameter = &params;
68 	mechanism.ulParameterLen = sizeof (params);
69 
70 	tmpl[attrs].type = CKA_CLASS;
71 	tmpl[attrs].pValue = &class;
72 	tmpl[attrs].ulValueLen = sizeof (class);
73 	attrs++;
74 
75 	rv = get_key_type(enctype, &keytype);
76 	if (rv != CKR_OK)
77 		return (PKCS_ERR);
78 
79 	tmpl[attrs].type = CKA_KEY_TYPE;
80 	tmpl[attrs].pValue = &keytype;
81 	tmpl[attrs].ulValueLen = sizeof (keytype);
82 	attrs++;
83 
84 	/*
85 	 * For DES key types, do not include the value len attr.
86 	 */
87 	if (out->length > 0 &&
88 	    enctype != ENCTYPE_DES_CBC_CRC &&
89 	    enctype != ENCTYPE_DES_CBC_MD5 &&
90 	    enctype != ENCTYPE_DES_CBC_RAW &&
91 	    enctype != ENCTYPE_DES_HMAC_SHA1 &&
92 	    enctype != ENCTYPE_DES3_CBC_SHA1 &&
93 	    enctype != ENCTYPE_DES3_CBC_RAW) {
94 		tmpl[attrs].type = CKA_VALUE_LEN;
95 		/* using outlen to avoid 64bit alignment issues */
96 		outlen = (CK_ULONG)out->length;
97 		tmpl[attrs].pValue = &outlen;
98 		tmpl[attrs].ulValueLen = sizeof (outlen);
99 		attrs++;
100 	}
101 
102 	params.saltSource = CKZ_SALT_SPECIFIED;
103 	params.pSaltSourceData = (void *)salt->data;
104 	params.ulSaltSourceDataLen = salt->length;
105 	params.iterations = count;
106 	params.prf = CKP_PKCS5_PBKD2_HMAC_SHA1;
107 	params.pPrfData = NULL;
108 	params.ulPrfDataLen = 0;
109 	params.pPassword = (CK_UTF8CHAR_PTR)pass->data;
110 	/* using passlen to avoid 64bit alignment issues */
111 	passlen = (CK_ULONG)pass->length;
112 	params.ulPasswordLen = &passlen;
113 
114 	rv = C_GenerateKey(krb_ctx_hSession(context), &mechanism, tmpl,
115 	    attrs, &hKey);
116 
117 	if (rv != CKR_OK)
118 		ret = PKCS_ERR;
119 	else {
120 		/* Get the value from the key object. */
121 		tmpl[0].type = CKA_VALUE;
122 		tmpl[0].pValue = out->data;
123 		tmpl[0].ulValueLen = out->length;
124 		rv = C_GetAttributeValue(krb_ctx_hSession(context), hKey,
125 		    tmpl, 1);
126 		if (rv != CKR_OK)
127 			ret = PKCS_ERR;
128 		(void) C_DestroyObject(krb_ctx_hSession(context), hKey);
129 	}
130 
131 	return (ret);
132 }
133 #endif /* !_KERNEL */
134