Coverage Report

Created: 2024-06-18 06:03

/src/gss-ntlmssp/src/crypto.c
Line
Count
Source (jump to first uncovered line)
1
/* Copyright 2013-2022 Simo Sorce <simo@samba.org>, see COPYING for license */
2
3
#include <errno.h>
4
#include <string.h>
5
6
#include <openssl/des.h>
7
#include <openssl/rc4.h>
8
#include <openssl/evp.h>
9
#include <openssl/rand.h>
10
#include <zlib.h>
11
12
#include "crypto.h"
13
14
/* legacy provider with openssl 3.0 */
15
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
16
#  include <openssl/provider.h>
17
#  include <openssl/crypto.h>
18
#endif
19
20
int RAND_BUFFER(struct ntlm_buffer *random)
21
957
{
22
957
    int ret;
23
24
957
    ret = RAND_bytes(random->data, random->length);
25
957
    if (ret != 1) {
26
0
        return ERR_CRYPTO;
27
0
    }
28
957
    return 0;
29
957
}
30
31
int HMAC_MD5_IOV(struct ntlm_buffer *key,
32
                 struct ntlm_iov *iov,
33
                 struct ntlm_buffer *result)
34
0
{
35
0
    EVP_MD_CTX* ctx = NULL;
36
0
    EVP_PKEY* pkey = NULL;
37
0
    size_t i;
38
0
    int ret = 0;
39
40
0
    if (result->length != 16) return EINVAL;
41
42
0
    pkey = EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, NULL, key->data, key->length);
43
0
    if (!pkey) {
44
0
        ret = ERR_CRYPTO;
45
0
        goto done;
46
0
    }
47
48
0
    ctx = EVP_MD_CTX_new();
49
0
    if (!ctx) {
50
0
        ret = ERR_CRYPTO;
51
0
        goto done;
52
0
    }
53
54
0
    ret = EVP_DigestSignInit(ctx, NULL, EVP_md5(), NULL, pkey);
55
0
    if (ret != 1) {
56
0
        ret = ERR_CRYPTO;
57
0
        goto done;
58
0
    }
59
60
0
    for (i = 0; i < iov->num; i++) {
61
0
        ret = EVP_DigestSignUpdate(ctx, iov->data[i]->data,
62
0
                                   iov->data[i]->length);
63
0
        if (ret != 1) {
64
0
            ret = ERR_CRYPTO;
65
0
            goto done;
66
0
        }
67
0
    }
68
69
0
    ret = EVP_DigestSignFinal(ctx, result->data, &result->length);
70
0
    if (ret != 1) {
71
0
        ret = ERR_CRYPTO;
72
0
        goto done;
73
0
    }
74
75
0
    ret = 0;
76
77
0
done:
78
0
    EVP_MD_CTX_free(ctx);
79
0
    EVP_PKEY_free(pkey);
80
0
    return ret;
81
0
}
82
83
int HMAC_MD5(struct ntlm_buffer *key,
84
             struct ntlm_buffer *payload,
85
             struct ntlm_buffer *result)
86
0
{
87
0
    struct ntlm_iov iov;
88
89
0
    iov.num = 1;
90
0
    iov.data = &payload;
91
0
    return HMAC_MD5_IOV(key, &iov, result);
92
0
}
93
94
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
95
typedef struct ossl3_library_context {
96
    OSSL_LIB_CTX *libctx;
97
    OSSL_PROVIDER *legacy_provider;
98
    OSSL_PROVIDER *default_provider;
99
} ossl3_context_t;
100
101
static pthread_once_t global_ossl3_ctx_init = PTHREAD_ONCE_INIT;
102
static ossl3_context_t *global_ossl3_ctx = NULL;
103
104
static void init_global_ossl3_ctx(void)
105
{
106
    ossl3_context_t *ctx = OPENSSL_malloc(sizeof(ossl3_context_t));
107
    if (!ctx) return;
108
109
    ctx->libctx = OSSL_LIB_CTX_new();
110
    if (!ctx->libctx) {
111
        OPENSSL_free(ctx);
112
        return;
113
    }
114
115
    /* Load both legacy and default provider as both may be needed */
116
    /* if they fail keep going and an error will be raised when we try to
117
     * fetch the cipher later */
118
    ctx->legacy_provider = OSSL_PROVIDER_load(ctx->libctx, "legacy");
119
    ctx->default_provider = OSSL_PROVIDER_load(ctx->libctx, "default");
120
    global_ossl3_ctx = ctx;
121
}
122
123
static ossl3_context_t *get_ossl3_ctx()
124
{
125
    int ret;
126
127
    ret = pthread_once(&global_ossl3_ctx_init, init_global_ossl3_ctx);
128
    if (ret != 0) {
129
        return NULL;
130
    }
131
132
    return global_ossl3_ctx;
133
}
134
135
__attribute__((destructor))
136
static void free_ossl3_ctx()
137
{
138
    ossl3_context_t *ctx = global_ossl3_ctx;
139
    if (ctx == NULL) return;
140
    if (ctx->legacy_provider) OSSL_PROVIDER_unload(ctx->legacy_provider);
141
    if (ctx->default_provider) OSSL_PROVIDER_unload(ctx->default_provider);
142
    if (ctx->libctx) OSSL_LIB_CTX_free(ctx->libctx);
143
144
    OPENSSL_free(ctx);
145
}
146
#endif
147
148
static int mdx_hash(const EVP_MD *type,
149
                    struct ntlm_buffer *payload,
150
                    struct ntlm_buffer *result)
