Coverage Report

Created: 2026-04-12 06:29

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/krb5/src/lib/crypto/builtin/kdf.c
Line
Count
Source
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.57k
{
37
2.57k
    krb5_crypto_iov iov[5];
38
2.57k
    krb5_error_code ret;
39
2.57k
    krb5_data prf;
40
2.57k
    unsigned char ibuf[4], lbuf[4];
41
42
2.57k
    if (hash == NULL || rnd_out->length > hash->hashsize)
43
0
        return KRB5_CRYPTO_INTERNAL;
44
45
    /* Allocate encryption data buffer. */
46
2.57k
    ret = alloc_data(&prf, hash->hashsize);
47
2.57k
    if (ret)
48
0
        return ret;
49
50
    /* [i]2: four-byte big-endian binary string giving the block counter (1) */
51
2.57k
    iov[0].flags = KRB5_CRYPTO_TYPE_DATA;
52
2.57k
    iov[0].data = make_data(ibuf, sizeof(ibuf));
53
2.57k
    store_32_be(1, ibuf);
54
    /* Label */
55
2.57k
    iov[1].flags = KRB5_CRYPTO_TYPE_DATA;
56
2.57k
    iov[1].data = *label;
57
    /* 0x00: separator byte */
58
2.57k
    iov[2].flags = KRB5_CRYPTO_TYPE_DATA;
59
2.57k
    iov[2].data = make_data("", 1);
60
    /* Context */
61
2.57k
    iov[3].flags = KRB5_CRYPTO_TYPE_DATA;
62
2.57k
    iov[3].data = *context;
63
    /* [L]2: four-byte big-endian binary string giving the output length */
64
2.57k
    iov[4].flags = KRB5_CRYPTO_TYPE_DATA;
65
2.57k
    iov[4].data = make_data(lbuf, sizeof(lbuf));
66
2.57k
    store_32_be(rnd_out->length * 8, lbuf);
67
68
2.57k
    ret = krb5int_hmac(hash, key, iov, 5, &prf);
69
2.57k
    if (!ret)
70
2.57k
        k5memcpy(rnd_out->data, prf.data, rnd_out->length);
71
2.57k
    zapfree(prf.data, prf.length);
72
2.57k
    return ret;
73
2.57k
}
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.57k
{
79
2.57k
    size_t blocksize, keybytes, n;
80
2.57k
    krb5_crypto_iov iov[6];
81
2.57k
    krb5_error_code ret;
82
2.57k
    krb5_data prf;
83
2.57k
    unsigned int i;
84
2.57k
    unsigned char ibuf[4], Lbuf[4];
85
86
2.57k
    blocksize = enc->block_size;
87
2.57k
    keybytes = enc->keybytes;
88
89
2.57k
    if (key->keyblock.length != enc->keylength || rnd_out->length != keybytes)
90
0
        return KRB5_CRYPTO_INTERNAL;
91
92
    /* Allocate encryption data buffer. */
93
2.57k
    ret = alloc_data(&prf, blocksize);
94
2.57k
    if (ret)
95
0
        return ret;
96
97
    /* K(i-1): the previous block of PRF output, initially all-zeros. */
98
2.57k
    iov[0].flags = KRB5_CRYPTO_TYPE_DATA;
99
2.57k
    iov[0].data = prf;
100
    /* [i]2: four-byte big-endian binary string giving the block counter */
101
2.57k
    iov[1].flags = KRB5_CRYPTO_TYPE_DATA;
102
2.57k
    iov[1].data = make_data(ibuf, sizeof(ibuf));
103
    /* Label: the fixed derived-key input */
104
2.57k
    iov[2].flags = KRB5_CRYPTO_TYPE_DATA;
105
2.57k
    iov[2].data = *label;
106
    /* 0x00: separator byte */
107
2.57k
    iov[3].flags = KRB5_CRYPTO_TYPE_DATA;
108
2.57k
    iov[3].data = make_data("", 1);
109
    /* Context: (unused) */
110
2.57k
    iov[4].flags = KRB5_CRYPTO_TYPE_DATA;
111
2.57k
    iov[4].data = empty_data();
112
    /* [L]2: four-byte big-endian binary string giving the output length */
113
2.57k
    iov[5].flags = KRB5_CRYPTO_TYPE_DATA;
114
2.57k
    iov[5].data = make_data(Lbuf, sizeof(Lbuf));
115
2.57k
    store_32_be(rnd_out->length * 8, Lbuf);
116
117
3.86k
    for (i = 1, n = 0; n < keybytes; i++) {
118
        /* Update the block counter. */
119
3.86k
        store_32_be(i, ibuf);
120
121
        /* Compute a CMAC checksum, storing the result into K(i-1). */
122
3.86k
        ret = krb5int_cmac_checksum(enc, key, iov, 6, &prf);
123
3.86k
        if (ret)
124
0
            goto cleanup;
125
126
        /* Copy the result into the appropriate part of the output buffer. */
127
3.86k
        if (keybytes - n <= blocksize) {
128
2.57k
            memcpy(rnd_out->data + n, prf.data, keybytes - n);
129
2.57k
            break;
130
2.57k
        }
131
1.28k
        memcpy(rnd_out->data + n, prf.data, blocksize);
132
1.28k
        n += blocksize;
133
1.28k
    }
134
135
2.57k
cleanup:
136
2.57k
    zapfree(prf.data, blocksize);
137
2.57k
    return ret;
138
2.57k
}
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.59k
{
144
3.59k
    size_t blocksize, keybytes, n;
145
3.59k
    krb5_error_code ret;
146
3.59k
    krb5_data block = empty_data();
147
148
3.59k
    blocksize = enc->block_size;
149
3.59k
    keybytes = enc->keybytes;
150
151
3.59k
    if (blocksize == 1)
152
0
        return KRB5_BAD_ENCTYPE;
153
3.59k
    if (key->keyblock.length != enc->keylength || rnd_out->length != keybytes)
154
0
        return KRB5_CRYPTO_INTERNAL;
155
156
    /* Allocate encryption data buffer. */
157
3.59k
    ret = alloc_data(&block, blocksize);
158
3.59k
    if (ret)
159
0
        return ret;
160
161
    /* Initialize the input block. */
162
3.59k
    if (constant->length == blocksize) {
163
0
        memcpy(block.data, constant->data, blocksize);
164
3.59k
    } else {
165
3.59k
        krb5int_nfold(constant->length * 8, (uint8_t *)constant->data,
166
3.59k
                      blocksize * 8, (uint8_t *)block.data);
167
3.59k
    }
168
169
    /* Loop encrypting the blocks until enough key bytes are generated. */
170
3.59k
    n = 0;
171
6.90k
    while (n < keybytes) {
172
6.90k
        ret = encrypt_block(enc, key, &block);
173
6.90k
        if (ret)
174
0
            goto cleanup;
175
176
6.90k
        if ((keybytes - n) <= blocksize) {
177
3.59k
            memcpy(rnd_out->data + n, block.data, (keybytes - n));
178
3.59k
            break;
179
3.59k
        }
180
181
3.31k
        memcpy(rnd_out->data + n, block.data, blocksize);
182
3.31k
        n += blocksize;
183
3.31k
    }
184
185
3.59k
cleanup:
186
3.59k
    zapfree(block.data, blocksize);
187
3.59k
    return ret;
188
3.59k
}
189
190
#endif /* K5_BUILTIN_KDF */