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 android.net.ipsec.ike; 18 19 import android.annotation.NonNull; 20 import android.net.ipsec.ike.exceptions.AuthenticationFailedException; 21 import android.os.PersistableBundle; 22 23 import java.nio.charset.Charset; 24 import java.security.cert.X509Certificate; 25 import java.util.Objects; 26 27 /** 28 * IkeFqdnIdentification represents an IKE entity identification based on a fully-qualified domain 29 * name (FQDN). An example might be ike.android.com 30 */ 31 public class IkeFqdnIdentification extends IkeIdentification { 32 private static final Charset ASCII = Charset.forName("US-ASCII"); 33 34 private static final String FQDN_KEY = "fqdn"; 35 36 /** The fully-qualified domain name(FQDN). */ 37 @NonNull public final String fqdn; 38 39 /** 40 * Construct an instance of IkeFqdnIdentification from a decoded inbound packet. 41 * 42 * @param fqdnBytes FQDN in byte array. 43 * @hide 44 */ IkeFqdnIdentification(byte[] fqdnBytes)45 public IkeFqdnIdentification(byte[] fqdnBytes) { 46 super(ID_TYPE_FQDN); 47 fqdn = new String(fqdnBytes, ASCII); 48 } 49 50 /** 51 * Construct an instance of {@link IkeFqdnIdentification} with a fully-qualified domain name. 52 * 53 * @param fqdn the fully-qualified domain name (FQDN). Must contain only US-ASCII characters, 54 * otherwise an IllegalArugmentException will be thrown. 55 */ IkeFqdnIdentification(@onNull String fqdn)56 public IkeFqdnIdentification(@NonNull String fqdn) { 57 super(ID_TYPE_FQDN); 58 if (!ASCII.newEncoder().canEncode(fqdn)) { 59 throw new IllegalArgumentException("Non US-ASCII character set used"); 60 } 61 62 this.fqdn = fqdn; 63 } 64 65 /** 66 * Constructs this object by deserializing a PersistableBundle 67 * 68 * @hide 69 */ 70 @NonNull fromPersistableBundle(@onNull PersistableBundle in)71 public static IkeFqdnIdentification fromPersistableBundle(@NonNull PersistableBundle in) { 72 Objects.requireNonNull(in, "PersistableBundle is null"); 73 74 return new IkeFqdnIdentification(in.getString(FQDN_KEY)); 75 } 76 /** 77 * Serializes this object to a PersistableBundle 78 * 79 * @hide 80 */ 81 @Override 82 @NonNull toPersistableBundle()83 public PersistableBundle toPersistableBundle() { 84 final PersistableBundle result = super.toPersistableBundle(); 85 result.putString(FQDN_KEY, fqdn); 86 return result; 87 } 88 89 /** @hide */ 90 @Override hashCode()91 public int hashCode() { 92 // idType is also hashed to prevent collisions with other IkeAuthentication subtypes 93 return Objects.hash(idType, fqdn); 94 } 95 96 /** @hide */ 97 @Override equals(Object o)98 public boolean equals(Object o) { 99 if (!(o instanceof IkeFqdnIdentification)) return false; 100 101 // idType already verified based on class type; no need to check again. 102 return fqdn.equals(((IkeFqdnIdentification) o).fqdn); 103 } 104 105 /** @hide */ 106 @Override getIdTypeString()107 public String getIdTypeString() { 108 return "FQDN"; 109 } 110 111 /** @hide */ 112 @Override validateEndCertIdOrThrow(X509Certificate endCert)113 public void validateEndCertIdOrThrow(X509Certificate endCert) 114 throws AuthenticationFailedException { 115 // The corresponding SAN type is DNS Name as per RFC 7296 116 validateEndCertSanOrThrow(endCert, SAN_TYPE_DNS, fqdn); 117 } 118 119 /** 120 * Retrieve the byte-representation of the FQDN. 121 * 122 * @return the byte-representation of the FQDN. 123 * @hide 124 */ 125 @Override getEncodedIdData()126 public byte[] getEncodedIdData() { 127 return fqdn.getBytes(ASCII); 128 } 129 } 130