Coverage Report

Created: 2025-08-09 06:30

/src/gss-ntlmssp/src/ntlm_crypto.c
Line
Count
Source (jump to first uncovered line)
1
/* Copyright 2013 Simo Sorce <simo@samba.org>, see COPYING for license */
2
3
/* This File implements the NTLM protocol as specified by:
4
 *      [MS-NLMP]: NT LAN Manager (NTLM) Authentication Protocol
5
 *
6
 * Additional cross checking with:
7
 * http://davenport.sourceforge.net/ntlm.html
8
 */
9
10
#include <errno.h>
11
#include <stddef.h>
12
#include <string.h>
13
14
#include <unicase.h>
15
#include <uniconv.h>
16
17
#include "ntlm.h"
18
#include "crypto.h"
19
20
/* signature structure, v1 or v2 */
21
#pragma pack(push, 1)
22
union wire_msg_signature {
23
    struct {
24
        uint32_t version;
25
        uint32_t random_pad;
26
        uint32_t checksum;
27
        uint32_t seq_num;
28
    } v1;
29
    struct {
30
        uint32_t version;
31
        uint64_t checksum;
32
        uint32_t seq_num;
33
    } v2;
34
};
35
#pragma pack(pop)
36
37
/* the max username is 20 chars, max NB domain len is 15, so 128 should be
38
 * plenty including conversion to UTF8 using max lenght for each code point
39
 */
40
0
#define MAX_USER_DOM_LEN 512
41
42
43
int NTOWFv1(const char *password, struct ntlm_key *result)
44
0
{
45
0
    struct ntlm_buffer payload;
46
0
    struct ntlm_buffer hash;
47
0
    char *retstr;
48
0
    size_t out;
49
0
    size_t len;
50
0
    int ret;
51
52
0
    len = strlen(password);
53
0
    retstr = u8_conv_to_encoding("UTF-16LE", iconveh_error,
54
0
                                 (const uint8_t *)password, len,
55
0
                                 NULL, NULL, &out);
56
0
    if (!retstr) return ERR_CRYPTO;
57
58
0
    payload.data = (uint8_t *)retstr;
59
0
    payload.length = out;
60
0
    hash.data = result->data;
61
0
    hash.length = result->length;
62
63
0
    ret = MD4_HASH(&payload, &hash);
64
0
    free(retstr);
65
0
    return ret;
66
0
}
67
68
#define DES_CONST "KGS!@#$%"
69
int LMOWFv1(const char *password, struct ntlm_key *result)
70
0
{
71
0
    struct ntlm_buffer key;
72
0
    struct ntlm_buffer plain;
73
0
    struct ntlm_buffer cipher;
74
0
    char upcased[15];
75
0
    char *retstr;
76
0
    size_t out;
77
0
    size_t len;
78
0
    int ret;
79
80
0
    if (result->length != 16) return EINVAL;
81
82
0
    len = strlen(password);
83
0
    if (len > 14) {
84
0
        memset(result->data, 0, result->length);
85
0
        return 0;
86
0
    }
87
88
0
    out = 15;
89
0
    retstr = (char *)u8_toupper((const uint8_t *)password, len,
90
0
                                NULL, NULL, (uint8_t *)upcased, &out);
91
0
    if (!retstr) return ERR_CRYPTO;
92
0
    if (retstr != upcased) {
93
0
        free(retstr);
94
0
        ret = EINVAL;
95
0
    }
96
0
    memset(&upcased[len], 0, 15 - len);
97
98
    /* part1 */
99
0
    key.data = (uint8_t *)upcased;
100
0
    key.length = 7;
101
0
    plain.data = discard_const(DES_CONST);
102
0
    plain.length = 8;
103
0
    cipher.data = result->data;
104
0
    cipher.length = 8;
105
0
    ret = WEAK_DES(&key, &plain, &cipher);
106
0
    if (ret) return ret;
107
108
    /* part2 */
109
0
    key.data = (uint8_t *)&upcased[7];
110
0
    key.length = 7;
111
0
    plain.data = discard_const(DES_CONST);
112
0
    plain.length = 8;
113
0
    cipher.data = &result->data[8];
114
0
    cipher.length = 8;
115
0
    return WEAK_DES(&key, &plain, &cipher);
116
0
}
117
118
int ntlm_compute_ext_sec_challenge(uint8_t *server_chal,
119
                                   uint8_t *client_chal,
120
                                   uint8_t *result_chal)
121
0
{
122
0
    uint8_t scbuf[16];
123
0
    uint8_t mdbuf[16];
124
0
    struct ntlm_buffer challenges = { scbuf, 16 };
125
0
    struct ntlm_buffer msgdigest = { mdbuf, 16 };
126
0
    int ret;
127
128
0
    memcpy(scbuf, server_chal, 8);
129
0
    memcpy(&scbuf[8], client_chal, 8);
130
0
    ret = MD5_HASH(&challenges, &msgdigest);
131
0
    if (ret) return ret;
132
133
0
    memcpy(result_chal, mdbuf, 8);
134
0
    return 0;
135
0
}
136
137
int ntlm_compute_nt_response(struct ntlm_key *nt_key, bool ext_sec,
138
                             uint8_t server_chal[8], uint8_t client_chal[8],
139
                             struct ntlm_buffer *nt_response)
