1 /*
2  * Copyright (C) 2020 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 package android.telephony.gba;
17 
18 import android.annotation.IntDef;
19 import android.annotation.NonNull;
20 import android.annotation.Nullable;
21 import android.annotation.SystemApi;
22 import android.os.Parcel;
23 import android.os.Parcelable;
24 import android.telephony.gba.TlsParams.TlsCipherSuite;
25 
26 import java.lang.annotation.Retention;
27 import java.lang.annotation.RetentionPolicy;
28 import java.nio.ByteBuffer;
29 import java.util.Objects;
30 
31 /**
32  * Description of ua security protocol identifier defined in 3GPP TS 33.220 H.2
33  * @hide
34  */
35 @SystemApi
36 public final class UaSecurityProtocolIdentifier implements Parcelable {
37 
38     /**
39      * Organization code defined in 3GPP TS 33.220 H.3
40      *
41      * @hide
42      */
43     @Retention(RetentionPolicy.SOURCE)
44     @IntDef(prefix = {"ORG_"}, value = {
45         ORG_NONE,
46         ORG_3GPP,
47         ORG_3GPP2,
48         ORG_OMA,
49         ORG_GSMA,
50         ORG_LOCAL})
51     public @interface OrganizationCode {}
52 
53     /**
54      * Organization octet value for default ua security protocol
55      */
56     public static final int ORG_NONE  = 0;
57     /**
58      * Organization octet value for 3GPP ua security protocol
59      */
60     public static final int ORG_3GPP  = 0x01;
61     /**
62      * Organization octet value for 3GPP2 ua security protocol
63      */
64     public static final int ORG_3GPP2 = 0x02;
65     /**
66      * Organization octet value for OMA ua security protocol
67      */
68     public static final int ORG_OMA   = 0x03;
69     /**
70      * Organization octet value for GSMA ua security protocol
71      */
72     public static final int ORG_GSMA  = 0x04;
73     /**
74      * Internal organization octet value for local/experimental protocols
75      */
76     public static final int ORG_LOCAL = 0xFF;
77 
78     /**
79      * 3GPP UA Security Protocol ID defined in 3GPP TS 33.220 H.3
80      *
81      * @hide
82      */
83     @Retention(RetentionPolicy.SOURCE)
84     @IntDef(prefix = {"UA_SECURITY_PROTOCOL_3GPP_"}, value = {
85         UA_SECURITY_PROTOCOL_3GPP_SUBSCRIBER_CERTIFICATE,
86         UA_SECURITY_PROTOCOL_3GPP_MBMS,
87         UA_SECURITY_PROTOCOL_3GPP_HTTP_DIGEST_AUTHENTICATION,
88         UA_SECURITY_PROTOCOL_3GPP_HTTP_BASED_MBMS,
89         UA_SECURITY_PROTOCOL_3GPP_SIP_BASED_MBMS,
90         UA_SECURITY_PROTOCOL_3GPP_GENERIC_PUSH_LAYER,
91         UA_SECURITY_PROTOCOL_3GPP_IMS_MEDIA_PLANE,
92         UA_SECURITY_PROTOCOL_3GPP_GENERATION_TMPI,
93         UA_SECURITY_PROTOCOL_3GPP_TLS_DEFAULT,
94         UA_SECURITY_PROTOCOL_3GPP_TLS_BROWSER})
95     public @interface UaSecurityProtocol3gpp {}
96 
97     /**
98      * Security protocol param according to TS 33.221 as described in TS
99      * 33.220 Annex H. Mapped to byte stream "0x01,0x00,0x00,0x00,0x00".
100      */
101     public static final int UA_SECURITY_PROTOCOL_3GPP_SUBSCRIBER_CERTIFICATE = 0;
102 
103     /**
104      * Security protocol param according to TS 33.246 for Multimedia
105      * broadcast/Multimedia services (MBMS) as described in TS
106      * 33.220 Annex H. Mapped to byte stream "0x01,0x00,0x00,0x00,0x01".
107      */
108     public static final int UA_SECURITY_PROTOCOL_3GPP_MBMS = 1;
109 
110     /**
111      * Security protocol param based on HTTP digest authentication
112      * according to TS 24.109 as described in TS 33.220 Annex H. Mapped to
113      * byte stream "0x01,0x00,0x00,0x00,0x02".
114      */
115     public static final int UA_SECURITY_PROTOCOL_3GPP_HTTP_DIGEST_AUTHENTICATION = 2;
116 
117     /**
118      * Security protocol param used with HTTP-based security procedures for
119      * Multimedia broadcast/Multimedia services (MBMS) user services
120      * according to TS 26.237 as described in TS 33.220 Annex H.
121      * Mapped to byte stream "0x01,0x00,0x00,0x00,0x03".
122      */
123     public static final int UA_SECURITY_PROTOCOL_3GPP_HTTP_BASED_MBMS = 3;
124 
125     /**
126      * Security protocol param used with SIP-based security procedures for
127      * Multimedia broadcast/Multimedia services (MBMS) user services
128      * according to TS 26.237 as described in TS 33.220 Annex H.
129      * Mapped to byte stream "0x01,0x00,0x00,0x00,0x04".
130      */
131     public static final int UA_SECURITY_PROTOCOL_3GPP_SIP_BASED_MBMS = 4;
132 
133     /**
134      * Security protocol param used with Generic Push Layer according to TS
135      * 33.224  as described in TS 33.220 Annex H. Mapped to byte stream
136      * "0x01,0x00,0x00,0x00,0x05".
137      */
138     public static final int UA_SECURITY_PROTOCOL_3GPP_GENERIC_PUSH_LAYER = 5;
139 
140     /**
141      * Security protocol param used for IMS UE to KMS http based message
142      * exchanges according to "IMS media plane security", TS 33.328   as
143      * described in TS 33.220 Annex H. Mapped to byte stream
144      * "0x01,0x00,0x00,0x00,0x06".
145      */
146     public static final int UA_SECURITY_PROTOCOL_3GPP_IMS_MEDIA_PLANE = 6;
147 
148     /**
149      * Security protocol param used for Generation of Temporary IP
150      * Multimedia Private Identity (TMPI) according to TS 33.220 Annex B.4
151      * Mapped to byte stream "0x01,0x00,0x00,0x01,0x00".
152      */
153     public static final int UA_SECURITY_PROTOCOL_3GPP_GENERATION_TMPI = 0x0100;
154 
155     /**
156      * Security protocol param used for Shared key-based UE authentication with
157      * certificate-based NAF authentication, according to TS 33.222 section 5.3,
158      * or Shared key-based mutual authentication between UE and NAF, according to
159      * TS 33.222 section 5.4. Mapped to byte stream "0x01,0x00,0x01,yy,zz".
160      * "yy, zz" is the TLS CipherSuite code.
161      */
162     public static final int UA_SECURITY_PROTOCOL_3GPP_TLS_DEFAULT = 0x010000;
163 
164     /**
165      * Security protocol param used for Shared key-based UE authentication with
166      * certificate-based NAF authentication, according to TS 33.222 Annex D.
167      * Mapped to byte stream "0x01,0x00,0x02,yy,zz".
168      * "yy, zz" is the TLS CipherSuite code.
169      */
170     public static final int UA_SECURITY_PROTOCOL_3GPP_TLS_BROWSER = 0x020000;
171 
172     private static final int PROTOCOL_SIZE = 5;
173     private static final int[] sUaSp3gppIds = new int[] {
174             UA_SECURITY_PROTOCOL_3GPP_SUBSCRIBER_CERTIFICATE,
175             UA_SECURITY_PROTOCOL_3GPP_MBMS,
176             UA_SECURITY_PROTOCOL_3GPP_HTTP_DIGEST_AUTHENTICATION,
177             UA_SECURITY_PROTOCOL_3GPP_HTTP_BASED_MBMS,
178             UA_SECURITY_PROTOCOL_3GPP_SIP_BASED_MBMS,
179             UA_SECURITY_PROTOCOL_3GPP_GENERIC_PUSH_LAYER,
180             UA_SECURITY_PROTOCOL_3GPP_IMS_MEDIA_PLANE,
181             UA_SECURITY_PROTOCOL_3GPP_GENERATION_TMPI,
182             UA_SECURITY_PROTOCOL_3GPP_TLS_DEFAULT,
183             UA_SECURITY_PROTOCOL_3GPP_TLS_BROWSER};
184 
185     private int mOrg;
186     private int mProtocol;
187     private int mTlsCipherSuite;
188 
UaSecurityProtocolIdentifier()189     private UaSecurityProtocolIdentifier() {}
190 
UaSecurityProtocolIdentifier(UaSecurityProtocolIdentifier sp)191     private UaSecurityProtocolIdentifier(UaSecurityProtocolIdentifier sp) {
192         mOrg = sp.mOrg;
193         mProtocol = sp.mProtocol;
194         mTlsCipherSuite = sp.mTlsCipherSuite;
195     }
196 
197     /**
198      * Returns the byte array representing the ua security protocol
199      */
200     @NonNull
toByteArray()201     public byte[] toByteArray() {
202         byte[] data = new byte[PROTOCOL_SIZE];
203         ByteBuffer buf = ByteBuffer.wrap(data);
204         buf.put((byte) mOrg);
205         buf.putInt(mProtocol | mTlsCipherSuite);
206         return data;
207     }
208 
209     /**
210      * Returns the organization code
211      */
getOrg()212     public @OrganizationCode int getOrg() {
213         return mOrg;
214     }
215 
216     /**
217      * Returns the security procotol id
218      *
219      * <p>Note that only 3GPP UA Security Protocols are supported for now
220      */
getProtocol()221     public @UaSecurityProtocol3gpp int getProtocol() {
222         return mProtocol;
223     }
224 
225     /**
226      * Returns the TLS cipher suite
227      */
getTlsCipherSuite()228     public @TlsCipherSuite int getTlsCipherSuite() {
229         return mTlsCipherSuite;
230     }
231 
232     /**
233      * {@link Parcelable#writeToParcel}
234      */
235     @Override
writeToParcel(@onNull Parcel out, int flags)236     public void writeToParcel(@NonNull Parcel out, int flags) {
237         out.writeInt(mOrg);
238         out.writeInt(mProtocol);
239         out.writeInt(mTlsCipherSuite);
240     }
241 
242     /**
243      * {@link Parcelable.Creator}
244      *
245      */
246     public static final @NonNull Parcelable.Creator<
247             UaSecurityProtocolIdentifier> CREATOR = new Creator<UaSecurityProtocolIdentifier>() {
248                 @Nullable
249                 @Override
250                 public UaSecurityProtocolIdentifier createFromParcel(Parcel in) {
251                     int org = in.readInt();
252                     int protocol = in.readInt();
253                     int cs = in.readInt();
254                     if (org < 0 || protocol < 0 || cs < 0) {
255                         return null;
256                     }
257                     Builder builder = new Builder();
258                     try {
259                         if (org > 0) {
260                             builder.setOrg(org);
261                         }
262                         if (protocol > 0) {
263                             builder.setProtocol(protocol);
264                         }
265                         if (cs > 0) {
266                             builder.setTlsCipherSuite(cs);
267                         }
268                     } catch (IllegalArgumentException e) {
269                         return null;
270                     }
271                     return builder.build();
272                 }
273 
274                 @NonNull
275                 @Override
276                 public UaSecurityProtocolIdentifier[] newArray(int size) {
277                     return new UaSecurityProtocolIdentifier[size];
278                 }
279             };
280 
281     /**
282      * {@link Parcelable#describeContents}
283      */
284     @Override
describeContents()285     public int describeContents() {
286         return 0;
287     }
288 
289     @Override
toString()290     public String toString() {
291         return "UaSecurityProtocolIdentifier[" + mOrg + " , " + (mProtocol | mTlsCipherSuite) + "]";
292     }
293 
294     @Override
equals(Object obj)295     public boolean equals(Object obj) {
296         if (!(obj instanceof UaSecurityProtocolIdentifier)) {
297             return false;
298         }
299 
300         UaSecurityProtocolIdentifier other = (UaSecurityProtocolIdentifier) obj;
301 
302         return mOrg == other.mOrg && mProtocol == other.mProtocol
303                 && mTlsCipherSuite == other.mTlsCipherSuite;
304     }
305 
306     @Override
hashCode()307     public int hashCode() {
308         return Objects.hash(mOrg, mProtocol, mTlsCipherSuite);
309     }
310 
isTlsSupported()311     private boolean isTlsSupported() {
312         //TODO May update to support non 3gpp protocol in the future
313         if (mOrg == ORG_3GPP && (mProtocol == UA_SECURITY_PROTOCOL_3GPP_TLS_DEFAULT
314                     || mProtocol == UA_SECURITY_PROTOCOL_3GPP_TLS_BROWSER)) {
315             return true;
316         }
317 
318         return false;
319     }
320 
321     /**
322      * Builder class for UaSecurityProtocolIdentifier
323      */
324     public static final class Builder {
325         private final UaSecurityProtocolIdentifier mSp;
326 
327         /**
328          * Creates a Builder with default UaSecurityProtocolIdentifier, a.k.a 0x00 00 00 00 00
329          */
Builder()330         public Builder() {
331             mSp = new UaSecurityProtocolIdentifier();
332         }
333 
334         /**
335          * Creates a Builder from a UaSecurityProtocolIdentifier
336          */
Builder(@onNull final UaSecurityProtocolIdentifier sp)337         public Builder(@NonNull final UaSecurityProtocolIdentifier sp) {
338             Objects.requireNonNull(sp);
339             mSp = new UaSecurityProtocolIdentifier(sp);
340         }
341 
342         /**
343          * Sets the organization code
344          *
345          * @param orgCode the organization code with the following value
346          * <ol>
347          * <li>{@link #ORG_NONE} </li>
348          * <li>{@link #ORG_3GPP} </li>
349          * <li>{@link #ORG_3GPP2} </li>
350          * <li>{@link #ORG_OMA} </li>
351          * <li>{@link #ORG_GSMA} </li>
352          * <li>{@link #ORG_LOCAL} </li>
353          * </ol>
354          * @throws IllegalArgumentException if it is not one of the value above.
355          *
356          * <p>Note that this method will reset the security protocol and TLS cipher suite
357          * if they have been set.
358          */
359         @NonNull
setOrg(@rganizationCode int orgCode)360         public Builder setOrg(@OrganizationCode int orgCode) {
361             if (orgCode < ORG_NONE || orgCode > ORG_LOCAL) {
362                 throw new IllegalArgumentException("illegal organization code");
363             }
364             mSp.mOrg = orgCode;
365             mSp.mProtocol = 0;
366             mSp.mTlsCipherSuite = 0;
367             return this;
368         }
369 
370         /**
371          * Sets the UA security protocol for 3GPP
372          *
373          * @param protocol only 3GPP ua security protocol ID is supported for now, which
374          * is one of the following value
375          * <ol>
376          * <li>{@link #UA_SECURITY_PROTOCOL_3GPP_SUBSCRIBER_CERTIFICATE} </li>
377          * <li>{@link #UA_SECURITY_PROTOCOL_3GPP_MBMS} </li>
378          * <li>{@link #UA_SECURITY_PROTOCOL_3GPP_HTTP_DIGEST_AUTHENTICATION} </li>
379          * <li>{@link #UA_SECURITY_PROTOCOL_3GPP_HTTP_BASED_MBMS} </li>
380          * <li>{@link #UA_SECURITY_PROTOCOL_3GPP_SIP_BASED_MBMS} </li>
381          * <li>{@link #UA_SECURITY_PROTOCOL_3GPP_GENERIC_PUSH_LAYER} </li>
382          * <li>{@link #UA_SECURITY_PROTOCOL_3GPP_IMS_MEDIA_PLANE} </li>
383          * <li>{@link #UA_SECURITY_PROTOCOL_3GPP_GENERATION_TMPI} </li>
384          * <li>{@link #UA_SECURITY_PROTOCOL_3GPP_TLS_DEFAULT} </li>
385          * <li>{@link #UA_SECURITY_PROTOCOL_3GPP_TLS_BROWSER} </li>
386          * </ol>
387          * @throws IllegalArgumentException if the protocol is not one of the value above.
388          *
389          * <p>Note that this method will reset TLS cipher suite if it has been set.
390          */
391         @NonNull
setProtocol(@aSecurityProtocol3gpp int protocol)392         public Builder setProtocol(@UaSecurityProtocol3gpp int protocol) {
393             //TODO May update to support non 3gpp protocol in the future
394             if (protocol < UA_SECURITY_PROTOCOL_3GPP_SUBSCRIBER_CERTIFICATE
395                     || (protocol > UA_SECURITY_PROTOCOL_3GPP_IMS_MEDIA_PLANE
396                     && protocol != UA_SECURITY_PROTOCOL_3GPP_GENERATION_TMPI
397                     && protocol != UA_SECURITY_PROTOCOL_3GPP_TLS_DEFAULT
398                     && protocol != UA_SECURITY_PROTOCOL_3GPP_TLS_BROWSER)
399                     || mSp.mOrg != ORG_3GPP) {
400                 throw new IllegalArgumentException("illegal protocol code");
401             }
402             mSp.mProtocol = protocol;
403             mSp.mTlsCipherSuite = 0;
404             return this;
405         }
406 
407         /**
408          * Sets the UA security protocol for 3GPP
409          *
410          * @param cs TLS cipher suite value defined by {@link TlsParams#TlsCipherSuite}
411          * @throws IllegalArgumentException if it is not a 3GPP ua security protocol,
412          * the protocol does not support TLS, or does not support the cipher suite.
413          */
414         @NonNull
setTlsCipherSuite(@lsCipherSuite int cs)415         public Builder setTlsCipherSuite(@TlsCipherSuite int cs) {
416             if (!mSp.isTlsSupported()) {
417                 throw new IllegalArgumentException("The protocol does not support TLS");
418             }
419             if (!TlsParams.isTlsCipherSuiteSupported(cs)) {
420                 throw new IllegalArgumentException("TLS cipher suite is not supported");
421             }
422             mSp.mTlsCipherSuite = cs;
423             return this;
424         }
425 
426         /**
427          * Builds the instance of UaSecurityProtocolIdentifier
428          *
429          * @return the built instance of UaSecurityProtocolIdentifier
430          */
431         @NonNull
build()432         public UaSecurityProtocolIdentifier build() {
433             return new UaSecurityProtocolIdentifier(mSp);
434         }
435     }
436 }
437