Coverage Report

Created: 2026-05-24 06:47

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/samba/third_party/heimdal/lib/krb5/salt.c
Line
Count
Source
1
/*
2
 * Copyright (c) 1997 - 2008 Kungliga Tekniska Högskolan
3
 * (Royal Institute of Technology, Stockholm, Sweden).
4
 * All rights reserved.
5
 *
6
 * Redistribution and use in source and binary forms, with or without
7
 * modification, are permitted provided that the following conditions
8
 * are met:
9
 *
10
 * 1. Redistributions of source code must retain the above copyright
11
 *    notice, this list of conditions and the following disclaimer.
12
 *
13
 * 2. Redistributions in binary form must reproduce the above copyright
14
 *    notice, this list of conditions and the following disclaimer in the
15
 *    documentation and/or other materials provided with the distribution.
16
 *
17
 * 3. Neither the name of the Institute nor the names of its contributors
18
 *    may be used to endorse or promote products derived from this software
19
 *    without specific prior written permission.
20
 *
21
 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31
 * SUCH DAMAGE.
32
 */
33
34
#include "krb5_locl.h"
35
36
/* coverity[+alloc : arg-*3] */
37
KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
38
krb5_salttype_to_string (krb5_context context,
39
       krb5_enctype etype,
40
       krb5_salttype stype,
41
       char **string)
42
0
{
43
0
    struct _krb5_encryption_type *e;
44
0
    struct salt_type *st;
45
46
0
    *string = NULL;
47
0
    e = _krb5_find_enctype (etype);
48
0
    if (e == NULL) {
49
0
  krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
50
0
             "encryption type %d not supported",
51
0
             etype);
52
0
  return KRB5_PROG_ETYPE_NOSUPP;
53
0
    }
54
0
    for (st = e->keytype->string_to_key; st && st->type; st++) {
55
0
  if (st->type == stype) {
56
0
      *string = strdup (st->name);
57
0
      if (*string == NULL)
58
0
    return krb5_enomem(context);
59
0
      return 0;
60
0
  }
61
0
    }
62
0
    krb5_set_error_message (context, HEIM_ERR_SALTTYPE_NOSUPP,
63
0
          "salttype %d not supported", stype);
64
0
    return HEIM_ERR_SALTTYPE_NOSUPP;
65
0
}
66
67
KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
68
krb5_string_to_salttype (krb5_context context,
69
       krb5_enctype etype,
70
       const char *string,
71
       krb5_salttype *salttype)
72
0
{
73
0
    struct _krb5_encryption_type *e;
74
0
    struct salt_type *st;
75
76
0
    e = _krb5_find_enctype (etype);
77
0
    if (e == NULL) {
78
0
  krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
79
0
             N_("encryption type %d not supported", ""),
80
0
             etype);
81
0
  return KRB5_PROG_ETYPE_NOSUPP;
82
0
    }
83
0
    for (st = e->keytype->string_to_key; st && st->type; st++) {
84
0
  if (strcasecmp (st->name, string) == 0) {
85
0
      *salttype = st->type;
86
0
      return 0;
87
0
  }
88
0
    }
89
0
    krb5_set_error_message(context, HEIM_ERR_SALTTYPE_NOSUPP,
90
0
         N_("salttype %s not supported", ""), string);
91
0
    return HEIM_ERR_SALTTYPE_NOSUPP;
92
0
}
93
94
/*
95
 * Like MIT's krb5_string_to_keysalts(), but simpler and with a context
96
 * argument.
97
 */
98
KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
99
krb5_string_to_keysalts2(krb5_context context, const char *string,
100
                         size_t *nksaltp, krb5_key_salt_tuple **ksaltp)
