Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 38421787 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Add westworld logging to signed config."

parents 5931297d b375be55
Loading
Loading
Loading
Loading
+42 −0
Original line number Diff line number Diff line
@@ -181,6 +181,7 @@ message Atom {
        DocsUISearchTypeReported docs_ui_search_type_reported = 120;
        DataStallEvent data_stall_event = 121;
        RescuePartyResetReported rescue_party_reset_reported = 122;
        SignedConfigReported signed_config_reported = 123;
    }

    // Pulled events will start at field 10000.
@@ -3859,3 +3860,44 @@ message RescuePartyResetReported {
    // The rescue level of this reset. A value of 0 indicates missing or unknown level information.
    optional int32 rescue_level = 1;
}

/**
 * Logs when signed config is received from an APK, and if that config was applied successfully.
 * Logged from:
 *   frameworks/base/services/core/java/com/android/server/signedconfig/SignedConfigService.java
 */
message SignedConfigReported {
    enum Type {
        UNKNOWN_TYPE = 0;
        GLOBAL_SETTINGS = 1;
    }
    optional Type type = 1;

    // The final status of the signed config received.
    enum Status {
        UNKNOWN_STATUS = 0;
        APPLIED = 1;
        BASE64_FAILURE_CONFIG = 2;
        BASE64_FAILURE_SIGNATURE = 3;
        SECURITY_EXCEPTION = 4;
        INVALID_CONFIG = 5;
        OLD_CONFIG = 6;
        SIGNATURE_CHECK_FAILED = 7;
        NOT_APPLICABLE = 8;
    }
    optional Status status = 2;

    // The version of the signed config processed.
    optional int32 version = 3;

    // The package name that the config was extracted from.
    optional string from_package = 4;

    enum Key {
        NO_KEY = 0;
        DEBUG = 1;
        PRODUCTION = 2;
    }
    // Which key was used to verify the config.
    optional Key verified_with = 5;
}
+11 −2
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@ import android.provider.Settings;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.Slog;
import android.util.StatsLog;

