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