140
0
{
141
0
    struct ntlm_buffer key = { nt_key->data, nt_key->length };
142
0
    uint8_t chal[8];
143
0
    struct ntlm_buffer payload = { chal, 8};
144
0
    int ret;
145
146
0
    if (ext_sec) {
147
0
        ret = ntlm_compute_ext_sec_challenge(server_chal, client_chal, chal);
148
0
        if (ret) return ret;
149
0
    } else {
150
0
        memcpy(chal, server_chal, 8);
151
0
    }
152
153
0
    return DESL(&key, &payload, nt_response);
154
0
}
155
156
int ntlm_compute_lm_response(struct ntlm_key *lm_key, bool ext_sec,
157
                             uint8_t server_chal[8], uint8_t client_chal[8],
158
                             struct ntlm_buffer *lm_response)
159
0
{
160
0
    struct ntlm_buffer key = { lm_key->data, lm_key->length };
161
0
    struct ntlm_buffer payload = { server_chal, 8 };
162
163
0
    if (ext_sec) {
164
0
        memcpy(lm_response->data, client_chal, 8);
165
0
        memset(&lm_response->data[8], 0, 16);
166
0
        return 0;
167
0
    }
168
0
    return DESL(&key, &payload, lm_response);
169
0
}
170
171
int ntlm_session_base_key(struct ntlm_key *nt_key,
172
                          struct ntlm_key *session_base_key)
173
0
{
174
0
    struct ntlm_buffer payload = { nt_key->data, nt_key->length };
175
0
    struct ntlm_buffer hash = { session_base_key->data,
176
0
                                session_base_key->length };
177
178
0
    return MD4_HASH(&payload, &hash);
179
0
}
180
181
int KXKEY(struct ntlm_ctx *ctx,
182
          bool ext_sec,
183
          bool neg_lm_key,
184
          bool non_nt_sess_key,
185
          uint8_t server_chal[8],
186
          struct ntlm_key *lm_key,
187
          struct ntlm_key *session_base_key,
188
          struct ntlm_buffer *lm_response,
189
          struct ntlm_key *key_exchange_key)
190
0
{
191
0
    struct ntlm_buffer payload;
192
0
    struct ntlm_buffer result;
193
0
    struct ntlm_buffer key;
194
0
    uint8_t buf[16];
195
0
    int ret = 0;
196
197
0
    if (ext_sec) {
198
0
        key.data = session_base_key->data;
199
0
        key.length = session_base_key->length;
200
0
        memcpy(buf, server_chal, 8);
201
0
        memcpy(&buf[8], lm_response->data, 8);
202
0
        payload.data = buf;
203
0
        payload.length = 16;
204
0
        result.data = key_exchange_key->data;
205
0
        result.length = key_exchange_key->length;
206
0
        ret = HMAC_MD5(&key, &payload, &result);
207
0
    } else if (neg_lm_key) {
208
0
        payload.data = lm_response->data;
209
0
        payload.length = 8;
210
0
        key.data = lm_key->data;
211
0
        key.length = 7;
212
0
        result.data = key_exchange_key->data;
213
0
        result.length = 8;
214
0
        ret = WEAK_DES(&key, &payload, &result);
215
0
        if (ret) return ret;
216
0
        buf[0] = lm_key->data[7];
217
0
        memset(&buf[1], 0xbd, 6);
218
0
        key.data = buf;
219
0
        result.data = &key_exchange_key->data[8];
220
0
        result.length = 8;
221
0
        ret = WEAK_DES(&key, &payload, &result);
222
0
    } else if (non_nt_sess_key) {
223
0
        memcpy(key_exchange_key->data, lm_key, 8);
224
0
        memset(&key_exchange_key->data[8], 0, 8);
225
0
    } else {
226
0
        memcpy(key_exchange_key->data, session_base_key->data, 16);
227
0
    }
228
0
    return ret;
229
0
}
230
231
int NTOWFv2(struct ntlm_ctx *ctx, struct ntlm_key *nt_hash,
232
            const char *user, const char *domain, struct ntlm_key *result)
233
0
{
234
0
    struct ntlm_buffer key = { nt_hash->data, nt_hash->length };
235
0
    struct ntlm_buffer hmac = { result->data, result->length };
236
0
    struct ntlm_buffer payload;
237
0
    uint8_t upcased[MAX_USER_DOM_LEN];
238
0
    uint8_t *retstr;
239
0
    size_t offs;
240
0
    size_t out;
241
0
    size_t len;
242
0
    int ret;
243
244
0
    len = strlen(user);
245
0
    out = MAX_USER_DOM_LEN;
246
0
    retstr = u8_toupper((const uint8_t *)user, len,
247
0
                        NULL, NULL, upcased, &out);
248
0
    if (!retstr) return ERR_CRYPTO;
249
0
    offs = out;
250
251
0
    if (domain) {
252
0
        len = strlen(domain);
253
0
        memcpy(&upcased[offs], domain, len);
254
0
        offs += len;
255
0
    }
256
257
0
    retstr = (uint8_t *)u8_conv_to_encoding("UTF-16LE", iconveh_error,
258
0
                                            upcased, offs, NULL, NULL, &out);
259
0
    if (!retstr) return ERR_CRYPTO;
260
261
0
    payload.data = (uint8_t *)retstr;
262
0
    payload.length = out;
263
264
0
    ret = HMAC_MD5(&key, &payload, &hmac);
265
0
    free(retstr);
266
0
    return ret;
267
0
}
268
269
int ntlmv2_compute_nt_response(struct ntlm_key *ntlmv2_key,
270
                               uint8_t server_chal[8], uint8_t client_chal[8],
271
                               uint64_t timestamp,
272
                               struct ntlm_buffer *target_info,
273
                               struct ntlm_buffer *nt_response)
