Coverage Report

Created: 2025-07-01 06:25

/src/krb5/src/lib/crypto/builtin/kdf.c
Line
Count
Source (jump to first uncovered line)
1
/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2
/*
3
 * Copyright (C) 1998 by the FundsXpress, INC.
4
 *
5
 * All rights reserved.
6
 *
7
 * Export of this software from the United States of America may require
8
 * a specific license from the United States Government.  It is the
9
 * responsibility of any person or organization contemplating export to
10
 * obtain such a license before exporting.
11
 *
12
 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
13
 * distribute this software and its documentation for any purpose and
14
 * without fee is hereby granted, provided that the above copyright
15
 * notice appear in all copies and that both that copyright notice and
16
 * this permission notice appear in supporting documentation, and that
17
 * the name of FundsXpress. not be used in advertising or publicity pertaining
18
 * to distribution of the software without specific, written prior
19
 * permission.  FundsXpress makes no representations about the suitability of
20
 * this software for any purpose.  It is provided "as is" without express
21
 * or implied warranty.
22
 *
23
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
24
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
25
 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
26
 */
27
28
#include "crypto_int.h"
29
30
#ifdef K5_BUILTIN_KDF
31
32
krb5_error_code
33
k5_sp800_108_counter_hmac(const struct krb5_hash_provider *hash,
34
                          krb5_key key, const krb5_data *label,
35
                          const krb5_data *context, krb5_data *rnd_out)
36
2.71k
{
37
2.71k
    krb5_crypto_iov iov[5];
38
2.71k
    krb5_error_code ret;
39
2.71k
    krb5_data prf;
40
2.71k
    unsigned char ibuf[4], lbuf[4];
41
42
2.71k
    if (hash == NULL || rnd_out->length > hash->hashsize)
43
0
        return KRB5_CRYPTO_INTERNAL;
44
45
    /* Allocate encryption data buffer. */
46
2.71k
    ret = alloc_data(&prf, hash->hashsize);
47
2.71k
    if (ret)
48
0
        return ret;
49
50
    /* [i]2: four-byte big-endian binary string giving the block counter (1) */
51
2.71k
    iov[0].flags = KRB5_CRYPTO_TYPE_DATA;
52
2.71k
    iov[0].data = make_data(ibuf, sizeof(ibuf));
53
2.71k
    store_32_be(1, ibuf);
54
    /* Label */
55
2.71k
    iov[1].flags = KRB5_CRYPTO_TYPE_DATA;
56
2.71k
    iov[1].data = *label;
57
    /* 0x00: separator byte */
58
2.71k
    iov[2].flags = KRB5_CRYPTO_TYPE_DATA;
59
2.71k
    iov[2].data = make_data("", 1);
60
    /* Context */
61
2.71k
    iov[3].flags = KRB5_CRYPTO_TYPE_DATA;
62
2.71k
    iov[3].data = *context;
63
    /* [L]2: four-byte big-endian binary string giving the output length */
64
2.71k
    iov[4].flags = KRB5_CRYPTO_TYPE_DATA;
65
2.71k
    iov[4].data = make_data(lbuf, sizeof(lbuf));
66
2.71k
    store_32_be(rnd_out->length * 8, lbuf);
67
68
2.71k
    ret = krb5int_hmac(hash, key, iov, 5, &prf);
69
2.71k
    if (!ret)
70
2.71k
        memcpy(rnd_out->data, prf.data, rnd_out->length);
71
2.71k
    zapfree(prf.data, prf.length);
72
2.71k
    return ret;
73
2.71k
}
74
75
krb5_error_code
76
k5_sp800_108_feedback_cmac(const struct krb5_enc_provider *enc, krb5_key key,
77
                           const krb5_data *label, krb5_data *rnd_out)
