1 /* 2 * Copyright (C) 2023 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.adservices.data.adselection; 18 19 import androidx.annotation.NonNull; 20 import androidx.room.ColumnInfo; 21 import androidx.room.Entity; 22 import androidx.room.Index; 23 24 import com.google.auto.value.AutoValue; 25 import com.google.auto.value.AutoValue.CopyAnnotations; 26 27 import java.time.Instant; 28 29 /** Table representing EncryptionKeys. */ 30 @AutoValue 31 @CopyAnnotations 32 @Entity( 33 tableName = "encryption_key", 34 indices = {@Index(value = {"encryption_key_type", "expiry_instant"})}, 35 primaryKeys = {"encryption_key_type", "key_identifier"}) 36 public abstract class DBEncryptionKey { 37 /** Type of Key. */ 38 @NonNull 39 @CopyAnnotations 40 @EncryptionKeyConstants.EncryptionKeyType 41 @ColumnInfo(name = "encryption_key_type") getEncryptionKeyType()42 public abstract int getEncryptionKeyType(); 43 44 /** KeyIdentifier used for versioning the keys. */ 45 @NonNull 46 @CopyAnnotations 47 @ColumnInfo(name = "key_identifier") getKeyIdentifier()48 public abstract String getKeyIdentifier(); 49 50 /** 51 * The actual public key. Encoding and parsing of this key is dependent on the keyType and will 52 * be managed by the Key Client. 53 */ 54 @NonNull 55 @CopyAnnotations 56 @ColumnInfo(name = "public_key") getPublicKey()57 public abstract String getPublicKey(); 58 59 /** Instant this EncryptionKey entry was created. */ 60 @CopyAnnotations 61 @ColumnInfo(name = "creation_instant") getCreationInstant()62 public abstract Instant getCreationInstant(); 63 64 /** 65 * Expiry TTL for this encryption key in seconds. This is sent by the server and stored on 66 * device for computing expiry Instant. Clients should directly read the expiryInstant unless 67 * they specifically need to know the expiry ttl seconds reported by the server. 68 */ 69 @NonNull 70 @CopyAnnotations 71 @ColumnInfo(name = "expiry_ttl_seconds") getExpiryTtlSeconds()72 public abstract Long getExpiryTtlSeconds(); 73 74 /** 75 * Expiry Instant for this encryption key computed as 76 * creationInstant.plusSeconds(expiryTtlSeconds). Clients should use this field to read the key 77 * expiry value instead of computing it from creation instant and expiry ttl seconds. 78 */ 79 @NonNull 80 @CopyAnnotations 81 @ColumnInfo(name = "expiry_instant") getExpiryInstant()82 public abstract Instant getExpiryInstant(); 83 84 /** Returns an AutoValue builder for a {@link DBEncryptionKey} entity. */ 85 @NonNull builder()86 public static DBEncryptionKey.Builder builder() { 87 return new AutoValue_DBEncryptionKey.Builder().setCreationInstant(Instant.now()); 88 } 89 90 /** 91 * Creates a {@link DBEncryptionKey} object using the builder. 92 * 93 * <p>Required for Room SQLite integration. 94 */ 95 @NonNull create( @ncryptionKeyConstants.EncryptionKeyType int encryptionKeyType, String keyIdentifier, String publicKey, Instant creationInstant, Long expiryTtlSeconds, Instant expiryInstant)96 public static DBEncryptionKey create( 97 @EncryptionKeyConstants.EncryptionKeyType int encryptionKeyType, 98 String keyIdentifier, 99 String publicKey, 100 Instant creationInstant, 101 Long expiryTtlSeconds, 102 Instant expiryInstant) { 103 104 return builder() 105 .setEncryptionKeyType(encryptionKeyType) 106 .setKeyIdentifier(keyIdentifier) 107 .setPublicKey(publicKey) 108 .setCreationInstant(creationInstant) 109 .setExpiryInstant(expiryInstant) 110 .setExpiryTtlSeconds(expiryTtlSeconds) 111 .build(); 112 } 113 114 /** Builder class for a {@link DBEncryptionKey}. */ 115 @AutoValue.Builder 116 public abstract static class Builder { 117 /** Sets encryption key tupe. */ setEncryptionKeyType( @ncryptionKeyConstants.EncryptionKeyType int encryptionKeyType)118 public abstract Builder setEncryptionKeyType( 119 @EncryptionKeyConstants.EncryptionKeyType int encryptionKeyType); 120 121 /** Identifier used to identify the encryptionKey. */ setKeyIdentifier(String keyIdentifier)122 public abstract Builder setKeyIdentifier(String keyIdentifier); 123 124 /** Public key of an asymmetric key pair represented by this encryptionKey. */ setPublicKey(String publicKey)125 public abstract Builder setPublicKey(String publicKey); 126 127 /** Creation instant for the key. */ setCreationInstant(Instant creationInstant)128 public abstract Builder setCreationInstant(Instant creationInstant); 129 130 /** Ttl in seconds for the EncryptionKey. */ setExpiryTtlSeconds(Long expiryTtlSeconds)131 public abstract Builder setExpiryTtlSeconds(Long expiryTtlSeconds); 132 133 /** Expiry instant for the key. */ setExpiryInstant(Instant expiryInstant)134 abstract Builder setExpiryInstant(Instant expiryInstant); 135 getCreationInstant()136 abstract Instant getCreationInstant(); getExpiryTtlSeconds()137 abstract Long getExpiryTtlSeconds(); 138 autoBuild()139 abstract DBEncryptionKey autoBuild(); 140 141 /** Builds the key based on the set values after validating the input. */ build()142 public final DBEncryptionKey build() { 143 // TODO(b/284445328): Set creation Instant as the instant key was fetched. 144 // This would allow accurate computation of expiry instant as fetchInstant + maxage. 145 setExpiryInstant(getCreationInstant().plusSeconds(getExpiryTtlSeconds())); 146 return autoBuild(); 147 } 148 } 149 } 150