1 /*
2  * Copyright (C) 2019 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.internal.net.eap.message.simaka;
18 
19 import android.annotation.NonNull;
20 
21 import com.android.internal.annotations.VisibleForTesting;
22 import com.android.internal.net.eap.message.EapMessage;
23 
24 import java.util.HashMap;
25 import java.util.HashSet;
26 import java.util.LinkedHashMap;
27 import java.util.List;
28 import java.util.Map;
29 import java.util.Set;
30 
31 /**
32  * EapAkaTypeData represents the Type Data for an {@link EapMessage} during an EAP-AKA session.
33  */
34 public class EapAkaTypeData extends EapSimAkaTypeData {
35     private static final String TAG = EapAkaTypeData.class.getSimpleName();
36 
37     // EAP-AKA Subtype values defined by IANA
38     // https://www.iana.org/assignments/eapsimaka-numbers/eapsimaka-numbers.xhtml
39     public static final int EAP_AKA_CHALLENGE = 1;
40     public static final int EAP_AKA_AUTHENTICATION_REJECT = 2;
41     public static final int EAP_AKA_SYNCHRONIZATION_FAILURE = 4;
42     public static final int EAP_AKA_IDENTITY = 5;
43     public static final int EAP_AKA_NOTIFICATION = 12;
44     public static final int EAP_AKA_REAUTHENTICATION = 13;
45     public static final int EAP_AKA_CLIENT_ERROR = 14;
46 
47     public static final Map<Integer, String> EAP_AKA_SUBTYPE_STRING = new HashMap<>();
48     static {
EAP_AKA_SUBTYPE_STRING.put(EAP_AKA_CHALLENGE, "Challenge")49         EAP_AKA_SUBTYPE_STRING.put(EAP_AKA_CHALLENGE, "Challenge");
EAP_AKA_SUBTYPE_STRING.put(EAP_AKA_AUTHENTICATION_REJECT, "Authentication-Reject")50         EAP_AKA_SUBTYPE_STRING.put(EAP_AKA_AUTHENTICATION_REJECT, "Authentication-Reject");
EAP_AKA_SUBTYPE_STRING.put(EAP_AKA_SYNCHRONIZATION_FAILURE, "Synchronization-Failure")51         EAP_AKA_SUBTYPE_STRING.put(EAP_AKA_SYNCHRONIZATION_FAILURE, "Synchronization-Failure");
EAP_AKA_SUBTYPE_STRING.put(EAP_AKA_IDENTITY, "Identity")52         EAP_AKA_SUBTYPE_STRING.put(EAP_AKA_IDENTITY, "Identity");
EAP_AKA_SUBTYPE_STRING.put(EAP_AKA_NOTIFICATION, "Notification")53         EAP_AKA_SUBTYPE_STRING.put(EAP_AKA_NOTIFICATION, "Notification");
EAP_AKA_SUBTYPE_STRING.put(EAP_AKA_REAUTHENTICATION, "Re-authentication")54         EAP_AKA_SUBTYPE_STRING.put(EAP_AKA_REAUTHENTICATION, "Re-authentication");
EAP_AKA_SUBTYPE_STRING.put(EAP_AKA_CLIENT_ERROR, "Client-Error")55         EAP_AKA_SUBTYPE_STRING.put(EAP_AKA_CLIENT_ERROR, "Client-Error");
56     }
57 
58     protected static final Set<Integer> SUPPORTED_SUBTYPES = new HashSet<>();
59     static {
60         SUPPORTED_SUBTYPES.add(EAP_AKA_CHALLENGE);
61         SUPPORTED_SUBTYPES.add(EAP_AKA_AUTHENTICATION_REJECT);
62         SUPPORTED_SUBTYPES.add(EAP_AKA_SYNCHRONIZATION_FAILURE);
63         SUPPORTED_SUBTYPES.add(EAP_AKA_IDENTITY);
64         SUPPORTED_SUBTYPES.add(EAP_AKA_NOTIFICATION);
65         SUPPORTED_SUBTYPES.add(EAP_AKA_REAUTHENTICATION);
66         SUPPORTED_SUBTYPES.add(EAP_AKA_CLIENT_ERROR);
67     }
68 
69     private static final EapAkaTypeDataDecoder sTypeDataDecoder = new EapAkaTypeDataDecoder();
70 
71     @VisibleForTesting
EapAkaTypeData(int eapSubType, LinkedHashMap<Integer, EapSimAkaAttribute> attributeMap)72     public EapAkaTypeData(int eapSubType, LinkedHashMap<Integer, EapSimAkaAttribute> attributeMap) {
73         super(eapSubType, attributeMap);
74     }
75 
EapAkaTypeData( int eapSubType, LinkedHashMap<Integer, EapSimAkaAttribute> attributeMap, byte[] reservedBytes)76     protected EapAkaTypeData(
77             int eapSubType,
78             LinkedHashMap<Integer, EapSimAkaAttribute> attributeMap,
79             byte[] reservedBytes) {
80         super(eapSubType, attributeMap, reservedBytes);
81     }
82 
83     /**
84      * Creates and returns an EapAkaTypeData instance with the given subtype and attributes.
85      *
86      * @param eapSubtype the subtype for the EAP-AKA type data
87      * @param attributes the List of EapSimAkaAttributes to be included in this type data
88      */
EapAkaTypeData(int eapSubtype, List<EapSimAkaAttribute> attributes)89     public EapAkaTypeData(int eapSubtype, List<EapSimAkaAttribute> attributes) {
90         super(eapSubtype, new LinkedHashMap<>());
91 
92         if (!SUPPORTED_SUBTYPES.contains(eapSubtype)) {
93             throw new IllegalArgumentException("Invalid subtype for EAP-AKA: " + eapSubtype);
94         }
95 
96         for (EapSimAkaAttribute attribute : attributes) {
97             if (attributeMap.containsKey(attribute.attributeType)) {
98                 throw new IllegalArgumentException(
99                         "Duplicate attribute in attributes: " + attribute.attributeType);
100             }
101             attributeMap.put(attribute.attributeType, attribute);
102         }
103     }
104 
getEapAkaTypeDataDecoder()105     public static EapAkaTypeDataDecoder getEapAkaTypeDataDecoder() {
106         return sTypeDataDecoder;
107     }
108 
109     /**
110      * EapAkaTypeDataDecoder will be used for decoding {@link EapAkaTypeData} objects.
111      */
112     public static class EapAkaTypeDataDecoder extends EapSimAkaTypeDataDecoder<EapAkaTypeData> {
113         private static final String TAG = EapAkaTypeDataDecoder.class.getSimpleName();
114         private static final String EAP_METHOD = "EAP-AKA";
115 
EapAkaTypeDataDecoder()116         protected EapAkaTypeDataDecoder() {
117             super(
118                     TAG,
119                     EAP_METHOD,
120                     SUPPORTED_SUBTYPES,
121                     EapAkaAttributeFactory.getInstance(),
122                     EAP_AKA_SUBTYPE_STRING);
123         }
124 
125         /**
126          * Decodes the given byte-array into a DecodeResult object.
127          *
128          * @param typeData the byte-encoding of the EapAkaTypeData to be parsed
129          * @return a DecodeResult object. If the decoding is successful, this will encapsulate an
130          *         EapAkaTypeData instance representing the data stored in typeData. Otherwise, it
131          *         will contain the relevant AtClientErrorCode for the decoding error.
132          */
decode(@onNull byte[] typeData)133         public DecodeResult<EapAkaTypeData> decode(@NonNull byte[] typeData) {
134             return super.decode(typeData);
135         }
136 
137         @Override
getInstance( int eapSubtype, LinkedHashMap<Integer, EapSimAkaAttribute> attributeMap, byte[] reservedBytes)138         protected EapAkaTypeData getInstance(
139                 int eapSubtype,
140                 LinkedHashMap<Integer, EapSimAkaAttribute> attributeMap,
141                 byte[] reservedBytes) {
142             return new EapAkaTypeData(eapSubtype, attributeMap, reservedBytes);
143         }
144     }
145 }
146