274
0
{
275
0
    union wire_ntlm_response *nt_resp = NULL;
276
0
    struct wire_ntlmv2_cli_chal *r;
277
0
    struct ntlm_buffer key = { ntlmv2_key->data, ntlmv2_key->length };
278
0
    struct ntlm_buffer payload;
279
0
    struct ntlm_buffer nt_proof;
280
0
    size_t r_len;
281
0
    int ret;
282
283
    /* add additional 4 0s trailing target_info */
284
0
    r_len = sizeof(struct wire_ntlmv2_cli_chal) + target_info->length + 4;
285
0
    nt_resp = calloc(1, sizeof(nt_resp->v2) + r_len);
286
0
    if (!nt_resp) return ENOMEM;
287
288
0
    r = (struct wire_ntlmv2_cli_chal *)nt_resp->v2.cli_chal;
289
0
    r->resp_version = 1;
290
0
    r->hi_resp_version = 1;
291
0
    r->timestamp = htole64(timestamp);
292
0
    memcpy(r->client_chal, client_chal, 8);
293
0
    memcpy(r->target_info, target_info->data, target_info->length);
294
295
    /* use nt_resp as a buffer to calculate the NT proof as they share
296
     * the cli_chal part */
297
0
    payload.data = &nt_resp->v2.resp[8];
298
0
    payload.length = 8 + r_len;
299
0
    memcpy(payload.data, server_chal, 8);
300
0
    nt_proof.data = nt_resp->v2.resp;
301
0
    nt_proof.length = 16;
302
0
    ret = HMAC_MD5(&key, &payload, &nt_proof);
303
304
0
    if (ret) {
305
0
        safefree(nt_resp);
306
0
    } else {
307
0
        nt_response->data = (uint8_t *)nt_resp;
308
0
        nt_response->length = 16 + r_len;
309
0
    }
310
0
    return ret;
311
0
}
312
313
int ntlmv2_compute_lm_response(struct ntlm_key *ntlmv2_key,
314
                               uint8_t server_chal[8], uint8_t client_chal[8],
315
                               struct ntlm_buffer *lm_response)
316
0
{
317
0
    union wire_ntlm_response *lm_resp = NULL;
318
0
    struct ntlm_buffer key = { ntlmv2_key->data, ntlmv2_key->length };
319
0
    uint8_t payload_buf[16];
320
0
    struct ntlm_buffer payload = { payload_buf, 16 };
321
0
    struct ntlm_buffer lm_proof;
322
0
    int ret;
323
324
    /* now caluclate the LM Proof */
325
0
    lm_resp = malloc(sizeof(union wire_ntlm_response));
326
0
    if (!lm_resp) {
327
0
        ret = ENOMEM;
328
0
        goto done;
329
0
    }
330
331
0
    memcpy(payload.data, server_chal, 8);
332
0
    memcpy(&payload.data[8], client_chal, 8);
333
0
    lm_proof.data = lm_resp->v2.resp;
334
0
    lm_proof.length = 16;
335
0
    ret = HMAC_MD5(&key, &payload, &lm_proof);
336
337
0
done:
338
0
    if (ret) {
339
0
        safefree(lm_resp);
340
0
    } else {
341
0
        memcpy(lm_resp->v2.cli_chal, client_chal, 8);
342
343
0
        lm_response->data = (uint8_t *)lm_resp;
344
0
        lm_response->length = 24;
345
0
    }
346
0
    return ret;
347
0
}
348
349
int ntlmv2_session_base_key(struct ntlm_key *ntlmv2_key,
350
                            struct ntlm_buffer *nt_response,
351
                            struct ntlm_key *session_base_key)
352
0
{
353
0
    struct ntlm_buffer key = { ntlmv2_key->data, ntlmv2_key->length };
354
0
    struct ntlm_buffer hmac = { session_base_key->data,
355
0
                                session_base_key->length };
356
357
0
    if (session_base_key->length != 16) return EINVAL;
358
359
0
    return HMAC_MD5(&key, nt_response, &hmac);
360
0
}
361
362
int ntlm_exported_session_key(struct ntlm_key *key_exchange_key,
363
                              bool key_exch,
364
                              struct ntlm_key *exported_session_key)
365
0
{
366
0
    struct ntlm_buffer nonce;
367
368
0
    if (!key_exch) {
369
0
        *exported_session_key = *key_exchange_key;
370
0
        return 0;
371
0
    }
372
373
0
    exported_session_key->length = 16;
374
0
    nonce.data = exported_session_key->data;
375
0
    nonce.length = exported_session_key->length;
376
0
    return RAND_BUFFER(&nonce);
377
0
}
378
379
int ntlm_encrypted_session_key(struct ntlm_key *key,
380
                               struct ntlm_key *in, struct ntlm_key *out)
381
0
{
382
0
    struct ntlm_buffer _key = { key->data, key->length };
383
0
    struct ntlm_buffer data = { in->data, in->length };
384
0
    struct ntlm_buffer result = { out->data, out->length };
385
386
0
    return RC4K(&_key, NTLM_CIPHER_ENCRYPT, &data, &result);
387
0
}
388
389
static int ntlm_key_derivation_function(struct ntlm_key *key,
390
                                        const char *magic_constant,
391
                                        struct ntlm_key *derived_key)