151
0
{
152
0
    EVP_MD_CTX *ctx;
153
0
    unsigned int len;
154
0
    int ret;
155
156
0
    if (result->length != 16) return EINVAL;
157
158
0
    ctx = EVP_MD_CTX_new();
159
0
    if (!ctx) {
160
0
        ret = ERR_CRYPTO;
161
0
        goto done;
162
0
    }
163
164
0
    EVP_MD_CTX_init(ctx);
165
0
    ret = EVP_DigestInit_ex(ctx, type, NULL);
166
0
    if (ret == 0) {
167
0
        ret = ERR_CRYPTO;
168
0
        goto done;
169
0
    }
170
171
0
    ret = EVP_DigestUpdate(ctx, payload->data, payload->length);
172
0
    if (ret == 0) {
173
0
        ret = ERR_CRYPTO;
174
0
        goto done;
175
0
    }
176
177
0
    ret = EVP_DigestFinal_ex(ctx, result->data, &len);
178
0
    if (ret == 0) {
179
0
        ret = ERR_CRYPTO;
180
0
        goto done;
181
0
    }
182
183
0
    ret = 0;
184
185
0
done:
186
0
    if (ctx) EVP_MD_CTX_free(ctx);
187
0
    return ret;
188
0
}
189
190
int MD4_HASH(struct ntlm_buffer *payload,
191
             struct ntlm_buffer *result)
192
0
{
193
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
194
    ossl3_context_t *ossl3_ctx = NULL;
195
    EVP_MD *md;
196
    int ret;
197
198
    ossl3_ctx = get_ossl3_ctx();
199
    if (ossl3_ctx == NULL) {
200
        ret = ERR_CRYPTO;
201
        goto done;
202
    }
203
204
    md = EVP_MD_fetch(ossl3_ctx->libctx, "MD4", "");
205
    if (md == NULL) {
206
        ret = ERR_CRYPTO;
207
        goto done;
208
    }
209
210
    ret = mdx_hash(md, payload, result);
211
212
done:
213
    return ret;
214
#else
215
0
    return mdx_hash(EVP_md4(), payload, result);
216
0
#endif
217
218
0
}
219
220
int MD5_HASH(struct ntlm_buffer *payload,
221
             struct ntlm_buffer *result)
222
0
{
223
0
    return mdx_hash(EVP_md5(), payload, result);
224
0
}
225
226
struct ntlm_rc4_handle {
227
    RC4_KEY key;
228
};
229
230
int RC4_INIT(struct ntlm_buffer *rc4_key,
231
             enum ntlm_cipher_mode mode,
232
             struct ntlm_rc4_handle **out)
233
0
{
234
0
    struct ntlm_rc4_handle *handle;
235
236
0
    handle = malloc(sizeof(struct ntlm_rc4_handle));
237
0
    if (!handle) return ENOMEM;
238
239
0
    RC4_set_key(&handle->key, rc4_key->length, rc4_key->data);
240
241
0
    *out = handle;
242
0
    return 0;
243
0
}
244
245
int RC4_UPDATE(struct ntlm_rc4_handle *handle,
246
               struct ntlm_buffer *in, struct ntlm_buffer *out)
