1 /* 2 * Copyright (C) 2022 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.nearby; 18 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 25 import com.android.internal.util.Preconditions; 26 27 import java.util.ArrayList; 28 import java.util.Arrays; 29 import java.util.List; 30 import java.util.Objects; 31 32 /** 33 * Represents a public credential. 34 * 35 * @hide 36 */ 37 @SystemApi 38 public final class PublicCredential extends PresenceCredential implements Parcelable { 39 @NonNull 40 public static final Creator<PublicCredential> CREATOR = 41 new Creator<PublicCredential>() { 42 @Override 43 public PublicCredential createFromParcel(Parcel in) { 44 in.readInt(); // Skip the type as it's used by parent class only. 45 return createFromParcelBody(in); 46 } 47 48 @Override 49 public PublicCredential[] newArray(int size) { 50 return new PublicCredential[size]; 51 } 52 }; 53 54 private final byte[] mPublicKey; 55 private final byte[] mEncryptedMetadata; 56 private final byte[] mEncryptedMetadataKeyTag; 57 PublicCredential( int identityType, byte[] secretId, byte[] authenticityKey, List<CredentialElement> credentialElements, byte[] publicKey, byte[] encryptedMetadata, byte[] metadataEncryptionKeyTag)58 private PublicCredential( 59 int identityType, 60 byte[] secretId, 61 byte[] authenticityKey, 62 List<CredentialElement> credentialElements, 63 byte[] publicKey, 64 byte[] encryptedMetadata, 65 byte[] metadataEncryptionKeyTag) { 66 super(CREDENTIAL_TYPE_PUBLIC, identityType, secretId, authenticityKey, credentialElements); 67 mPublicKey = publicKey; 68 mEncryptedMetadata = encryptedMetadata; 69 mEncryptedMetadataKeyTag = metadataEncryptionKeyTag; 70 } 71 PublicCredential(Parcel in)72 private PublicCredential(Parcel in) { 73 super(CREDENTIAL_TYPE_PUBLIC, in); 74 mPublicKey = new byte[in.readInt()]; 75 in.readByteArray(mPublicKey); 76 mEncryptedMetadata = new byte[in.readInt()]; 77 in.readByteArray(mEncryptedMetadata); 78 mEncryptedMetadataKeyTag = new byte[in.readInt()]; 79 in.readByteArray(mEncryptedMetadataKeyTag); 80 } 81 createFromParcelBody(Parcel in)82 static PublicCredential createFromParcelBody(Parcel in) { 83 return new PublicCredential(in); 84 } 85 86 /** Returns the public key associated with this credential. */ 87 @NonNull getPublicKey()88 public byte[] getPublicKey() { 89 return mPublicKey; 90 } 91 92 /** Returns the encrypted metadata associated with this credential. */ 93 @NonNull getEncryptedMetadata()94 public byte[] getEncryptedMetadata() { 95 return mEncryptedMetadata; 96 } 97 98 /** Returns the metadata encryption key tag associated with this credential. */ 99 @NonNull getEncryptedMetadataKeyTag()100 public byte[] getEncryptedMetadataKeyTag() { 101 return mEncryptedMetadataKeyTag; 102 } 103 104 @Override describeContents()105 public int describeContents() { 106 return 0; 107 } 108 109 @Override equals(@ullable Object obj)110 public boolean equals(@Nullable Object obj) { 111 if (obj instanceof PublicCredential) { 112 PublicCredential that = (PublicCredential) obj; 113 return super.equals(obj) 114 && Arrays.equals(mPublicKey, that.mPublicKey) 115 && Arrays.equals(mEncryptedMetadata, that.mEncryptedMetadata) 116 && Arrays.equals(mEncryptedMetadataKeyTag, that.mEncryptedMetadataKeyTag); 117 } 118 return false; 119 } 120 121 @Override hashCode()122 public int hashCode() { 123 return Objects.hash( 124 super.hashCode(), 125 Arrays.hashCode(mPublicKey), 126 Arrays.hashCode(mEncryptedMetadata), 127 Arrays.hashCode(mEncryptedMetadataKeyTag)); 128 } 129 130 @Override writeToParcel(@onNull Parcel dest, int flags)131 public void writeToParcel(@NonNull Parcel dest, int flags) { 132 super.writeToParcel(dest, flags); 133 dest.writeInt(mPublicKey.length); 134 dest.writeByteArray(mPublicKey); 135 dest.writeInt(mEncryptedMetadata.length); 136 dest.writeByteArray(mEncryptedMetadata); 137 dest.writeInt(mEncryptedMetadataKeyTag.length); 138 dest.writeByteArray(mEncryptedMetadataKeyTag); 139 } 140 141 /** Builder class for {@link PresenceCredential}. */ 142 public static final class Builder { 143 private final List<CredentialElement> mCredentialElements; 144 145 private @IdentityType int mIdentityType; 146 private final byte[] mSecretId; 147 private final byte[] mAuthenticityKey; 148 private final byte[] mPublicKey; 149 private final byte[] mEncryptedMetadata; 150 private final byte[] mEncryptedMetadataKeyTag; 151 Builder( @onNull byte[] secretId, @NonNull byte[] authenticityKey, @NonNull byte[] publicKey, @NonNull byte[] encryptedMetadata, @NonNull byte[] encryptedMetadataKeyTag)152 public Builder( 153 @NonNull byte[] secretId, 154 @NonNull byte[] authenticityKey, 155 @NonNull byte[] publicKey, 156 @NonNull byte[] encryptedMetadata, 157 @NonNull byte[] encryptedMetadataKeyTag) { 158 Preconditions.checkState( 159 secretId != null && secretId.length > 0, "secret id cannot be empty"); 160 Preconditions.checkState( 161 authenticityKey != null && authenticityKey.length > 0, 162 "authenticity key cannot be empty"); 163 Preconditions.checkState( 164 publicKey != null && publicKey.length > 0, "publicKey cannot be empty"); 165 Preconditions.checkState( 166 encryptedMetadata != null && encryptedMetadata.length > 0, 167 "encryptedMetadata cannot be empty"); 168 Preconditions.checkState( 169 encryptedMetadataKeyTag != null && encryptedMetadataKeyTag.length > 0, 170 "encryptedMetadataKeyTag cannot be empty"); 171 172 mSecretId = secretId; 173 mAuthenticityKey = authenticityKey; 174 mPublicKey = publicKey; 175 mEncryptedMetadata = encryptedMetadata; 176 mEncryptedMetadataKeyTag = encryptedMetadataKeyTag; 177 mCredentialElements = new ArrayList<>(); 178 } 179 180 /** Sets the identity type for the presence credential. */ 181 @NonNull setIdentityType(@dentityType int identityType)182 public Builder setIdentityType(@IdentityType int identityType) { 183 mIdentityType = identityType; 184 return this; 185 } 186 187 /** Adds an element to the credential. */ 188 @NonNull addCredentialElement(@onNull CredentialElement credentialElement)189 public Builder addCredentialElement(@NonNull CredentialElement credentialElement) { 190 Objects.requireNonNull(credentialElement); 191 mCredentialElements.add(credentialElement); 192 return this; 193 } 194 195 /** Builds the {@link PresenceCredential}. */ 196 @NonNull build()197 public PublicCredential build() { 198 return new PublicCredential( 199 mIdentityType, 200 mSecretId, 201 mAuthenticityKey, 202 mCredentialElements, 203 mPublicKey, 204 mEncryptedMetadata, 205 mEncryptedMetadataKeyTag); 206 } 207 } 208 } 209