392
0
{
393
0
    uint8_t buf[80]; /* key + constant is never larger than 80 */
394
0
    struct ntlm_buffer payload = { buf, 0 };
395
0
    struct ntlm_buffer result = { derived_key->data, 16 };
396
0
    size_t len;
397
0
    int ret;
398
399
0
    if (key->length > 16) return ERR_CRYPTO;
400
0
    len = strlen(magic_constant) + 1;
401
0
    if (len > 64) return ERR_CRYPTO;
402
403
0
    payload.length = key->length;
404
0
    memcpy(payload.data, key->data, key->length);
405
0
    memcpy(&payload.data[payload.length], magic_constant, len);
406
0
    payload.length += len;
407
408
0
    ret = MD5_HASH(&payload, &result);
409
0
    if (ret == 0) {
410
0
        derived_key->length = 16;
411
0
    }
412
0
    return ret;
413
0
}
414
415
0
#define NTLM_MODE_CLIENT true
416
0
#define NTLM_MODE_SERVER false
417
418
static int ntlm_signkey(bool mode,
419
                        struct ntlm_key *session_key,
420
                        struct ntlm_key *signing_key)
421
0
{
422
0
    const char *mc;
423
424
0
    if (mode == NTLM_MODE_CLIENT) {
425
0
        mc = "session key to client-to-server signing key magic constant";
426
0
    } else {
427
0
        mc = "session key to server-to-client signing key magic constant";
428
0
    }
429
0
    return ntlm_key_derivation_function(session_key,
430
0
                                        mc, signing_key);
431
0
}
432
433
static int ntlm_sealkey(uint32_t flags, bool mode,
434
                        struct ntlm_key *session_key,
435
                        struct ntlm_key *sealing_key)
436
0
{
437
0
    struct ntlm_key key;
438
0
    const char *mc;
439
440
0
    if (flags & NTLMSSP_NEGOTIATE_128) {
441
0
        key.length = 16;
442
0
    } else if (flags & NTLMSSP_NEGOTIATE_56) {
443
0
        key.length = 7;
444
0
    } else {
445
0
        key.length = 5;
446
0
    }
447
0
    memcpy(key.data, session_key->data, key.length);
448
449
0
    if (mode == NTLM_MODE_CLIENT) {
450
0
        mc = "session key to client-to-server sealing key magic constant";
451
0
    } else {
452
0
        mc = "session key to server-to-client sealing key magic constant";
453
0
    }
454
455
0
    return ntlm_key_derivation_function(&key, mc, sealing_key);
456
0
}
457
458
static void no_ext_sec_sealkey(uint32_t flags,
459
                               struct ntlm_key *session_key,
460
                               struct ntlm_buffer *sealing_key)
461
0
{
462
0
    if (flags & NTLMSSP_NEGOTIATE_LM_KEY) {
463
0
        if (flags & NTLMSSP_NEGOTIATE_56) {
464
0
            memcpy(sealing_key->data, session_key->data, 7);
465
0
            sealing_key->data[7] = 0xA0;
466
0
        } else {
467
0
            memcpy(sealing_key->data, session_key->data, 5);
468
0
            sealing_key->data[5] = 0xE5;
469
0
            sealing_key->data[6] = 0x38;
470
0
            sealing_key->data[7] = 0xB0;
471
0
        }
472
0
        sealing_key->length = 8;
473
0
    } else {
474
0
        memcpy(sealing_key->data, session_key->data, 16);
475
0
        sealing_key->length = session_key->length;
476
0
    }
477
0
}
478
479
static int no_ext_sec_handle(uint32_t flags,
480
                             struct ntlm_key *session_key,
481
                             struct ntlm_rc4_handle **seal_handle)
482
0
{
483
0
    uint8_t skbuf[16];
484
0
    struct ntlm_buffer sealing_key = { skbuf, 16 };
485
486
0
    no_ext_sec_sealkey(flags, session_key, &sealing_key);
487
488
0
    return RC4_INIT(&sealing_key, NTLM_CIPHER_ENCRYPT, seal_handle);
489
0
}
490
491
492
static int ext_sec_keys(uint32_t flags, bool client,
493
                        struct ntlm_key *session_key,
494
                        struct ntlm_signseal_state *state)
495
0
{
496
0
    struct ntlm_buffer rc4_key;
497
0
    bool mode;
498
0
    int ret;
499
500
0
    state->ext_sec = true;
501
0
    if (flags & NTLMSSP_NEGOTIATE_DATAGRAM) {
502
0
        state->datagram = true;
503
0
    }
504
505
    /* send key */
506
0
    mode = client ? NTLM_MODE_CLIENT : NTLM_MODE_SERVER;
507
0
    ret = ntlm_signkey(mode, session_key, &state->send.sign_key);
508
0
    if (ret) return ret;
509
    /* recv key */
510
0
    mode = client ? NTLM_MODE_SERVER : NTLM_MODE_CLIENT;
511
0
    ret = ntlm_signkey(mode, session_key, &state->recv.sign_key);
512
0
    if (ret) return ret;
513
514
    /* send key */
515
0
    mode = client ? NTLM_MODE_CLIENT : NTLM_MODE_SERVER;
516
0
    ret = ntlm_sealkey(flags, mode, session_key, &state->send.seal_key);
517
0
    if (ret) return ret;
518
    /* recv key */
519
0
    mode = client ? NTLM_MODE_SERVER : NTLM_MODE_CLIENT;
520
0
    ret = ntlm_sealkey(flags, mode, session_key, &state->recv.seal_key);
521
0
    if (ret) return ret;
522
523
0
    rc4_key.data = state->send.seal_key.data;
524
0
    rc4_key.length = state->send.seal_key.length;
525
0
    ret = RC4_INIT(&rc4_key, NTLM_CIPHER_ENCRYPT, &state->send.seal_handle);
526
0
    if (ret) return ret;
527
528
0
    rc4_key.data = state->recv.seal_key.data;
529
0
    rc4_key.length = state->recv.seal_key.length;
530
0
    ret = RC4_INIT(&rc4_key, NTLM_CIPHER_DECRYPT, &state->recv.seal_handle);
531
0
    if (ret) return ret;
532
533
0
    return 0;
534
0
}
535
536
int ntlm_signseal_keys(uint32_t flags, bool client,
537
                       struct ntlm_key *session_key,
538
                       struct ntlm_signseal_state *state)
