aboutsummaryrefslogtreecommitdiff
path: root/components/service/attestation/client/provision/attest_provision_client.c
blob: 9209cc1badeda844691108c63b628ff30c92049a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
/*
 * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */

#include <stddef.h>
#include <string.h>
#include "attest_provision_client.h"
#include <common/tlv/tlv.h>
#include <provision/attest_provision.h>
#include <protocols/service/attestation/packed-c/export_iak_public_key.h>
#include <protocols/service/attestation/packed-c/import_iak.h>
#include <protocols/service/attestation/packed-c/opcodes.h>
#include <protocols/rpc/common/packed-c/status.h>

/**
 * @brief      The singleton attest_provision_client instance
 *
 * The attest provison C API assumes a single backend service provider.  This
 * structure defines the state used by the attest_provision_client that communicates
 * with a remote provider using the provided rpc caller.
 */
static struct attest_provision_client
{
    struct rpc_caller *caller;
    int rpc_status;
} instance;


psa_status_t attest_provision_client_init(struct rpc_caller *caller)
{
	instance.caller = caller;
	instance.rpc_status = TS_RPC_CALL_ACCEPTED;

	return PSA_SUCCESS;
}

void attest_provision_client_deinit(void)
{
	instance.caller = NULL;
}

int attest_provision_client_rpc_status(void)
{
	return instance.rpc_status;
}

psa_status_t attest_provision_export_iak_public_key(
    uint8_t *data,
    size_t data_size,
    size_t *data_length)
{
    psa_status_t psa_status = PSA_ERROR_GENERIC_ERROR;

    *data_length = 0; /* For failure case */

    rpc_call_handle call_handle;
    uint8_t *req_buf;

    call_handle = rpc_caller_begin(instance.caller, &req_buf, 0);

    if (call_handle) {

        uint8_t *resp_buf;
        size_t resp_len;
        int opstatus;

        instance.rpc_status = rpc_caller_invoke(instance.caller, call_handle,
            TS_ATTESTATION_OPCODE_EXPORT_IAK_PUBLIC_KEY, &opstatus, &resp_buf, &resp_len);

        if (instance.rpc_status == TS_RPC_CALL_ACCEPTED) {

            psa_status = opstatus;

            if (psa_status == PSA_SUCCESS) {

                struct tlv_const_iterator resp_iter;
                struct tlv_record decoded_record;
                tlv_const_iterator_begin(&resp_iter, resp_buf, resp_len);

                if (tlv_find_decode(&resp_iter,
                    TS_ATTESTATION_EXPORT_IAK_PUBLIC_KEY_OUT_TAG_DATA, &decoded_record)) {

                    if (decoded_record.length <= data_size) {

                        memcpy(data, decoded_record.value, decoded_record.length);
                        *data_length = decoded_record.length;
                    }
                    else {
                        /* Provided buffer is too small */
                        psa_status = PSA_ERROR_BUFFER_TOO_SMALL;
                    }
                }
                else {
                    /* Mandatory response parameter missing */
                    psa_status = PSA_ERROR_GENERIC_ERROR;
                }
            }
        }

        rpc_caller_end(instance.caller, call_handle);
    }

    return psa_status;
}

psa_status_t attest_provision_import_iak(
    const uint8_t *data,
    size_t data_length)
{
    psa_status_t psa_status = PSA_ERROR_GENERIC_ERROR;
    size_t req_len = tlv_required_space(data_length);

    struct tlv_record key_record;
    key_record.tag = TS_ATTESTATION_IMPORT_IAK_IN_TAG_DATA;
    key_record.length = data_length;
    key_record.value = data;

    rpc_call_handle call_handle;
    uint8_t *req_buf;

    call_handle = rpc_caller_begin(instance.caller, &req_buf, req_len);

    if (call_handle) {

        uint8_t *resp_buf;
        size_t resp_len;
        int opstatus;
        struct tlv_iterator req_iter;

        tlv_iterator_begin(&req_iter, req_buf, req_len);
        tlv_encode(&req_iter, &key_record);

        instance.rpc_status = rpc_caller_invoke(instance.caller, call_handle,
            TS_ATTESTATION_OPCODE_IMPORT_IAK, &opstatus, &resp_buf, &resp_len);

        if (instance.rpc_status == TS_RPC_CALL_ACCEPTED) {

            psa_status = opstatus;
        }

        rpc_caller_end(instance.caller, call_handle);
    }

    return psa_status;

}