~kvalo/wpasupplicant/bug-638303

« back to all changes in this revision

Viewing changes to eap_sim_common.c

  • Committer: Bazaar Package Importer
  • Author(s): Kel Modderman
  • Date: 2006-10-05 08:04:01 UTC
  • mfrom: (1.2.1 upstream) (2.1.14 edgy)
  • Revision ID: james.westby@ubuntu.com-20061005080401-myfwjtq7di70dyeo
* Update madwifi headers to latest SVN. (Closes: #388316)
* Remove failed attempt at action locking. [debian/functions.sh,
  debian/wpa_action.sh]
* Add hysteresis checking functions, to avoid "event loops" while
  using wpa-roam. [debian/functions.sh, debian/wpa_action.sh]
* Change of co-maintainer email address.
* Add ishex() function to functions.sh to determine wpa-psk value type in
  plaintext or hex. This effectively eliminates the need for the bogus and
  somewhat confusing wpa-passphrase contruct specific to our scripts and
  allows wpa-psk to work with either a 8 to 63 character long plaintext
  string or 64 character long hex string.
* Adjust README.modes to not refer to the redundant wpa-passphrase stuff.
* Add big fat NOTE about acceptable wpa-psk's to top of example gallery.
* Strip surrounding quotes from wpa-ssid if present, instead of just whining
  about them.
* Update email address in copyright blurb of functions.sh, ifupdown.sh and
  wpa_action.sh.  

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
 
 * WPA Supplicant / EAP-SIM/AKA shared routines
 
2
 * EAP peer: EAP-SIM/AKA shared routines
3
3
 * Copyright (c) 2004-2005, Jouni Malinen <jkmaline@cc.hut.fi>
4
4
 *
5
5
 * This program is free software; you can redistribute it and/or modify
12
12
 * See README and COPYING for more details.
13
13
 */
14
14
 
15
 
#include <stdlib.h>
16
 
#include <stdio.h>
17
 
#include <string.h>
 
15
#include "includes.h"
18
16
 
19
17
#include "common.h"
20
18
#include "eap_i.h"
21
19
#include "sha1.h"
 
20
#include "crypto.h"
22
21
#include "aes_wrap.h"
23
22
#include "eap_sim_common.h"
24
23
 
25
24
 
26
 
#define MSK_LEN 8
27
 
#define EMSK_LEN 8
28
 
 
29
 
 
30
 
static void eap_sim_prf(const u8 *key, u8 *x, size_t xlen)
31
 
{
32
 
        u8 xkey[64];
33
 
        u32 t[5], _t[5];
34
 
        int i, j, m, k;
35
 
        u8 *xpos = x;
36
 
        u32 carry;
37
 
 
38
 
        /* FIPS 186-2 + change notice 1 */
39
 
 
40
 
        memcpy(xkey, key, EAP_SIM_MK_LEN);
41
 
        memset(xkey + EAP_SIM_MK_LEN, 0, 64 - EAP_SIM_MK_LEN);
42
 
        t[0] = 0x67452301;
43
 
        t[1] = 0xEFCDAB89;
44
 
        t[2] = 0x98BADCFE;
45
 
        t[3] = 0x10325476;
46
 
        t[4] = 0xC3D2E1F0;
47
 
 
48
 
        m = xlen / 40;
49
 
        for (j = 0; j < m; j++) {
50
 
                /* XSEED_j = 0 */
51
 
                for (i = 0; i < 2; i++) {
52
 
                        /* XVAL = (XKEY + XSEED_j) mod 2^b */
53
 
 
54
 
                        /* w_i = G(t, XVAL) */
55
 
                        memcpy(_t, t, 20);
56
 
                        sha1_transform((u8 *) _t, xkey);
57
 
                        _t[0] = host_to_be32(_t[0]);
58
 
                        _t[1] = host_to_be32(_t[1]);
59
 
                        _t[2] = host_to_be32(_t[2]);
60
 
                        _t[3] = host_to_be32(_t[3]);
61
 
                        _t[4] = host_to_be32(_t[4]);
62
 
                        memcpy(xpos, _t, 20);
63
 
 
64
 
                        /* XKEY = (1 + XKEY + w_i) mod 2^b */
65
 
                        carry = 1;
66
 
                        for (k = 19; k >= 0; k--) {
67
 
                                carry += xkey[k] + xpos[k];
68
 
                                xkey[k] = carry & 0xff;
69
 
                                carry >>= 8;
70
 
                        }
71
 
 
72
 
                        xpos += SHA1_MAC_LEN;
73
 
                }
74
 
                /* x_j = w_0|w_1 */
75
 
        }
76
 
}
77
 
 
78
 
 
79
 
void eap_sim_derive_keys(const u8 *mk, u8 *k_encr, u8 *k_aut, u8 *msk)
 
25
static int eap_sim_prf(const u8 *key, u8 *x, size_t xlen)
 
26
{
 
27
        return fips186_2_prf(key, EAP_SIM_MK_LEN, x, xlen);
 
28
}
 
29
 
 
30
 
 
31
void eap_sim_derive_mk(const u8 *identity, size_t identity_len,
 
32
                       const u8 *nonce_mt, u16 selected_version,
 
33
                       const u8 *ver_list, size_t ver_list_len,
 
34
                       int num_chal, const u8 *kc, u8 *mk)
 
35
{
 
36
        u8 sel_ver[2];
 
37
        const unsigned char *addr[5];
 
38
        size_t len[5];
 
39
 
 
40
        addr[0] = identity;
 
41
        len[0] = identity_len;
 
42
        addr[1] = kc;
 
43
        len[1] = num_chal * EAP_SIM_KC_LEN;
 
44
        addr[2] = nonce_mt;
 
45
        len[2] = EAP_SIM_NONCE_MT_LEN;
 
46
        addr[3] = ver_list;
 
47
        len[3] = ver_list_len;
 
48
        addr[4] = sel_ver;
 
49
        len[4] = 2;
 
50
 
 
51
        WPA_PUT_BE16(sel_ver, selected_version);
 
52
 
 
53
        /* MK = SHA1(Identity|n*Kc|NONCE_MT|Version List|Selected Version) */
 
54
        sha1_vector(5, addr, len, mk);
 
55
        wpa_hexdump_key(MSG_DEBUG, "EAP-SIM: MK", mk, EAP_SIM_MK_LEN);
 
56
}
 
57
 
 
58
 
 
59
void eap_aka_derive_mk(const u8 *identity, size_t identity_len,
 
60
                       const u8 *ik, const u8 *ck, u8 *mk)
 
61
{
 
62
        const u8 *addr[3];
 
63
        size_t len[3];
 
64
 
 
65
        addr[0] = identity;
 
66
        len[0] = identity_len;
 
67
        addr[1] = ik;
 
68
        len[1] = EAP_AKA_IK_LEN;
 
69
        addr[2] = ck;
 
70
        len[2] = EAP_AKA_CK_LEN;
 
71
 
 
72
        /* MK = SHA1(Identity|IK|CK) */
 
73
        sha1_vector(3, addr, len, mk);
 
74
        wpa_hexdump_key(MSG_DEBUG, "EAP-AKA: IK", ik, EAP_AKA_IK_LEN);
 
75
        wpa_hexdump_key(MSG_DEBUG, "EAP-AKA: CK", ck, EAP_AKA_CK_LEN);
 
76
        wpa_hexdump_key(MSG_DEBUG, "EAP-AKA: MK", mk, EAP_SIM_MK_LEN);
 
77
}
 
78
 
 
79
 
 
80
int eap_sim_derive_keys(const u8 *mk, u8 *k_encr, u8 *k_aut, u8 *msk)
80
81
{
81
82
        u8 buf[120], *pos;
82
 
        eap_sim_prf(mk, buf, 120);
 
83
        if (eap_sim_prf(mk, buf, 120) < 0) {
 
84
                wpa_printf(MSG_ERROR, "EAP-SIM: Failed to derive keys");
 
85
                return -1;
 
86
        }
83
87
        pos = buf;
84
88
        memcpy(k_encr, pos, EAP_SIM_K_ENCR_LEN);
85
89
        pos += EAP_SIM_K_ENCR_LEN;
86
90
        memcpy(k_aut, pos, EAP_SIM_K_AUT_LEN);
87
91
        pos += EAP_SIM_K_AUT_LEN;
88
92
        memcpy(msk, pos, EAP_SIM_KEYING_DATA_LEN);
89
 
        pos += MSK_LEN;
90
93
 
91
94
        wpa_hexdump_key(MSG_DEBUG, "EAP-SIM: K_encr",
92
95
                        k_encr, EAP_SIM_K_ENCR_LEN);
93
96
        wpa_hexdump_key(MSG_DEBUG, "EAP-SIM: K_aut",
94
97
                        k_aut, EAP_SIM_K_ENCR_LEN);
95
 
        wpa_hexdump_key(MSG_DEBUG, "EAP-SIM: MSK",
96
 
                        msk, MSK_LEN);
97
 
        wpa_hexdump_key(MSG_DEBUG, "EAP-SIM: Ext. MSK",
98
 
                        msk + MSK_LEN, EMSK_LEN);
99
98
        wpa_hexdump_key(MSG_DEBUG, "EAP-SIM: keying material",
100
 
                    msk, EAP_SIM_KEYING_DATA_LEN);
 
99
                        msk, EAP_SIM_KEYING_DATA_LEN);
 
100
 
 
101
        return 0;
101
102
}
102
103
 