539
0
{
540
541
0
    memset(state, 0, sizeof(struct ntlm_signseal_state));
542
543
0
    if (flags & NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY) {
544
0
        state->datagram = (flags & NTLMSSP_NEGOTIATE_DATAGRAM);
545
0
        return ext_sec_keys(flags, client, session_key, state);
546
0
    } else {
547
0
        return no_ext_sec_handle(flags, session_key,
548
0
                                 &state->send.seal_handle);
549
0
    }
550
0
}
551
552
int ntlm_reset_rc4_state(uint32_t flags, bool recv,
553
                         struct ntlm_key *session_key,
554
                         struct ntlm_signseal_state *state)
555
0
{
556
0
    struct ntlm_buffer rc4_key;
557
0
    int ret;
558
559
0
    if (!(flags & NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY)) {
560
0
        return no_ext_sec_handle(flags, session_key,
561
0
                                 &state->send.seal_handle);
562
0
    }
563
564
0
    if (recv) {
565
0
        RC4_FREE(&state->recv.seal_handle);
566
0
        rc4_key.data = state->recv.seal_key.data;
567
0
        rc4_key.length = state->recv.seal_key.length;
568
0
        ret = RC4_INIT(&rc4_key, NTLM_CIPHER_DECRYPT,
569
0
                       &state->recv.seal_handle);
570
0
    } else {
571
0
        RC4_FREE(&state->send.seal_handle);
572
0
        rc4_key.data = state->send.seal_key.data;
573
0
        rc4_key.length = state->send.seal_key.length;
574
0
        ret = RC4_INIT(&rc4_key, NTLM_CIPHER_ENCRYPT,
575
0
                       &state->send.seal_handle);
576
0
    }
577
0
    return ret;
578
0
}
579
580
void ntlm_release_rc4_state(struct ntlm_signseal_state *state)
581
1.20k
{
582
1.20k
    RC4_FREE(&state->recv.seal_handle);
583
1.20k
    RC4_FREE(&state->send.seal_handle);
584
1.20k
}
585
586
static int ntlm_seal_regen(struct ntlm_signseal_handle *h)
587
0
{
588
0
    struct ntlm_buffer payload;
589
0
    struct ntlm_buffer result;
590
0
    uint8_t inbuf[20];
591
0
    uint8_t outbuf[16];
592
0
    uint32_t le;
593
0
    int ret;
594
595
0
    RC4_FREE(&h->seal_handle);
596
597
0
    memcpy(inbuf, h->seal_key.data, h->seal_key.length);
598
0
    le = htole32(h->seq_num);
599
0
    memcpy(&inbuf[h->seal_key.length], &le, 4);
600
601
0
    payload.data = inbuf;
602
0
    payload.length = h->seal_key.length + 4;
603
0
    result.data = outbuf;
604
0
    result.length = 16;
605
606
0
    ret = MD5_HASH(&payload, &result);
607
0
    if (ret) return ret;
608
609
0
    ret = RC4_INIT(&result, NTLM_CIPHER_ENCRYPT, &h->seal_handle);
610
0
    return ret;
611
0
}
612
613
int ntlm_verify_nt_response(struct ntlm_buffer *nt_response,
614
                            struct ntlm_key *nt_key, bool ext_sec,
615
                            uint8_t server_chal[8], uint8_t client_chal[8])
616
0
{
617
0
    uint8_t buf[24];
618
0
    struct ntlm_buffer expected_response = { buf, 24 };
619
0
    int ret;
620
621
0
    ret = ntlm_compute_nt_response(nt_key, ext_sec,
622
0
                                   server_chal, client_chal,
623
0
                                   &expected_response);
624
0
    if (ret) return ret;
625
626
0
    ret = EINVAL;
627
0
    if (memcmp(nt_response->data, expected_response.data, 24) == 0) {
628
0
        ret = 0;
629
0
    }
630
631
0
    return ret;
632
0
}
633
634
int ntlm_verify_lm_response(struct ntlm_buffer *lm_response,
635
                            struct ntlm_key *lm_key, bool ext_sec,
636
                            uint8_t server_chal[8], uint8_t client_chal[8])
637
0
{
638
0
    uint8_t buf[24];
639
0
    struct ntlm_buffer expected_response = { buf, 24 };
640
0
    int ret;
641
642
0
    ret = ntlm_compute_lm_response(lm_key, ext_sec,
643
0
                                   server_chal, client_chal,
644
0
                                   &expected_response);
645
0
    if (ret) return ret;
646
647
0
    ret = EINVAL;
648
0
    if (memcmp(lm_response->data, expected_response.data, 24) == 0) {
649
0
        ret = 0;
650
0
    }
651
652
0
    return ret;
653
0
}
654
655
int ntlmv2_verify_nt_response(struct ntlm_buffer *nt_response,
656
                              struct ntlm_key *ntlmv2_key,
657
                              uint8_t server_chal[8])
