/*
 * Copyright (C) 2016 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.google.attestationexample;

import com.google.common.base.CharMatcher;
import com.google.common.io.BaseEncoding;

import org.bouncycastle.asn1.ASN1Sequence;

import java.security.cert.CertificateParsingException;
import java.security.cert.X509Certificate;

/**
 * Parses an attestation certificate and provides an easy-to-use interface for examining the
 * contents.
 */
public class Attestation {
    static final String KEY_DESCRIPTION_OID = "1.3.6.1.4.1.11129.2.1.17";
    static final int ATTESTATION_VERSION_INDEX = 0;
    static final int ATTESTATION_SECURITY_LEVEL_INDEX = 1;
    static final int KEYMASTER_VERSION_INDEX = 2;
    static final int KEYMASTER_SECURITY_LEVEL_INDEX = 3;
    static final int ATTESTATION_CHALLENGE_INDEX = 4;
    static final int UNIQUE_ID_INDEX = 5;
    static final int SW_ENFORCED_INDEX = 6;
    static final int TEE_ENFORCED_INDEX = 7;

    public static final int KM_SECURITY_LEVEL_SOFTWARE = 0;
    public static final int KM_SECURITY_LEVEL_TRUSTED_ENVIRONMENT = 1;
    public static final int KM_SECURITY_LEVEL_STRONGBOX = 2;

    private final boolean haveAttestation;
    private final int attestationVersion;
    private final int attestationSecurityLevel;
    private final int keymasterVersion;
    private final int keymasterSecurityLevel;
    private final byte[] attestationChallenge;
    private final byte[] uniqueId;
    private final AuthorizationList softwareEnforced;
    private final AuthorizationList teeEnforced;


    /**
     * Constructs an {@code Attestation} object from the provided {@link X509Certificate},
     * extracting the attestation data from the attestation extension.
     *
     * @throws CertificateParsingException if the certificate does not contain a properly-formatted
     *                                     attestation extension.
     */
    public Attestation(X509Certificate x509Cert) throws CertificateParsingException {
        ASN1Sequence seq = getAttestationSequence(x509Cert);
        if (seq == null) {
            haveAttestation = false;
            attestationVersion = 0;
            attestationSecurityLevel = 0;
            keymasterVersion = 0;
            keymasterSecurityLevel = 0;
            attestationChallenge = null;
            uniqueId = null;
            softwareEnforced = null;
            teeEnforced = null;
            return;
        }

        haveAttestation = true;
        attestationVersion =
                Asn1Utils.getIntegerFromAsn1(seq.getObjectAt(ATTESTATION_VERSION_INDEX));
        attestationSecurityLevel =
                Asn1Utils.getIntegerFromAsn1(seq.getObjectAt(ATTESTATION_SECURITY_LEVEL_INDEX));
        keymasterVersion = Asn1Utils.getIntegerFromAsn1(seq.getObjectAt(KEYMASTER_VERSION_INDEX));
        keymasterSecurityLevel =
                Asn1Utils.getIntegerFromAsn1(seq.getObjectAt(KEYMASTER_SECURITY_LEVEL_INDEX));

        attestationChallenge =
                Asn1Utils.getByteArrayFromAsn1(
                        seq.getObjectAt(Attestation.ATTESTATION_CHALLENGE_INDEX));

        uniqueId = Asn1Utils.getByteArrayFromAsn1(seq.getObjectAt(Attestation.UNIQUE_ID_INDEX));

        softwareEnforced = new AuthorizationList(seq.getObjectAt(SW_ENFORCED_INDEX));
        teeEnforced = new AuthorizationList(seq.getObjectAt(TEE_ENFORCED_INDEX));
    }

    public static String securityLevelToString(int attestationSecurityLevel) {
        switch (attestationSecurityLevel) {
            case KM_SECURITY_LEVEL_SOFTWARE:
                return "Software";
            case KM_SECURITY_LEVEL_TRUSTED_ENVIRONMENT:
                return "TEE";
            case KM_SECURITY_LEVEL_STRONGBOX:
                return "StrongBox";
            default:
                return "Unknown";
        }
    }

    public int getAttestationVersion() {
        return attestationVersion;
    }

    public int getAttestationSecurityLevel() {
        return attestationSecurityLevel;
    }

    public int getKeymasterVersion() {
        return keymasterVersion;
    }

    public int getKeymasterSecurityLevel() {
        return keymasterSecurityLevel;
    }

    public byte[] getAttestationChallenge() {
        return attestationChallenge;
    }

    public byte[] getUniqueId() {
        return uniqueId;
    }

    public AuthorizationList getSoftwareEnforced() {
        return softwareEnforced;
    }

    public AuthorizationList getTeeEnforced() {
        return teeEnforced;
    }

    @Override
    public String toString() {
        if (!haveAttestation) {
            return "No attestation";
        }

        StringBuilder s = new StringBuilder();
        s.append("Attestation version: " + attestationVersion);
        s.append("\nAttestation security: " + securityLevelToString(attestationSecurityLevel));
        s.append("\nKM version: " + keymasterVersion);
        s.append("\nKM security: " + securityLevelToString(keymasterSecurityLevel));

        s.append("\nChallenge");
        String stringChallenge = new String(attestationChallenge);
        if (CharMatcher.ascii().matchesAllOf(stringChallenge)) {
            s.append(": [" + stringChallenge + "]");
        } else {
            s.append(" (base64): [" + BaseEncoding.base64().encode(attestationChallenge) + "]");
        }
        if (uniqueId != null) {
            s.append("\nUnique ID (base64): [" + BaseEncoding.base64().encode(uniqueId) + "]");
        }

        s.append("\n\n-- SW enforced --");
        s.append(softwareEnforced);
        s.append("\n\n-- TEE enforced --");
        s.append(teeEnforced);
        s.append("\n");

        return s.toString();
    }

    private ASN1Sequence getAttestationSequence(X509Certificate x509Cert)
            throws CertificateParsingException {
        byte[] attestationExtensionBytes = x509Cert.getExtensionValue(KEY_DESCRIPTION_OID);
        if (attestationExtensionBytes == null || attestationExtensionBytes.length == 0) {
            return null;
        }
        return Asn1Utils.getAsn1SequenceFromBytes(attestationExtensionBytes);
    }

}
