• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2024 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.service.adselection.encryption;
18 
19 import static com.android.adservices.service.common.httpclient.AdServicesHttpUtil.REQUEST_PROPERTIES_PROTOBUF_CONTENT_TYPE;
20 import static com.android.adservices.service.common.httpclient.AdServicesHttpUtil.RESPONSE_PROPERTIES_CONTENT_TYPE;
21 import static com.android.adservices.service.stats.AdsRelevanceStatusUtils.SERVER_AUCTION_ENCRYPTION_KEY_SOURCE_NETWORK;
22 
23 import android.net.Uri;
24 
25 import androidx.annotation.NonNull;
26 import androidx.annotation.Nullable;
27 
28 import com.android.adservices.LoggerFactory;
29 import com.android.adservices.data.adselection.DBEncryptionKey;
30 import com.android.adservices.data.adselection.EncryptionKeyConstants;
31 import com.android.adservices.ohttp.ObliviousHttpKeyConfig;
32 import com.android.adservices.service.Flags;
33 import com.android.adservices.service.common.httpclient.AdServicesHttpClientRequest;
34 import com.android.adservices.service.common.httpclient.AdServicesHttpClientResponse;
35 import com.android.adservices.service.common.httpclient.AdServicesHttpsClient;
36 import com.android.adservices.service.devapi.DevContext;
37 import com.android.adservices.service.stats.AdServicesLogger;
38 import com.android.adservices.service.stats.FetchProcessLogger;
39 
40 import com.google.common.collect.ImmutableList;
41 import com.google.common.util.concurrent.FluentFuture;
42 import com.google.common.util.concurrent.ListenableFuture;
43 
44 import java.security.spec.InvalidKeySpecException;
45 import java.time.Clock;
46 import java.time.Instant;
47 import java.util.List;
48 import java.util.Objects;
49 import java.util.Set;
50 import java.util.concurrent.ExecutorService;
51 
52 public abstract class ProtectedServersEncryptionConfigManagerBase {
53     protected static final LoggerFactory.Logger sLogger = LoggerFactory.getFledgeLogger();
54     protected final Clock mClock;
55     protected final ExecutorService mLightweightExecutor;
56 
57     protected final Flags mFlags;
58     protected final AdServicesLogger mAdServicesLogger;
59 
60     protected final AuctionEncryptionKeyParser mAuctionEncryptionKeyParser;
61     protected final JoinEncryptionKeyParser mJoinEncryptionKeyParser;
62     protected final AdServicesHttpsClient mAdServicesHttpsClient;
63 
64     @Nullable
getLatestOhttpKeyConfigOfType( @dSelectionEncryptionKey.AdSelectionEncryptionKeyType int adSelectionEncryptionKeyType, long timeoutMs, @Nullable Uri coordinatorUrl, DevContext devContext)65     abstract FluentFuture<ObliviousHttpKeyConfig> getLatestOhttpKeyConfigOfType(
66             @AdSelectionEncryptionKey.AdSelectionEncryptionKeyType int adSelectionEncryptionKeyType,
67             long timeoutMs,
68             @Nullable Uri coordinatorUrl,
69             DevContext devContext);
70 
fetchAndPersistActiveKeysOfType( @dSelectionEncryptionKey.AdSelectionEncryptionKeyType int adSelectionKeyType, Instant keyExpiryInstant, long timeoutMs, @Nullable Uri coordinatorUrl, DevContext devContext, FetchProcessLogger keyFetchLogger)71     abstract FluentFuture<List<DBEncryptionKey>> fetchAndPersistActiveKeysOfType(
72             @AdSelectionEncryptionKey.AdSelectionEncryptionKeyType int adSelectionKeyType,
73             Instant keyExpiryInstant,
74             long timeoutMs,
75             @Nullable Uri coordinatorUrl,
76             DevContext devContext,
77             FetchProcessLogger keyFetchLogger);
78 
getExpiredAdSelectionEncryptionKeyTypes(Instant keyExpiryInstant)79     abstract Set<Integer> getExpiredAdSelectionEncryptionKeyTypes(Instant keyExpiryInstant);
80 
getAbsentAdSelectionEncryptionKeyTypes()81     abstract Set<Integer> getAbsentAdSelectionEncryptionKeyTypes();
82 
ProtectedServersEncryptionConfigManagerBase( @onNull Flags flags, @NonNull Clock clock, @NonNull AuctionEncryptionKeyParser auctionEncryptionKeyParser, @NonNull JoinEncryptionKeyParser joinEncryptionKeyParser, @NonNull AdServicesHttpsClient adServicesHttpsClient, @NonNull ExecutorService lightweightExecutor, @NonNull AdServicesLogger adServicesLogger)83     protected ProtectedServersEncryptionConfigManagerBase(
84             @NonNull Flags flags,
85             @NonNull Clock clock,
86             @NonNull AuctionEncryptionKeyParser auctionEncryptionKeyParser,
87             @NonNull JoinEncryptionKeyParser joinEncryptionKeyParser,
88             @NonNull AdServicesHttpsClient adServicesHttpsClient,
89             @NonNull ExecutorService lightweightExecutor,
90             @NonNull AdServicesLogger adServicesLogger) {
91         Objects.requireNonNull(flags);
92         Objects.requireNonNull(clock);
93         Objects.requireNonNull(auctionEncryptionKeyParser);
94         Objects.requireNonNull(joinEncryptionKeyParser);
95         Objects.requireNonNull(adServicesHttpsClient);
96         Objects.requireNonNull(lightweightExecutor);
97         Objects.requireNonNull(adServicesLogger);
98 
99         this.mFlags = flags;
100         this.mClock = clock;
101         this.mAuctionEncryptionKeyParser = auctionEncryptionKeyParser;
102         this.mJoinEncryptionKeyParser = joinEncryptionKeyParser;
103         this.mAdServicesHttpsClient = adServicesHttpsClient;
104         this.mLightweightExecutor = lightweightExecutor;
105         this.mAdServicesLogger = adServicesLogger;
106     }
107 
parseKeyResponse( AdServicesHttpClientResponse keyFetchResponse, @AdSelectionEncryptionKey.AdSelectionEncryptionKeyType int encryptionKeyType)108     protected List<DBEncryptionKey> parseKeyResponse(
109             AdServicesHttpClientResponse keyFetchResponse,
110             @AdSelectionEncryptionKey.AdSelectionEncryptionKeyType int encryptionKeyType) {
111         switch (encryptionKeyType) {
112             case AdSelectionEncryptionKey.AdSelectionEncryptionKeyType.AUCTION:
113                 return mAuctionEncryptionKeyParser.getDbEncryptionKeys(keyFetchResponse);
114             case AdSelectionEncryptionKey.AdSelectionEncryptionKeyType.JOIN:
115                 return mJoinEncryptionKeyParser.getDbEncryptionKeys(keyFetchResponse);
116             case AdSelectionEncryptionKey.AdSelectionEncryptionKeyType.UNASSIGNED:
117             default:
118                 return ImmutableList.of();
119         }
120     }
121 
parseDbEncryptionKey(DBEncryptionKey dbEncryptionKey)122     protected AdSelectionEncryptionKey parseDbEncryptionKey(DBEncryptionKey dbEncryptionKey) {
123         switch (dbEncryptionKey.getEncryptionKeyType()) {
124             case EncryptionKeyConstants.EncryptionKeyType.ENCRYPTION_KEY_TYPE_AUCTION:
125                 return mAuctionEncryptionKeyParser.parseDbEncryptionKey(dbEncryptionKey);
126             case EncryptionKeyConstants.EncryptionKeyType.ENCRYPTION_KEY_TYPE_JOIN:
127                 return mJoinEncryptionKeyParser.parseDbEncryptionKey(dbEncryptionKey);
128             case EncryptionKeyConstants.EncryptionKeyType.ENCRYPTION_KEY_TYPE_QUERY:
129             default:
130                 return null;
131         }
132     }
133 
getKeyCountForType( @dSelectionEncryptionKey.AdSelectionEncryptionKeyType int type)134     protected int getKeyCountForType(
135             @AdSelectionEncryptionKey.AdSelectionEncryptionKeyType int type) {
136         switch (type) {
137             case AdSelectionEncryptionKey.AdSelectionEncryptionKeyType.AUCTION:
138                 // For auctions, more than one key is fetched from the DB to mitigate impact
139                 // due to key leakage.
140                 return mFlags.getFledgeAuctionServerAuctionKeySharding();
141             case AdSelectionEncryptionKey.AdSelectionEncryptionKeyType.JOIN:
142                 return 1;
143             case AdSelectionEncryptionKey.AdSelectionEncryptionKeyType.UNASSIGNED:
144             default:
145                 return 0;
146         }
147     }
148 
getOhttpKeyConfigForKey(AdSelectionEncryptionKey encryptionKey)149     protected ObliviousHttpKeyConfig getOhttpKeyConfigForKey(AdSelectionEncryptionKey encryptionKey)
150             throws InvalidKeySpecException {
151         Objects.requireNonNull(encryptionKey);
152         switch (encryptionKey.keyType()) {
153             case AdSelectionEncryptionKey.AdSelectionEncryptionKeyType.AUCTION:
154                 return mAuctionEncryptionKeyParser.getObliviousHttpKeyConfig(encryptionKey);
155             case AdSelectionEncryptionKey.AdSelectionEncryptionKeyType.JOIN:
156                 return mJoinEncryptionKeyParser.getObliviousHttpKeyConfig(encryptionKey);
157             case AdSelectionEncryptionKey.AdSelectionEncryptionKeyType.UNASSIGNED:
158             default:
159                 throw new IllegalArgumentException(
160                         "Encryption Key of given type is not supported.");
161         }
162     }
163 
fetchKeyPayload( @dSelectionEncryptionKey.AdSelectionEncryptionKeyType int adSelectionKeyType, Uri fetchUri, DevContext devContext, FetchProcessLogger keyFetchLogger)164     protected ListenableFuture<AdServicesHttpClientResponse> fetchKeyPayload(
165             @AdSelectionEncryptionKey.AdSelectionEncryptionKeyType int adSelectionKeyType,
166             Uri fetchUri,
167             DevContext devContext,
168             FetchProcessLogger keyFetchLogger) {
169         keyFetchLogger.setEncryptionKeySource(SERVER_AUCTION_ENCRYPTION_KEY_SOURCE_NETWORK);
170         switch (adSelectionKeyType) {
171             case AdSelectionEncryptionKey.AdSelectionEncryptionKeyType.AUCTION:
172                 return mAdServicesHttpsClient.fetchPayloadWithLogging(
173                         fetchUri, devContext, keyFetchLogger);
174             case AdSelectionEncryptionKey.AdSelectionEncryptionKeyType.JOIN:
175                 AdServicesHttpClientRequest fetchKeyRequest =
176                         AdServicesHttpClientRequest.builder()
177                                 .setUri(fetchUri)
178                                 .setRequestProperties(REQUEST_PROPERTIES_PROTOBUF_CONTENT_TYPE)
179                                 .setResponseHeaderKeys(RESPONSE_PROPERTIES_CONTENT_TYPE)
180                                 .setDevContext(devContext)
181                                 .build();
182                 return mAdServicesHttpsClient.performRequestGetResponseInBase64StringWithLogging(
183                         fetchKeyRequest, keyFetchLogger);
184             case AdSelectionEncryptionKey.AdSelectionEncryptionKeyType.UNASSIGNED:
185             default:
186                 throw new IllegalStateException(
187                         "AdSelectionEncryptionKeyType: "
188                                 + adSelectionKeyType
189                                 + " is not supported.");
190         }
191     }
192 }
193