103
104
 
104
 
void eap_sim_derive_keys_reauth(unsigned int _counter,
105
 
                                const u8 *identity, size_t identity_len,
106
 
                                const u8 *nonce_s, const u8 *mk, u8 *msk)
 
105
int eap_sim_derive_keys_reauth(u16 _counter,
 
106
                               const u8 *identity, size_t identity_len,
 
107
                               const u8 *nonce_s, const u8 *mk, u8 *msk)
107
108
{
108
109
        u8 xkey[SHA1_MAC_LEN];
109
110
        u8 counter[2];
119
120
        addr[3] = mk;
120
121
        len[3] = EAP_SIM_MK_LEN;
121
122
 
122
 
        counter[0] = _counter >> 8;
123
 
        counter[1] = _counter & 0xff;
 
123
        WPA_PUT_BE16(counter, _counter);
124
124
 
125
125
        wpa_printf(MSG_DEBUG, "EAP-SIM: Deriving keying data from reauth");
126
126
        wpa_hexdump_ascii(MSG_DEBUG, "EAP-SIM: Identity",
134
134
        sha1_vector(4, addr, len, xkey);
135
135
        wpa_hexdump(MSG_DEBUG, "EAP-SIM: XKEY'", xkey, SHA1_MAC_LEN);
136
136
 
137
 
        eap_sim_prf(xkey, msk, EAP_SIM_KEYING_DATA_LEN);
138
 
        wpa_hexdump(MSG_DEBUG, "EAP-SIM: MSK", msk, MSK_LEN);
139
 
        wpa_hexdump(MSG_DEBUG, "EAP-SIM: Ext. MSK", msk + MSK_LEN, EMSK_LEN);
 
137
        if (eap_sim_prf(xkey, msk, EAP_SIM_KEYING_DATA_LEN) < 0) {
 
138
                wpa_printf(MSG_ERROR, "EAP-SIM: Failed to derive keys");
 
139
                return -1;
 
140
        }
140
141
        wpa_hexdump(MSG_DEBUG, "EAP-SIM: keying material",
141
142
                    msk, EAP_SIM_KEYING_DATA_LEN);
 
143
 
 
144
        return 0;
142
145
}
143
146
 
144
147
 
145
 
int eap_sim_verify_mac(const u8 *k_aut, u8 *req, size_t req_len, u8 *mac,
146
 
                       u8 *extra, size_t extra_len)
 
148
int eap_sim_verify_mac(const u8 *k_aut, const u8 *req, size_t req_len,
 
149
                       const u8 *mac, const u8 *extra, size_t extra_len)
147
150
{
148
151
        unsigned char hmac[SHA1_MAC_LEN];
149
152
        const u8 *addr[2];
150
153
        size_t len[2];
151
 
        u8 rx_mac[EAP_SIM_MAC_LEN];
152
 
 
153
 
        if (mac == NULL)
154
 
                return -1;
155
 
 
156
 
        addr[0] = req;
 
154
        u8 *tmp;
 
155
 
 
156
        if (mac == NULL || req_len < EAP_SIM_MAC_LEN || mac < req ||
 
157
            mac > req + req_len - EAP_SIM_MAC_LEN)
 
158
                return -1;
 
159
 
 
160
        tmp = malloc(req_len);
 
161
        if (tmp == NULL)
 
162
                return -1;
 
163
 
 
164
        addr[0] = tmp;
157
165
        len[0] = req_len;
158
166
        addr[1] = extra;
159
167
        len[1] = extra_len;
160
168
 
161
169
        /* HMAC-SHA1-128 */
162
 
        memcpy(rx_mac, mac, EAP_SIM_MAC_LEN);
163
 
        memset(mac, 0, EAP_SIM_MAC_LEN);
 
170
        memcpy(tmp, req, req_len);
 
171
        memset(tmp + (mac - req), 0, EAP_SIM_MAC_LEN);
164
172
        hmac_sha1_vector(k_aut, EAP_SIM_K_AUT_LEN, 2, addr, len, hmac);
165
 
        memcpy(mac, rx_mac, EAP_SIM_MAC_LEN);
 
173
        free(tmp);
166
174
 
167
175
        return (memcmp(hmac, mac, EAP_SIM_MAC_LEN) == 0) ? 0 : 1;
168
176
}
187
195
}
188
196
 
