Browse Source

[802.11] Add core support for detecting and using encrypted networks

Signed-off-by: Marty Connor <mdc@etherboot.org>
tags/v1.0.0-rc1
Joshua Oreman 15 years ago
parent
commit
dd8a3e2e70

+ 1
- 0
src/include/gpxe/errfile.h View File

158
 #define ERRFILE_ib_mi			( ERRFILE_NET | 0x00200000 )
158
 #define ERRFILE_ib_mi			( ERRFILE_NET | 0x00200000 )
159
 #define ERRFILE_ib_cmrc			( ERRFILE_NET | 0x00210000 )
159
 #define ERRFILE_ib_cmrc			( ERRFILE_NET | 0x00210000 )
160
 #define ERRFILE_ib_srp			( ERRFILE_NET | 0x00220000 )
160
 #define ERRFILE_ib_srp			( ERRFILE_NET | 0x00220000 )
161
+#define ERRFILE_sec80211		( ERRFILE_NET | 0x00230000 )
161
 
162
 
162
 #define ERRFILE_image		      ( ERRFILE_IMAGE | 0x00000000 )
163
 #define ERRFILE_image		      ( ERRFILE_IMAGE | 0x00000000 )
163
 #define ERRFILE_elf		      ( ERRFILE_IMAGE | 0x00010000 )
164
 #define ERRFILE_elf		      ( ERRFILE_IMAGE | 0x00010000 )

+ 105
- 127
src/include/gpxe/ieee80211.h View File

2
 #define _GPXE_IEEE80211_H
2
 #define _GPXE_IEEE80211_H
3
 
3
 
4
 #include <gpxe/if_ether.h>	/* for ETH_ALEN */
4
 #include <gpxe/if_ether.h>	/* for ETH_ALEN */
5
+#include <endian.h>
5
 
6
 
6
 /** @file
7
 /** @file
7
  * Constants and data structures defined in IEEE 802.11, subsetted
8
  * Constants and data structures defined in IEEE 802.11, subsetted
779
  *
780
  *
780
  * Showing once again a striking clarity of design, the IEEE folks put
781
  * Showing once again a striking clarity of design, the IEEE folks put
781
  * dynamically-sized data in the middle of this structure. As such,
782
  * dynamically-sized data in the middle of this structure. As such,
782
- * the below structure definition is only a guideline; the
783
- * @c IEEE80211_RSN_FIELD, @c IEEE80211_RSN_CIPHER, and
784
- * @c IEEE80211_RSN_AUTHTYPE macros should be used to access any
785
- * data.
783
+ * the below structure definition only works for IEs we create
784
+ * ourselves, which always have one pairwise cipher and one AKM;
785
+ * received IEs should be parsed piecemeal.
786
  *
786
  *
787
  * Also inspired was IEEE's choice of 16-bit fields to count the
787
  * Also inspired was IEEE's choice of 16-bit fields to count the
788
  * number of 4-byte elements in a structure with a maximum length of
788
  * number of 4-byte elements in a structure with a maximum length of
790
  *
790
  *
791
  * Many fields reference a cipher or authentication-type ID; this is a
791
  * Many fields reference a cipher or authentication-type ID; this is a
792
  * three-byte OUI followed by one byte identifying the cipher with
792
  * three-byte OUI followed by one byte identifying the cipher with
793
- * respect to that OUI. For all standard ciphers the OUI is 00:0F:AC.
794
- *
795
- * The authentication types referenced in this structure have nothing
796
- * to do with 802.11 authentication frames or the @c algorithm field
797
- * within them.
793
+ * respect to that OUI. For all standard ciphers the OUI is 00:0F:AC,
794
+ * except in old-style WPA IEs encapsulated in vendor-specific IEs,
795
+ * where it's 00:50:F2.
798
  */
796
  */
799
 struct ieee80211_ie_rsn {
797
 struct ieee80211_ie_rsn {
800
 	/** Information element ID */
798
 	/** Information element ID */
807
 	u16 version;
805
 	u16 version;
808
 
806
 
809
 	/** Cipher ID for the cipher used in multicast/broadcast frames */
807
 	/** Cipher ID for the cipher used in multicast/broadcast frames */
810
-	u8 group_cipher[4];
808
+	u32 group_cipher;
811
 
809
 
812
 	/** Number of unicast ciphers supported */
810
 	/** Number of unicast ciphers supported */
813
 	u16 pairwise_count;
811
 	u16 pairwise_count;
814
 
812
 
815
 	/** List of cipher IDs for supported unicast frame ciphers */
813
 	/** List of cipher IDs for supported unicast frame ciphers */
816
-	u8 pairwise_cipher[4];
814
+	u32 pairwise_cipher[1];
817
 
815
 
818
 	/** Number of authentication types supported */
816
 	/** Number of authentication types supported */
819
 	u16 akm_count;
817
 	u16 akm_count;
820
 
818
 
821
 	/** List of authentication type IDs for supported types */
819
 	/** List of authentication type IDs for supported types */
822
-	u8 akm_list[4];
820
+	u32 akm_list[1];
823
 
821
 
824
-	/** Security capabilities field. */
822
+	/** Security capabilities field (RSN only) */
825
 	u16 rsn_capab;
823
 	u16 rsn_capab;
826
 
824
 
827
 	/** Number of PMKIDs included (present only in association frames) */
825
 	/** Number of PMKIDs included (present only in association frames) */
834
 /** Information element ID for Robust Security Network information element */
832
 /** Information element ID for Robust Security Network information element */
835
 #define IEEE80211_IE_RSN	48
833
 #define IEEE80211_IE_RSN	48
836
 
834
 
837
-/** OUI for standard ciphers in RSN information element */
838
-#define  IEEE80211_RSN_OUI	"\x00\x0F\xAC"
839
-
840
-/** Extract RSN IE version field */
841
-#define  IEEE80211_RSN_FIELD_version( rsnp ) ( (rsnp)->version )
842
-
843
-/** Extract RSN IE group_cipher field */
844
-#define  IEEE80211_RSN_FIELD_group_cipher( rsnp ) ( (rsnp)->group_cipher )
845
-
846
-/** Extract RSN IE pairwise_count field */
847
-#define  IEEE80211_RSN_FIELD_pairwise_count( rsnp ) ( (rsnp)->pairwise_count )
848
-
849
-/** Extract RSN IE akm_count field */
850
-#define  IEEE80211_RSN_FIELD_akm_count( rsnp )			\
851
-	( ( ( struct ieee80211_ie_rsn * ) ( ( void * ) ( rsnp ) + \
852
-		4*( ( rsnp )->pairwise_count - 1 ) ) )->akm_count )
853
-
854
-/** Extract RSN IE rsn_capab field */
855
-#define  IEEE80211_RSN_FIELD_rsn_capab( rsnp )			\
856
-	( ( ( struct ieee80211_ie_rsn * ) ( ( void * ) ( rsnp ) + \
857
-		4*( ( rsnp )->pairwise_count - 1 ) +		\
858
-		4*( ( rsnp )->akm_count - 1 ) ) )->rsn_capab )
859
-
860
-/** Extract RSN IE pmkid_count field */
861
-#define  IEEE80211_RSN_FIELD_pmkid_count( rsnp )		\
862
-	( ( ( struct ieee80211_ie_rsn * ) ( ( void * ) ( rsnp ) + \
863
-		4*( ( rsnp )->pairwise_count - 1 ) +		\
864
-		4*( ( rsnp )->akm_count - 1 ) ) )->pmkid_count )
865
-
866
-/** Extract field from RSN information element
867
- *
868
- * @v rsnp	Pointer to RSN information element
869
- * @v field	Name of field to extract
870
- * @ret val	Lvalue of the requested field
871
- *
872
- * You must fill the fields of the structure in order for this to work
873
- * properly.
874
- */
875
-#define  IEEE80211_RSN_FIELD( rsnp, field )	\
876
-	IEEE80211_RSN_FIELD_ ## field ( rsnp )
877
-
878
-/** Get pointer to pairwise cipher from RSN information element
879
- *
880
- * @v rsnp	Pointer to RSN information element
881
- * @v cipher	Index of pairwise cipher to extract
882
- * @ret ptr	Pointer to requested cipher
883
- */
884
-#define  IEEE80211_RSN_CIPHER( rsnp, cipher )	\
885
-	( ( rsnp )->pairwise_cipher + 4 * ( cipher ) )
886
-
887
-/** Get pointer to authentication type from RSN information element
888
- *
889
- * @v rsnp	Pointer to RSN information element
890
- * @v akm	Index of authentication type to extract
891
- * @ret ptr	Pointer to requested authentication type
892
- *
893
- * The @c pairwise_count field must be correct.
894
- */
895
-#define  IEEE80211_RSN_AUTHTYPE( rsnp, akm )	\
896
-    ( ( rsnp )->akm_list + 4 * ( ( rsnp )->pairwise_count - 1 ) + 4 * ( akm ) )
897
-
898
-/** Get pointer to PMKID from RSN information element
899
- *
900
- * @v rsnp	Pointer to RSN information element
901
- * @v idx	Index of PMKID to extract
902
- * @ret ptr	Pointer to requested PMKID
903
- *
904
- * The @c pairwise_count and @c akm_count fields must be correct.
905
- */
906
-#define  IEEE80211_RSN_PMKID( rsnp, idx )	\
907
-	( ( rsnp )->pmkid_list + 4 * ( ( rsnp )->pairwise_count - 1 ) +	\
908
-			4 * ( ( rsnp )->akm_count - 1 ) + 16 * ( idx ) )
909
-
910
-/** Verify size of RSN information element
911
- *
912
- * @v rsnp	Pointer to RSN information element
913
- * @ret ok	TRUE if count fields are consistent with length field
914
- *
915
- * It is important to drop any RSN IE that does not pass this function
916
- * before using the @c IEEE80211_RSN_FIELD, @c IEEE80211_RSN_CIPHER,
917
- * and @c IEEE80211_RSN_AUTHTYPE macros, to avoid potential security
918
- * compromise due to a malformed RSN IE.
919
- *
920
- * This function does not consider the possibility of some PMKIDs
921
- * included in the RSN IE, because PMKIDs are only included in RSN IEs
922
- * sent in association request frames, and we should never receive an
923
- * association request frame. An RSN IE that includes PMKIDs will
924
- * always fail this check.
925
- */
926
-static inline int ieee80211_rsn_check ( struct ieee80211_ie_rsn *rsnp ) {
927
-	if ( rsnp->len < 12 + 4 * rsnp->pairwise_count )
928
-		return 0;
929
-	return ( rsnp->len == 12 + 4 * ( rsnp->pairwise_count +
930
-				IEEE80211_RSN_FIELD ( rsnp, akm_count ) ) );
931
-}
932
-
933
 /** Calculate necessary size of RSN information element
835
 /** Calculate necessary size of RSN information element
934
  *
836
  *
935
  * @v npair	Number of pairwise ciphers supported
837
  * @v npair	Number of pairwise ciphers supported
936
  * @v nauth	Number of authentication types supported
838
  * @v nauth	Number of authentication types supported
937
  * @v npmkid	Number of PMKIDs to include
839
  * @v npmkid	Number of PMKIDs to include
938
- * @ret size	Necessary size of RSN IE, including header bytes
840
+ * @v is_rsn	If TRUE, calculate RSN IE size; if FALSE, calculate WPA IE size
841
+ * @ret size	Necessary size of IE, including header bytes
939
  */
842
  */
940
-static inline size_t ieee80211_rsn_size ( int npair, int nauth, int npmkid ) {
941
-	return 16 + 4 * ( npair + nauth ) + 16 * npmkid;
843
+static inline size_t ieee80211_rsn_size ( int npair, int nauth, int npmkid,
844
+					  int rsn_ie ) {
845
+	return 16 + 4 * ( npair + nauth ) + 16 * npmkid - 4 * ! rsn_ie;
942
 }
846
 }
943
 
847
 
848
+/** Make OUI plus type byte into 32-bit integer for easy comparison */
849
+#if __BYTE_ORDER == __BIG_ENDIAN
850
+#define _MKOUI( a, b, c, t )	\
851
+		( ( ( a ) << 24 ) | ( ( b ) << 16 ) | ( ( c ) << 8 ) | ( d ) )
852
+#define  OUI_ORG_MASK		0xFFFFFF00
853
+#define  OUI_TYPE_MASK		0x000000FF
854
+#else
855
+#define _MKOUI( a, b, c, t )	\
856
+		( ( ( t ) << 24 ) | ( ( c ) << 16 ) | ( ( b ) << 8 ) | ( a ) )
857
+#define  OUI_ORG_MASK		0x00FFFFFF
858
+#define  OUI_TYPE_MASK		0xFF000000
859
+#endif
860
+
861
+/** Organization part for OUIs in standard RSN IE */
862
+#define  IEEE80211_RSN_OUI	_MKOUI ( 0x00, 0x0F, 0xAC, 0 )
863
+
864
+/** Organization part for OUIs in old WPA IE */
865
+#define  IEEE80211_WPA_OUI	_MKOUI ( 0x00, 0x50, 0xF2, 0 )
866
+
867
+/** Old vendor-type WPA IE OUI type + subtype */
868
+#define  IEEE80211_WPA_OUI_VEN	_MKOUI ( 0x00, 0x50, 0xF2, 0x01 )
869
+
870
+
944
 /** 802.11 RSN IE: expected version number */
871
 /** 802.11 RSN IE: expected version number */
945
 #define  IEEE80211_RSN_VERSION		1
872
 #define  IEEE80211_RSN_VERSION		1
946
 
873
 
947
-/** 802.11 RSN IE: fourth byte of cipher type for 40-bit WEP */
948
-#define  IEEE80211_RSN_CTYPE_WEP40	1
874
+/** 802.11 RSN IE: cipher type for 40-bit WEP */
875
+#define  IEEE80211_RSN_CTYPE_WEP40	_MKOUI ( 0, 0, 0, 0x01 )
949
 
876
 
950
-/** 802.11 RSN IE: fourth byte of cipher type for 104-bit WEP */
951
-#define  IEEE80211_RSN_CTYPE_WEP104	5
877
+/** 802.11 RSN IE: cipher type for 104-bit WEP */
878
+#define  IEEE80211_RSN_CTYPE_WEP104	_MKOUI ( 0, 0, 0, 0x05 )
952
 
879
 
953
-/** 802.11 RSN IE: fourth byte of cipher type for TKIP ("WPA") */
954
-#define  IEEE80211_RSN_CTYPE_TKIP	2
880
+/** 802.11 RSN IE: cipher type for TKIP ("WPA") */
881
+#define  IEEE80211_RSN_CTYPE_TKIP	_MKOUI ( 0, 0, 0, 0x02 )
955
 
882
 
956
-/** 802.11 RSN IE: fourth byte of cipher type for CCMP ("WPA2") */
957
-#define  IEEE80211_RSN_CTYPE_CCMP	4
883
+/** 802.11 RSN IE: cipher type for CCMP ("WPA2") */
884
+#define  IEEE80211_RSN_CTYPE_CCMP	_MKOUI ( 0, 0, 0, 0x04 )
958
 
885
 
959
-/** 802.11 RSN IE: fourth byte of cipher type for "use group"
886
+/** 802.11 RSN IE: cipher type for "use group"
960
  *
887
  *
961
  * This can only appear as a pairwise cipher, and means unicast frames
888
  * This can only appear as a pairwise cipher, and means unicast frames
962
  * should be encrypted in the same way as broadcast/multicast frames.
889
  * should be encrypted in the same way as broadcast/multicast frames.
963
  */
890
  */
964
-#define  IEEE80211_RSN_CTYPE_USEGROUP	0
891
+#define  IEEE80211_RSN_CTYPE_USEGROUP	_MKOUI ( 0, 0, 0, 0x00 )
965
 
892
 
966
-/** 802.11 RSN IE: fourth byte of auth method type for using an 802.1X server */
967
-#define  IEEE80211_RSN_ATYPE_8021X	1
893
+/** 802.11 RSN IE: auth method type for using an 802.1X server */
894
+#define  IEEE80211_RSN_ATYPE_8021X	_MKOUI ( 0, 0, 0, 0x01 )
968
 
895
 
969
-/** 802.11 RSN IE: fourth byte of auth method type for using a pre-shared key */
970
-#define  IEEE80211_RSN_ATYPE_PSK	2
896
+/** 802.11 RSN IE: auth method type for using a pre-shared key */
897
+#define  IEEE80211_RSN_ATYPE_PSK	_MKOUI ( 0, 0, 0, 0x02 )
971
 
898
 
972
 /** 802.11 RSN IE capabilities: AP supports pre-authentication */
899
 /** 802.11 RSN IE capabilities: AP supports pre-authentication */
973
 #define  IEEE80211_RSN_CAPAB_PREAUTH	0x001
900
 #define  IEEE80211_RSN_CAPAB_PREAUTH	0x001
997
 #define  IEEE80211_RSN_CAPAB_PEERKEY	0x200
924
 #define  IEEE80211_RSN_CAPAB_PEERKEY	0x200
998
 
925
 
999
 
926
 
927
+/** 802.11 RSN IE capabilities: One replay counter
928
+ *
929
+ * This should be AND'ed with @c IEEE80211_RSN_CAPAB_PTKSA_REPLAY or
930
+ * @c IEEE80211_RSN_CAPAB_GTKSA_REPLAY (or both) to produce a value
931
+ * which can be OR'ed into the capabilities field.
932
+ */
933
+#define IEEE80211_RSN_1_CTR		0x000
934
+
935
+/** 802.11 RSN IE capabilities: Two replay counters */
936
+#define IEEE80211_RSN_2_CTR		0x014
937
+
938
+/** 802.11 RSN IE capabilities: Four replay counters */
939
+#define IEEE80211_RSN_4_CTR		0x028
940
+
941
+/** 802.11 RSN IE capabilities: 16 replay counters */
942
+#define IEEE80211_RSN_16_CTR		0x03C
943
+
944
+
945
+/** 802.11 Vendor Specific information element
946
+ *
947
+ * One often sees the RSN IE masquerading as vendor-specific on
948
+ * devices that were produced prior to 802.11i (the WPA amendment)
949
+ * being finalized.
950
+ */
951
+struct ieee80211_ie_vendor {
952
+	u8 id;			/**< Vendor-specific ID: 221 */
953
+	u8 len;			/**< Vendor-specific length: variable */
954
+	u32 oui;		/**< OUI and vendor-specific type byte */
955
+	u8 data[0];		/**< Vendor-specific data */
956
+} __attribute__ ((packed));
957
+
958
+/** Information element ID for Vendor Specific information element */
959
+#define IEEE80211_IE_VENDOR	221
960
+
961
+
962
+
1000
 
963
 
1001
 /** Any 802.11 information element
964
 /** Any 802.11 information element
1002
  *
965
  *
1034
 
997
 
1035
 	/** Security information */
998
 	/** Security information */
1036
 	struct ieee80211_ie_rsn rsn;
999
 	struct ieee80211_ie_rsn rsn;
1000
+
1001
+	/** Vendor-specific */
1002
+	struct ieee80211_ie_vendor vendor;
1037
 };
1003
 };