247
0
{
248
0
    if (out->length < in->length) return EINVAL;
249
250
0
    if (in->length > 0) {
251
0
        RC4(&handle->key, in->length, in->data, out->data);
252
0
    }
253
254
0
    out->length = in->length;
255
0
    return 0;
256
0
}
257
258
void RC4_FREE(struct ntlm_rc4_handle **handle)
259
2.29k
{
260
2.29k
    if (!handle || !*handle) return;
261
0
    safezero((uint8_t *)(&((*handle)->key)), sizeof(RC4_KEY));
262
0
    safefree(*handle);
263
0
}
264
265
int RC4_EXPORT(struct ntlm_rc4_handle *handle, struct ntlm_buffer *out)
266
0
{
267
0
    RC4_INT *data = (RC4_INT *)out->data;
268
0
    int len = 258 * sizeof(RC4_INT);
269
270
0
    if (out->length < len) return EINVAL;
271
272
0
    data[0] = handle->key.x;
273
0
    data[1] = handle->key.y;
274
0
    memcpy(&data[2], handle->key.data, sizeof(RC4_INT) * 256);
275
0
    out->length = len;
276
0
    return 0;
277
0
}
278
279
int RC4_IMPORT(struct ntlm_rc4_handle **_handle, struct ntlm_buffer *in)
280
0
{
281
0
    struct ntlm_rc4_handle *handle;
282
0
    RC4_INT *data = (RC4_INT *)in->data;
283
0
    int len = 258 * sizeof(RC4_INT);
284
285
0
    if (in->length != len) return EINVAL;
286
287
0
    handle = malloc(sizeof(struct ntlm_rc4_handle));
288
0
    if (!handle) return ENOMEM;
289
290
0
    handle->key.x = data[0];
291
0
    handle->key.y = data[1];
292
0
    memcpy(handle->key.data, &data[2], sizeof(RC4_INT) * 256);
293
294
0
    *_handle = handle;
295
0
    return 0;
296
0
}
297
298
int RC4K(struct ntlm_buffer *key,
299
         enum ntlm_cipher_mode mode,
300
         struct ntlm_buffer *payload,
301
         struct ntlm_buffer *result)
302
0
{
303
0
    struct ntlm_rc4_handle *handle;
304
0
    int ret;
305
306
0
    if (result->length < payload->length) return EINVAL;
307
308
0
    ret = RC4_INIT(key, mode, &handle);
309
0
    if (ret) return ret;
310
311
0
    ret = RC4_UPDATE(handle, payload, result);
312
313
0
    RC4_FREE(&handle);
314
0
    return ret;
315
0
}
316
317
int WEAK_DES(struct ntlm_buffer *key,
318
             struct ntlm_buffer *payload,
319
             struct ntlm_buffer *result)
320
0
{
321
0
    DES_key_schedule schedule;
322
0
    DES_cblock key8;
323
324
0
    if ((key->length != 7) ||
325
0
        (payload->length != 8) ||
326
0
        (result->length != 8)) {
327
0
        return EINVAL;
328
0
    }
329
330
    /* Undocumented shuffle needed before calling DES_set_key_unchecked */
331
0
    key8[0] =  key->data[0];
332
0
    key8[1] = (key->data[0] << 7) | (key->data[1] >> 1);
333
0
    key8[2] = (key->data[1] << 6) | (key->data[2] >> 2);
334
0
    key8[3] = (key->data[2] << 5) | (key->data[3] >> 3);
335
0
    key8[4] = (key->data[3] << 4) | (key->data[4] >> 4);
336
0
    key8[5] = (key->data[4] << 3) | (key->data[5] >> 5);
337
0
    key8[6] = (key->data[5] << 2) | (key->data[6] >> 6);
338
0
    key8[7] = (key->data[6] << 1);
339
340
0
    DES_set_key_unchecked(&key8, &schedule);
341
0
    DES_ecb_encrypt((DES_cblock *)payload->data,
342
0
                    (DES_cblock *)result->data, &schedule, 1);
343
0
    return 0;
344
0
}
345
346
int DESL(struct ntlm_buffer *key,
347
         struct ntlm_buffer *payload,
348
         struct ntlm_buffer *result)
349
0
{
350
0
    uint8_t buf7[7];
351
0
    struct ntlm_buffer key7;
352
0
    struct ntlm_buffer res8;
353
354
0
    if ((key->length != 16) ||
355
0
        (payload->length != 8) ||
356
0
        (result->length != 24)) {
357
0
        return EINVAL;
358
0
    }
359
360
    /* part 1 */
361
0
    key7.data = key->data;
362
0
    key7.length = 7;
363
0
    res8.data = result->data;
364
0
    res8.length = 8;
365
0
    WEAK_DES(&key7, payload, &res8);
366
    /* part 2 */
367
0
    key7.data = &key->data[7];
368
0
    key7.length = 7;
369
0
    res8.data = &result->data[8];
370
0
    res8.length = 8;
371
0
    WEAK_DES(&key7, payload, &res8);
372
    /* part 3 */
373
0
    memcpy(buf7, &key->data[14], 2);
374
0
    memset(&buf7[2], 0, 5);
375
0
    key7.data = buf7;
376
0
    key7.length = 7;
377
0
    res8.data = &result->data[16];
378
0
    res8.length = 8;
379
0
    WEAK_DES(&key7, payload, &res8);
380
381
0
    return 0;
382
0
}
383
384
uint32_t CRC32(uint32_t crc, struct ntlm_buffer *payload)
385
0
{
386
0
    return crc32(crc, payload->data, payload->length);
387
0
}