658
0
{
659
0
    union wire_ntlm_response *nt_resp = NULL;
660
0
    struct ntlm_buffer key = { ntlmv2_key->data, ntlmv2_key->length };
661
0
    uint8_t proof[16];
662
0
    struct ntlm_buffer nt_proof = { proof, 16 };
663
0
    struct ntlm_buffer payload;
664
0
    int ret;
665
666
0
    if (nt_response->length < 24) return EINVAL;
667
668
0
    nt_resp = (union wire_ntlm_response *)nt_response->data;
669
670
0
    payload.length = nt_response->length - sizeof(nt_resp->v2.resp) + 8;
671
0
    payload.data = malloc(payload.length);
672
0
    if (!payload.data) return ENOMEM;
673
0
    memcpy(payload.data, server_chal, 8);
674
0
    memcpy(&payload.data[8], nt_resp->v2.cli_chal, payload.length - 8);
675
676
0
    ret = HMAC_MD5(&key, &payload, &nt_proof);
677
678
0
    if (ret) goto done;
679
680
0
    ret = EINVAL;
681
0
    if (memcmp(nt_resp->v2.resp, proof, 16) == 0) {
682
0
        ret = 0;
683
0
    }
684
685
0
done:
686
0
    safefree(payload.data);
687
0
    return ret;
688
0
}
689
690
int ntlmv2_verify_lm_response(struct ntlm_buffer *lm_response,
691
                              struct ntlm_key *ntlmv2_key,
692
                              uint8_t server_chal[8])
693
0
{
694
0
    struct ntlm_buffer key = { ntlmv2_key->data, ntlmv2_key->length };
695
0
    union wire_ntlm_response *lm_resp = NULL;
696
0
    uint8_t payload_buf[16];
697
0
    struct ntlm_buffer payload = { payload_buf, 16 };
698
0
    uint8_t proof[16];
699
0
    struct ntlm_buffer lm_proof = { proof, 16 };
700
0
    int ret;
701
702
0
    if (lm_response->length != 24) return EINVAL;
703
704
    /* now caluclate the LM Proof */
705
0
    lm_resp = (union wire_ntlm_response *)lm_response->data;
706
707
0
    memcpy(payload.data, server_chal, 8);
708
0
    memcpy(&payload.data[8], lm_resp->v2.cli_chal, 8);
709
0
    ret = HMAC_MD5(&key, &payload, &lm_proof);
710
711
0
    if (ret) return ret;
712
713
0
    if (memcmp(lm_resp->v2.resp, proof, 16) == 0) return 0;
714
715
0
    return EINVAL;
716
0
}
717
718
static int ntlmv2_sign(struct ntlm_key *sign_key, uint32_t seq_num,
719
                       struct ntlm_rc4_handle *handle, bool keyex,
720
                       struct ntlm_buffer *message,
721
                       struct ntlm_buffer *signature)
722
0
{
723
0
    struct ntlm_buffer key = { sign_key->data, sign_key->length };
724
0
    union wire_msg_signature *msg_sig;
725
0
    uint32_t le_seq;
726
0
    uint8_t le8seq[8];
727
0
    struct ntlm_buffer seq = { le8seq, 4 };
728
0
    struct ntlm_buffer *data[2];
729
0
    struct ntlm_iov iov;
730
0
    uint8_t hmac_sig[NTLM_SIGNATURE_SIZE];
731
0
    struct ntlm_buffer hmac = { hmac_sig, NTLM_SIGNATURE_SIZE };
732
0
    struct ntlm_buffer rc4buf;
733
0
    struct ntlm_buffer rc4res;
734
0
    int ret;
735
736
0
    msg_sig = (union wire_msg_signature *)signature->data;
737
0
    if (signature->length != NTLM_SIGNATURE_SIZE) {
738
0
        return EINVAL;
739
0
    }
740
741
0
    le_seq = htole32(seq_num);
742
0
    memcpy(seq.data, &le_seq, 4);
743
0
    data[0] = &seq;
744
0
    data[1] = message;
745
0
    iov.data = data;
746
0
    iov.num = 2;
747
748
0
    ret = HMAC_MD5_IOV(&key, &iov, &hmac);
749
0
    if (ret) return ret;
750
751
    /* put version */
752
0
    msg_sig->v2.version = htole32(NTLMSSP_MESSAGE_SIGNATURE_VERSION);
753
754
    /* put actual MAC */
755
0
    if (keyex) {
756
        /* encrypt truncated hmac */
757
0
        rc4buf.data = hmac.data;
758
0
        rc4buf.length = 8;
759
        /* and put it in the middle of the output signature */
760
0
        rc4res.data = (uint8_t *)&msg_sig->v2.checksum;
761
0
        rc4res.length = 8;
762
0
        ret = RC4_UPDATE(handle, &rc4buf, &rc4res);
763
0
        if (ret) return ret;
764
0
    } else {
765
0
        memcpy(&msg_sig->v2.checksum, hmac.data, 8);
766
0
    }
767
768
    /* put used seq_num */
769
0
    msg_sig->v2.seq_num = le_seq;
770
771
0
    return 0;
772
0
}
773
774
static int ntlmv1_sign(struct ntlm_rc4_handle *handle,
775
                       uint32_t random_pad, uint32_t seq_num,
776
                       struct ntlm_buffer *message,
777
                       struct ntlm_buffer *signature)
