~ubuntu-branches/ubuntu/saucy/wpasupplicant/saucy

« back to all changes in this revision

Viewing changes to src/common/wpa_common.c

  • Committer: Bazaar Package Importer
  • Author(s): Mathieu Trudel-Lapierre
  • Date: 2010-11-22 09:43:43 UTC
  • mfrom: (1.1.16 upstream)
  • Revision ID: james.westby@ubuntu.com-20101122094343-qgsxaojvmswfri77
Tags: 0.7.3-0ubuntu1
* Get wpasupplicant 0.7.3 from Debian's SVN. Leaving 0.7.3-1 as unreleased
  for now.
* Build-Depend on debhelper 8, since the packaging from Debian uses compat 8.

Show diffs side-by-side

added added

removed removed

Lines of Context:
15
15
#include "includes.h"
16
16
 
17
17
#include "common.h"
18
 
#include "md5.h"
19
 
#include "sha1.h"
20
 
#include "sha256.h"
21
 
#include "aes_wrap.h"
22
 
#include "crypto.h"
 
18
#include "crypto/md5.h"
 
19
#include "crypto/sha1.h"
 
20
#include "crypto/sha256.h"
 
21
#include "crypto/aes_wrap.h"
 
22
#include "crypto/crypto.h"
23
23
#include "ieee802_11_defs.h"
24
24
#include "defs.h"
25
25
#include "wpa_common.h"
50
50
 
51
51
        switch (ver) {
52
52
        case WPA_KEY_INFO_TYPE_HMAC_MD5_RC4:
53
 
                hmac_md5(key, 16, buf, len, mic);
54
 
                break;
 
53
                return hmac_md5(key, 16, buf, len, mic);
55
54
        case WPA_KEY_INFO_TYPE_HMAC_SHA1_AES:
56
 
                hmac_sha1(key, 16, buf, len, hash);
 
55
                if (hmac_sha1(key, 16, buf, len, hash))
 
56
                        return -1;
57
57
                os_memcpy(mic, hash, MD5_MAC_LEN);
58
58
                break;
59
59
#if defined(CONFIG_IEEE80211R) || defined(CONFIG_IEEE80211W)
568
568
}
569
569
 
570
570
#endif /* CONFIG_IEEE80211R */
 
571
 
 
572
 
 
573
/**
 
574
 * rsn_pmkid - Calculate PMK identifier
 
575
 * @pmk: Pairwise master key
 
576
 * @pmk_len: Length of pmk in bytes
 
577
 * @aa: Authenticator address
 
578
 * @spa: Supplicant address
 
579
 * @pmkid: Buffer for PMKID
 
580
 * @use_sha256: Whether to use SHA256-based KDF
 
581
 *
 
582
 * IEEE Std 802.11i-2004 - 8.5.1.2 Pairwise key hierarchy
 
583
 * PMKID = HMAC-SHA1-128(PMK, "PMK Name" || AA || SPA)
 
584
 */
 
585
void rsn_pmkid(const u8 *pmk, size_t pmk_len, const u8 *aa, const u8 *spa,
 
586
               u8 *pmkid, int use_sha256)
 
587
{
 
588
        char *title = "PMK Name";
 
589
        const u8 *addr[3];
 
590
        const size_t len[3] = { 8, ETH_ALEN, ETH_ALEN };
 
591
        unsigned char hash[SHA256_MAC_LEN];
 
592
 
 
593
        addr[0] = (u8 *) title;
 
594
        addr[1] = aa;
 
595
        addr[2] = spa;
 
596
 
 
597
#ifdef CONFIG_IEEE80211W
 
598
        if (use_sha256)
 
599
                hmac_sha256_vector(pmk, pmk_len, 3, addr, len, hash);
 
600
        else
 
601
#endif /* CONFIG_IEEE80211W */
 
602
                hmac_sha1_vector(pmk, pmk_len, 3, addr, len, hash);
 
603
        os_memcpy(pmkid, hash, PMKID_LEN);
 
604
}
 
605
 
 
606
 
 
607
/**
 
608
 * wpa_cipher_txt - Convert cipher suite to a text string
 
609
 * @cipher: Cipher suite (WPA_CIPHER_* enum)
 
610
 * Returns: Pointer to a text string of the cipher suite name
 
611
 */
 
612
const char * wpa_cipher_txt(int cipher)
 
