1226031Sstas/*
2226031Sstas * Copyright (c) 1997 - 2008 Kungliga Tekniska H��gskolan
3226031Sstas * (Royal Institute of Technology, Stockholm, Sweden).
4226031Sstas * All rights reserved.
5226031Sstas *
6226031Sstas * Redistribution and use in source and binary forms, with or without
7226031Sstas * modification, are permitted provided that the following conditions
8226031Sstas * are met:
9226031Sstas *
10226031Sstas * 1. Redistributions of source code must retain the above copyright
11226031Sstas *    notice, this list of conditions and the following disclaimer.
12226031Sstas *
13226031Sstas * 2. Redistributions in binary form must reproduce the above copyright
14226031Sstas *    notice, this list of conditions and the following disclaimer in the
15226031Sstas *    documentation and/or other materials provided with the distribution.
16226031Sstas *
17226031Sstas * 3. Neither the name of the Institute nor the names of its contributors
18226031Sstas *    may be used to endorse or promote products derived from this software
19226031Sstas *    without specific prior written permission.
20226031Sstas *
21226031Sstas * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22226031Sstas * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23226031Sstas * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24226031Sstas * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25226031Sstas * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26226031Sstas * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27226031Sstas * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28226031Sstas * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29226031Sstas * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30226031Sstas * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31226031Sstas * SUCH DAMAGE.
32226031Sstas */
33226031Sstas
34226031Sstas#include "krb5_locl.h"
35226031Sstas
36226031Sstasstatic krb5_error_code
37226031SstasARCFOUR_string_to_key(krb5_context context,
38226031Sstas		      krb5_enctype enctype,
39226031Sstas		      krb5_data password,
40226031Sstas		      krb5_salt salt,
41226031Sstas		      krb5_data opaque,
42226031Sstas		      krb5_keyblock *key)
43226031Sstas{
44226031Sstas    krb5_error_code ret;
45226031Sstas    uint16_t *s = NULL;
46226031Sstas    size_t len = 0, i;
47226031Sstas    EVP_MD_CTX *m;
48226031Sstas
49226031Sstas    m = EVP_MD_CTX_create();
50226031Sstas    if (m == NULL) {
51226031Sstas	ret = ENOMEM;
52226031Sstas	krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
53226031Sstas	goto out;
54226031Sstas    }
55226031Sstas
56226031Sstas    EVP_DigestInit_ex(m, EVP_md4(), NULL);
57226031Sstas
58226031Sstas    ret = wind_utf8ucs2_length(password.data, &len);
59226031Sstas    if (ret) {
60226031Sstas	krb5_set_error_message (context, ret,
61226031Sstas				N_("Password not an UCS2 string", ""));
62226031Sstas	goto out;
63226031Sstas    }
64226031Sstas
65226031Sstas    s = malloc (len * sizeof(s[0]));
66226031Sstas    if (len != 0 && s == NULL) {
67226031Sstas	krb5_set_error_message (context, ENOMEM,
68226031Sstas				N_("malloc: out of memory", ""));
69226031Sstas	ret = ENOMEM;
70226031Sstas	goto out;
71226031Sstas    }
72226031Sstas
73226031Sstas    ret = wind_utf8ucs2(password.data, s, &len);
74226031Sstas    if (ret) {
75226031Sstas	krb5_set_error_message (context, ret,
76226031Sstas				N_("Password not an UCS2 string", ""));
77226031Sstas	goto out;
78226031Sstas    }
79226031Sstas
80226031Sstas    /* LE encoding */
81226031Sstas    for (i = 0; i < len; i++) {
82226031Sstas	unsigned char p;
83226031Sstas	p = (s[i] & 0xff);
84226031Sstas	EVP_DigestUpdate (m, &p, 1);
85226031Sstas	p = (s[i] >> 8) & 0xff;
86226031Sstas	EVP_DigestUpdate (m, &p, 1);
87226031Sstas    }
88226031Sstas
89226031Sstas    key->keytype = enctype;
90226031Sstas    ret = krb5_data_alloc (&key->keyvalue, 16);
91226031Sstas    if (ret) {
92226031Sstas	krb5_set_error_message (context, ENOMEM, N_("malloc: out of memory", ""));
93226031Sstas	goto out;
94226031Sstas    }
95226031Sstas    EVP_DigestFinal_ex (m, key->keyvalue.data, NULL);
96226031Sstas
97226031Sstas out:
98226031Sstas    EVP_MD_CTX_destroy(m);
99226031Sstas    if (s)
100226031Sstas	memset (s, 0, len);
101226031Sstas    free (s);
102226031Sstas    return ret;
103226031Sstas}
104226031Sstas
105226031Sstasstruct salt_type _krb5_arcfour_salt[] = {
106226031Sstas    {
107226031Sstas	KRB5_PW_SALT,
108226031Sstas	"pw-salt",
109226031Sstas	ARCFOUR_string_to_key
110226031Sstas    },
111226031Sstas    { 0 }
112226031Sstas};
113