<commit_before>/* SPDX-License-Identifier: BSD-3-Clause */

#include <errno.h>
#include <inttypes.h>
#include <stdbool.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#include <limits.h>
#include <ctype.h>

#include <tss2/tss2_esys.h>

#include "files.h"
#include "log.h"
#include "tpm2_auth_util.h"
#include "tpm2_error.h"
#include "tpm2_options.h"
#include "tpm2_util.h"
#include "tpm2_session.h"
#include "tpm2_tool.h"

typedef struct tpm_activatecred_ctx tpm_activatecred_ctx;
struct tpm_activatecred_ctx {

    struct {
        UINT8 i : 1;
        UINT8 o : 1;
    } flags;

    struct {
        char *auth_str;
        tpm2_session *session;
        const char *ctx_arg;
    } key;

    struct {
        char *auth_str;
        tpm2_session *session;
    } endorse;

    TPM2B_ID_OBJECT credentialBlob;
    TPM2B_ENCRYPTED_SECRET secret;

    const char *output_file;
    const char *ctx_arg;
    tpm2_loaded_object ctx_obj;
    tpm2_loaded_object key_ctx_obj;
};

static tpm_activatecred_ctx ctx;

static bool read_cert_secret(const char *path, TPM2B_ID_OBJECT *cred,
        TPM2B_ENCRYPTED_SECRET *secret) {

    bool result = false;
    FILE *fp = fopen(path, "rb");
    if (!fp) {
        LOG_ERR("Could not open file \"%s\" error: \"%s\"", path,
                strerror(errno));
        return false;
    }

    uint32_t version;
    result = files_read_header(fp, &version);
    if (!result) {
        LOG_ERR("Could not read version header");
        goto out;
    }

    if (version != 1) {
        LOG_ERR("Unknown credential format, got %"PRIu32" expected 1",
                version);
        goto out;
    }

    result = files_read_16(fp, &cred->size);
    if (!result) {
        LOG_ERR("Could not read credential size");
        goto out;
    }

    result = files_read_bytes(fp, cred->credential, cred->size);
    if (!result) {
        LOG_ERR("Could not read credential data");
        goto out;
    }

    result = files_read_16(fp, &secret->size);
    if (!result) {
        LOG_ERR("Could not read secret size");
        goto out;
    }

    result = files_read_bytes(fp, secret->secret, secret->size);
    if (!result) {
        LOG_ERR("Could not write secret data");
        goto out;
    }

    result = true;

out:
    fclose(fp);
    return result;
}

static bool output_and_save(TPM2B_DIGEST *digest, const char *path) {

    tpm2_tool_output("certinfodata:");

    unsigned k;
    for (k = 0; k < digest->size; k++) {
        tpm2_tool_output("%.2x", digest->buffer[k]);
    }
    tpm2_tool_output("\n");

    return files_save_bytes_to_file(path, digest->buffer, digest->size);
}