613
{
 
614
        switch (cipher) {
 
615
        case WPA_CIPHER_NONE:
 
616
                return "NONE";
 
617
        case WPA_CIPHER_WEP40:
 
618
                return "WEP-40";
 
619
        case WPA_CIPHER_WEP104:
 
620
                return "WEP-104";
 
621
        case WPA_CIPHER_TKIP:
 
622
                return "TKIP";
 
623
        case WPA_CIPHER_CCMP:
 
624
                return "CCMP";
 
625
        case WPA_CIPHER_CCMP | WPA_CIPHER_TKIP:
 
626
                return "CCMP+TKIP";
 
627
        default:
 
628
                return "UNKNOWN";
 
629
        }
 
630
}
 
631
 
 
632
 
 
633
/**
 
634
 * wpa_key_mgmt_txt - Convert key management suite to a text string
 
635
 * @key_mgmt: Key management suite (WPA_KEY_MGMT_* enum)
 
636
 * @proto: WPA/WPA2 version (WPA_PROTO_*)
 
637
 * Returns: Pointer to a text string of the key management suite name
 
638
 */
 
639
const char * wpa_key_mgmt_txt(int key_mgmt, int proto)
 
640
{
 
641
        switch (key_mgmt) {
 
642
        case WPA_KEY_MGMT_IEEE8021X:
 
643
                if (proto == (WPA_PROTO_RSN | WPA_PROTO_WPA))
 
644
                        return "WPA2+WPA/IEEE 802.1X/EAP";
 
645
                return proto == WPA_PROTO_RSN ?
 
646
                        "WPA2/IEEE 802.1X/EAP" : "WPA/IEEE 802.1X/EAP";
 
647
        case WPA_KEY_MGMT_PSK:
 
648
                if (proto == (WPA_PROTO_RSN | WPA_PROTO_WPA))
 
649
                        return "WPA2-PSK+WPA-PSK";
 
650
                return proto == WPA_PROTO_RSN ?
 
651
                        "WPA2-PSK" : "WPA-PSK";
 
652
        case WPA_KEY_MGMT_NONE:
 
653
                return "NONE";
 
654
        case WPA_KEY_MGMT_IEEE8021X_NO_WPA:
 
655
                return "IEEE 802.1X (no WPA)";
 
656
#ifdef CONFIG_IEEE80211R
 
657
        case WPA_KEY_MGMT_FT_IEEE8021X:
 
658
                return "FT-EAP";
 
659
        case WPA_KEY_MGMT_FT_PSK:
 
660
                return "FT-PSK";
 
661
#endif /* CONFIG_IEEE80211R */
 
662
#ifdef CONFIG_IEEE80211W
 
663
        case WPA_KEY_MGMT_IEEE8021X_SHA256:
 
664
                return "WPA2-EAP-SHA256";
 
665
        case WPA_KEY_MGMT_PSK_SHA256:
 
666
                return "WPA2-PSK-SHA256";
 
667
#endif /* CONFIG_IEEE80211W */
 
668
        default:
 
669
                return "UNKNOWN";
 
670
        }
 
671
}
 
672
 
 
673
 
 
674
int wpa_compare_rsn_ie(int ft_initial_assoc,
 
675
                       const u8 *ie1, size_t ie1len,
 
676
                       const u8 *ie2, size_t ie2len)
 
677
{
 
678
        if (ie1 == NULL || ie2 == NULL)
 
679
                return -1;
 
680
 
 
681
        if (ie1len == ie2len && os_memcmp(ie1, ie2, ie1len) == 0)
 
682
                return 0; /* identical IEs */
 
683
 
 
684
#ifdef CONFIG_IEEE80211R
 
685
        if (ft_initial_assoc) {
 
686
                struct wpa_ie_data ie1d, ie2d;
 
687
                /*
 
688
                 * The PMKID-List in RSN IE is different between Beacon/Probe
 
689
                 * Response/(Re)Association Request frames and EAPOL-Key
 
690
                 * messages in FT initial mobility domain association. Allow
 
691
                 * for this, but verify that other parts of the RSN IEs are
 
692
                 * identical.
 
693
                 */
 
694
                if (wpa_parse_wpa_ie_rsn(ie1, ie1len, &ie1d) < 0 ||
 
695
                    wpa_parse_wpa_ie_rsn(ie2, ie2len, &ie2d) < 0)
 
696
                        return -1;
 
697
                if (ie1d.proto == ie2d.proto &&
 
698
                    ie1d.pairwise_cipher == ie2d.pairwise_cipher &&
 
699
                    ie1d.group_cipher == ie2d.group_cipher &&
 
700
                    ie1d.key_mgmt == ie2d.key_mgmt &&
 
701
                    ie1d.capabilities == ie2d.capabilities &&
 
702
                    ie1d.mgmt_group_cipher == ie2d.mgmt_group_cipher)
 
703
                        return 0;
 
704
        }
 
705
#endif /* CONFIG_IEEE80211R */
 
706
 
 
707
        return -1;
 
708
}
 