101
0
{
102
    /* deleted: tupleseps, ksaltseps, dups */
103
0
    krb5_key_salt_tuple *tmp = NULL;
104
0
    krb5_error_code ret = 0;
105
0
    char *copy, *token, *stype_str;
106
0
    char *lasts = NULL;
107
0
    krb5_enctype etype;
108
0
    krb5_salttype stype;
109
0
    size_t i;
110
111
0
    *ksaltp = NULL;
112
0
    *nksaltp = 0;
113
0
    if ((copy = strdup(string)) == NULL)
114
0
        return krb5_enomem(context);
115
0
    for (token = strtok_r(copy, ", \t", &lasts), ret = 0;
116
0
         token != NULL;
117
0
         token = strtok_r(NULL, ", \t", &lasts)) {
118
0
        if ((stype_str = strchr(token, ':')) != NULL)
119
0
            *(stype_str++) = '\0';
120
0
        if ((ret = krb5_string_to_enctype(context, token, &etype)))
121
0
            continue;
122
0
        if (stype_str == NULL)
123
0
            stype = KRB5_PW_SALT;
124
0
        else if ((ret = krb5_string_to_salttype(context, etype, stype_str, &stype)))
125
0
            continue;
126
0
        for (i = 0; i < *nksaltp; i++) {
127
0
            if ((*ksaltp)[i].ks_enctype == etype &&
128
0
                (*ksaltp)[i].ks_salttype == stype)
129
0
                goto skip;
130
0
        }
131
0
        tmp = realloc(*ksaltp, ((*nksaltp) + 1) * sizeof(**ksaltp));
132
0
        if (tmp == NULL) {
133
0
            ret = krb5_enomem(context);
134
0
            break;
135
0
        }
136
0
        *ksaltp = tmp;
137
0
        (*ksaltp)[*nksaltp].ks_enctype = etype;
138
0
        (*ksaltp)[*nksaltp].ks_salttype = stype;
139
0
        (*nksaltp)++;
140
0
skip:
141
0
        (void)1;
142
0
    }
143
0
    free(copy);
144
0
    if (ret == ENOMEM) {
145
0
        free(*ksaltp);
146
0
        *nksaltp = 0;
147
0
        *ksaltp = NULL;
148
0
    } else if (*nksaltp) {
149
0
        return 0;
150
0
    } else if (ret == 0) {
151
0
        return KRB5_PROG_ETYPE_NOSUPP;
152
0
    }
153
0
    return ret;
154
0
}
155
156
157
KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
158
krb5_get_pw_salt(krb5_context context,
159
     krb5_const_principal principal,
160
     krb5_salt *salt)
161
0
{
162
0
    size_t len;
163
0
    size_t i;
164
0
    krb5_error_code ret;
165
0
    char *p;
166
167
0
    salt->salttype = KRB5_PW_SALT;
168
0
    len = strlen(principal->realm);
169
0
    for (i = 0; i < principal->name.name_string.len; ++i)
170
0
  len += strlen(principal->name.name_string.val[i]);
171
0
    ret = krb5_data_alloc (&salt->saltvalue, len);
172
0
    if (ret)
173
0
  return ret;
174
0
    p = salt->saltvalue.data;
175
0
    memcpy (p, principal->realm, strlen(principal->realm));
176
0
    p += strlen(principal->realm);
177
0
    for (i = 0; i < principal->name.name_string.len; ++i) {
178
0
  memcpy (p,
179
0
    principal->name.name_string.val[i],
180
0
    strlen(principal->name.name_string.val[i]));
181
0
  p += strlen(principal->name.name_string.val[i]);
182
0
    }
183
0
    return 0;
184
0
}
185
186
KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
187
krb5_free_salt(krb5_context context,
188
         krb5_salt salt)
189
0
{
190
0
    krb5_data_free(&salt.saltvalue);
191
0
    return 0;
192
0
}
193
194
KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
195
krb5_string_to_key_data (krb5_context context,
196
       krb5_enctype enctype,
197
       krb5_data password,
198
       krb5_const_principal principal,
199
       krb5_keyblock *key)
200
0
{
201
0
    krb5_error_code ret;
202
0
    krb5_salt salt;
203
204
0
    ret = krb5_get_pw_salt(context, principal, &salt);
205
0
    if(ret)
206
0
  return ret;
207
0
    ret = krb5_string_to_key_data_salt(context, enctype, password, salt, key);
208
0
    krb5_free_salt(context, salt);
209
0
    return ret;
210
0
}
211
212
KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
213
krb5_string_to_key (krb5_context context,
214
        krb5_enctype enctype,
215
        const char *password,
216
        krb5_const_principal principal,
217
        krb5_keyblock *key)
218
0
{
219
0
    krb5_data pw;
220
0
    pw.data = rk_UNCONST(password);
221
0
    pw.length = strlen(password);
222
0
    return krb5_string_to_key_data(context, enctype, pw, principal, key);
223
0
}
224
225
KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
226
krb5_string_to_key_data_salt (krb5_context context,
227
            krb5_enctype enctype,
228
            krb5_data password,
229
            krb5_salt salt,
230
            krb5_keyblock *key)
231
0
{
232
0
    krb5_data opaque;
233
0
    krb5_data_zero(&opaque);
234
0
    return krb5_string_to_key_data_salt_opaque(context, enctype, password,
235
0
                 salt, opaque, key);
236
0
}
237
238
/*
239
 * Do a string -> key for encryption type `enctype' operation on
240
 * `password' (with salt `salt' and the enctype specific data string
241
 * `opaque'), returning the resulting key in `key'
242
 */