static bool activate_credential_and_output(ESYS_CONTEXT *ectx) {

    bool retval = false;

    TPM2B_DIGEST *certInfoData;

    tpm2_session_data *d = tpm2_session_data_new(TPM2_SE_POLICY);
    if (!d) {
        LOG_ERR("oom");
        return false;
    }

    tpm2_session *session = tpm2_session_open(ectx, d);
    if (!session) {
        LOG_ERR("Could not start tpm session");
        return false;
    }

    // Set session up
    ESYS_TR sess_handle = tpm2_session_get_handle(session);

    ESYS_TR endorse_shandle = tpm2_auth_util_get_shandle(ectx, sess_handle,
                                ctx.endorse.session);
    if (endorse_shandle == ESYS_TR_NONE) {
        goto out_session;
    }

    TSS2_RC rval = Esys_PolicySecret(ectx, ESYS_TR_RH_ENDORSEMENT, sess_handle,
                    endorse_shandle, ESYS_TR_NONE, ESYS_TR_NONE,
                    NULL, NULL, NULL, 0, NULL, NULL);
    if (rval != TPM2_RC_SUCCESS) {
        LOG_PERR(Esys_PolicySecret, rval);
        goto out_session;
    }

    ESYS_TR key_shandle = tpm2_auth_util_get_shandle(ectx,
                            ctx.key_ctx_obj.tr_handle,
                            ctx.key.session);
    if (key_shandle == ESYS_TR_NONE) {
        goto out_session;
    }

    // NOTE: key_shandle and sess_handle don't seem to match docs
    rval = Esys_ActivateCredential(ectx, ctx.ctx_obj.tr_handle,
            ctx.key_ctx_obj.tr_handle,
            key_shandle, sess_handle, ESYS_TR_NONE,
            &ctx.credentialBlob, &ctx.secret, &certInfoData);
    if (rval != TPM2_RC_SUCCESS) {
        LOG_PERR(Esys_ActivateCredential, rval);
        goto out_all;
    }

    retval = output_and_save(certInfoData, ctx.output_file);

out_all:
    free(certInfoData);
out_session:
    tpm2_session_close(&session);
<commit_msg>tpm2_activatecredential: Fix an issue where in credential activation fails if ak password is set<commit_after>/* SPDX-License-Identifier: BSD-3-Clause */

#include <errno.h>
#include <inttypes.h>
#include <stdbool.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#include <limits.h>
#include <ctype.h>

#include <tss2/tss2_esys.h>

#include "files.h"
#include "log.h"
#include "tpm2_auth_util.h"
#include "tpm2_error.h"
#include "tpm2_options.h"
#include "tpm2_util.h"
#include "tpm2_session.h"
#include "tpm2_tool.h"

typedef struct tpm_activatecred_ctx tpm_activatecred_ctx;
struct tpm_activatecred_ctx {

    struct {
        UINT8 i : 1;
        UINT8 o : 1;
    } flags;

    struct {
        char *auth_str;
        tpm2_session *session;
        const char *ctx_arg;
    } key;

    struct {
        char *auth_str;
        tpm2_session *session;
    } endorse;

    TPM2B_ID_OBJECT credentialBlob;
    TPM2B_ENCRYPTED_SECRET secret;

    const char *output_file;
    const char *ctx_arg;
    tpm2_loaded_object ctx_obj;
    tpm2_loaded_object key_ctx_obj;
};

static tpm_activatecred_ctx ctx;

static bool read_cert_secret(const char *path, TPM2B_ID_OBJECT *cred,
        TPM2B_ENCRYPTED_SECRET *secret) {

    bool result = false;
    FILE *fp = fopen(path, "rb");
    if (!fp) {
        LOG_ERR("Could not open file \"%s\" error: \"%s\"", path,
                strerror(errno));
        return false;
    }

    uint32_t version;
    result = files_read_header(fp, &version);
    if (!result) {
        LOG_ERR("Could not read version header");
        goto out;
    }

    if (version != 1) {
        LOG_ERR("Unknown credential format, got %"PRIu32" expected 1",
                version);
        goto out;
    }

    result = files_read_16(fp, &cred->size);
    if (!result) {
        LOG_ERR("Could not read credential size");
        goto out;
    }

    result = files_read_bytes(fp, cred->credential, cred->size);
    if (!result) {
        LOG_ERR("Could not read credential data");
        goto out;
    }

    result = files_read_16(fp, &secret->size);
    if (!result) {
        LOG_ERR("Could not read secret size");
        goto out;
    }

    result = files_read_bytes(fp, secret->secret, secret->size);
    if (!result) {
        LOG_ERR("Could not write secret data");
        goto out;
    }

    result = true;

out:
    fclose(fp);
    return result;
}

static bool output_and_save(TPM2B_DIGEST *digest, const char *path) {

    tpm2_tool_output("certinfodata:");

    unsigned k;
    for (k = 0; k < digest->size; k++) {
        tpm2_tool_output("%.2x", digest->buffer[k]);
    }
    tpm2_tool_output("\n");

    return files_save_bytes_to_file(path, digest->buffer, digest->size);
}

static bool activate_credential_and_output(ESYS_CONTEXT *ectx) {

    bool retval = false;

    TPM2B_DIGEST *certInfoData;

    tpm2_session_data *d = tpm2_session_data_new(TPM2_SE_POLICY);
    if (!d) {
        LOG_ERR("oom");
        return false;
    }

    tpm2_session *session = tpm2_session_open(ectx, d);
    if (!session) {
        LOG_ERR("Could not start tpm session");
        return false;
    }

    // Set session up
    ESYS_TR sess_handle = tpm2_session_get_handle(session);

    ESYS_TR endorse_shandle = tpm2_auth_util_get_shandle(ectx, sess_handle,
                                ctx.endorse.session);
    if (endorse_shandle == ESYS_TR_NONE) {
        goto out_session;
    }

    TSS2_RC rval = Esys_PolicySecret(ectx, ESYS_TR_RH_ENDORSEMENT, sess_handle,
                    endorse_shandle, ESYS_TR_NONE, ESYS_TR_NONE,
                    NULL, NULL, NULL, 0, NULL, NULL);
    if (rval != TPM2_RC_SUCCESS) {
        LOG_PERR(Esys_PolicySecret, rval);
        goto out_session;
    }

    ESYS_TR key_shandle = tpm2_auth_util_get_shandle(ectx,
                            ctx.ctx_obj.tr_handle,
                            ctx.key.session);
    if (key_shandle == ESYS_TR_NONE) {
        goto out_session;
    }

    // NOTE: key_shandle and sess_handle don't seem to match docs
    rval = Esys_ActivateCredential(ectx, ctx.ctx_obj.tr_handle,
            ctx.key_ctx_obj.tr_handle,
            key_shandle, sess_handle, ESYS_TR_NONE,
            &ctx.credentialBlob, &ctx.secret, &certInfoData);
    if (rval != TPM2_RC_SUCCESS) {
        LOG_PERR(Esys_ActivateCredential, rval);
        goto out_all;
    }

    retval = output_and_save(certInfoData, ctx.output_file);

out_all:
    free(certInfoData);
out_session:
    tpm2_session_close(&session);

{'fraction_non_alphanumeric': 0.11048919735811037, 'fraction_numerical': 0.011530280980633606, 'mean_word_length': 2.617004048582996, 'pattern_counts': {'":': 0, '<': 23, '<?xml version=': 0, '>': 41, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5877471', 'n_tokens_mistral': 3300, 'n_tokens_neox': 3187, 'n_words': 669}