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 android.annotation.Nullable;
20 
21 import androidx.room.Dao;
22 import androidx.room.Insert;
23 import androidx.room.OnConflictStrategy;
24 import androidx.room.Query;
25 
26 import com.android.adservices.data.adselection.datahandlers.DBValidator;
27 import com.android.adservices.data.adselection.datahandlers.EncryptionContext;
28 import com.android.adservices.ohttp.EncapsulatedSharedSecret;
29 import com.android.adservices.ohttp.ObliviousHttpKeyConfig;
30 import com.android.adservices.ohttp.ObliviousHttpRequestContext;
31 
32 import java.time.Instant;
33 
34 /** Dao to manage access to entities in Encryption Context table. */
35 @Dao
36 public abstract class EncryptionContextDao {
37 
38     /** Returns the EncryptionContext of given ad selection id if it exists. */
39     @Nullable
40     @Query(
41             "SELECT * FROM encryption_context "
42                     + "WHERE context_id = :contextId AND encryption_key_type = :encryptionKeyType")
getEncryptionContext( long contextId, @EncryptionKeyConstants.EncryptionKeyType int encryptionKeyType)43     public abstract DBEncryptionContext getEncryptionContext(
44             long contextId, @EncryptionKeyConstants.EncryptionKeyType int encryptionKeyType);
45 
46     /** Inserts the given EncryptionContext in table. */
47     @Insert(onConflict = OnConflictStrategy.REPLACE)
insertEncryptionContext(DBEncryptionContext context)48     public abstract void insertEncryptionContext(DBEncryptionContext context);
49 
50     /**
51      * Clean up expired encryption context entries if it is older than the given timestamp.
52      *
53      * @param expirationTime is the cutoff time to expire the Encryption Context.
54      */
55     @Query("DELETE FROM encryption_context WHERE creation_instant < :expirationTime")
removeExpiredEncryptionContext(Instant expirationTime)56     public abstract void removeExpiredEncryptionContext(Instant expirationTime);
57 
58     /** Persists the encryption context in the {@link DBEncryptionContext} table. */
persistEncryptionContext( long contextId, EncryptionContext encryptionContext, Instant creationInstant)59     public void persistEncryptionContext(
60             long contextId, EncryptionContext encryptionContext, Instant creationInstant) {
61         DBValidator.validateEncryptionContext(encryptionContext);
62 
63         ObliviousHttpRequestContext requestContext = encryptionContext.getOhttpRequestContext();
64         insertEncryptionContext(
65                 DBEncryptionContext.builder()
66                         .setContextId(contextId)
67                         .setEncryptionKeyType(
68                                 EncryptionKeyConstants.from(
69                                         encryptionContext.getAdSelectionEncryptionKeyType()))
70                         .setCreationInstant(creationInstant)
71                         .setSeed(requestContext.seed())
72                         .setKeyConfig(requestContext.keyConfig().serializeKeyConfigToBytes())
73                         .setSharedSecret(
74                                 requestContext.encapsulatedSharedSecret().serializeToBytes())
75                         .setHasMediaTypeChanged(requestContext.hasMediaTypeChanged())
76                         .build());
77     }
78 
79     /**
80      * Method to get {@link EncryptionContext} associated with the given adSelectionId and key type.
81      */
getEncryptionContextForIdAndKeyType( long contextId, @EncryptionKeyConstants.EncryptionKeyType int encryptionKeyType)82     public EncryptionContext getEncryptionContextForIdAndKeyType(
83             long contextId, @EncryptionKeyConstants.EncryptionKeyType int encryptionKeyType)
84             throws Exception {
85         DBEncryptionContext dbEncryptionContext =
86                 getEncryptionContext(contextId, encryptionKeyType);
87 
88         return EncryptionContext.builder()
89                 .setAdSelectionEncryptionKeyType(encryptionKeyType)
90                 .setOhttpRequestContext(
91                         ObliviousHttpRequestContext.create(
92                                 ObliviousHttpKeyConfig.fromSerializedKeyConfig(
93                                         dbEncryptionContext.getKeyConfig()),
94                                 EncapsulatedSharedSecret.create(
95                                         dbEncryptionContext.getSharedSecret()),
96                                 dbEncryptionContext.getSeed(),
97                                 dbEncryptionContext.getHasMediaTypeChanged()))
98                 .build();
99     }
100 }
101