1 /*
2  * Copyright (C) 2018 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 android.net.ipsec.ike;
18 
19 import android.annotation.IntDef;
20 import android.annotation.SystemApi;
21 import android.util.ArraySet;
22 
23 import com.android.internal.net.ipsec.ike.exceptions.AuthenticationFailedException;
24 
25 import java.lang.annotation.Retention;
26 import java.lang.annotation.RetentionPolicy;
27 import java.security.cert.CertificateParsingException;
28 import java.security.cert.X509Certificate;
29 import java.util.Collection;
30 import java.util.List;
31 import java.util.Set;
32 
33 /**
34  * IkeIdentification is abstract base class that represents the common information for all types of
35  * IKE entity identification.
36  *
37  * <p>{@link IkeIdentification} is used in IKE authentication.
38  *
39  * @see <a href="https://tools.ietf.org/html/rfc7296#section-3.5">RFC 7296, Internet Key Exchange
40  *     Protocol Version 2 (IKEv2)</a>
41  * @hide
42  */
43 @SystemApi
44 public abstract class IkeIdentification {
45     // Set of supported ID types.
46     private static final Set<Integer> SUPPORTED_ID_TYPES;
47 
48     private static final int INDEX_SAN_TYPE = 0;
49     private static final int INDEX_SAN_DATA = 1;
50 
51     /** @hide */
52     @Retention(RetentionPolicy.SOURCE)
53     @IntDef({
54         ID_TYPE_IPV4_ADDR,
55         ID_TYPE_FQDN,
56         ID_TYPE_RFC822_ADDR,
57         ID_TYPE_IPV6_ADDR,
58         ID_TYPE_DER_ASN1_DN,
59         ID_TYPE_KEY_ID
60     })
61     public @interface IdType {}
62 
63     /** @hide */
64     public static final int ID_TYPE_IPV4_ADDR = 1;
65     /** @hide */
66     public static final int ID_TYPE_FQDN = 2;
67     /** @hide */
68     public static final int ID_TYPE_RFC822_ADDR = 3;
69     /** @hide */
70     public static final int ID_TYPE_IPV6_ADDR = 5;
71     /** @hide */
72     public static final int ID_TYPE_DER_ASN1_DN = 9;
73     /** @hide */
74     public static final int ID_TYPE_KEY_ID = 11;
75 
76     static {
77         SUPPORTED_ID_TYPES = new ArraySet();
78         SUPPORTED_ID_TYPES.add(ID_TYPE_IPV4_ADDR);
79         SUPPORTED_ID_TYPES.add(ID_TYPE_FQDN);
80         SUPPORTED_ID_TYPES.add(ID_TYPE_RFC822_ADDR);
81         SUPPORTED_ID_TYPES.add(ID_TYPE_IPV6_ADDR);
82         SUPPORTED_ID_TYPES.add(ID_TYPE_DER_ASN1_DN);
83         SUPPORTED_ID_TYPES.add(ID_TYPE_KEY_ID);
84     }
85 
86     /** @hide Subject Alternative Name Type for RFC822 Email Address defined in RFC 5280 */
87     protected static final int SAN_TYPE_RFC822_NAME = 1;
88     /** @hide Subject Alternative Name Type for DNS Name defined in RFC 5280 */
89     protected static final int SAN_TYPE_DNS = 2;
90     /** @hide Subject Alternative Name Type for IP Address defined in RFC 5280 */
91     protected static final int SAN_TYPE_IP_ADDRESS = 7;
92 
93     /** @hide */
94     public final int idType;
95 
96     /** @hide */
IkeIdentification(@dType int type)97     protected IkeIdentification(@IdType int type) {
98         idType = type;
99     }
100 
101     /**
102      * Returns ID type as a String
103      *
104      * @hide
105      */
getIdTypeString()106     public abstract String getIdTypeString();
107 
108     /**
109      * Check if the end certificate's subject DN or SAN matches this identification
110      *
111      * @hide
112      */
validateEndCertIdOrThrow(X509Certificate endCert)113     public abstract void validateEndCertIdOrThrow(X509Certificate endCert)
114             throws AuthenticationFailedException;
115 
116     /**
117      * Check if the end certificate SAN matches the identification
118      *
119      * <p>According to RFC 7296, the received IKE ID that types are FQDN, IPv4/IPv6 Address and
120      * RFC822 Address should match the end certificate Subject Alternative Name (SAN).
121      *
122      * @hide
123      */
validateEndCertSanOrThrow( X509Certificate endCert, int expectedSanType, Object expectedSanData)124     protected void validateEndCertSanOrThrow(
125             X509Certificate endCert, int expectedSanType, Object expectedSanData)
126             throws AuthenticationFailedException {
127         try {
128             // Each List is one SAN whose first entry is an Integer that represents a SAN type and
129             // second entry is a String or a byte array that represents the SAN data
130             Collection<List<?>> allSans = endCert.getSubjectAlternativeNames();
131             if (allSans == null) {
132                 throw new AuthenticationFailedException("End certificate does not contain SAN");
133             }
134 
135             for (List<?> san : allSans) {
136                 if ((Integer) san.get(INDEX_SAN_TYPE) == expectedSanType) {
137                     Object item = san.get(INDEX_SAN_DATA);
138                     if (expectedSanData.equals(item)) {
139                         return;
140                     }
141                 }
142             }
143             throw new AuthenticationFailedException(
144                     "End certificate SAN and " + getIdTypeString() + " ID mismatched");
145         } catch (CertificateParsingException e) {
146             throw new AuthenticationFailedException(e);
147         }
148     }
149     /**
150      * Return the encoded identification data in a byte array.
151      *
152      * @return the encoded identification data.
153      * @hide
154      */
getEncodedIdData()155     public abstract byte[] getEncodedIdData();
156 }
157