Home | History | Annotate | Download | only in crypto
      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
     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