| /** |
| * Copyright (C) 2022 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package com.android.remoteprovisioner; |
| |
| import android.security.remoteprovisioning.AttestationPoolStatus; |
| import android.util.Log; |
| |
| public class StatsProcessor { |
| public static final double LIMIT_SCALER = .4; |
| |
| private static final String TAG = "RemoteProvisioningService.KeyPoolStats"; |
| |
| private StatsProcessor() {} |
| |
| public static int calcMinUnassignedToTriggerProvisioning(int extraSignedKeysAvailable) { |
| return (int) Math.ceil(LIMIT_SCALER * extraSignedKeysAvailable); |
| } |
| |
| /** |
| * Creates a PoolStats. Takes an {@Code AttestationPoolStatus} and calculates different |
| * pieces of status to inform the caller if any action needs to be taken to reprovision the pool |
| * and what action is needed in terms of keys to generate. |
| * |
| * @parameter pool the current status of the keypool in Keystore2 |
| * @parameter extraSignedKeysAvailable how many extra attested keys should ideally be available |
| * for assignment. |
| * @return the PoolStats object describing higher level info about the state of the key pool. |
| */ |
| public static PoolStats processPool( |
| AttestationPoolStatus pool, int extraSignedKeysAvailable) { |
| PoolStats stats = new PoolStats(); |
| stats.unattestedKeys = pool.total - pool.attested; |
| stats.keysInUse = pool.attested - pool.unassigned; |
| stats.idealTotalSignedKeys = stats.keysInUse + extraSignedKeysAvailable; |
| // If nothing is expiring, and the amount of available unassigned keys is sufficient, |
| // then do nothing. Otherwise, generate the complete amount of idealTotalSignedKeys. It will |
| // reduce network usage if the app just provisions an entire new batch in one go, rather |
| // than consistently grabbing just a few at a time as the expiration dates become |
| // misaligned. |
| stats.provisioningNeeded = |
| pool.unassigned - pool.expiring |
| <= calcMinUnassignedToTriggerProvisioning(extraSignedKeysAvailable); |
| if (!stats.provisioningNeeded) { |
| Log.i(TAG, "Sufficient keys are available, no CSR needed."); |
| stats.keysToGenerate = 0; |
| } else { |
| stats.keysToGenerate = Math.max(0, stats.idealTotalSignedKeys - stats.unattestedKeys); |
| } |
| return stats; |
| } |
| |
| public static class PoolStats { |
| public int unattestedKeys; |
| public int keysInUse; |
| public int idealTotalSignedKeys; |
| public int keysToGenerate; |
| public boolean provisioningNeeded = true; |
| } |
| } |