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 com.android.rkpdapp.database; 18 19 import androidx.annotation.NonNull; 20 import androidx.room.ColumnInfo; 21 import androidx.room.Entity; 22 import androidx.room.Ignore; 23 import androidx.room.Index; 24 import androidx.room.PrimaryKey; 25 26 import java.time.Instant; 27 import java.time.temporal.ChronoUnit; 28 import java.util.Arrays; 29 import java.util.Objects; 30 31 /** 32 * Representation of the remotely provisioned key record to be stored in Rkpd Database. Ignored 33 * columns (macedPublicKey and coseKey) are not stored. 34 */ 35 @Entity(tableName = "provisioned_keys", 36 indices = {@Index(value = {"client_uid", "key_id", "irpc_hal"}, unique = true)}) 37 public class ProvisionedKey { 38 @PrimaryKey 39 @NonNull 40 @ColumnInfo(name = "key_blob") 41 public byte[] keyBlob; 42 43 @ColumnInfo(name = "irpc_hal") 44 @NonNull 45 public String irpcHal; 46 47 @ColumnInfo(name = "public_key") 48 @NonNull 49 public byte[] publicKey; 50 51 @ColumnInfo(name = "certificate_chain") 52 @NonNull 53 public byte[] certificateChain; 54 55 @ColumnInfo(name = "expiration_time", index = true) 56 @NonNull 57 public Instant expirationTime; 58 59 @ColumnInfo(name = "client_uid") 60 public Integer clientUid; 61 62 @ColumnInfo(name = "key_id") 63 public Integer keyId; 64 65 // Provide default ctor just for Room generated code ProvisionedKey()66 public ProvisionedKey() {} 67 68 @Ignore ProvisionedKey(@onNull byte[] keyBlob, @NonNull String irpcHal, @NonNull byte[] publicKey, @NonNull byte[] certificateChain, @NonNull Instant expirationTime)69 public ProvisionedKey(@NonNull byte[] keyBlob, @NonNull String irpcHal, 70 @NonNull byte[] publicKey, @NonNull byte[] certificateChain, 71 @NonNull Instant expirationTime) { 72 this.keyBlob = keyBlob; 73 this.irpcHal = irpcHal; 74 this.publicKey = publicKey; 75 this.certificateChain = certificateChain; 76 this.expirationTime = expirationTime; 77 } 78 79 @Override equals(Object o)80 public boolean equals(Object o) { 81 if (this == o) return true; 82 if (!(o instanceof ProvisionedKey)) return false; 83 ProvisionedKey that = (ProvisionedKey) o; 84 return Arrays.equals(keyBlob, that.keyBlob) 85 && Objects.equals(irpcHal, that.irpcHal) 86 && Arrays.equals(publicKey, that.publicKey) 87 && Arrays.equals(certificateChain, that.certificateChain) 88 && Objects.equals(truncate(expirationTime), truncate(that.expirationTime)) 89 && Objects.equals(clientUid, that.clientUid) 90 && Objects.equals(keyId, that.keyId); 91 } 92 93 @Override hashCode()94 public int hashCode() { 95 int result = Objects.hash(irpcHal, truncate(expirationTime), clientUid, keyId); 96 result = 31 * result + Arrays.hashCode(keyBlob); 97 result = 31 * result + Arrays.hashCode(publicKey); 98 result = 31 * result + Arrays.hashCode(certificateChain); 99 return result; 100 } 101 truncate(Instant original)102 private static Instant truncate(Instant original) { 103 return original == null ? null : original.truncatedTo(ChronoUnit.MILLIS); 104 } 105 106 @Override toString()107 public String toString() { 108 return "ProvisionedKey{" 109 + "keyBlob=" + Arrays.toString(keyBlob) 110 + ", irpcHal='" + irpcHal + '\'' 111 + ", publicKey=" + Arrays.toString(publicKey) 112 + ", certificateChain=" + Arrays.toString(certificateChain) 113 + ", expirationTime=" + expirationTime 114 + ", clientUid=" + clientUid 115 + ", keyId=" + keyId 116 + '}'; 117 } 118 } 119