+static int calc_ntlmv2_hash(struct cifsSesInfo *ses,
+ const struct nls_table *nls_cp)
+{
+ int rc = 0;
+ int len;
+ char nt_hash[16];
+ struct HMACMD5Context *pctxt;
+ wchar_t *user;
+ wchar_t *domain;
+
+ pctxt = kmalloc(sizeof(struct HMACMD5Context), GFP_KERNEL);
+
+ if (pctxt == NULL)
+ return -ENOMEM;
+
+ /* calculate md4 hash of password */
+ E_md4hash(ses->password, nt_hash);
+
+ /* convert Domainname to unicode and uppercase */
+ hmac_md5_init_limK_to_64(nt_hash, 16, pctxt);
+
+ /* convert ses->userName to unicode and uppercase */
+ len = strlen(ses->userName);
+ user = kmalloc(2 + (len * 2), GFP_KERNEL);
+ if (user == NULL)
+ goto calc_exit_2;
+ len = cifs_strtoUCS((__le16 *)user, ses->userName, len, nls_cp);
+ UniStrupr(user);
+ hmac_md5_update((char *)user, 2*len, pctxt);
+
+ /* convert ses->domainName to unicode and uppercase */
+ if (ses->domainName) {
+ len = strlen(ses->domainName);
+
+ domain = kmalloc(2 + (len * 2), GFP_KERNEL);
+ if (domain == NULL)
+ goto calc_exit_1;
+ len = cifs_strtoUCS((__le16 *)domain, ses->domainName, len,
+ nls_cp);
+ /* the following line was removed since it didn't work well
+ with lower cased domain name that passed as an option.
+ Maybe converting the domain name earlier makes sense */
+ /* UniStrupr(domain); */
+
+ hmac_md5_update((char *)domain, 2*len, pctxt);
+
+ kfree(domain);
+ }
+calc_exit_1:
+ kfree(user);
+calc_exit_2:
+ /* BB FIXME what about bytes 24 through 40 of the signing key?
+ compare with the NTLM example */
+ hmac_md5_final(ses->server->ntlmv2_hash, pctxt);
+
+ kfree(pctxt);
+ return rc;
+}
+
+void setup_ntlmv2_rsp(struct cifsSesInfo *ses, char *resp_buf,
+ const struct nls_table *nls_cp)