1 /** 2 * Copyright (C) 2022 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.remoteprovisioner; 18 19 import android.security.remoteprovisioning.AttestationPoolStatus; 20 import android.util.Log; 21 22 public class StatsProcessor { 23 public static final double LIMIT_SCALER = .4; 24 25 private static final String TAG = "RemoteProvisioningService.KeyPoolStats"; 26 StatsProcessor()27 private StatsProcessor() {} 28 calcMinUnassignedToTriggerProvisioning(int extraSignedKeysAvailable)29 public static int calcMinUnassignedToTriggerProvisioning(int extraSignedKeysAvailable) { 30 return (int) Math.ceil(LIMIT_SCALER * extraSignedKeysAvailable); 31 } 32 33 /** 34 * Creates a PoolStats. Takes an {@Code AttestationPoolStatus} and calculates different 35 * pieces of status to inform the caller if any action needs to be taken to reprovision the pool 36 * and what action is needed in terms of keys to generate. 37 * 38 * @parameter pool the current status of the keypool in Keystore2 39 * @parameter extraSignedKeysAvailable how many extra attested keys should ideally be available 40 * for assignment. 41 * @return the PoolStats object describing higher level info about the state of the key pool. 42 */ processPool( AttestationPoolStatus pool, int extraSignedKeysAvailable)43 public static PoolStats processPool( 44 AttestationPoolStatus pool, int extraSignedKeysAvailable) { 45 PoolStats stats = new PoolStats(); 46 stats.unattestedKeys = pool.total - pool.attested; 47 stats.keysInUse = pool.attested - pool.unassigned; 48 stats.idealTotalSignedKeys = stats.keysInUse + extraSignedKeysAvailable; 49 // If nothing is expiring, and the amount of available unassigned keys is sufficient, 50 // then do nothing. Otherwise, generate the complete amount of idealTotalSignedKeys. It will 51 // reduce network usage if the app just provisions an entire new batch in one go, rather 52 // than consistently grabbing just a few at a time as the expiration dates become 53 // misaligned. 54 stats.provisioningNeeded = 55 pool.unassigned - pool.expiring 56 <= calcMinUnassignedToTriggerProvisioning(extraSignedKeysAvailable); 57 if (!stats.provisioningNeeded) { 58 Log.i(TAG, "Sufficient keys are available, no CSR needed."); 59 stats.keysToGenerate = 0; 60 } else { 61 stats.keysToGenerate = Math.max(0, stats.idealTotalSignedKeys - stats.unattestedKeys); 62 } 63 return stats; 64 } 65 66 public static class PoolStats { 67 public int unattestedKeys; 68 public int keysInUse; 69 public int idealTotalSignedKeys; 70 public int keysToGenerate; 71 public boolean provisioningNeeded = true; 72 } 73 } 74