Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Android/trusty/trusty/user/base/lib/hwkey/   (Android Betriebssystem Version 17©)  Datei vom 26.5.2026 mit Größe 9 kB image not shown  

Quelle  hwkey.c

  Sprache: C
 

/*
 * Copyright (C) 2015 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.
 */


#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <trusty_ipc.h>
#include <uapi/err.h>

#include <lib/hwkey/hwkey.h>
#include <lib/tipc/tipc.h>
#include "interface/hwkey/hwkey.h"

#define LOG_TAG "libhwkey"
#define TLOGE(fmt, ...) \
    fprintf(stderr, "%s: %d: " fmt, LOG_TAG, __LINE__, ##__VA_ARGS__)

/**
 * long hwkey_err_to_tipc_err() - translates hwkey err value to tipc/lk err
 * value
 * @hwkey_err: hwkey err value
 *
 * Returns: enum hwkey_err value
 */

static long hwkey_err_to_tipc_err(enum hwkey_err hwkey_err) {
    switch (hwkey_err) {
    case HWKEY_NO_ERROR:
        return NO_ERROR;
    case HWKEY_ERR_NOT_VALID:
        return ERR_NOT_VALID;
    case HWKEY_ERR_BAD_LEN:
        return ERR_BAD_LEN;
    case HWKEY_ERR_NOT_IMPLEMENTED:
        return ERR_NOT_IMPLEMENTED;
    case HWKEY_ERR_NOT_FOUND:
        return ERR_NOT_FOUND;
    case HWKEY_ERR_ALREADY_EXISTS:
        return ERR_ALREADY_EXISTS;
    default:
        return ERR_GENERIC;
    }
}

/**
 * long send_req() - sends request to hwkey server
 * @session: the hwkey session handle
 * @msg: the request header to send to the hwkey server
 * @req_buf: the request payload to send to the hwkey server
 * @req_buf_len: the length of the request payload @req_buf
 * @rsp_buf: buffer in which to store the response payload
 * @rsp_buf_len: the size of the response buffer. Inout param, set
 *               to the actual response payload length.
 *
 * Returns: NO_ERROR on success, negative error code on failure
 */

static long send_req(hwkey_session_t session,
                     struct hwkey_msg* msg,
                     uint8_t* req_buf,
                     uint32_t req_buf_len,
                     uint8_t* rsp_buf,
                     uint32_t* rsp_buf_len) {
    long rc;

    struct iovec tx_iov[2] = {
            {.iov_base = msg, .iov_len = sizeof(*msg)},
            {.iov_base = req_buf, .iov_len = req_buf_len},
    };
    ipc_msg_t tx_msg = {
            .iov = tx_iov,
            .num_iov = 2,
    };

    rc = send_msg(session, &tx_msg);
    if (rc < 0) {
        goto err_send_fail;
    }

    if (((size_t)rc) != sizeof(*msg) + req_buf_len) {
        rc = ERR_IO;
        goto err_send_fail;
    }

    uevent_t uevt;
    rc = wait(session, &uevt, INFINITE_TIME);
    if (rc != NO_ERROR) {
        goto err_send_fail;
    }

    ipc_msg_info_t inf;
    rc = get_msg(session, &inf);
    if (rc != NO_ERROR) {
        TLOGE("%s: failed to get_msg (%ld)\n", __func__, rc);
        goto err_send_fail;
    }

    if (inf.len > sizeof(*msg) + (size_t)*rsp_buf_len) {
        TLOGE("%s: insufficient output buffer size (%zu > %zu)\n", __func__,
              inf.len - sizeof(*msg), (size_t)*rsp_buf_len);
        rc = ERR_TOO_BIG;
        goto err_get_fail;
    }

    if (inf.len < sizeof(*msg)) {
        TLOGE("%s: short buffer (%zu)\n", __func__, inf.len);
        rc = ERR_NOT_VALID;
        goto err_get_fail;
    }

    uint32_t cmd_sent = msg->header.cmd;

    struct iovec rx_iov[2] = {
            {.iov_base = msg, .iov_len = sizeof(*msg)},
            {.iov_base = rsp_buf, .iov_len = *rsp_buf_len},
    };
    ipc_msg_t rx_msg = {
            .iov = rx_iov,
            .num_iov = 2,
    };

    rc = read_msg(session, inf.id, 0, &rx_msg);
    put_msg(session, inf.id);
    if (rc < 0) {
        goto err_read_fail;
    }

    size_t read_len = (size_t)rc;
    if (read_len != inf.len) {
        // data read in does not match message length
        TLOGE("%s: invalid read length (%zu != %zu)\n", __func__, read_len,
              inf.len);
        rc = ERR_IO;
        goto err_read_fail;
    }

    if (msg->header.cmd != (cmd_sent | HWKEY_RESP_BIT)) {
        TLOGE("%s: invalid response id (0x%x) for cmd (0x%x)\n", __func__,
              msg->header.cmd, cmd_sent);
        return ERR_NOT_VALID;
    }

    *rsp_buf_len = read_len - sizeof(*msg);
    return hwkey_err_to_tipc_err(msg->header.status);

err_get_fail:
    put_msg(session, inf.id);
err_send_fail:
err_read_fail:
    TLOGE("%s: failed read_msg (%ld)\n", __func__, rc);
    return rc;
}

long hwkey_open(void) {
    return connect(HWKEY_PORT, IPC_CONNECT_WAIT_FOR_PORT);
}

long hwkey_get_keyslot_data(hwkey_session_t session,
                            const char* slot_id,
                            uint8_t* data,
                            uint32_t* data_size) {
    if (slot_id == NULL || data == NULL || data_size == NULL ||
        *data_size == 0) {
        return ERR_NOT_VALID;
    }

    struct hwkey_msg msg = {
            .header.cmd = HWKEY_GET_KEYSLOT,
    };

    // TODO: remove const cast when const APIs are available
    return send_req(session, &msg, (uint8_t*)slot_id, strlen(slot_id), data,
                    data_size);
}

long hwkey_derive(hwkey_session_t session,
                  uint32_t* kdf_version,
                  const uint8_t* src,
                  uint8_t* dest,
                  uint32_t buf_size) {
    if (src == NULL || buf_size == 0 || dest == NULL || kdf_version == NULL) {
        // invalid input
        return ERR_NOT_VALID;
    }

    struct hwkey_msg msg = {
            .header.cmd = HWKEY_DERIVE,
            .arg1 = *kdf_version,
    };

    // TODO: remove const cast when const APIs are available
    uint32_t stored_buf_size = buf_size;
    long rc = send_req(session, &msg, (uint8_t*)src, buf_size, dest, &buf_size);

    if (rc == NO_ERROR && stored_buf_size != buf_size) {
        return ERR_BAD_LEN;
    }

    *kdf_version = msg.arg1;

    return rc;
}

long hwkey_derive_versioned(hwkey_session_t session,
                            struct hwkey_versioned_key_options* args) {
    if (args == NULL) {
        TLOGE("Args pointer is null\n");
        return ERR_NOT_VALID;
    }
    if (args->context == NULL && args->context_len != 0) {
        TLOGE("Context pointer is null with non-zero length\n");
        return ERR_NOT_VALID;
    }
    if (args->context != NULL && args->context_len == 0) {
        TLOGE("Context pointer is non-null with zero length\n");
        return ERR_NOT_VALID;
    }
    if (args->key == NULL && args->key_len != 0) {
        TLOGE("Key pointer is null with non-zero length\n");
        return ERR_NOT_VALID;
    }
    if (args->key != NULL && args->key_len == 0) {
        TLOGE("Key pointer is non-null with zero length\n");
        return ERR_NOT_VALID;
    }
    if (args->os_rollback_version < 0 &&
        args->os_rollback_version != HWKEY_ROLLBACK_VERSION_CURRENT) {
        TLOGE("OS rollback version is invalid: %d\n",
              args->os_rollback_version);
        return ERR_NOT_VALID;
    }

    size_t max_payload_len =
            HWKEY_MAX_MSG_SIZE - sizeof(struct hwkey_derive_versioned_msg);
    if (args->context_len > max_payload_len ||
        args->key_len > max_payload_len) {
        return ERR_BAD_LEN;
    }

    uint32_t key_options = args->shared_key ? HWKEY_SHARED_KEY_TYPE
                                            : HWKEY_DEVICE_UNIQUE_KEY_TYPE;

    struct hwkey_derive_versioned_msg req_msg = {
            .header.cmd = HWKEY_DERIVE_VERSIONED,
            .kdf_version = args->kdf_version,
            .rollback_version_source = args->rollback_version_source,
            .rollback_versions[HWKEY_ROLLBACK_VERSION_OS_INDEX] =
                    args->os_rollback_version,
            .key_options = key_options,
            .key_len = args->key_len,
    };

    int rc = tipc_send2(session, &req_msg, sizeof(req_msg), args->context,
                        args->context_len);
    if (rc < 0) {
        return rc;
    }

    if (((size_t)rc) != sizeof(req_msg) + args->context_len) {
        TLOGE("%s: failed to send entire message\n", __func__);
        return ERR_IO;
    }

    uevent_t uevt;
    rc = wait(session, &uevt, INFINITE_TIME);
    if (rc != NO_ERROR) {
        return rc;
    }

    struct hwkey_derive_versioned_msg resp_msg = {0};

    rc = tipc_recv2(session, sizeof(struct hwkey_msg_header), &resp_msg,
                    sizeof(resp_msg), args->key, args->key_len);
    if (rc < 0) {
        return rc;
    }

    if (resp_msg.header.cmd != (req_msg.header.cmd | HWKEY_RESP_BIT)) {
        TLOGE("%s: invalid response id (0x%x) for cmd (0x%x)\n", __func__,
              resp_msg.header.cmd, req_msg.header.cmd);
        return ERR_NOT_VALID;
    }

    if (resp_msg.header.status == HWKEY_NO_ERROR &&
        (size_t)rc != sizeof(resp_msg) + args->key_len) {
        TLOGE("%s: unexpected response length (%zu != %zu)\n", __func__,
              (size_t)rc, sizeof(resp_msg) + args->key_len);
        return ERR_BAD_LEN;
    }

    if (resp_msg.header.status == HWKEY_NO_ERROR) {
        args->kdf_version = resp_msg.kdf_version;
        args->os_rollback_version =
                resp_msg.rollback_versions[HWKEY_ROLLBACK_VERSION_OS_INDEX];
    }

    return hwkey_err_to_tipc_err(resp_msg.header.status);
}

void hwkey_close(hwkey_session_t session) {
    close(session);
}

Messung V0.5 in Prozent
C=90 H=89 G=89

¤ Dauer der Verarbeitung: 0.10 Sekunden  (vorverarbeitet am  2026-06-26) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.