189
197
 
190
 
int eap_sim_parse_attr(u8 *start, u8 *end, struct eap_sim_attrs *attr, int aka,
191
 
                       int encr)
 
198
int eap_sim_parse_attr(const u8 *start, const u8 *end,
 
199
                       struct eap_sim_attrs *attr, int aka, int encr)
192
200
{
193
 
        u8 *pos = start, *apos;
194
 
        size_t alen, plen;
195
 
        int list_len, i;
 
201
        const u8 *pos = start, *apos;
 
202
        size_t alen, plen, i, list_len;
196
203
 
197
204
        memset(attr, 0, sizeof(*attr));
198
205
        attr->id_req = NO_ID_REQ;
225
232
                        apos += 2;
226
233
                        alen -= 2;
227
234
                        if ((!aka && (alen % GSM_RAND_LEN)) ||
228
 
                            (aka && alen != AKA_RAND_LEN)) {
 
235
                            (aka && alen != EAP_AKA_RAND_LEN)) {
229
236
                                wpa_printf(MSG_INFO, "EAP-SIM: Invalid AT_RAND"
230
237
                                           " (len %lu)",
231
238
                                           (unsigned long) alen);
243
250
                        }
244
251
                        apos += 2;
245
252
                        alen -= 2;
246
 
                        if (alen != AKA_AUTN_LEN) {
 
253
                        if (alen != EAP_AKA_AUTN_LEN) {
247
254
                                wpa_printf(MSG_INFO, "EAP-AKA: Invalid AT_AUTN"
248
255
                                           " (len %lu)",
249
256
                                           (unsigned long) alen);
322
329
                        wpa_printf(MSG_DEBUG, "EAP-SIM: AT_VERSION_LIST");
323
330
                        if (list_len < 2 || list_len > alen - 2) {
324
331
                                wpa_printf(MSG_WARNING, "EAP-SIM: Invalid "
325
 
                                           "AT_VERSION_LIST (list_len=%d "
326
 
                                           "attr_len=%lu)", list_len,
 
332
                                           "AT_VERSION_LIST (list_len=%lu "
 
333
                                           "attr_len=%lu)",
 
334
                                           (unsigned long) list_len,
327
335
                                           (unsigned long) alen);
328
336
                                return -1;
329
337
                        }
450
458
                        attr->next_reauth_id = pos + 4;
451
459
                        attr->next_reauth_id_len = plen;
452
460
                        break;
 
461
                case EAP_SIM_AT_RES:
 
462
                        wpa_printf(MSG_DEBUG, "EAP-SIM: AT_RES");
 
463
                        apos += 2;
 
464
                        alen -= 2;
 
465
                        if (!aka || alen < EAP_AKA_MIN_RES_LEN ||
 
466
                            alen > EAP_AKA_MAX_RES_LEN) {
 
467
                                wpa_printf(MSG_INFO, "EAP-SIM: Invalid AT_RES "
 
468
                                           "(len %lu)",
 
469
                                           (unsigned long) alen);
 
470
                                return -1;
 
471
                        }
 
472
                        attr->res = apos;
 
473
                        attr->res_len = alen;
 
474
                        break;
 
475
                case EAP_SIM_AT_AUTS:
 
476
                        wpa_printf(MSG_DEBUG, "EAP-AKA: AT_AUTS");
 
477
                        if (!aka) {
 
478
                                wpa_printf(MSG_DEBUG, "EAP-SIM: "
 
479
                                           "Unexpected AT_AUTS");
 
480
                                return -1;
 
481
                        }
 
482
                        if (alen != EAP_AKA_AUTS_LEN) {
 
483
                                wpa_printf(MSG_INFO, "EAP-AKA: Invalid AT_AUTS"
 
484
                                           " (len %lu)",
 
485
                                           (unsigned long) alen);
 
486
                                return -1;
 
487
                        }
 
488
                        attr->auts = apos;
 
489
                        break;
453
490
                default:
454
491
                        if (pos[0] < 128) {
455
492
                                wpa_printf(MSG_INFO, "EAP-SIM: Unrecognized "
473
510
}
474
511
 
475
512
 
476
 
int eap_sim_parse_encr(const u8 *k_encr, u8 *encr_data, size_t encr_data_len,
477
 
                       const u8 *iv, struct eap_sim_attrs *attr, int aka)
 
513
u8 * eap_sim_parse_encr(const u8 *k_encr, const u8 *encr_data,
 
514
                        size_t encr_data_len, const u8 *iv,
 
515
                        struct eap_sim_attrs *attr, int aka)
478
516
{
 
517
        u8 *decrypted;
 
518
 
479
519
        if (!iv) {
480
520
                wpa_printf(MSG_INFO, "EAP-SIM: Encrypted data, but no IV");
481
 
                return -1;
 
521
                return NULL;
482
522
        }
483
 
        aes_128_cbc_decrypt(k_encr, iv, encr_data, encr_data_len);
 
523
 
 
524
        decrypted = malloc(encr_data_len);
 
525
        if (decrypted == NULL)
 
526
                return NULL;
 
527
        memcpy(decrypted, encr_data, encr_data_len);
 
528
 
 
529
        aes_128_cbc_decrypt(k_encr, iv, decrypted, encr_data_len);
484
530
        wpa_hexdump(MSG_MSGDUMP, "EAP-SIM: Decrypted AT_ENCR_DATA",
485
 
                    encr_data, encr_data_len);
 
531
                    decrypted, encr_data_len);
486
532
 
487
 
        if (eap_sim_parse_attr(encr_data, encr_data + encr_data_len, attr,
 
533
        if (eap_sim_parse_attr(decrypted, decrypted + encr_data_len, attr,
488
534
                               aka, 1)) {
489
535
                wpa_printf(MSG_INFO, "EAP-SIM: (encr) Failed to parse "
490
536
                           "decrypted AT_ENCR_DATA");
491
 
                return -1;
 
537
                free(decrypted);
 
538
                return NULL;
492
539
        }
493
540
 
494
 
        return 0;
 
541
        return decrypted;
495
542
}
496
543
 
497
544
 
510
557
        struct eap_hdr *eap;
511
558
        u8 *pos;
512
559
 
513
 
        msg = malloc(sizeof(*msg));
 
560
        msg = wpa_zalloc(sizeof(*msg));
514
561
        if (msg == NULL)
515
562
                return NULL;
516
 
        memset(msg, 0, sizeof(*msg));
517
563
 
518
 
        msg->buf = malloc(EAP_SIM_INIT_LEN);
 
564
        msg->buf = wpa_zalloc(EAP_SIM_INIT_LEN);
519
565
        if (msg->buf == NULL) {
520
566
                free(msg);
521
567
                return NULL;
522
568
        }
523
 
        memset(msg->buf, 0, EAP_SIM_INIT_LEN);
524
569
        msg->buf_len = EAP_SIM_INIT_LEN;
525
570
        eap = (struct eap_hdr *) msg->buf;
526
571
        eap->code = code;
628
673
        start = pos = msg->buf + msg->used;
629
674
        *pos++ = attr;
630
675
        *pos++ = attr_len / 4;
631
 
        *pos++ = value >> 8;
632
 
        *pos++ = value & 0xff;
 
676
        WPA_PUT_BE16(pos, value);
 
677
        pos += 2;
633
678
        if (data)
634
679
                memcpy(pos, data, len);
635
680
        if (pad_len) {
709
754
 
710
755
void eap_sim_report_notification(void *msg_ctx, int notification, int aka)
711
756
{
 
757
#ifndef CONFIG_NO_STDOUT_DEBUG
712
758
        const char *type = aka ? "AKA" : "SIM";
 
759
#endif /* CONFIG_NO_STDOUT_DEBUG */
713
760
 
714
761
        switch (notification) {
715
762
        case EAP_SIM_GENERAL_FAILURE_AFTER_AUTH:
746
793
                }
747
794
        }
748
795
}
749
 
 
750
 
 
751
 
#ifdef TEST_MAIN_EAP_SIM_COMMON
752
 
static int test_eap_sim_prf(void)
753
 
{
754
 
        /* http://csrc.nist.gov/encryption/dss/Examples-1024bit.pdf */
755
 
        u8 xkey[] = {
756
 
                0xbd, 0x02, 0x9b, 0xbe, 0x7f, 0x51, 0x96, 0x0b,
757
 
                0xcf, 0x9e, 0xdb, 0x2b, 0x61, 0xf0, 0x6f, 0x0f,
758
 
                0xeb, 0x5a, 0x38, 0xb6
759
 
        };
760
 
        u8 w[] = {
761
 
                0x20, 0x70, 0xb3, 0x22, 0x3d, 0xba, 0x37, 0x2f,
762
 
                0xde, 0x1c, 0x0f, 0xfc, 0x7b, 0x2e, 0x3b, 0x49,
763
 
                0x8b, 0x26, 0x06, 0x14, 0x3c, 0x6c, 0x18, 0xba,
764
 
                0xcb, 0x0f, 0x6c, 0x55, 0xba, 0xbb, 0x13, 0x78,
765
 
                0x8e, 0x20, 0xd7, 0x37, 0xa3, 0x27, 0x51, 0x16
766
 
        };
767
 
        u8 buf[40];
768
 
 
769
 
        printf("Testing EAP-SIM PRF (FIPS 186-2 + change notice 1)\n");
770
 
        eap_sim_prf(xkey, buf, sizeof(buf));
771
 
        if (memcmp(w, buf, sizeof(w) != 0)) {
772
 
                printf("eap_sim_prf failed\n");
773
 
                return 1;
774
 
        }
775
 
 
776
 
        return 0;
777
 
}
778
 
 
779
 
 
780
 
int main(int argc, char *argv[])
781
 
{
782
 
        int errors = 0;
783
 
 
784
 
        errors += test_eap_sim_prf();
785
 
 
786
 
        return errors;
787
 
}
788
 
#endif /* TEST_MAIN_EAP_SIM_COMMON */