pbkdf2.c revision 7934:6aeeafc994de
1/*
2 * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
3 * Use is subject to license terms.
4 */
5
6
7/*
8 * lib/crypto/pbkdf2.c
9 *
10 * Copyright 2002 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 * Implementation of PBKDF2 from RFC 2898.
34 * Not currently used; likely to be used when we get around to AES support.
35 */
36
37#ifndef _KERNEL
38
39#include <ctype.h>
40#include "k5-int.h"
41#include "hash_provider.h"
42
43/*
44 * Solaris Kerberos:
45 * MIT code ripped out, use PBKDF2 algorithm from PKCS#11
46 * provider.
47 */
48krb5_error_code
49krb5int_pbkdf2_hmac_sha1(
50	krb5_context context,
51	const krb5_data *out,
52	unsigned long count,
53	krb5_enctype enctype,
54	const krb5_data *pass, const krb5_data *salt)
55{
56	krb5_error_code ret = 0;
57	CK_RV rv;
58	CK_PKCS5_PBKD2_PARAMS params;
59	CK_MECHANISM mechanism;
60	CK_OBJECT_CLASS class = CKO_SECRET_KEY;
61	CK_ATTRIBUTE tmpl[3];
62	CK_KEY_TYPE	keytype;
63	CK_OBJECT_HANDLE hKey;
64	int attrs = 0;
65	CK_ULONG outlen, passlen;
66
67	mechanism.mechanism = CKM_PKCS5_PBKD2;
68	mechanism.pParameter = &params;
69	mechanism.ulParameterLen = sizeof (params);
70
71	tmpl[attrs].type = CKA_CLASS;
72	tmpl[attrs].pValue = &class;
73	tmpl[attrs].ulValueLen = sizeof (class);
74	attrs++;
75
76	rv = get_key_type(enctype, &keytype);
77	if (rv != CKR_OK)
78		return (PKCS_ERR);
79
80	tmpl[attrs].type = CKA_KEY_TYPE;
81	tmpl[attrs].pValue = &keytype;
82	tmpl[attrs].ulValueLen = sizeof (keytype);
83	attrs++;
84
85	/*
86	 * For DES key types, do not include the value len attr.
87	 */
88	if (out->length > 0 &&
89	    enctype != ENCTYPE_DES_CBC_CRC &&
90	    enctype != ENCTYPE_DES_CBC_MD5 &&
91	    enctype != ENCTYPE_DES_CBC_RAW &&
92	    enctype != ENCTYPE_DES_HMAC_SHA1 &&
93	    enctype != ENCTYPE_DES3_CBC_SHA1 &&
94	    enctype != ENCTYPE_DES3_CBC_RAW) {
95		tmpl[attrs].type = CKA_VALUE_LEN;
96		/* using outlen to avoid 64bit alignment issues */
97		outlen = (CK_ULONG)out->length;
98		tmpl[attrs].pValue = &outlen;
99		tmpl[attrs].ulValueLen = sizeof(outlen);
100		attrs++;
101	}
102
103	params.saltSource = CKZ_SALT_SPECIFIED;
104	params.pSaltSourceData = (void *)salt->data;
105	params.ulSaltSourceDataLen = salt->length;
106	params.iterations = count;
107	params.prf = CKP_PKCS5_PBKD2_HMAC_SHA1;
108	params.pPrfData = NULL;
109	params.ulPrfDataLen = 0;
110	params.pPassword = (CK_UTF8CHAR_PTR)pass->data;
111	/* using passlen to avoid 64bit alignment issues */
112	passlen = (CK_ULONG)pass->length;
113	params.ulPasswordLen = &passlen;
114
115	rv = C_GenerateKey(krb_ctx_hSession(context), &mechanism, tmpl,
116		attrs, &hKey);
117
118	if (rv != CKR_OK)
119		ret = PKCS_ERR;
120	else {
121		/* Get the value from the key object. */
122		tmpl[0].type = CKA_VALUE;
123		tmpl[0].pValue = out->data;
124		tmpl[0].ulValueLen = out->length;
125		rv = C_GetAttributeValue(krb_ctx_hSession(context), hKey,
126			tmpl, 1);
127		if (rv != CKR_OK)
128			ret = PKCS_ERR;
129	}
130
131	(void) C_DestroyObject(krb_ctx_hSession(context), hKey);
132	return (ret);
133}
134#endif /* !_KERNEL */
135