78
2.71k
{
79
2.71k
    size_t blocksize, keybytes, n;
80
2.71k
    krb5_crypto_iov iov[6];
81
2.71k
    krb5_error_code ret;
82
2.71k
    krb5_data prf;
83
2.71k
    unsigned int i;
84
2.71k
    unsigned char ibuf[4], Lbuf[4];
85
86
2.71k
    blocksize = enc->block_size;
87
2.71k
    keybytes = enc->keybytes;
88
89
2.71k
    if (key->keyblock.length != enc->keylength || rnd_out->length != keybytes)
90
0
        return KRB5_CRYPTO_INTERNAL;
91
92
    /* Allocate encryption data buffer. */
93
2.71k
    ret = alloc_data(&prf, blocksize);
94
2.71k
    if (ret)
95
0
        return ret;
96
97
    /* K(i-1): the previous block of PRF output, initially all-zeros. */
98
2.71k
    iov[0].flags = KRB5_CRYPTO_TYPE_DATA;
99
2.71k
    iov[0].data = prf;
100
    /* [i]2: four-byte big-endian binary string giving the block counter */
101
2.71k
    iov[1].flags = KRB5_CRYPTO_TYPE_DATA;
102
2.71k
    iov[1].data = make_data(ibuf, sizeof(ibuf));
103
    /* Label: the fixed derived-key input */
104
2.71k
    iov[2].flags = KRB5_CRYPTO_TYPE_DATA;
105
2.71k
    iov[2].data = *label;
106
    /* 0x00: separator byte */
107
2.71k
    iov[3].flags = KRB5_CRYPTO_TYPE_DATA;
108
2.71k
    iov[3].data = make_data("", 1);
109
    /* Context: (unused) */
110
2.71k
    iov[4].flags = KRB5_CRYPTO_TYPE_DATA;
111
2.71k
    iov[4].data = empty_data();
112
    /* [L]2: four-byte big-endian binary string giving the output length */
113
2.71k
    iov[5].flags = KRB5_CRYPTO_TYPE_DATA;
114
2.71k
    iov[5].data = make_data(Lbuf, sizeof(Lbuf));
115
2.71k
    store_32_be(rnd_out->length * 8, Lbuf);
116
117
4.07k
    for (i = 1, n = 0; n < keybytes; i++) {
118
        /* Update the block counter. */
119
4.07k
        store_32_be(i, ibuf);
120
121
        /* Compute a CMAC checksum, storing the result into K(i-1). */
122
4.07k
        ret = krb5int_cmac_checksum(enc, key, iov, 6, &prf);
123
4.07k
        if (ret)
124
0
            goto cleanup;
125
126
        /* Copy the result into the appropriate part of the output buffer. */
127
4.07k
        if (keybytes - n <= blocksize) {
128
2.71k
            memcpy(rnd_out->data + n, prf.data, keybytes - n);
129
2.71k
            break;
130
2.71k
        }
131
1.35k
        memcpy(rnd_out->data + n, prf.data, blocksize);
132
1.35k
        n += blocksize;
133
1.35k
    }
134
135
2.71k
cleanup:
136
2.71k
    zapfree(prf.data, blocksize);
137
2.71k
    return ret;
138
2.71k
}
139
140
krb5_error_code
141
k5_derive_random_rfc3961(const struct krb5_enc_provider *enc, krb5_key key,
142
                         const krb5_data *constant, krb5_data *rnd_out)
143
3.77k
{
144
3.77k
    size_t blocksize, keybytes, n;
145
3.77k
    krb5_error_code ret;
146
3.77k
    krb5_data block = empty_data();
147
148
3.77k
    blocksize = enc->block_size;
149
3.77k
    keybytes = enc->keybytes;
150
151
3.77k
    if (blocksize == 1)
152
0
        return KRB5_BAD_ENCTYPE;
153
3.77k
    if (key->keyblock.length != enc->keylength || rnd_out->length != keybytes)
154
0
        return KRB5_CRYPTO_INTERNAL;
155
156
    /* Allocate encryption data buffer. */
157
3.77k
    ret = alloc_data(&block, blocksize);
158
3.77k
    if (ret)
159
0
        return ret;
160
161
    /* Initialize the input block. */
162
3.77k
    if (constant->length == blocksize) {
163
0
        memcpy(block.data, constant->data, blocksize);
164
3.77k
    } else {
165
3.77k
        krb5int_nfold(constant->length * 8, (uint8_t *)constant->data,
166
3.77k
                      blocksize * 8, (uint8_t *)block.data);
167
3.77k
    }
168
169
    /* Loop encrypting the blocks until enough key bytes are generated. */
170
3.77k
    n = 0;
171
7.26k
    while (n < keybytes) {
172
7.26k
        ret = encrypt_block(enc, key, &block);
173
7.26k
        if (ret)
174
0
            goto cleanup;
175
176
7.26k
        if ((keybytes - n) <= blocksize) {
177
3.77k
            memcpy(rnd_out->data + n, block.data, (keybytes - n));
178
3.77k
            break;
179
3.77k
        }
180
181
3.48k
        memcpy(rnd_out->data + n, block.data, blocksize);
182
3.48k
        n += blocksize;
183
3.48k
    }
184
185
3.77k
cleanup:
186
3.77k
    zapfree(block.data, blocksize);
187
3.77k
    return ret;
188
3.77k
}
189
190
#endif /* K5_BUILTIN_KDF */