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.net.ipsec.ike; 17 18 import android.annotation.NonNull; 19 import android.net.ipsec.ike.exceptions.AuthenticationFailedException; 20 import android.net.vcn.util.PersistableBundleUtils; 21 import android.os.PersistableBundle; 22 23 import java.security.cert.X509Certificate; 24 import java.util.Objects; 25 26 import javax.security.auth.x500.X500Principal; 27 28 /** 29 * This class represents an IKE entity ID based on a DER encoded ASN.1 X.500 Distinguished Name. 30 * 31 * <p>An example might be "CN=ike.test.android.net, O=Android, C=US". 32 */ 33 public final class IkeDerAsn1DnIdentification extends IkeIdentification { 34 private static final String DER_ASN1_DN_KEY = "derAsn1Dn"; 35 /** The ASN.1 X.500 Distinguished Name */ 36 @NonNull public final X500Principal derAsn1Dn; 37 38 /** 39 * Construct an instance of IkeDerAsn1DnIdentification from a decoded inbound packet. 40 * 41 * @param derAsn1Dn the ASN.1 X.500 Distinguished Name that has been DER encoded. 42 * @hide 43 */ IkeDerAsn1DnIdentification(byte[] derAsn1DnBytes)44 public IkeDerAsn1DnIdentification(byte[] derAsn1DnBytes) throws AuthenticationFailedException { 45 super(ID_TYPE_DER_ASN1_DN); 46 47 Objects.requireNonNull(derAsn1DnBytes, "derAsn1DnBytes not provided"); 48 49 try { 50 derAsn1Dn = new X500Principal(derAsn1DnBytes); 51 } catch (IllegalArgumentException e) { 52 // Incorrect form for DN 53 throw new AuthenticationFailedException(e); 54 } 55 } 56 57 /** 58 * Construct an instance of IkeDerAsn1DnIdentification with an ASN.1 X.500 Distinguished Name 59 * 60 * @param derAsn1Dn the ASN.1 X.500 Distinguished Name. 61 */ IkeDerAsn1DnIdentification(@onNull X500Principal derAsn1Dn)62 public IkeDerAsn1DnIdentification(@NonNull X500Principal derAsn1Dn) { 63 super(ID_TYPE_DER_ASN1_DN); 64 65 Objects.requireNonNull(derAsn1Dn, "derAsn1Dn not provided"); 66 this.derAsn1Dn = derAsn1Dn; 67 } 68 69 /** 70 * Constructs this object by deserializing a PersistableBundle 71 * 72 * @hide 73 */ 74 @NonNull fromPersistableBundle(@onNull PersistableBundle in)75 public static IkeDerAsn1DnIdentification fromPersistableBundle(@NonNull PersistableBundle in) { 76 Objects.requireNonNull(in, "PersistableBundle is null"); 77 78 PersistableBundle dnBundle = in.getPersistableBundle(DER_ASN1_DN_KEY); 79 Objects.requireNonNull(dnBundle, "ASN1 DN bundle is null"); 80 81 return new IkeDerAsn1DnIdentification( 82 new X500Principal(PersistableBundleUtils.toByteArray(dnBundle))); 83 } 84 /** 85 * Serializes this object to a PersistableBundle 86 * 87 * @hide 88 */ 89 @Override 90 @NonNull toPersistableBundle()91 public PersistableBundle toPersistableBundle() { 92 final PersistableBundle result = super.toPersistableBundle(); 93 result.putPersistableBundle( 94 DER_ASN1_DN_KEY, PersistableBundleUtils.fromByteArray(derAsn1Dn.getEncoded())); 95 return result; 96 } 97 98 /** @hide */ 99 @Override hashCode()100 public int hashCode() { 101 // idType is also hashed to prevent collisions with other IkeAuthentication subtypes 102 return Objects.hash(idType, derAsn1Dn); 103 } 104 105 /** @hide */ 106 @Override equals(Object o)107 public boolean equals(Object o) { 108 if (!(o instanceof IkeDerAsn1DnIdentification)) return false; 109 110 // idType already verified based on class type; no need to check again. 111 return derAsn1Dn.equals(((IkeDerAsn1DnIdentification) o).derAsn1Dn); 112 } 113 114 /** @hide */ 115 @Override getIdTypeString()116 public String getIdTypeString() { 117 return "DER ASN.1 DN"; 118 } 119 120 /** @hide */ 121 @Override validateEndCertIdOrThrow(X509Certificate endCert)122 public void validateEndCertIdOrThrow(X509Certificate endCert) 123 throws AuthenticationFailedException { 124 if (!derAsn1Dn.equals(endCert.getSubjectX500Principal())) { 125 throw new AuthenticationFailedException( 126 "End cert subject DN and DER ASN1 DN ID mismtached"); 127 } 128 } 129 130 /** 131 * Retrieve the byte-representation of the ASN.1 X.500 DN. 132 * 133 * @return the byte-representation of the ASN.1 X.500 DN. 134 * @hide 135 */ 136 @Override getEncodedIdData()137 public byte[] getEncodedIdData() { 138 return derAsn1Dn.getEncoded(); 139 } 140 } 141