1038
 
1004
 
1005
+/** Check that 802.11 information element is bounded by buffer
1006
+ *
1007
+ * @v ie	Information element
1008
+ * @v end	End of buffer in which information element is stored
1009
+ * @ret ok	TRUE if the IE is completely contained within the buffer
1010
+ */
1011
+static inline int ieee80211_ie_bound ( union ieee80211_ie *ie, void *end )
1012
+{
1013
+	void *iep = ie;
1014
+	return ( iep + 2 <= end && iep + 2 + ie->len <= end );
1015
+}
1016
+
1039
 /** Advance to next 802.11 information element
1017
 /** Advance to next 802.11 information element
1040
  *
1018
  *
1041
  * @v ie	Current information element pointer
1019
  * @v ie	Current information element pointer
1055
 	if ( ! end )
1033
 	if ( ! end )
1056
 		return next_ie;
1034
 		return next_ie;
1057
 
1035
 
1058
-	if ( next_ie_byte < end && next_ie_byte + next_ie->len <= end )
1036
+	if ( ieee80211_ie_bound ( next_ie, end ) )
1059
 		return next_ie;
1037
 		return next_ie;
1060
 
1038
 
1061
 	return NULL;
1039
 	return NULL;

+ 187
- 17
src/include/gpxe/net80211.h View File

119
 	 * in the same 4-way handshake as the PSK method.
119
 	 * in the same 4-way handshake as the PSK method.
120
 	 */
120
 	 */
121
 	NET80211_SECPROT_EAP = 2,
121
 	NET80211_SECPROT_EAP = 2,
122
+
123
+	/** Dummy value used when the handshaking type can't be detected */
124
+	NET80211_SECPROT_UNKNOWN = 3,
122
 };
125
 };
123
 
126
 
124
 
127
 
169
 	 * against WEP and minor success against TKIP fail.
172
 	 * against WEP and minor success against TKIP fail.
170
 	 */
173
 	 */
171
 	NET80211_CRYPT_CCMP = 3,
174
 	NET80211_CRYPT_CCMP = 3,
175
+
176
+	/** Dummy value used when the cryptosystem can't be detected */
177
+	NET80211_CRYPT_UNKNOWN = 4,
172
 };
178
 };
173
 
179
 
174
 
180
 
539
 	struct io_buffer *iob[16];
545
 	struct io_buffer *iob[16];
540
 };
546
 };
541
 
547
 