import java.security.GeneralSecurityException;
import java.util.Arrays;
@@ -66,12 +67,14 @@ class GlobalSettingsConfigApplicator {

    private final Context mContext;
    private final String mSourcePackage;
    private final SignedConfigEvent mEvent;
    private final SignatureVerifier mVerifier;

    GlobalSettingsConfigApplicator(Context context, String sourcePackage) {
    GlobalSettingsConfigApplicator(Context context, String sourcePackage, SignedConfigEvent event) {
        mContext = context;
        mSourcePackage = sourcePackage;
        mVerifier = new SignatureVerifier();
        mEvent = event;
        mVerifier = new SignatureVerifier(mEvent);
    }

    private boolean checkSignature(String data, String signature) {
@@ -79,6 +82,7 @@ class GlobalSettingsConfigApplicator {
            return mVerifier.verifySignature(data, signature);
        } catch (GeneralSecurityException e) {
            Slog.e(TAG, "Failed to verify signature", e);
            mEvent.status = StatsLog.SIGNED_CONFIG_REPORTED__STATUS__SECURITY_EXCEPTION;
            return false;
        }
    }
@@ -109,14 +113,17 @@ class GlobalSettingsConfigApplicator {
        SignedConfig config;
        try {
            config = SignedConfig.parse(configStr, ALLOWED_KEYS, KEY_VALUE_MAPPERS);
            mEvent.version = config.version;
        } catch (InvalidConfigException e) {
            Slog.e(TAG, "Failed to parse global settings from package " + mSourcePackage, e);
            mEvent.status = StatsLog.SIGNED_CONFIG_REPORTED__STATUS__INVALID_CONFIG;
            return;
        }
        int currentVersion = getCurrentConfigVersion();
        if (currentVersion >= config.version) {
            Slog.i(TAG, "Global settings from package " + mSourcePackage
                    + " is older than existing: " + config.version + "<=" + currentVersion);
            mEvent.status = StatsLog.SIGNED_CONFIG_REPORTED__STATUS__OLD_CONFIG;
            return;
        }
        // We have new config!
@@ -126,10 +133,12 @@ class GlobalSettingsConfigApplicator {
                config.getMatchingConfig(Build.VERSION.SDK_INT);
        if (matchedConfig == null) {
            Slog.i(TAG, "Settings is not applicable to current SDK version; ignoring");
            mEvent.status = StatsLog.SIGNED_CONFIG_REPORTED__STATUS__NOT_APPLICABLE;
            return;
        }

        Slog.i(TAG, "Updating global settings to version " + config.version);
        updateCurrentConfig(config.version, matchedConfig.values);
        mEvent.status = StatsLog.SIGNED_CONFIG_REPORTED__STATUS__APPLIED;
    }
}
+7 −1
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ package com.android.server.signedconfig;

import android.os.Build;
import android.util.Slog;
import android.util.StatsLog;

import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
@@ -43,9 +44,11 @@ public class SignatureVerifier {
            "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEaAn2XVifsLTHg616nTsOMVmlhBoECGbTEBTKKvdd2hO60"
            + "pj1pnU8SMkhYfaNxZuKgw9LNvOwlFwStboIYeZ3lQ==";

    private final SignedConfigEvent mEvent;
    private final PublicKey mDebugKey;

    public SignatureVerifier() {
    public SignatureVerifier(SignedConfigEvent event) {
        mEvent = event;
        mDebugKey = createKey(DEBUG_KEY);
    }

@@ -80,6 +83,7 @@ public class SignatureVerifier {
        try {
            signature = Base64.getDecoder().decode(base64Signature);
        } catch (IllegalArgumentException e) {
            mEvent.status = StatsLog.SIGNED_CONFIG_REPORTED__STATUS__BASE64_FAILURE_SIGNATURE;
            Slog.e(TAG, "Failed to base64 decode signature");
            return false;
        }
@@ -94,6 +98,7 @@ public class SignatureVerifier {
                verifier.update(data);
                if (verifier.verify(signature)) {
                    Slog.i(TAG, "Verified config using debug key");
                    mEvent.verifiedWith = StatsLog.SIGNED_CONFIG_REPORTED__VERIFIED_WITH__DEBUG;
                    return true;
                } else {
                    if (DBG) Slog.i(TAG, "Config verification failed using debug key");
@@ -104,6 +109,7 @@ public class SignatureVerifier {
        }
        // TODO verify production key.
        Slog.w(TAG, "NO PRODUCTION KEY YET, FAILING VERIFICATION");
        mEvent.status = StatsLog.SIGNED_CONFIG_REPORTED__STATUS__SIGNATURE_CHECK_FAILED;
        return false;
    }
}
+39 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2019 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.server.signedconfig;

import android.util.StatsLog;

/**
 * Helper class to allow a SignedConfigReported event to be built up in stages.
 */
public class SignedConfigEvent {

    public int type = StatsLog.SIGNED_CONFIG_REPORTED__TYPE__UNKNOWN_TYPE;
    public int status = StatsLog.SIGNED_CONFIG_REPORTED__STATUS__UNKNOWN_STATUS;
    public int version = 0;
    public String fromPackage = null;
    public int verifiedWith = StatsLog.SIGNED_CONFIG_REPORTED__VERIFIED_WITH__NO_KEY;

    /**
     * Write this event to statslog.
     */
    public void send() {
        StatsLog.write(StatsLog.SIGNED_CONFIG_REPORTED,
                type, status, version, fromPackage, verifiedWith);
    }

}
+23 −13
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@ import android.content.pm.PackageManagerInternal;
import android.net.Uri;
import android.os.Bundle;
import android.util.Slog;
import android.util.StatsLog;

import com.android.server.LocalServices;

@@ -82,21 +83,30 @@ public class SignedConfigService {
        }
        if (metaData.containsKey(KEY_GLOBAL_SETTINGS)
                && metaData.containsKey(KEY_GLOBAL_SETTINGS_SIGNATURE)) {
            SignedConfigEvent event = new SignedConfigEvent();
            try {
                event.type = StatsLog.SIGNED_CONFIG_REPORTED__TYPE__GLOBAL_SETTINGS;
                event.fromPackage = packageName;
                String config = metaData.getString(KEY_GLOBAL_SETTINGS);
                String signature = metaData.getString(KEY_GLOBAL_SETTINGS_SIGNATURE);
                try {
                    // Base64 encoding is standard (not URL safe) encoding: RFC4648
                    config = new String(Base64.getDecoder().decode(config), StandardCharsets.UTF_8);
                } catch (IllegalArgumentException iae) {
                Slog.e(TAG, "Failed to base64 decode global settings config from " + packageName);
                    Slog.e(TAG, "Failed to base64 decode global settings config from "
                            + packageName);
                    event.status = StatsLog.SIGNED_CONFIG_REPORTED__STATUS__BASE64_FAILURE_CONFIG;
                    return;
                }
                if (DBG) {
                    Slog.d(TAG, "Got global settings config: " + config);
                    Slog.d(TAG, "Got global settings signature: " + signature);
                }
            new GlobalSettingsConfigApplicator(mContext, packageName).applyConfig(
                new GlobalSettingsConfigApplicator(mContext, packageName, event).applyConfig(
                        config, signature);
            } finally {
                event.send();
            }
        } else {
            if (DBG) Slog.d(TAG, "Package has no global settings config/signature.");
        }