778
0
{
779
0
    union wire_msg_signature *msg_sig;
780
0
    uint32_t rc4buf[3];
781
0
    struct ntlm_buffer payload;
782
0
    struct ntlm_buffer result;
783
0
    int ret;
784
785
0
    msg_sig = (union wire_msg_signature *)signature->data;
786
0
    if (signature->length != NTLM_SIGNATURE_SIZE) {
787
0
        return EINVAL;
788
0
    }
789
790
0
    rc4buf[0] = random_pad;
791
0
    rc4buf[1] = htole32(CRC32(0, message));
792
0
    rc4buf[2] = htole32(seq_num);
793
794
0
    payload.data = (uint8_t *)rc4buf;
795
0
    payload.length = 12;
796
0
    result.data = (uint8_t *)&msg_sig->v1.random_pad;
797
0
    result.length = 12;
798
0
    ret = RC4_UPDATE(handle, &payload, &result);
799
0
    if (ret) return ret;
800
801
0
    msg_sig->v1.version = htole32(NTLMSSP_MESSAGE_SIGNATURE_VERSION);
802
0
    msg_sig->v1.random_pad = 0;
803
804
0
    return 0;
805
0
}
806
807
int ntlm_sign(uint32_t flags, int direction,
808
              struct ntlm_signseal_state *state,
809
              struct ntlm_buffer *message,
810
              struct ntlm_buffer *signature)
811
0
{
812
0
    struct ntlm_signseal_handle *h;
813
0
    int ret;
814
815
0
    if (direction == NTLM_SEND || !state->ext_sec) {
816
0
        h = &state->send;
817
0
    } else {
818
0
        h = &state->recv;
819
0
    }
820
821
0
    if (flags & NTLMSSP_NEGOTIATE_SIGN) {
822
0
        if (state->ext_sec) {
823
0
            if (state->datagram) {
824
0
                ret = ntlm_seal_regen(h);
825
0
                if (ret) return ret;
826
0
            }
827
828
0
            ret = ntlmv2_sign(&h->sign_key, h->seq_num, h->seal_handle,
829
0
                              (flags & NTLMSSP_NEGOTIATE_KEY_EXCH),
830
0
                              message, signature);
831
0
        } else {
832
0
            ret = ntlmv1_sign(h->seal_handle, 0, h->seq_num,
833
0
                              message, signature);
834
0
        }
835
0
        if (ret) return ret;
836
837
0
        if (!state->datagram) {
838
0
            h->seq_num++;
839
0
        }
840
0
        return 0;
841
842
0
    } else if (flags & NTLMSSP_NEGOTIATE_ALWAYS_SIGN) {
843
0
        uint32_t sig_ver = htole32(NTLMSSP_MESSAGE_SIGNATURE_VERSION);
844
0
        memcpy(signature->data, &sig_ver, 4);
845
0
        memset(&signature->data[4], 0, 12);
846
0
        return 0;
847
0
    }
848
849
0
    return ENOTSUP;
850
0
}
851
852
int ntlm_seal(uint32_t flags,
853
              struct ntlm_signseal_state *state,
854
              struct ntlm_buffer *message,
855
              struct ntlm_buffer *output,
856
              struct ntlm_buffer *signature)
857
0
{
858
0
    struct ntlm_signseal_handle *h;
859
0
    int ret;
860
861
0
    h = &state->send;
862
863
0
    if (h->seal_handle == NULL) {
864
0
        return EINVAL;
865
0
    }
866
867
0
    ret = RC4_UPDATE(h->seal_handle, message, output);
868
0
    if (ret) return ret;
869
870
0
    if (state->ext_sec) {
871
0
        if (state->datagram) {
872
0
            ret = ntlm_seal_regen(h);
873
0
            if (ret) return ret;
874
0
        }
875
0
        ret = ntlmv2_sign(&h->sign_key, h->seq_num, h->seal_handle,
876
0
                          (flags & NTLMSSP_NEGOTIATE_KEY_EXCH),
877
0
                          message, signature);
878
0
    } else {
879
0
        ret = ntlmv1_sign(h->seal_handle, 0, h->seq_num, message, signature);
880
0
    }
881
0
    if (ret) return ret;
882
883
0
    if (!state->datagram) {
884
0
        h->seq_num++;
885
0
    }
886
0
    return 0;
887
0
}
888
889
int ntlm_unseal(uint32_t flags,
890
                struct ntlm_signseal_state *state,
891
                struct ntlm_buffer *message,
892
                struct ntlm_buffer *output,
893
                struct ntlm_buffer *signature)
894
0
{
895
0
    struct ntlm_signseal_handle *h;
896
0
    int ret;
897
898
0
    if (!state->ext_sec) {
899
0
        h = &state->send;
900
0
    } else {
901
0
        h = &state->recv;
902
0
    }
903
904
0
    if (h->seal_handle == NULL) {
905
0
        return EINVAL;
906
0
    }
907
908
0
    ret = RC4_UPDATE(h->seal_handle, message, output);
909
0
    if (ret) return ret;
910
911
0
    if (state->ext_sec) {
912
0
        if (state->datagram) {
913
0
            ret = ntlm_seal_regen(h);
914
0
            if (ret) return ret;
915
0
        }
916
0
        ret = ntlmv2_sign(&h->sign_key, h->seq_num, h->seal_handle,
917
0
                          (flags & NTLMSSP_NEGOTIATE_KEY_EXCH),
918
0
                          output, signature);
919
0
    } else {
920
0
        ret = ntlmv1_sign(h->seal_handle, 0, h->seq_num, output, signature);
921
0
    }
922
0
    if (ret) return ret;
923
924
0
    if (!state->datagram) {
925
0
        h->seq_num++;
926
0
    }
927
0
    return 0;
928
0
}
929
930
int ntlm_mic(struct ntlm_key *exported_session_key,
931
             struct ntlm_buffer *negotiate_message,
932
             struct ntlm_buffer *challenge_message,
933
             struct ntlm_buffer *authenticate_message,
934
             struct ntlm_buffer *mic)