542
-/** Interface to an 802.11 cryptographic algorithm
548
+
549
+/** Interface to an 802.11 security handshaking protocol
550
+ *
551
+ * Security handshaking protocols handle parsing a user-specified key
552
+ * into a suitable input to the encryption algorithm, and for WPA and
553
+ * better systems, manage performing whatever authentication with the
554
+ * network is necessary.
543
  *
555
  *
544
- * Cryptographic algorithms define a net80211_crypto structure
545
- * statically, using a gPXE linker table to make it available to the
546
- * 802.11 layer. When the algorithm needs to be used, the 802.11 code
547
- * will allocate a copy of the static definition plus whatever space
548
- * the algorithm has requested for private state, and point
549
- * net80211_device::crypto at it.
556
+ * At all times when any method in this structure is called with a
557
+ * net80211_device argument @a dev, a dynamically allocated copy of
558
+ * the handshaker structure itself with space for the requested amount
559
+ * of private data may be accessed as @c dev->handshaker. The
560
+ * structure will not be modified, and will only be freed during
561
+ * reassociation and device closing after the @a stop method has been
562
+ * called.
563
+ */
564
+struct net80211_handshaker
565
+{
566
+	/** The security handshaking protocol implemented */
567
+	enum net80211_security_proto protocol;
568
+
569
+	/** Initialize security handshaking protocol
570
+	 *
571
+	 * @v dev	802.11 device
572
+	 * @ret rc	Return status code
573
+	 *
574
+	 * This method is expected to access @c netX/key or other
575
+	 * applicable settings to determine the parameters for
576
+	 * handshaking. If no handshaking is required, it should call
577
+	 * sec80211_install() with the cryptosystem and key that are
578
+	 * to be used, and @c start and @c step should be set to @c
579
+	 * NULL.
580
+	 *
581
+	 * This is always called just before association is performed,
582
+	 * but after its parameters have been set; in particular, you
583
+	 * may rely on the contents of the @a essid field in @a dev.
584
+	 */
585
+	int ( * init ) ( struct net80211_device *dev );
586
+
587
+	/** Start handshaking
588
+	 *
589
+	 * @v dev	802.11 device
590
+	 * @ret rc	Return status code
591
+	 *
592
+	 * This method is expected to set up internal state so that
593
+	 * packets sent immediately after association, before @a step
594
+	 * can be called, will be handled appropriately.
595
+	 *
596
+	 * This is always called just before association is attempted.
597
+	 */
598
+	int ( * start ) ( struct net80211_device *dev );
599
+
600
+	/** Process handshaking state
601
+	 *
602
+	 * @v dev	802.11 device
603
+	 * @ret rc	Return status code, or positive if done
604
+	 *
605
+	 * This method is expected to perform as much progress on the
606
+	 * protocol it implements as is possible without blocking. It
607
+	 * should return 0 if it wishes to be called again, a negative
608
+	 * return status code on error, or a positive value if
609
+	 * handshaking is complete. In the case of a positive return,
610
+	 * net80211_crypto_install() must have been called.
611
+	 *
612
+	 * If handshaking may require further action (e.g. an AP that
613
+	 * might decide to rekey), handlers must be installed by this
614
+	 * function that will act without further calls to @a step.
615
+	 */
616
+	int ( * step ) ( struct net80211_device *dev );
617
+
618
+	/** Change cryptographic key based on setting
619
+	 *
620
+	 * @v dev	802.11 device
621
+	 * @ret rc	Return status code
622
+	 *
623
+	 * This method is called whenever the @c netX/key setting
624
+	 * @e may have been changed. It is expected to determine
625
+	 * whether it did in fact change, and if so, to install the
626
+	 * new key using net80211_crypto_install(). If it is not
627
+	 * possible to do this immediately, this method should return
628
+	 * an error; in that case the 802.11 stack will reassociate,
629
+	 * following the usual init/start/step sequence.
630
+	 *
631
+	 * This method is only relevant when it is possible to
632
+	 * associate successfully with an incorrect key. When it is
633
+	 * not, a failed association will be retried until the user
634
+	 * changes the key setting, and a successful association will
635
+	 * not be dropped due to such a change. When association with
636
+	 * an incorrect key is impossible, this function should return
637
+	 * 0 after performing no action.
638
+	 */
639
+	int ( * change_key ) ( struct net80211_device *dev );
640
+
641
+	/** Stop security handshaking handlers
642
+	 *
643
+	 * @v dev	802.11 device
644
+	 *
645
+	 * This method is called just before freeing a security
646
+	 * handshaker; it could, for example, delete a process that @a
647
+	 * start had created to manage the security of the connection.
648
+	 * If not needed it may be set to NULL.
649
+	 */
650
+	void ( * stop ) ( struct net80211_device *dev );
651
+
652
+	/** Amount of private data requested
653
+	 *
654
+	 * Before @c init is called for the first time, this structure's
655
+	 * @c priv pointer will point to this many bytes of allocated
656
+	 * data, where the allocation will be performed separately for
657
+	 * each net80211_device.
658
+	 */
659
+	int priv_len;
660
+
661
+	/** Whether @a start has been called
662
+	 *
663
+	 * Reset to 0 after @a stop is called.
664
+	 */
665
+	int started;
666
+
667
+	/** Pointer to private data
668
+	 *
669
+	 * In initializing this structure statically for a linker
670
+	 * table, set this to NULL.
671
+	 */
672
+	void *priv;
673
+};
674
+
675
+#define NET80211_HANDSHAKERS __table ( struct net80211_handshaker, \
676
+				       "net80211_handshakers" )
677
+#define __net80211_handshaker __table_entry ( NET80211_HANDSHAKERS, 01 )
678
+
679
+
680
+/** Interface to an 802.11 cryptosystem
681
+ *
682
+ * Cryptosystems define a net80211_crypto structure statically, using
683
+ * a gPXE linker table to make it available to the 802.11 layer. When
684
+ * the cryptosystem needs to be used, the 802.11 code will allocate a
685
+ * copy of the static definition plus whatever space the algorithm has
686
+ * requested for private state, and point net80211_device::crypto or
687
+ * net80211_device::gcrypto at it.
550
  */
688
  */
551
 struct net80211_crypto
689
 struct net80211_crypto
552
 {
690
 {
553
 	/** The cryptographic algorithm implemented */
691
 	/** The cryptographic algorithm implemented */
554
 	enum net80211_crypto_alg algorithm;
692
 	enum net80211_crypto_alg algorithm;
555
 
693
 
556
-	/** Initialize cryptographic algorithm using a given key
694
+	/** Initialize cryptosystem using a given key
557
 	 *
695
 	 *
558
-	 * @v crypto	802.11 cryptographic algorithm
696
+	 * @v crypto	802.11 cryptosystem
559
 	 * @v key	Pointer to key bytes
697
 	 * @v key	Pointer to key bytes
560
 	 * @v keylen	Number of key bytes
698
 	 * @v keylen	Number of key bytes
699
+	 * @v rsc	Initial receive sequence counter, if applicable
561
 	 * @ret rc	Return status code
700
 	 * @ret rc	Return status code
562
 	 *
701
 	 *
563
 	 * This method is passed the communication key provided by the
702
 	 * This method is passed the communication key provided by the
564
 	 * security handshake handler, which will already be in the
703
 	 * security handshake handler, which will already be in the
565
-	 * low-level form required.
704
+	 * low-level form required. It may not store a pointer to the
705
+	 * key after returning; it must copy it to its private storage.
566
 	 */
706
 	 */
567
-	int ( * initialize ) ( struct net80211_crypto *crypto, u8 *key,
568
-			       int keylen );
707
+	int ( * init ) ( struct net80211_crypto *crypto, const void *key,
708
+			 int keylen, const void *rsc );
569
 
709
 
570
-	/** Encrypt a frame using the cryptographic algorithm
710
+	/** Encrypt a frame using the cryptosystem
571
 	 *
711
 	 *
572
-	 * @v crypto	802.11 cryptographic algorithm
712
+	 * @v crypto	802.11 cryptosystem
573
 	 * @v iob	I/O buffer
713
 	 * @v iob	I/O buffer
574
 	 * @ret eiob	Newly allocated I/O buffer with encrypted packet
714
 	 * @ret eiob	Newly allocated I/O buffer with encrypted packet
575
 	 *
715
 	 *
593
 	struct io_buffer * ( * encrypt ) ( struct net80211_crypto *crypto,
733
 	struct io_buffer * ( * encrypt ) ( struct net80211_crypto *crypto,
594
 					   struct io_buffer *iob );
734
 					   struct io_buffer *iob );
595
 
735
 
596
-	/** Decrypt a frame using the cryptographic algorithm
736
+	/** Decrypt a frame using the cryptosystem
597
 	 *
737
 	 *
598
-	 * @v crypto	802.11 cryptographic algorithm
738
+	 * @v crypto	802.11 cryptosystem
599
 	 * @v eiob	Encrypted I/O buffer
739
 	 * @v eiob	Encrypted I/O buffer
600
 	 * @ret iob	Newly allocated I/O buffer with decrypted packet
740
 	 * @ret iob	Newly allocated I/O buffer with decrypted packet
601
 	 *
741
 	 *
626
 	void *priv;
766
 	void *priv;
627
 };
767
 };
628
 
768
 
769
+#define NET80211_CRYPTOS __table ( struct net80211_crypto, "net80211_cryptos" )
770
+#define __net80211_crypto __table_entry ( NET80211_CRYPTOS, 01 )
771
+
629
 
772
 
630
 struct net80211_probe_ctx;
773
 struct net80211_probe_ctx;
631
 struct net80211_assoc_ctx;
774
 struct net80211_assoc_ctx;
732
 		struct net80211_assoc_ctx *assoc;
875
 		struct net80211_assoc_ctx *assoc;
733
 	} ctx;
876
 	} ctx;
734
 
877
 
878
+	/** Security handshaker being used */
879
+	struct net80211_handshaker *handshaker;
880
+
735
 	/** State of our association to the network
881
 	/** State of our association to the network
736
 	 *
882
 	 *
737
 	 * Since the association process happens asynchronously, it's
883
 	 * Since the association process happens asynchronously, it's
777
 	/** Return status code associated with @c state */
923
 	/** Return status code associated with @c state */
778
 	int assoc_rc;
924
 	int assoc_rc;
779
 
925
 
926
+	/** RSN or WPA information element to include with association
927
+	 *
928
+	 * If set to @c NULL, none will be included. It is expected
929
+	 * that this will be set by the @a init function of a security
930
+	 * handshaker if it is needed.
931
+	 */
932
+	union ieee80211_ie *rsn_ie;
933
+
780
 	/* ---------- Parameters of currently associated network ---------- */
934
 	/* ---------- Parameters of currently associated network ---------- */
781
 
935
 
782
-	/** 802.11 cryptographic algorithm for our current network
936
+	/** 802.11 cryptosystem for our current network
783
 	 *
937
 	 *
784
 	 * For an open network, this will be set to NULL.
938
 	 * For an open network, this will be set to NULL.
785
 	 */
939
 	 */
786
 	struct net80211_crypto *crypto;
940
 	struct net80211_crypto *crypto;
787
 
941
 
942
+	/** 802.11 cryptosystem for multicast and broadcast frames
943
+	 *
944
+	 * If this is NULL, the cryptosystem used for receiving
945
+	 * unicast frames will also be used for receiving multicast
946
+	 * and broadcast frames. Transmitted multicast and broadcast
947
+	 * frames are always sent unicast to the AP, who multicasts
948
+	 * them on our behalf; thus they always use the unicast
949
+	 * cryptosystem.
950
+	 */
951
+	struct net80211_crypto *gcrypto;
952
+
788
 	/** MAC address of the access point most recently associated */
953
 	/** MAC address of the access point most recently associated */
789
 	u8 bssid[ETH_ALEN];
954
 	u8 bssid[ETH_ALEN];
790
 
955
 
927
 };
1092
 };
928
 
1093
 
929
 
1094
 
1095
+/** 802.11 encryption key setting */
1096
+extern struct setting net80211_key_setting __setting;
1097
+
1098
+
930
 /**
1099
 /**
931
  * @defgroup net80211_probe 802.11 network location API
1100
  * @defgroup net80211_probe 802.11 network location API
932
  * @{
1101
  * @{
974
 			 struct net80211_wlan *wlan, int method );
1143
 			 struct net80211_wlan *wlan, int method );
975
 int net80211_send_assoc ( struct net80211_device *dev,
1144
 int net80211_send_assoc ( struct net80211_device *dev,
976
 			  struct net80211_wlan *wlan );
1145
 			  struct net80211_wlan *wlan );
1146
+void net80211_deauthenticate ( struct net80211_device *dev, int rc );
977
 /** @} */
1147
 /** @} */
978
 
1148
 
979
 
1149
 

+ 83
- 0
src/include/gpxe/sec80211.h View File