709
 
 
710
 
 
711
#ifdef CONFIG_IEEE80211R
 
712
int wpa_insert_pmkid(u8 *ies, size_t ies_len, const u8 *pmkid)
 
713
{
 
714
        u8 *start, *end, *rpos, *rend;
 
715
        int added = 0;
 
716
 
 
717
        start = ies;
 
718
        end = ies + ies_len;
 
719
 
 
720
        while (start < end) {
 
721
                if (*start == WLAN_EID_RSN)
 
722
                        break;
 
723
                start += 2 + start[1];
 
724
        }
 
725
        if (start >= end) {
 
726
                wpa_printf(MSG_ERROR, "FT: Could not find RSN IE in "
 
727
                           "IEs data");
 
728
                return -1;
 
729
        }
 
730
        wpa_hexdump(MSG_DEBUG, "FT: RSN IE before modification",
 
731
                    start, 2 + start[1]);
 
732
 
 
733
        /* Find start of PMKID-Count */
 
734
        rpos = start + 2;
 
735
        rend = rpos + start[1];
 
736
 
 
737
        /* Skip Version and Group Data Cipher Suite */
 
738
        rpos += 2 + 4;
 
739
        /* Skip Pairwise Cipher Suite Count and List */
 
740
        rpos += 2 + WPA_GET_LE16(rpos) * RSN_SELECTOR_LEN;
 
741
        /* Skip AKM Suite Count and List */
 
742
        rpos += 2 + WPA_GET_LE16(rpos) * RSN_SELECTOR_LEN;
 
743
 
 
744
        if (rpos == rend) {
 
745
                /* Add RSN Capabilities */
 
746
                os_memmove(rpos + 2, rpos, end - rpos);
 
747
                *rpos++ = 0;
 
748
                *rpos++ = 0;
 
749
        } else {
 
750
                /* Skip RSN Capabilities */
 
751
                rpos += 2;
 
752
                if (rpos > rend) {
 
753
                        wpa_printf(MSG_ERROR, "FT: Could not parse RSN IE in "
 
754
                                   "IEs data");
 
755
                        return -1;
 
756
                }
 
757
        }
 
758
 
 
759
        if (rpos == rend) {
 
760
                /* No PMKID-Count field included; add it */
 
761
                os_memmove(rpos + 2 + PMKID_LEN, rpos, end - rpos);
 
762
                WPA_PUT_LE16(rpos, 1);
 
763
                rpos += 2;
 
764
                os_memcpy(rpos, pmkid, PMKID_LEN);
 
765
                added += 2 + PMKID_LEN;
 
766
                start[1] += 2 + PMKID_LEN;
 
767
        } else {
 
768
                /* PMKID-Count was included; use it */
 
769
                if (WPA_GET_LE16(rpos) != 0) {
 
770
                        wpa_printf(MSG_ERROR, "FT: Unexpected PMKID "
 
771
                                   "in RSN IE in EAPOL-Key data");
 
772
                        return -1;
 
773
                }
 
774
                WPA_PUT_LE16(rpos, 1);
 
775
                rpos += 2;
 
776
                os_memmove(rpos + PMKID_LEN, rpos, end - rpos);
 
777
                os_memcpy(rpos, pmkid, PMKID_LEN);
 
778
                added += PMKID_LEN;
 
779
                start[1] += PMKID_LEN;
 
780
        }
 
781
 
 
782
        wpa_hexdump(MSG_DEBUG, "FT: RSN IE after modification "
 
783
                    "(PMKID inserted)", start, 2 + start[1]);
 
784
 
 
785
        return added;
 
786
}
 
787
#endif /* CONFIG_IEEE80211R */