wlan_rsn/key/exchange/handshake/group_key/
mod.rs

1// Copyright 2018 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5use crate::key::exchange::handshake::group_key::supplicant::Supplicant;
6use crate::key::exchange::{self};
7use crate::rsna::{Dot11VerifiedKeyFrame, NegotiatedProtection, Role, UpdateSink};
8use crate::{rsn_ensure, Error};
9use bytes::Bytes;
10use zerocopy::SplitByteSlice;
11
12mod supplicant;
13
14#[derive(Debug, PartialEq)]
15enum RoleHandler {
16    Supplicant(Supplicant),
17}
18
19// Struct which carries EAPOL key frames which comply with IEEE Std 802.11-2016, 12.7.2 and
20// IEEE Std 802.11-2016, 12.7.7.
21pub struct GroupKeyHandshakeFrame<B: SplitByteSlice> {
22    frame: Dot11VerifiedKeyFrame<B>,
23}
24
25impl<B: SplitByteSlice> GroupKeyHandshakeFrame<B> {
26    #[allow(clippy::result_large_err, reason = "mass allow for https://fxbug.dev/381896734")]
27    pub fn from_verified(frame: Dot11VerifiedKeyFrame<B>, role: Role) -> Result<Self, Error> {
28        // Safe since the frame will be wrapped again in a `Dot11VerifiedKeyFrame` when being accessed.
29        let raw_frame = frame.unsafe_get_raw();
30
31        let sender = match role {
32            Role::Supplicant => Role::Authenticator,
33            Role::Authenticator => Role::Supplicant,
34        };
35
36        let key_info = raw_frame.key_frame_fields.key_info();
37
38        // IEEE Std 802.11-2016, 12.7.7.2 & IEEE Std 802.11-2016, 12.7.7.3
39        rsn_ensure!(
40            key_info.key_type() == eapol::KeyType::GROUP_SMK,
41            "only group key messages are allowed in Group Key Handshake"
42        );
43        rsn_ensure!(
44            !key_info.install(),
45            "installbit must not be set in Group Key Handshake messages"
46        );
47        rsn_ensure!(key_info.key_mic(), "MIC bit must be set in Group Key Handshake messages");
48        rsn_ensure!(key_info.secure(), "secure bit must be set in Group Key Handshake messages");
49        rsn_ensure!(!key_info.error(), "error bit must not be set in Group Key Handshake messages");
50        rsn_ensure!(
51            !key_info.request(),
52            "request bit must not be set in Group Key Handshake messages"
53        );
54
55        // IEEE Std 802.11-2016, 12.7.7.2 requires the key length to be set to 0 in
56        // group key handshakes messages. Some routers, such as Apple Airport Extreme
57        // violate this specification and do send the pairwise cipher key length in group
58        // key messages as well. To support interoperability, the key length is allowed to
59        // be arbitrary as it's not used in the Group Key handshake.
60
61        // IEEE Std 802.11-2016, 12.7.7.2 requires the nonce to be zeroed in group key handshakes
62        // messages. Some routers, such as Apple Airport Extreme violate this specification and do
63        // send a nonce other than zero. To support interoperability, the nonce is allowed to
64        // be an arbitrary value as it's not used in the Group Key handshake.
65
66        match &sender {
67            // IEEE Std 802.11-2016, 12.7.7.2
68            Role::Authenticator => {
69                rsn_ensure!(
70                    key_info.key_ack(),
71                    "ACK bit must be set in 1st message of Group Key Handshake"
72                );
73
74                // WFA, WPA1 Spec. 3.1, Chapter 2.2.4
75                // WPA1 does not use the encrypted key data bit, so we don't bother checking it.
76                if raw_frame.key_frame_fields.descriptor_type != eapol::KeyDescriptor::LEGACY_WPA1 {
77                    rsn_ensure!(
78                        key_info.encrypted_key_data(),
79                        "encrypted data bit must be set in 1st message of Group Key Handshake"
80                    );
81                }
82
83                // IEEE Std 802.11-2016, 12.7.7.2 requires the key frame's IV to be zero'ed when
84                // using 802.1X-2004. Some routers, such as Linksys, violate this constraint.
85                // The IV is not used in the Group Key Handshake, thus, ignoring this requirement is
86                // safe.
87
88                // RSC is currently not taken into account.
89            }
90            // IEEE Std 802.11-2016, 12.7.7.3
91            Role::Supplicant => {
92                rsn_ensure!(
93                    !key_info.key_ack(),
94                    "ACK bit must not be set in 2nd message of Group Key Handshake"
95                );
96                rsn_ensure!(
97                    !key_info.encrypted_key_data(),
98                    "encrypted data bit must not be set in 2nd message of Group Key Handshake"
99                );
100                rsn_ensure!(
101                    is_zero(&raw_frame.key_frame_fields.key_iv[..]),
102                    "IV must be zero in 2nd message of Group Key Handshake"
103                );
104                rsn_ensure!(
105                    raw_frame.key_frame_fields.key_rsc.to_native() == 0,
106                    "RSC must be zero in 2nd message of Group Key Handshake"
107                );
108            }
109        };
110
111        Ok(GroupKeyHandshakeFrame { frame })
112    }
113
114    pub fn get(self) -> Dot11VerifiedKeyFrame<B> {
115        self.frame
116    }
117}
118
119#[derive(Debug, Clone, PartialEq)]
120pub struct Config {
121    pub role: Role,
122    pub protection: NegotiatedProtection,
123}
124
125#[derive(Debug, PartialEq)]
126pub struct GroupKey(RoleHandler);
127
128impl GroupKey {
129    #[allow(clippy::result_large_err, reason = "mass allow for https://fxbug.dev/381896734")]
130    pub fn new(cfg: Config, kck: &[u8], kek: &[u8]) -> Result<GroupKey, Error> {
131        let handler = match &cfg.role {
132            Role::Supplicant => RoleHandler::Supplicant(Supplicant {
133                cfg,
134                kck: Bytes::copy_from_slice(kck),
135                kek: Bytes::copy_from_slice(kek),
136            }),
137            _ => {
138                return Err(Error::GenericError(
139                    "Authenticator not yet support in Group-Key Handshake".to_string(),
140                ))
141            }
142        };
143
144        Ok(GroupKey(handler))
145    }
146
147    pub fn destroy(self) -> exchange::Config {
148        match self.0 {
149            RoleHandler::Supplicant(s) => exchange::Config::GroupKeyHandshake(s.destroy()),
150        }
151    }
152
153    #[allow(clippy::result_large_err, reason = "mass allow for https://fxbug.dev/381896734")]
154    pub fn on_eapol_key_frame<B: SplitByteSlice>(
155        &mut self,
156        update_sink: &mut UpdateSink,
157        frame: Dot11VerifiedKeyFrame<B>,
158    ) -> Result<(), Error> {
159        match &mut self.0 {
160            RoleHandler::Supplicant(s) => {
161                let frame = GroupKeyHandshakeFrame::from_verified(frame, Role::Supplicant)?;
162                s.on_eapol_key_frame(update_sink, frame)
163            }
164        }
165    }
166}
167
168fn is_zero(slice: &[u8]) -> bool {
169    slice.iter().all(|&x| x == 0)
170}
171
172#[cfg(test)]
173mod tests {
174    use super::*;
175    use crate::rsna::test_util;
176    use wlan_common::ie::rsn::fake_wpa2_s_rsne;
177
178    fn verify_group_key_frame(key_frame: eapol::KeyFrameBuf, role: Role) {
179        let protection =
180            NegotiatedProtection::from_rsne(&fake_wpa2_s_rsne()).expect("error getting RNSE");
181        let parsed_frame = eapol::KeyFrameRx::parse(test_util::mic_len(), &key_frame[..])
182            .expect("failed to parse group key frame");
183        let frame = Dot11VerifiedKeyFrame::from_frame(parsed_frame, &role, &protection, 0)
184            .expect("couldn't verify frame");
185        GroupKeyHandshakeFrame::from_verified(frame, role).expect("error verifying group_frame");
186    }
187
188    fn fake_key_frame() -> eapol::KeyFrameTx {
189        let mut key_frame_fields = eapol::KeyFrameFields::default();
190        key_frame_fields.descriptor_type = eapol::KeyDescriptor::IEEE802DOT11;
191        key_frame_fields.set_key_info(eapol::KeyInformation(0b01001110000010));
192        eapol::KeyFrameTx::new(
193            eapol::ProtocolVersion::IEEE802DOT1X2004,
194            key_frame_fields,
195            vec![],
196            test_util::mic_len(),
197        )
198    }
199
200    #[test]
201    fn zeroed_iv_8021x2004() {
202        let mut key_frame = fake_key_frame();
203        key_frame.protocol_version = eapol::ProtocolVersion::IEEE802DOT1X2004;
204        let key_frame = key_frame
205            .serialize()
206            .finalize_with_mic(&vec![0u8; test_util::mic_len()][..])
207            .expect("failed to construct key frame");
208        verify_group_key_frame(key_frame, Role::Supplicant);
209    }
210
211    #[test]
212    fn random_iv_8021x2004() {
213        let mut key_frame = fake_key_frame();
214        key_frame.protocol_version = eapol::ProtocolVersion::IEEE802DOT1X2004;
215        // IEEE does not allow random IV in combination with 802.1X-2004.
216        key_frame.key_frame_fields.key_iv.copy_from_slice(&[1; 16]);
217        let key_frame = key_frame
218            .serialize()
219            .finalize_with_mic(&vec![0u8; test_util::mic_len()][..])
220            .expect("failed to construct key frame");
221        verify_group_key_frame(key_frame, Role::Supplicant);
222    }
223
224    #[test]
225    fn zeroed_iv_8021x2001() {
226        let mut key_frame = fake_key_frame();
227        key_frame.protocol_version = eapol::ProtocolVersion::IEEE802DOT1X2001;
228        let key_frame = key_frame
229            .serialize()
230            .finalize_with_mic(&vec![0u8; test_util::mic_len()][..])
231            .expect("failed to construct key frame");
232        verify_group_key_frame(key_frame, Role::Supplicant);
233    }
234
235    #[test]
236    fn random_iv_8021x2001() {
237        let mut key_frame = fake_key_frame();
238        key_frame.protocol_version = eapol::ProtocolVersion::IEEE802DOT1X2001;
239        key_frame.key_frame_fields.key_iv.copy_from_slice(&[1; 16]);
240        let key_frame = key_frame
241            .serialize()
242            .finalize_with_mic(&vec![0u8; test_util::mic_len()][..])
243            .expect("failed to construct key frame");
244        verify_group_key_frame(key_frame, Role::Supplicant);
245    }
246}