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 = ¶ms;
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