1
+/*
2
+ * Copyright (c) 2009 Joshua Oreman <oremanj@rwcr.net>.
3
+ *
4
+ * This program is free software; you can redistribute it and/or
5
+ * modify it under the terms of the GNU General Public License as
6
+ * published by the Free Software Foundation; either version 2 of the
7
+ * License, or any later version.
8
+ *
9
+ * This program is distributed in the hope that it will be useful, but
10
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12
+ * General Public License for more details.
13
+ *
14
+ * You should have received a copy of the GNU General Public License
15
+ * along with this program; if not, write to the Free Software
16
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
+ */
18
+
19
+#ifndef _GPXE_SEC80211_H
20
+#define _GPXE_SEC80211_H
21
+
22
+FILE_LICENCE ( GPL2_OR_LATER );
23
+
24
+#include <gpxe/net80211.h>
25
+#include <errno.h>
26
+
27
+/** @file
28
+ *
29
+ * Definitions for general secured-network routines.
30
+ *
31
+ * Any function in this file which may be referenced by code which is
32
+ * not exclusive to encryption-enabled builds (e.g. sec80211_detect(),
33
+ * which is called by net80211_probe_step() to fill the net80211_wlan
34
+ * structure's security fields) must be declared as a weak symbol,
35
+ * using an inline interface similar to that used for
36
+ * sec80211_detect() below. This prevents secure network support from
37
+ * bloating general builds by any more than a few tiny hooks to call
38
+ * crypto functions when crypto structures are non-NULL.
39
+ */
40
+
41
+int _sec80211_detect ( struct io_buffer *iob,
42
+		       enum net80211_security_proto *secprot,
43
+		       enum net80211_crypto_alg *crypt )
44
+	__attribute__ (( weak ));
45
+
46
+
47
+/**
48
+ * Inline safety wrapper for _sec80211_detect()
49
+ *
50
+ * @v iob	I/O buffer containing beacon frame
51
+ * @ret secprot	Security handshaking protocol used by network
52
+ * @ret crypt	Cryptosystem used by network
53
+ * @ret rc	Return status code
54
+ *
55
+ * This function transparently calls _sec80211_detect() if the file
56
+ * containing it was compiled in, or returns an error indication of
57
+ * @c -ENOTSUP if not.
58
+ */
59
+static inline int sec80211_detect ( struct io_buffer *iob,
60
+				    enum net80211_security_proto *secprot,
61
+				    enum net80211_crypto_alg *crypt ) {
62
+	if ( _sec80211_detect )
63
+		return _sec80211_detect ( iob, secprot, crypt );
64
+	return -ENOTSUP;
65
+}
66
+
67
+int sec80211_detect_ie ( int is_rsn, u8 *start, u8 *end,
68
+			 enum net80211_security_proto *secprot,
69
+			 enum net80211_crypto_alg *crypt );
70
+u8 * sec80211_find_rsn ( union ieee80211_ie *ie, void *ie_end,
71
+			 int *is_rsn, u8 **end );
72
+
73
+int sec80211_install ( struct net80211_crypto **which,
74
+		       enum net80211_crypto_alg crypt,
75
+		       const void *key, int len, const void *rsc );
76
+
77
+u32 sec80211_rsn_get_crypto_desc ( enum net80211_crypto_alg crypt, int rsnie );
78
+u32 sec80211_rsn_get_akm_desc ( enum net80211_security_proto secprot,
79
+				int rsnie );
80
+enum net80211_crypto_alg sec80211_rsn_get_net80211_crypt ( u32 desc );
81
+
82
+#endif /* _GPXE_SEC80211_H */
83
+

+ 248
- 59
src/net/80211/net80211.c View File

29
 #include <gpxe/ieee80211.h>
29
 #include <gpxe/ieee80211.h>
30
 #include <gpxe/netdevice.h>
30
 #include <gpxe/netdevice.h>
31
 #include <gpxe/net80211.h>
31
 #include <gpxe/net80211.h>
32
+#include <gpxe/sec80211.h>
32
 #include <gpxe/timer.h>
33
 #include <gpxe/timer.h>
33
 #include <gpxe/nap.h>
34
 #include <gpxe/nap.h>
34
 #include <unistd.h>
35
 #include <unistd.h>
188
 				   struct io_buffer *iob );
189
 				   struct io_buffer *iob );
189
 static void net80211_handle_assoc_reply ( struct net80211_device *dev,
190
 static void net80211_handle_assoc_reply ( struct net80211_device *dev,
190
 					  struct io_buffer *iob );
191
 					  struct io_buffer *iob );
191
-static int net80211_send_disassoc ( struct net80211_device *dev, int reason );
192
+static int net80211_send_disassoc ( struct net80211_device *dev, int reason,
193
+				    int deauth );
192
 static void net80211_handle_mgmt ( struct net80211_device *dev,
194
 static void net80211_handle_mgmt ( struct net80211_device *dev,
193
 				   struct io_buffer *iob, int signal );
195
 				   struct io_buffer *iob, int signal );
194
 /** @} */
196
 /** @} */
208
  * @defgroup net80211_settings 802.11 settings handlers
210
  * @defgroup net80211_settings 802.11 settings handlers
209
  * @{
211
  * @{
210
  */
212
  */
211
-static int net80211_check_ssid_update ( void );
213
+static int net80211_check_settings_update ( void );
212
 
214
 
213
 /** 802.11 settings applicator
215
 /** 802.11 settings applicator
214
  *
216
  *
215
  * When the SSID is changed, this will cause any open devices to
217
  * When the SSID is changed, this will cause any open devices to
216
- * re-associate.
218
+ * re-associate; when the encryption key is changed, we similarly
219
+ * update their state.
217
  */
220
  */
218
-struct settings_applicator net80211_ssid_applicator __settings_applicator = {
219
-	.apply = net80211_check_ssid_update,
221
+struct settings_applicator net80211_applicator __settings_applicator = {
222
+	.apply = net80211_check_settings_update,
220
 };
223
 };
221
 
224
 
222
 /** The network name to associate with
225
 /** The network name to associate with
242
 	.type = &setting_type_int8,
245
 	.type = &setting_type_int8,
243
 };
246
 };
244
 
247
 
248
+/** The cryptographic key to use
249
+ *
250
+ * For hex WEP keys, as is common, this must be entered using the
251
+ * normal gPXE method for entering hex settings; an ASCII string of
252
+ * hex characters will not behave as expected.
253
+ */
254
+struct setting net80211_key_setting __setting = {
255
+	.name = "key",
256
+	.description = "Encryption key for protected 802.11 networks",
257
+	.type = &setting_type_string,
258
+};
259
+
245
 /** @} */
260
 /** @} */
246
 
261
 
247
 
262
 
294
 
309
 
295
 	/* Send disassociation frame to AP, to be polite */
310
 	/* Send disassociation frame to AP, to be polite */
296
 	if ( dev->state & NET80211_ASSOCIATED )
311
 	if ( dev->state & NET80211_ASSOCIATED )
297
-		net80211_send_disassoc ( dev, IEEE80211_REASON_LEAVING );
312
+		net80211_send_disassoc ( dev, IEEE80211_REASON_LEAVING, 0 );
313
+
314
+	if ( dev->handshaker && dev->handshaker->stop &&
315
+	     dev->handshaker->started )
316
+		dev->handshaker->stop ( dev );
317
+
318
+	free ( dev->crypto );
319
+	free ( dev->handshaker );
320
+	dev->crypto = NULL;
321
+	dev->handshaker = NULL;
298
 
322
 
299
 	netdev_link_down ( netdev );
323
 	netdev_link_down ( netdev );
300
 	dev->state = 0;
324
 	dev->state = 0;
317
 				      struct io_buffer *iobuf )
341
 				      struct io_buffer *iobuf )