935
0
{
936
0
    struct ntlm_buffer key = { exported_session_key->data,
937
0
                               exported_session_key->length };
938
0
    struct ntlm_buffer *data[3] = { negotiate_message,
939
0
                                    challenge_message,
940
0
                                    authenticate_message };
941
0
    struct ntlm_iov iov;
942
943
0
    if (negotiate_message->length == 0) {
944
        /* connectionless case */
945
0
        iov.data = &data[1];
946
0
        iov.num = 2;
947
0
    } else {
948
0
        iov.data = data;
949
0
        iov.num = 3;
950
0
    }
951
952
0
    return HMAC_MD5_IOV(&key, &iov, mic);
953
0
}
954
955
int ntlm_verify_mic(struct ntlm_key *key,
956
                    struct ntlm_buffer *negotiate_message,
957
                    struct ntlm_buffer *challenge_message,
958
                    struct ntlm_buffer *authenticate_message,
959
                    struct ntlm_buffer *mic)
960
0
{
961
0
    uint8_t micbuf[NTLM_SIGNATURE_SIZE];
962
0
    struct ntlm_buffer check_mic = { micbuf, NTLM_SIGNATURE_SIZE };
963
0
    struct wire_auth_msg *msg;
964
0
    size_t payload_offs;
965
0
    uint32_t flags;
966
0
    int ret;
967
968
0
    msg = (struct wire_auth_msg *)authenticate_message->data;
969
0
    payload_offs = offsetof(struct wire_auth_msg, payload);
970
971
    /* flags must be checked as they may push the payload further down */
972
0
    flags = le32toh(msg->neg_flags);
973
0
    if ((flags & NTLMSSP_NEGOTIATE_VERSION) == 0) {
974
0
        struct wire_version zver = {0};
975
        /* mic is at payload_offs right now, but this offset may
976
         * need to be reduced if the sender completely omitted
977
         * the version struct, as some older clients do */
978
0
        if (memcmp(&msg->version, &zver,
979
0
                   sizeof(struct wire_version)) != 0) {
980
            /* version struct is not all zeros, this indicates the actual
981
             * struct was omitted and payload is shifted down */
982
0
            payload_offs -= sizeof(struct wire_version);
983
0
        }
984
0
    }
985
986
0
    if (payload_offs + NTLM_SIGNATURE_SIZE > authenticate_message->length) {
987
0
        return EINVAL;
988
0
    }
989
990
    /* payload_offs now points at the MIC buffer, clear it off in order
991
     * to be able to calculate the original chcksum */
992
0
    memset(&authenticate_message->data[payload_offs], 0, NTLM_SIGNATURE_SIZE);
993
994
0
    ret = ntlm_mic(key, negotiate_message, challenge_message,
995
0
                        authenticate_message, &check_mic);
996
0
    if (ret) return ret;
997
998
0
    if (memcmp(mic->data, check_mic.data, NTLM_SIGNATURE_SIZE) != 0) {
999
0
        return EACCES;
1000
0
    }
1001
1002
0
    return 0;
1003
0
}
1004
1005
int ntlm_hash_channel_bindings(struct ntlm_buffer *unhashed,
1006
                               struct ntlm_buffer *signature)
1007
0
{
1008
0
    struct ntlm_buffer input;
1009
0
    uint32_t ulen;
1010
0
    int ret;
1011
1012
    /* The channel bindings are calculated according to RFC4121, 4.1.1.2,
1013
     * with a all initiator and acceptor fields zeroed, so we need 4 zeroed
1014
     * 32bit fields, and one little endian length field to include in the
1015
     * MD5 calculation */
1016
0
    input.length = sizeof(uint32_t) * 5 + unhashed->length;
1017
0
    input.data = malloc(input.length);
1018
0
    if (!input.data) return EINVAL;
1019
1020
0
    memset(input.data, 0, sizeof(uint32_t) * 4);
1021
0
    ulen = unhashed->length;
1022
0
    ulen = htole32(ulen);
1023
0
    memcpy(&input.data[sizeof(uint32_t) * 4], &ulen, sizeof(uint32_t));
1024
0
    memcpy(&input.data[sizeof(uint32_t) * 5], unhashed->data, unhashed->length);
1025
1026
0
    ret = MD5_HASH(&input, signature);
1027
1028
0
    safefree(input.data);
1029
0
    return ret;
1030
0
}
1031
1032
int ntlm_verify_channel_bindings(struct ntlm_buffer *unhashed,
1033
                                 struct ntlm_buffer *signature)
1034
0
{
1035
0
    uint8_t cbbuf[16];
1036
0
    struct ntlm_buffer cb = { cbbuf, 16 };
1037
0
    int ret;
1038
1039
0
    if (signature->length != 16) return EINVAL;
1040
1041
0
    ret = ntlm_hash_channel_bindings(unhashed, &cb);
1042
0
    if (ret) return ret;
1043
1044
0
    if (memcmp(cb.data, signature->data, 16) != 0) return EACCES;
1045
1046
0
    return 0;
1047
0
}