243
244
KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
245
krb5_string_to_key_data_salt_opaque (krb5_context context,
246
             krb5_enctype enctype,
247
             krb5_data password,
248
             krb5_salt salt,
249
             krb5_data opaque,
250
             krb5_keyblock *key)
251
0
{
252
0
    struct _krb5_encryption_type *et =_krb5_find_enctype(enctype);
253
0
    struct salt_type *st;
254
0
    if(et == NULL) {
255
0
  krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
256
0
             N_("encryption type %d not supported", ""),
257
0
             enctype);
258
0
  return KRB5_PROG_ETYPE_NOSUPP;
259
0
    }
260
0
    for(st = et->keytype->string_to_key; st && st->type; st++)
261
0
  if(st->type == salt.salttype)
262
0
      return (*st->string_to_key)(context, enctype, password,
263
0
          salt, opaque, key);
264
0
    krb5_set_error_message(context, HEIM_ERR_SALTTYPE_NOSUPP,
265
0
         N_("salt type %d not supported", ""),
266
0
         salt.salttype);
267
0
    return HEIM_ERR_SALTTYPE_NOSUPP;
268
0
}
269
270
/*
271
 * Do a string -> key for encryption type `enctype' operation on the
272
 * string `password' (with salt `salt'), returning the resulting key
273
 * in `key'
274
 */
275
276
KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
277
krb5_string_to_key_salt (krb5_context context,
278
       krb5_enctype enctype,
279
       const char *password,
280
       krb5_salt salt,
281
       krb5_keyblock *key)
282
0
{
283
0
    krb5_data pw;
284
0
    pw.data = rk_UNCONST(password);
285
0
    pw.length = strlen(password);
286
0
    return krb5_string_to_key_data_salt(context, enctype, pw, salt, key);
287
0
}
288
289
KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
290
krb5_string_to_key_salt_opaque (krb5_context context,
291
        krb5_enctype enctype,
292
        const char *password,
293
        krb5_salt salt,
294
        krb5_data opaque,
295
        krb5_keyblock *key)
296
0
{
297
0
    krb5_data pw;
298
0
    pw.data = rk_UNCONST(password);
299
0
    pw.length = strlen(password);
300
0
    return krb5_string_to_key_data_salt_opaque(context, enctype,
301
0
                 pw, salt, opaque, key);
302
0
}
303
304
305
KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
306
krb5_string_to_key_derived(krb5_context context,
307
         const void *str,
308
         size_t len,
309
         krb5_enctype etype,
310
         krb5_keyblock *key)
311
0
{
312
0
    struct _krb5_encryption_type *et = _krb5_find_enctype(etype);
313
0
    krb5_error_code ret;
314
0
    struct _krb5_key_data kd;
315
0
    size_t keylen;
316
0
    u_char *tmp;
317
318
0
    if(et == NULL) {
319
0
  krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
320
0
        N_("encryption type %d not supported", ""),
321
0
        etype);
322
0
  return KRB5_PROG_ETYPE_NOSUPP;
323
0
    }
324
0
    keylen = et->keytype->bits / 8;
325
326
0
    ALLOC(kd.key, 1);
327
0
    if (kd.key == NULL)
328
0
  return krb5_enomem(context);
329
0
    ret = krb5_data_alloc(&kd.key->keyvalue, et->keytype->size);
330
0
    if(ret) {
331
0
  free(kd.key);
332
0
  return ret;
333
0
    }
334
0
    kd.key->keytype = etype;
335
0
    tmp = malloc (keylen);
336
0
    if(tmp == NULL) {
337
0
  krb5_free_keyblock(context, kd.key);
338
0
  return krb5_enomem(context);
339
0
    }
340
0
    ret = _krb5_n_fold(str, len, tmp, keylen);
341
0
    if (ret) {
342
0
  free(tmp);
343
0
  krb5_enomem(context);
344
0
  return ret;
345
0
    }
346
0
    kd.schedule = NULL;
347
0
    _krb5_DES3_random_to_key(context, kd.key, tmp, keylen);
348
0
    memset(tmp, 0, keylen);
349
0
    free(tmp);
350
0
    ret = _krb5_derive_key(context,
351
0
         et,
352
0
         &kd,
353
0
         "kerberos", /* XXX well known constant */
354
0
         strlen("kerberos"));
355
0
    if (ret) {
356
0
  _krb5_free_key_data(context, &kd, et);
357
0
  return ret;
358
0
    }
359
0
    ret = krb5_copy_keyblock_contents(context, kd.key, key);
360
0
    _krb5_free_key_data(context, &kd, et);
361
0
    return ret;
362
0
}