318
 {
342
 {
319
 	struct net80211_device *dev = netdev->priv;
343
 	struct net80211_device *dev = netdev->priv;
344
+	struct ieee80211_frame *hdr = iobuf->data;
320
 	int rc = -ENOSYS;
345
 	int rc = -ENOSYS;
321
 
346
 
322
-	if ( dev->crypto ) {
347
+	if ( dev->crypto && ! ( hdr->fc & IEEE80211_FC_PROTECTED ) &&
348
+	     ( ( hdr->fc & IEEE80211_FC_TYPE ) == IEEE80211_TYPE_DATA ) ) {
323
 		struct io_buffer *niob = dev->crypto->encrypt ( dev->crypto,
349
 		struct io_buffer *niob = dev->crypto->encrypt ( dev->crypto,
324
 								iobuf );
350
 								iobuf );
325
 		if ( ! niob )
351
 		if ( ! niob )
326
 			return -ENOMEM;	/* only reason encryption could fail */
352
 			return -ENOMEM;	/* only reason encryption could fail */
327
 
353
 
328
-		free_iob ( iobuf );
329
-		iobuf = niob;
354
+		/* Free the non-encrypted iob */
355
+		netdev_tx_complete ( netdev, iobuf );
356
+
357
+		/* Transmit the encrypted iob; the Protected flag is
358
+		   set, so we won't recurse into here again */
359
+		netdev_tx ( netdev, niob );
360
+
361
+		/* Don't transmit the freed packet */
362
+		return 0;
330
 	}
363
 	}
331
 
364
 
332
 	if ( dev->op->transmit )
365
 	if ( dev->op->transmit )
482
 		( void * ) hdr + IEEE80211_TYP_FRAME_HEADER_LEN;
515
 		( void * ) hdr + IEEE80211_TYP_FRAME_HEADER_LEN;
483
 
516
 
484
 	/* We can't send data packets if we're not associated. */
517
 	/* We can't send data packets if we're not associated. */
485
-	if ( ! netdev_link_ok ( netdev ) ) {
518
+	if ( ! ( dev->state & NET80211_ASSOCIATED ) ) {
486
 		if ( dev->assoc_rc )
519
 		if ( dev->assoc_rc )
487
 			return dev->assoc_rc;
520
 			return dev->assoc_rc;
488
 		return -ENETUNREACH;
521
 		return -ENETUNREACH;
1032
 	int changed = 0;
1065
 	int changed = 0;
1033
 	int band = dev->channels[dev->channel].band;
1066
 	int band = dev->channels[dev->channel].band;
1034
 
1067
 
1035
-	if ( ( void * ) ie >= ie_end )
1068
+	if ( ! ieee80211_ie_bound ( ie, ie_end ) )
1036
 		return 0;
1069
 		return 0;
1037
 
1070
 
1038
 	for ( ; ie; ie = ieee80211_next_ie ( ie, ie_end ) ) {
1071
 	for ( ; ie; ie = ieee80211_next_ie ( ie, ie_end ) ) {
1103
 			if ( ! ( ie->erp_info & IEEE80211_ERP_BARKER_LONG ) )
1136
 			if ( ! ( ie->erp_info & IEEE80211_ERP_BARKER_LONG ) )
1104
 				dev->phy_flags |= NET80211_PHY_USE_SHORT_PREAMBLE;
1137
 				dev->phy_flags |= NET80211_PHY_USE_SHORT_PREAMBLE;
1105
 			break;
1138
 			break;
1106
-
1107
-		case IEEE80211_IE_RSN:
1108
-			/* XXX need to implement WPA stuff */
1109
-			break;
1110
 		}
1139
 		}
1111
 	}
1140
 	}
1112
 
1141
 
1140
 		   exist, so insertion sort works well. */
1169
 		   exist, so insertion sort works well. */
1141
 		for ( i = 1; i < dev->nr_rates; i++ ) {
1170
 		for ( i = 1; i < dev->nr_rates; i++ ) {
1142
 			u16 rate = dev->rates[i];
1171
 			u16 rate = dev->rates[i];
1172
+			u32 tmp, br, mask;
1143
 
1173
 
1144
 			for ( j = i - 1; j >= 0 && dev->rates[j] >= rate; j-- )
1174
 			for ( j = i - 1; j >= 0 && dev->rates[j] >= rate; j-- )
1145
 				dev->rates[j + 1] = dev->rates[j];
1175
 				dev->rates[j + 1] = dev->rates[j];
1146
 			dev->rates[j + 1] = rate;
1176
 			dev->rates[j + 1] = rate;
1177
+
1178
+			/* Adjust basic_rates to match by rotating the
1179
+			   bits from bit j+1 to bit i left one position. */
1180
+			mask = ( ( 1 << i ) - 1 ) & ~( ( 1 << ( j + 1 ) ) - 1 );
1181
+			br = dev->basic_rates;
1182
+			tmp = br & ( 1 << i );
1183
+			br = ( br & ~( mask | tmp ) ) | ( ( br & mask ) << 1 );
1184
+			br |= ( tmp >> ( i - j - 1 ) );
1185
+			dev->basic_rates = br;
1147
 		}
1186
 		}
1148
 
1187
 
1149
 		net80211_set_rtscts_rate ( dev );
1188
 		net80211_set_rtscts_rate ( dev );
1187
 
1226
 
1188
 	ie->id = IEEE80211_IE_RATES;
1227
 	ie->id = IEEE80211_IE_RATES;
1189
 	ie->len = dev->nr_rates;
1228
 	ie->len = dev->nr_rates;
1229
+	if ( ie->len > 8 )
1230
+		ie->len = 8;
1231
+
1190
 	for ( i = 0; i < ie->len; i++ ) {
1232
 	for ( i = 0; i < ie->len; i++ ) {
1191
 		ie->rates[i] = dev->rates[i] / 5;
1233
 		ie->rates[i] = dev->rates[i] / 5;
1192
 		if ( dev->basic_rates & ( 1 << i ) )
1234
 		if ( dev->basic_rates & ( 1 << i ) )
1193
 			ie->rates[i] |= 0x80;
1235
 			ie->rates[i] |= 0x80;
1194
 	}
1236
 	}
1195
 
1237
 
1196
-	if ( ie->len > 8 ) {
1238
+	ie = ieee80211_next_ie ( ie, NULL );
1239
+
1240
+	if ( dev->rsn_ie && dev->rsn_ie->id == IEEE80211_IE_RSN ) {
1241
+		memcpy ( ie, dev->rsn_ie, dev->rsn_ie->len + 2 );
1242
+		ie = ieee80211_next_ie ( ie, NULL );
1243
+	}
1244
+
1245
+	if ( dev->nr_rates > 8 ) {
1197
 		/* 802.11 requires we use an Extended Basic Rates IE
1246
 		/* 802.11 requires we use an Extended Basic Rates IE
1198
 		   for the rates beyond the eighth. */
1247
 		   for the rates beyond the eighth. */
1199
-		int rates = ie->len;
1200
 
1248
 
1201
-		memmove ( ( void * ) ie + 2 + 8 + 2, ( void * ) ie + 2 + 8,
1202
-			  rates - 8 );
1203
-		ie->len = 8;
1249
+		ie->id = IEEE80211_IE_EXT_RATES;
1250
+		ie->len = dev->nr_rates - 8;
1204
 
1251
 
1205
-		ie = ieee80211_next_ie ( ie, NULL );
1252
+		for ( ; i < dev->nr_rates; i++ ) {
1253
+			ie->rates[i - 8] = dev->rates[i] / 5;
1254
+			if ( dev->basic_rates & ( 1 << i ) )
1255
+				ie->rates[i - 8] |= 0x80;
1256
+		}
1206
 
1257
 
1207
-		ie->id = IEEE80211_IE_EXT_RATES;
1208
-		ie->len = rates - 8;
1258
+		ie = ieee80211_next_ie ( ie, NULL );
1209
 	}
1259
 	}
1210
 
1260
 
1211
-	ie = ieee80211_next_ie ( ie, NULL );
1261
+	if ( dev->rsn_ie && dev->rsn_ie->id == IEEE80211_IE_VENDOR ) {
1262
+		memcpy ( ie, dev->rsn_ie, dev->rsn_ie->len + 2 );
1263
+		ie = ieee80211_next_ie ( ie, NULL );
1264
+	}
1212
 
1265
 
1213
 	return ie;
1266
 	return ie;
1214
 }
1267
 }
1275
 
1328
 
1276
 		ie = net80211_marshal_request_info ( dev,
1329
 		ie = net80211_marshal_request_info ( dev,
1277
 						     probe_req->info_element );
1330
 						     probe_req->info_element );
1278
-		ie->id = IEEE80211_IE_REQUEST;
1279
-		ie->len = 3;
1280
-		ie->request[0] = IEEE80211_IE_COUNTRY;
1281
-		ie->request[1] = IEEE80211_IE_ERP_INFO;
1282
-		ie->request[2] = IEEE80211_IE_RSN;
1283
-
1284
-		ie = ieee80211_next_ie ( ie, NULL );
1285
 
1331
 
1286
 		iob_put ( ctx->probe, ( void * ) ie - ctx->probe->data );
1332
 		iob_put ( ctx->probe, ( void * ) ie - ctx->probe->data );
1287
 	}
1333
 	}
1404
 		}
1450
 		}
1405
 
1451
 
1406
 		ie = beacon->info_element;
1452
 		ie = beacon->info_element;
1453
+
1454
+		if ( ! ieee80211_ie_bound ( ie, iob->tail ) )
1455
+			ie = NULL;
1456
+
1407
 		while ( ie && ie->id != IEEE80211_IE_SSID )
1457
 		while ( ie && ie->id != IEEE80211_IE_SSID )
1408
 			ie = ieee80211_next_ie ( ie, iob->tail );
1458
 			ie = ieee80211_next_ie ( ie, iob->tail );
1409
 
1459
 
1459
 		memcpy ( iob_put ( wlan->beacon, iob_len ( iob ) ),
1509
 		memcpy ( iob_put ( wlan->beacon, iob_len ( iob ) ),
1460
 			 iob->data, iob_len ( iob ) );
1510
 			 iob->data, iob_len ( iob ) );
1461
 
1511
 
1462
-		/* XXX actually check capab and RSN ie to
1463
-		   figure this out */
1464
-		wlan->handshaking = NET80211_SECPROT_NONE;
1465
-		wlan->crypto = NET80211_CRYPT_NONE;
1512
+		if ( ( rc = sec80211_detect ( wlan->beacon, &wlan->handshaking,
1513
+					      &wlan->crypto ) ) == -ENOTSUP ) {
1514
+			struct ieee80211_beacon *beacon =
1515
+				( struct ieee80211_beacon * ) hdr->data;
1516
+
1517
+			if ( beacon->capability & IEEE80211_CAPAB_PRIVACY ) {
1518
+				DBG ( "802.11 %p probe: secured network %s but "
1519
+				      "encryption support not compiled in\n",
1520
+				      dev, wlan->essid );
1521
+				wlan->handshaking = NET80211_SECPROT_UNKNOWN;
1522
+				wlan->crypto = NET80211_CRYPT_UNKNOWN;
1523
+			} else {
1524
+				wlan->handshaking = NET80211_SECPROT_NONE;
1525
+				wlan->crypto = NET80211_CRYPT_NONE;
1526
+			}
1527
+		} else if ( rc != 0 ) {
1528
+			DBGC ( dev, "802.11 %p probe warning: network "
1529
+			       "%s with unidentifiable security "
1530
+			       "settings: %s\n", dev, wlan->essid,
1531
+			       strerror ( rc ) );
1532
+		}
1466
 
1533
 
1467
 		ctx->ticks_beacon = now;
1534
 		ctx->ticks_beacon = now;
1468
 
1535
 
1739
 
1806
 
1740
 		DBGC ( dev, "802.11 %p associating\n", dev );
1807
 		DBGC ( dev, "802.11 %p associating\n", dev );
1741
 
1808
 
1809
+		if ( dev->handshaker && dev->handshaker->start &&
1810
+		     ! dev->handshaker->started ) {
1811
+			rc = dev->handshaker->start ( dev );
1812
+			if ( rc < 0 )
1813
+				goto fail;
1814
+			dev->handshaker->started = 1;
1815
+		}
1816
+
1742
 		rc = net80211_send_assoc ( dev, dev->associating );
1817
 		rc = net80211_send_assoc ( dev, dev->associating );
1743
 		if ( rc )
1818
 		if ( rc )
1744
 			goto fail;
1819
 			goto fail;
1750
 		/* state: crypto sync */
1825
 		/* state: crypto sync */
1751
 		DBGC ( dev, "802.11 %p security handshaking\n", dev );
1826
 		DBGC ( dev, "802.11 %p security handshaking\n", dev );
1752
 
1827
 
1753
-		dev->state |= NET80211_CRYPTO_SYNCED;
1754
-		/* XXX need to actually do something here once we
1755
-		   support WPA */
1828
+		if ( ! dev->handshaker || ! dev->handshaker->step ) {
1829
+			dev->state |= NET80211_CRYPTO_SYNCED;
1830
+			return;
1831
+		}
1832
+
1833
+		rc = dev->handshaker->step ( dev );
1834
+
1835
+		if ( rc < 0 ) {
1836
+			/* Only record the returned error if we're
1837
+			   still marked as associated, because an
1838
+			   asynchronous error will have already been
1839
+			   reported to net80211_deauthenticate() and
1840
+			   assoc_rc thereby set. */
1841
+			if ( dev->state & NET80211_ASSOCIATED )
1842
+				dev->assoc_rc = rc;
1843
+			rc = 0;
1844
+			goto fail;
1845
+		}
1846
+
1847
+		if ( rc > 0 ) {
1848
+			dev->assoc_rc = 0;
1849
+			dev->state |= NET80211_CRYPTO_SYNCED;
1850
+		}
1756
 		return;
1851
 		return;
1757
 	}
1852
 	}
1758
 
1853
 
1804
 }
1899
 }
1805
 
1900
 
1806
 /**
1901
 /**
1807
- * Check for 802.11 SSID updates
1902
+ * Check for 802.11 SSID or key updates
1808
  *
1903
  *
1809
  * This acts as a settings applicator; if the user changes netX/ssid,
1904
  * This acts as a settings applicator; if the user changes netX/ssid,
1810
  * and netX is currently open, the association task will be invoked
1905
  * and netX is currently open, the association task will be invoked
1811
- * again.
1906
+ * again. If the user changes the encryption key, the current security
1907
+ * handshaker will be asked to update its state to match; if that is
1908
+ * impossible without reassociation, we reassociate.
1812
  */
1909
  */
1813
-static int net80211_check_ssid_update ( void )
1910
+static int net80211_check_settings_update ( void )
1814
 {
1911
 {
1815
 	struct net80211_device *dev;
1912
 	struct net80211_device *dev;
1816
 	char ssid[IEEE80211_MAX_SSID_LEN + 1];
1913
 	char ssid[IEEE80211_MAX_SSID_LEN + 1];
1914
+	int key_reassoc;
1817
 
1915
 
1818
 	list_for_each_entry ( dev, &net80211_devices, list ) {
1916
 	list_for_each_entry ( dev, &net80211_devices, list ) {
1819
 		if ( ! ( dev->netdev->state & NETDEV_OPEN ) )
1917
 		if ( ! ( dev->netdev->state & NETDEV_OPEN ) )
1820
 			continue;
1918
 			continue;
1821
 
1919
 
1920
+		key_reassoc = 0;
1921
+		if ( dev->handshaker && dev->handshaker->change_key &&
1922
+		     dev->handshaker->change_key ( dev ) < 0 )
1923
+			key_reassoc = 1;
1924
+
1822
 		fetch_string_setting ( netdev_settings ( dev->netdev ),
1925
 		fetch_string_setting ( netdev_settings ( dev->netdev ),
1823
 				       &net80211_ssid_setting, ssid,
1926
 				       &net80211_ssid_setting, ssid,
1824
 				       IEEE80211_MAX_SSID_LEN + 1 );
1927
 				       IEEE80211_MAX_SSID_LEN + 1 );
1825
 
1928
 
1826
-		if ( strcmp ( ssid, dev->essid ) != 0 &&
1827
-		     ! ( ! ssid[0] && ( dev->state & NET80211_AUTO_SSID ) ) ) {
1929
+		if ( key_reassoc ||
1930
+		     ( ! ( ! ssid[0] && ( dev->state & NET80211_AUTO_SSID ) ) &&
1931
+		       strcmp ( ssid, dev->essid ) != 0 ) ) {
1828
 			DBGC ( dev, "802.11 %p updating association: "
1932
 			DBGC ( dev, "802.11 %p updating association: "
1829
 			       "%s -> %s\n", dev, dev->essid, ssid );
1933
 			       "%s -> %s\n", dev, dev->essid, ssid );
1830
 			net80211_autoassociate ( dev );
1934
 			net80211_autoassociate ( dev );
1846
 	if ( ! ( dev->state & NET80211_WORKING ) ) {
1950
 	if ( ! ( dev->state & NET80211_WORKING ) ) {
1847
 		DBGC2 ( dev, "802.11 %p spawning association process\n", dev );
1951
 		DBGC2 ( dev, "802.11 %p spawning association process\n", dev );
1848
 		process_add ( &dev->proc_assoc );
1952
 		process_add ( &dev->proc_assoc );
1953
+	} else {
1954
+		DBGC2 ( dev, "802.11 %p restarting association\n", dev );
1849
 	}
1955
 	}
1850
 
1956
 
1851
 	/* Clean up everything an earlier association process might
1957
 	/* Clean up everything an earlier association process might
1865
 			       IEEE80211_MAX_SSID_LEN + 1 );
1971
 			       IEEE80211_MAX_SSID_LEN + 1 );
1866
 	dev->ctx.probe = NULL;
1972
 	dev->ctx.probe = NULL;
1867
 	dev->associating = NULL;
1973
 	dev->associating = NULL;
1974
+	dev->assoc_rc = 0;
1868
 	net80211_set_state ( dev, NET80211_PROBED, NET80211_WORKING, 0 );
1975
 	net80211_set_state ( dev, NET80211_PROBED, NET80211_WORKING, 0 );
1869
 }
1976
 }
1870
 
1977
 
2020
 	struct ieee80211_frame *hdr = wlan->beacon->data;
2127
 	struct ieee80211_frame *hdr = wlan->beacon->data;
2021
 	struct ieee80211_beacon *beacon =
2128
 	struct ieee80211_beacon *beacon =
2022
 		( struct ieee80211_beacon * ) hdr->data;
2129
 		( struct ieee80211_beacon * ) hdr->data;
2130
+	struct net80211_handshaker *handshaker;
2023
 	int rc;
2131
 	int rc;
2024
 
2132
 
2025
 	assert ( dev->netdev->state & NETDEV_OPEN );
2133
 	assert ( dev->netdev->state & NETDEV_OPEN );
2028
 	memcpy ( dev->bssid, wlan->bssid, ETH_ALEN );
2136
 	memcpy ( dev->bssid, wlan->bssid, ETH_ALEN );
2029
 	strcpy ( dev->essid, wlan->essid );
2137
 	strcpy ( dev->essid, wlan->essid );
2030
 
2138
 
2139
+	free ( dev->rsn_ie );
2140
+	dev->rsn_ie = NULL;
2141
+
2031
 	dev->last_beacon_timestamp = beacon->timestamp;
2142
 	dev->last_beacon_timestamp = beacon->timestamp;
2032
 	dev->tx_beacon_interval = 1024 * beacon->beacon_interval;
2143
 	dev->tx_beacon_interval = 1024 * beacon->beacon_interval;
2033
 
2144
 
2034
-	/* XXX do crypto setup here */
2035
-
2036
 	/* Barring an IE that tells us the channel outright, assume
2145
 	/* Barring an IE that tells us the channel outright, assume
2037
 	   the channel we heard this AP best on is the channel it's
2146
 	   the channel we heard this AP best on is the channel it's
2038
 	   communicating on. */
2147
 	   communicating on. */
2051
 	dev->rate = 0;
2160
 	dev->rate = 0;
2052
 	dev->op->config ( dev, NET80211_CFG_RATE );
2161
 	dev->op->config ( dev, NET80211_CFG_RATE );
2053
 
2162
 
2163
+	/* Free old handshaker and crypto, if they exist */
2164
+	if ( dev->handshaker && dev->handshaker->stop &&
2165
+	     dev->handshaker->started )
2166
+		dev->handshaker->stop ( dev );
2167
+	free ( dev->handshaker );
2168
+	dev->handshaker = NULL;
2169
+	free ( dev->crypto );
2170
+	free ( dev->gcrypto );
2171
+	dev->crypto = dev->gcrypto = NULL;
2172
+
2173
+	/* Find new security handshaker to use */
2174
+	for_each_table_entry ( handshaker, NET80211_HANDSHAKERS ) {
2175
+		if ( handshaker->protocol == wlan->handshaking ) {
2176
+			dev->handshaker = zalloc ( sizeof ( *handshaker ) +
2177
+						   handshaker->priv_len );
2178
+			if ( ! dev->handshaker )
2179
+				return -ENOMEM;
2180
+
2181
+			memcpy ( dev->handshaker, handshaker,
2182
+				 sizeof ( *handshaker ) );
2183
+			dev->handshaker->priv = ( ( void * ) dev->handshaker +
2184
+						  sizeof ( *handshaker ) );
2185
+			break;
2186
+		}
2187
+	}
2188
+
2189
+	if ( ( wlan->handshaking != NET80211_SECPROT_NONE ) &&
2190
+	     ! dev->handshaker ) {
2191
+		DBGC ( dev, "802.11 %p no support for handshaking scheme %d\n",
2192
+		       dev, wlan->handshaking );
2193
+		return -( ENOTSUP | ( wlan->handshaking << 8 ) );
2194
+	}
2195
+
2196
+	/* Initialize security handshaker */
2197
+	if ( dev->handshaker ) {
2198
+		rc = dev->handshaker->init ( dev );
2199
+		if ( rc < 0 )
2200
+			return rc;
2201
+	}
2202
+
2054
 	return 0;
2203
 	return 0;
2055
 }
2204
 }
2056
 
2205
 
2091
  *
2240
  *
2092
  * If the authentication method being used is Shared Key, and the
2241
  * If the authentication method being used is Shared Key, and the
2093
  * frame that was received included challenge text, the frame is
2242
  * frame that was received included challenge text, the frame is
2094
- * encrypted using the cryptographic algorithm currently in effect and
2095
- * sent back to the AP to complete the authentication.
2243
+ * encrypted using the cryptosystem currently in effect and sent back
2244
+ * to the AP to complete the authentication.
2096
  */
2245
  */
2097
 static void net80211_handle_auth ( struct net80211_device *dev,
2246
 static void net80211_handle_auth ( struct net80211_device *dev,
2098
 				   struct io_buffer *iob )
2247
 				   struct io_buffer *iob )
2181
 	DBGP ( "802.11 %p about to send association request:\n", dev );
2330
 	DBGP ( "802.11 %p about to send association request:\n", dev );
2182
 	DBGP_HD ( iob->data, ( void * ) ie - iob->data );
2331
 	DBGP_HD ( iob->data, ( void * ) ie - iob->data );
2183
 
2332
 
2184
-	/* XXX add RSN ie for WPA support */
2185
-
2186
 	iob_put ( iob, ( void * ) ie - iob->data );
2333
 	iob_put ( iob, ( void * ) ie - iob->data );
2187
 
2334
 
2188
 	return net80211_tx_mgmt ( dev, IEEE80211_STYPE_ASSOC_REQ,
2335
 	return net80211_tx_mgmt ( dev, IEEE80211_STYPE_ASSOC_REQ,
2227
  *
2374
  *
2228
  * @v dev	802.11 device
2375
  * @v dev	802.11 device
2229
  * @v reason	Reason for disassociation
2376
  * @v reason	Reason for disassociation
2377
+ * @v deauth	If TRUE, send deauthentication instead of disassociation
2230
  * @ret rc	Return status code
2378
  * @ret rc	Return status code
2231
  */
2379
  */
2232
-static int net80211_send_disassoc ( struct net80211_device *dev, int reason )
2380
+static int net80211_send_disassoc ( struct net80211_device *dev, int reason,
2381
+				    int deauth )
2233
 {
2382
 {
2234
 	struct io_buffer *iob = alloc_iob ( 64 );
2383
 	struct io_buffer *iob = alloc_iob ( 64 );
2235
 	struct ieee80211_disassoc *disassoc;
2384
 	struct ieee80211_disassoc *disassoc;
2242
 	disassoc = iob_put ( iob, sizeof ( *disassoc ) );
2391
 	disassoc = iob_put ( iob, sizeof ( *disassoc ) );
2243
 	disassoc->reason = reason;
2392
 	disassoc->reason = reason;
2244
 
2393
 
2245
-	return net80211_tx_mgmt ( dev, IEEE80211_STYPE_DISASSOC, dev->bssid,
2246
-				  iob );
2394
+	return net80211_tx_mgmt ( dev, deauth ? IEEE80211_STYPE_DEAUTH :
2395
+				  IEEE80211_STYPE_DISASSOC, dev->bssid, iob );
2396
+}
2397
+
2398
+
2399
+/**
2400
+ * Deauthenticate from current network and try again
2401
+ *
2402
+ * @v dev	802.11 device
2403
+ * @v rc	Return status code indicating reason
2404
+ *
2405
+ * The deauthentication will be sent using an 802.11 "unspecified
2406
+ * reason", as is common, but @a rc will be set as a link-up
2407
+ * error to aid the user in debugging.
2408
+ */
2409
+void net80211_deauthenticate ( struct net80211_device *dev, int rc )
2410
+{
2411
+	net80211_send_disassoc ( dev, IEEE80211_REASON_UNSPECIFIED, 1 );
2412
+	dev->assoc_rc = rc;
2413
+	netdev_link_err ( dev->netdev, rc );
2414
+
2415
+	net80211_autoassociate ( dev );
2247
 }
2416
 }
2248
 
2417
 
2249
 
2418
 
2557
 		iob_unput ( iob, 4 );
2726
 		iob_unput ( iob, 4 );
2558
 	}
2727
 	}
2559
 
2728
 
2560
-	if ( hdr->fc & IEEE80211_FC_PROTECTED ) {
2729
+	/* Only decrypt packets from our BSSID, to avoid spurious errors */
2730
+	if ( ( hdr->fc & IEEE80211_FC_PROTECTED ) &&
2731
+	     ! memcmp ( hdr->addr2, dev->bssid, ETH_ALEN ) ) {
2732
+		/* Decrypt packet; record and drop if it fails */
2561
 		struct io_buffer *niob;
2733
 		struct io_buffer *niob;
2562
-		if ( ! dev->crypto )
2563
-			goto drop;	/* can't decrypt packets on an open network */
2734
+		struct net80211_crypto *crypto = dev->crypto;
2564
 
2735
 
2565
-		niob = dev->crypto->decrypt ( dev->crypto, iob );
2566
-		if ( ! niob )
2567
-			goto drop;	/* drop failed decryption */
2736
+		if ( ! dev->crypto ) {
2737
+			DBGC ( dev, "802.11 %p cannot decrypt packet "
2738
+			       "without a cryptosystem\n", dev );
2739
+			goto drop_crypt;
2740
+		}
2741
+
2742
+		if ( ( hdr->addr1[0] & 1 ) && dev->gcrypto ) {
2743
+			/* Use group decryption if needed */
2744
+			crypto = dev->gcrypto;
2745
+		}
2746
+
2747
+		niob = crypto->decrypt ( crypto, iob );
2748
+		if ( ! niob ) {
2749
+			DBGC ( dev, "802.11 %p decryption error\n", dev );
2750
+			goto drop_crypt;
2751
+		}
2568
 		free_iob ( iob );
2752
 		free_iob ( iob );
2569
 		iob = niob;
2753
 		iob = niob;
2570
 	}
2754
 	}
2593
 		rc80211_update_rx ( dev, hdr->fc & IEEE80211_FC_RETRY, rate );
2777
 		rc80211_update_rx ( dev, hdr->fc & IEEE80211_FC_RETRY, rate );
2594
 
2778
 
2595
 	/* Pass packet onward */
2779
 	/* Pass packet onward */
2596
-	if ( netdev_link_ok ( dev->netdev ) ) {
2780
+	if ( dev->state & NET80211_ASSOCIATED ) {
2597
 		netdev_rx ( dev->netdev, iob );
2781
 		netdev_rx ( dev->netdev, iob );
2598
 		return;
2782
 		return;
2599
 	}
2783
 	}
2600
 
2784
 
2785
+	/* No association? Drop it. */
2786
+	goto drop;
2787
+
2788
+ drop_crypt:
2789
+	netdev_rx_err ( dev->netdev, NULL, EINVAL_CRYPTO_REQUEST );
2601
  drop:
2790
  drop:
2602
 	DBGC2 ( dev, "802.11 %p dropped packet fc=%04x seq=%04x\n", dev,
2791
 	DBGC2 ( dev, "802.11 %p dropped packet fc=%04x seq=%04x\n", dev,
2603
 		hdr->fc, hdr->seq );
2792
 		hdr->fc, hdr->seq );

+ 503
- 0
src/net/80211/sec80211.c View File

1
+/*
2
+ * Copyright (c) 2009 Joshua Oreman <oremanj@rwcr.net>.
3
+ *
4
+ * This program is free software; you can redistribute it and/or
5
+ * modify it under the terms of the GNU General Public License as
6
+ * published by the Free Software Foundation; either version 2 of the
7
+ * License, or any later version.
8
+ *
9
+ * This program is distributed in the hope that it will be useful, but
10
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12
+ * General Public License for more details.
13
+ *
14
+ * You should have received a copy of the GNU General Public License
15
+ * along with this program; if not, write to the Free Software
16
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
+ */
18
+
19
+FILE_LICENCE ( GPL2_OR_LATER );
20
+
21
+#include <stdlib.h>
22
+#include <string.h>
23
+#include <errno.h>
24
+#include <gpxe/ieee80211.h>
25
+#include <gpxe/net80211.h>
26
+#include <gpxe/sec80211.h>
27
+
28
+/** @file
29
+ *
30
+ * General secured-network routines required whenever any secure
31
+ * network support at all is compiled in. This involves things like
32
+ * installing keys, determining the type of security used by a probed
33
+ * network, and some small helper functions that take advantage of
34
+ * static data in this file.
35
+ */
36
+
37
+/** Mapping from net80211 crypto/secprot types to RSN OUI descriptors */
38
+struct descriptor_map {
39
+	/** Value of net80211_crypto_alg or net80211_security_proto */
40
+	u32 net80211_type;
41
+
42
+	/** OUI+type in appropriate byte order, masked to exclude vendor */
43
+	u32 oui_type;
44
+};
45
+
46
+/** Magic number in @a oui_type showing end of list */
47
+#define END_MAGIC	0xFFFFFFFF
48
+
49
+/** Mapping between net80211 cryptosystems and 802.11i cipher IDs */
50
+static struct descriptor_map rsn_cipher_map[] = {
51
+	{ .net80211_type = NET80211_CRYPT_WEP,
52
+	  .oui_type = IEEE80211_RSN_CTYPE_WEP40 },
53
+
54
+	{ .net80211_type = NET80211_CRYPT_WEP,
55
+	  .oui_type = IEEE80211_RSN_CTYPE_WEP104 },
56
+
57
+	{ .net80211_type = NET80211_CRYPT_TKIP,
58
+	  .oui_type = IEEE80211_RSN_CTYPE_TKIP },
59
+
60
+	{ .net80211_type = NET80211_CRYPT_CCMP,
61
+	  .oui_type = IEEE80211_RSN_CTYPE_CCMP },
62
+
63
+	{ .net80211_type = NET80211_CRYPT_UNKNOWN,
64
+	  .oui_type = END_MAGIC },
65
+};
66
+
67
+/** Mapping between net80211 handshakers and 802.11i AKM IDs */
68
+static struct descriptor_map rsn_akm_map[] = {
69
+	{ .net80211_type = NET80211_SECPROT_EAP,
70
+	  .oui_type = IEEE80211_RSN_ATYPE_8021X },
71
+
72
+	{ .net80211_type = NET80211_SECPROT_PSK,
73
+	  .oui_type = IEEE80211_RSN_ATYPE_PSK },
74
+
75
+	{ .net80211_type = NET80211_SECPROT_UNKNOWN,
76
+	  .oui_type = END_MAGIC },
77
+};
78
+
79
+
80
+/**
81
+ * Install 802.11 cryptosystem
82
+ *
83
+ * @v which	Pointer to the cryptosystem structure to install in
84
+ * @v crypt	Cryptosystem ID number
85
+ * @v key	Encryption key to use
86
+ * @v len	Length of encryption key
87
+ * @v rsc	Initial receive sequence counter, if applicable
88
+ * @ret rc	Return status code
89
+ *
90
+ * The encryption key will not be accessed via the provided pointer
91
+ * after this function returns, so you may keep it on the stack.
92
+ *
93
+ * @a which must point to either @c dev->crypto (for the normal case
94
+ * of installing a unicast cryptosystem) or @c dev->gcrypto (to
95
+ * install a cryptosystem that will be used only for decrypting
96
+ * group-source frames).
97
+ */
98
+int sec80211_install ( struct net80211_crypto **which,
99
+		       enum net80211_crypto_alg crypt,
100
+		       const void *key, int len, const void *rsc )
101
+{
102
+	struct net80211_crypto *crypto = *which;
103
+	struct net80211_crypto *tbl_crypto;
104
+
105
+	/* Remove old crypto if it exists */
106
+	free ( *which );
107
+	*which = NULL;
108
+
109
+	if ( crypt == NET80211_CRYPT_NONE ) {
110
+		DBG ( "802.11-Sec not installing null cryptography\n" );
111
+		return 0;
112
+	}
113
+
114
+	/* Find cryptosystem to use */
115
+	for_each_table_entry ( tbl_crypto, NET80211_CRYPTOS ) {
116
+		if ( tbl_crypto->algorithm == crypt ) {
117
+			crypto = zalloc ( sizeof ( *crypto ) +
118
+					  tbl_crypto->priv_len );
119
+			if ( ! crypto ) {
120
+				DBG ( "802.11-Sec out of memory\n" );
121
+				return -ENOMEM;
122
+			}
123
+
124
+			memcpy ( crypto, tbl_crypto, sizeof ( *crypto ) );
125
+			crypto->priv = ( ( void * ) crypto +
126
+					 sizeof ( *crypto ) );
127
+			break;
128
+		}
129
+	}
130
+
131
+	if ( ! crypto ) {
132
+		DBG ( "802.11-Sec no support for cryptosystem %d\n", crypt );
133
+		return -( ENOTSUP | EUNIQ_10 | ( crypt << 8 ) );
134
+	}
135
+
136
+	*which = crypto;
137
+
138
+	DBG ( "802.11-Sec installing cryptosystem %d as %p with key of "
139
+	      "length %d\n", crypt, crypto, len );
140
+
141
+	return crypto->init ( crypto, key, len, rsc );
142
+}
143
+
144
+
145
+/**
146
+ * Determine net80211 crypto or handshaking type value to return for RSN info
147
+ *
148
+ * @v rsnp		Pointer to next descriptor count field in RSN IE
149
+ * @v rsn_end		Pointer to end of RSN IE
150
+ * @v map		Descriptor map to use
151
+ * @v tbl_start		Start of linker table to examine for gPXE support
152
+ * @v tbl_end		End of linker table to examine for gPXE support
153
+ * @ret rsnp		Updated to point to first byte after descriptors
154
+ * @ret map_ent		Descriptor map entry of translation to use
155
+ *
156
+ * The entries in the linker table must be either net80211_crypto or
157
+ * net80211_handshaker structures, and @a tbl_stride must be set to
158
+ * sizeof() the appropriate one.
159
+ *
160
+ * This function expects @a rsnp to point at a two-byte descriptor
161
+ * count followed by a list of four-byte cipher or AKM descriptors; it
162
+ * will return @c NULL if the input packet is malformed, and otherwise
163
+ * set @a rsnp to the first byte it has not looked at. It will return
164
+ * the first cipher in the list that is supported by the current build
165
+ * of gPXE, or the first of all if none are supported.
166
+ *
167
+ * We play rather fast and loose with type checking, because this
168
+ * function is only called from two well-defined places in the
169
+ * RSN-checking code. Don't try to use it for anything else.
170
+ */
171
+static struct descriptor_map * rsn_pick_desc ( u8 **rsnp, u8 *rsn_end,
172
+					       struct descriptor_map *map,
173
+					       void *tbl_start, void *tbl_end )
174
+{
175
+	int ndesc;
176
+	int ok = 0;
177
+	struct descriptor_map *map_ent, *map_ret = NULL;
178
+	u8 *rsn = *rsnp;
179
+	void *tblp;
180
+	size_t tbl_stride = ( map == rsn_cipher_map ?
181
+			      sizeof ( struct net80211_crypto ) :
182
+			      sizeof ( struct net80211_handshaker ) );
183
+
184
+	if ( map != rsn_cipher_map && map != rsn_akm_map )
185
+		return NULL;
186
+
187
+	/* Determine which types we support */
188
+	for ( tblp = tbl_start; tblp < tbl_end; tblp += tbl_stride ) {
189
+		struct net80211_crypto *crypto = tblp;
190
+		struct net80211_handshaker *hs = tblp;
191
+
192
+		if ( map == rsn_cipher_map )
193
+			ok |= ( 1 << crypto->algorithm );
194
+		else
195
+			ok |= ( 1 << hs->protocol );
196
+	}
197
+
198
+	/* RSN sanity checks */
199
+	if ( rsn + 2 > rsn_end ) {
200
+		DBG ( "RSN detect: malformed descriptor count\n" );
201
+		return NULL;
202
+	}
203
+
204
+	ndesc = *( u16 * ) rsn;
205
+	rsn += 2;
206
+
207
+	if ( ! ndesc ) {
208
+		DBG ( "RSN detect: no descriptors\n" );
209
+		return NULL;
210
+	}
211
+
212
+	/* Determine which net80211 crypto types are listed */
213
+	while ( ndesc-- ) {
214
+		u32 desc;
215
+
216
+		if ( rsn + 4 > rsn_end ) {
217
+			DBG ( "RSN detect: malformed descriptor (%d left)\n",
218
+			      ndesc );
219
+			return NULL;
220
+		}
221
+
222
+		desc = *( u32 * ) rsn;
223
+		rsn += 4;
224
+
225
+		for ( map_ent = map; map_ent->oui_type != END_MAGIC; map_ent++ )
226
+			if ( map_ent->oui_type == ( desc & OUI_TYPE_MASK ) )
227
+				break;
228
+
229
+		/* Use first cipher as a fallback */
230
+		if ( ! map_ret )
231
+			map_ret = map_ent;
232
+
233
+		/* Once we find one we support, use it */
234
+		if ( ok & ( 1 << map_ent->net80211_type ) ) {
235
+			map_ret = map_ent;
236
+			break;
237
+		}
238
+	}
239
+
240
+	if ( ndesc > 0 )
241
+		rsn += 4 * ndesc;
242
+
243
+	*rsnp = rsn;
244
+	return map_ret;
245
+}
246
+
247
+
248
+/**
249
+ * Find the RSN or WPA information element in the provided beacon frame
250
+ *
251
+ * @v ie	Pointer to first information element to check
252
+ * @v ie_end	Pointer to end of information element space
253
+ * @ret is_rsn	TRUE if returned IE is RSN, FALSE if it's WPA
254
+ * @ret end	Pointer to byte immediately after last byte of data
255
+ * @ret data	Pointer to first byte of data (the `version' field)
256
+ *
257
+ * If both an RSN and a WPA information element are found, this
258
+ * function will return the first one seen, which by ordering rules
259
+ * should always prefer the newer RSN IE.
260
+ *
261
+ * If no RSN or WPA infomration element is found, returns @c NULL and
262
+ * leaves @a is_rsn and @a end in an undefined state.
263
+ *
264
+ * This function will not return a pointer to an information element
265
+ * that states it extends past the tail of the io_buffer, or whose @a
266
+ * version field is incorrect.
267
+ */
268
+u8 * sec80211_find_rsn ( union ieee80211_ie *ie, void *ie_end,
269
+			 int *is_rsn, u8 **end )
270
+{
271
+	u8 *rsn = NULL;
272
+
273
+	if ( ! ieee80211_ie_bound ( ie, ie_end ) )
274
+		return NULL;
275
+
276
+	while ( ie ) {
277
+		if ( ie->id == IEEE80211_IE_VENDOR &&
278
+		     ie->vendor.oui == IEEE80211_WPA_OUI_VEN ) {
279
+			DBG ( "RSN detect: old-style WPA IE found\n" );
280
+			rsn = &ie->vendor.data[0];
281
+			*end = rsn + ie->len - 4;
282
+			*is_rsn = 0;
283
+		} else if ( ie->id == IEEE80211_IE_RSN ) {
284
+			DBG ( "RSN detect: 802.11i RSN IE found\n" );
285
+			rsn = ( u8 * ) &ie->rsn.version;
286
+			*end = rsn + ie->len;
287
+			*is_rsn = 1;
288
+		}
289
+
290
+		if ( rsn && ( *end > ( u8 * ) ie_end || rsn >= *end ||
291
+			      *( u16 * ) rsn != IEEE80211_RSN_VERSION ) ) {
292
+			DBG ( "RSN detect: malformed RSN IE or unknown "
293
+			      "version, keep trying\n" );
294
+			rsn = NULL;
295
+		}
296
+
297
+		if ( rsn )
298
+			break;
299
+
300
+		ie = ieee80211_next_ie ( ie, ie_end );
301
+	}
302
+
303
+	if ( ! ie ) {
304
+		DBG ( "RSN detect: no RSN IE found\n" );
305
+		return NULL;
306
+	}
307
+
308
+	return rsn;
309
+}
310
+
311
+
312
+/**
313
+ * Detect crypto and AKM types from RSN information element
314
+ *
315
+ * @v is_rsn	If TRUE, IE is a new-style RSN information element
316
+ * @v start	Pointer to first byte of @a version field
317
+ * @v end	Pointer to first byte not in the RSN IE
318
+ * @ret secprot	Security handshaking protocol used by network
319
+ * @ret crypt	Cryptosystem used by network
320
+ * @ret rc	Return status code
321
+ *
322
+ * If the IE cannot be parsed, returns an error indication and leaves
323
+ * @a secprot and @a crypt unchanged.
324
+ */
325
+int sec80211_detect_ie ( int is_rsn, u8 *start, u8 *end,
326
+			 enum net80211_security_proto *secprot,
327
+			 enum net80211_crypto_alg *crypt )
328
+{
329
+	enum net80211_security_proto sp;
330
+	enum net80211_crypto_alg cr;
331
+	struct descriptor_map *map;
332
+	u8 *rsn = start;
333
+
334
+	/* Set some defaults */
335
+	cr = ( is_rsn ? NET80211_CRYPT_CCMP : NET80211_CRYPT_TKIP );
336
+	sp = NET80211_SECPROT_EAP;
337
+
338
+	rsn += 2;		/* version - already checked */
339
+	rsn += 4;		/* group cipher - we don't use it here */
340
+
341
+	if ( rsn >= end )
342
+		goto done;
343
+
344
+	/* Pick crypto algorithm */
345
+	map = rsn_pick_desc ( &rsn, end, rsn_cipher_map,
346
+			      table_start ( NET80211_CRYPTOS ),
347
+			      table_end ( NET80211_CRYPTOS ) );
348
+	if ( ! map )
349
+		goto invalid_rsn;
350
+
351
+	cr = map->net80211_type;
352
+
353
+	if ( rsn >= end )
354
+		goto done;
355
+
356
+	/* Pick handshaking algorithm */
357
+	map = rsn_pick_desc ( &rsn, end, rsn_akm_map,
358
+			      table_start ( NET80211_HANDSHAKERS ),
359
+			      table_end ( NET80211_HANDSHAKERS ) );
360
+	if ( ! map )
361
+		goto invalid_rsn;
362
+
363
+	sp = map->net80211_type;
364
+
365
+ done:
366
+	DBG ( "RSN detect: OK, crypto type %d, secprot type %d\n", cr, sp );
367
+	*secprot = sp;
368
+	*crypt = cr;
369
+	return 0;
370
+
371
+ invalid_rsn:
372
+	DBG ( "RSN detect: invalid RSN IE\n" );
373
+	return -EINVAL;
374
+}
375
+
376
+
377
+/**
378
+ * Detect the cryptosystem and handshaking protocol used by an 802.11 network
379
+ *
380
+ * @v iob	I/O buffer containing beacon frame
381
+ * @ret secprot	Security handshaking protocol used by network
382
+ * @ret crypt	Cryptosystem used by network
383
+ * @ret rc	Return status code
384
+ *
385
+ * This function uses weak linkage, as it must be called from generic
386
+ * contexts but should only be linked in if some encryption is
387
+ * supported; you must test its address against @c NULL before calling
388
+ * it. If it does not exist, any network with the PRIVACY bit set in
389
+ * beacon->capab should be considered unknown.
390
+ */
391
+int _sec80211_detect ( struct io_buffer *iob,
392
+		       enum net80211_security_proto *secprot,
393
+		       enum net80211_crypto_alg *crypt )
394
+{
395
+	struct ieee80211_frame *hdr = iob->data;
396
+	struct ieee80211_beacon *beacon =
397
+		( struct ieee80211_beacon * ) hdr->data;
398
+	u8 *rsn, *rsn_end;
399
+	int is_rsn, rc;
400
+
401
+	*crypt = NET80211_CRYPT_UNKNOWN;
402
+	*secprot = NET80211_SECPROT_UNKNOWN;
403
+
404
+	/* Find RSN or WPA IE */
405
+	if ( ! ( rsn = sec80211_find_rsn ( beacon->info_element, iob->tail,
406
+					   &is_rsn, &rsn_end ) ) ) {
407
+		/* No security IE at all; either WEP or no security. */
408
+		*secprot = NET80211_SECPROT_NONE;
409
+
410
+		if ( beacon->capability & IEEE80211_CAPAB_PRIVACY )
411
+			*crypt = NET80211_CRYPT_WEP;
412
+		else
413
+			*crypt = NET80211_CRYPT_NONE;
414
+
415
+		return 0;
416
+	}
417
+
418
+	/* Determine type of security */
419
+	if ( ( rc = sec80211_detect_ie ( is_rsn, rsn, rsn_end, secprot,
420
+					 crypt ) ) == 0 )
421
+		return 0;
422
+
423
+	/* If we get here, the RSN IE was invalid */
424
+
425
+	*crypt = NET80211_CRYPT_UNKNOWN;
426
+	*secprot = NET80211_SECPROT_UNKNOWN;
427
+	DBG ( "Failed to handle RSN IE:\n" );
428
+	DBG_HD ( rsn, rsn_end - rsn );
429
+	return rc;
430
+}
431
+
432
+
433
+/**
434
+ * Determine RSN descriptor for specified net80211 ID
435
+ *
436
+ * @v id	net80211 ID value
437
+ * @v rsnie	Whether to return a new-format (RSN IE) descriptor
438
+ * @v map	Map to use in translation
439
+ * @ret desc	RSN descriptor, or 0 on error
440
+ *
441
+ * If @a rsnie is false, returns an old-format (WPA vendor IE)
442
+ * descriptor.
443
+ */
444
+static u32 rsn_get_desc ( unsigned id, int rsnie, struct descriptor_map *map )
445
+{
446
+	u32 vendor = ( rsnie ? IEEE80211_RSN_OUI : IEEE80211_WPA_OUI );
447
+
448
+	for ( ; map->oui_type != END_MAGIC; map++ ) {
449
+		if ( map->net80211_type == id )
450
+			return map->oui_type | vendor;
451
+	}
452
+
453
+	return 0;
454
+}
455
+
456
+/**
457
+ * Determine RSN descriptor for specified net80211 cryptosystem number
458
+ *
459
+ * @v crypt	Cryptosystem number
460
+ * @v rsnie	Whether to return a new-format (RSN IE) descriptor
461
+ * @ret desc	RSN descriptor
462
+ *
463
+ * If @a rsnie is false, returns an old-format (WPA vendor IE)
464
+ * descriptor.
465
+ */
466
+u32 sec80211_rsn_get_crypto_desc ( enum net80211_crypto_alg crypt, int rsnie )
467
+{
468
+	return rsn_get_desc ( crypt, rsnie, rsn_cipher_map );
469
+}
470
+
471
+/**
472
+ * Determine RSN descriptor for specified net80211 handshaker number
473
+ *
474
+ * @v secprot	Handshaker number
475
+ * @v rsnie	Whether to return a new-format (RSN IE) descriptor
476
+ * @ret desc	RSN descriptor
477
+ *
478
+ * If @a rsnie is false, returns an old-format (WPA vendor IE)
479
+ * descriptor.
480
+ */
481
+u32 sec80211_rsn_get_akm_desc ( enum net80211_security_proto secprot,
482
+				int rsnie )
483
+{
484
+	return rsn_get_desc ( secprot, rsnie, rsn_akm_map );
485
+}
486
+
487
+/**
488
+ * Determine net80211 cryptosystem number from RSN descriptor
489
+ *
490
+ * @v desc	RSN descriptor
491
+ * @ret crypt	net80211 cryptosystem enumeration value
492
+ */
493
+enum net80211_crypto_alg sec80211_rsn_get_net80211_crypt ( u32 desc )
494
+{
495
+	struct descriptor_map *map = rsn_cipher_map;
496
+
497
+	for ( ; map->oui_type != END_MAGIC; map++ ) {
498
+		if ( map->oui_type == ( desc & OUI_TYPE_MASK ) )
499
+			break;
500
+	}
501
+
502
+	return map->net80211_type;
503
+}

Loading…
Cancel
Save