suit_bootloader.c 4.93 KB
Newer Older
Brendan Moran's avatar
Brendan Moran committed
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
// ----------------------------------------------------------------------------
// Copyright 2020 ARM Ltd.
//
// SPDX-License-Identifier: Apache-2.0
//
// 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 "suit_parser.h"
#include "suit_bootloader.h"
#include "mbedtls/sha256.h" /* SHA-256 only */
// #include "mbedtls/md.h"     /* generic interface */
#include "uecc/uECC.h"
#include "mbed_application.h"

#include <stdio.h>
#include <string.h>

29

Brendan Moran's avatar
Brendan Moran committed
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


size_t bl_slot_index;

int suit_platform_do_run() {
    int rc = -1;
    if (bl_slot_index < n_entrypoints) {
        rc = 0;
        mbed_start_application((uintptr_t)entrypoints[bl_slot_index].app_offset);
    }
    return rc;
}

int suit_platform_get_image_ref(
    const uint8_t *component_id,
    const uint8_t **image
) {
    if (bl_slot_index >= n_entrypoints) {
        return -1;
    }

    *image = (const uint8_t *)((uintptr_t)entrypoints[bl_slot_index].app_offset);
    return 0;
}

55
56
57
58
59
60
61
62
63
void compute_sha256(uint8_t *hash, const uint8_t *msg, size_t msg_len) {
    mbedtls_sha256_context ctx;
    mbedtls_sha256_init (&ctx);
    mbedtls_sha256_starts_ret (&ctx, 0);
    mbedtls_sha256_update_ret(&ctx, msg, msg_len);
    mbedtls_sha256_finish_ret(&ctx, hash);
    mbedtls_sha256_free(&ctx);
}

Brendan Moran's avatar
Brendan Moran committed
64
65
66
67
68
69
70
71
72
73
74
75
int suit_platform_verify_image(
    const uint8_t *component_id,
    int digest_type,
    const uint8_t* expected_digest,
    size_t image_size
) {
    if (bl_slot_index >= n_entrypoints) {
        return -1;
    }

    const uint8_t *image = (const uint8_t *)((uintptr_t)entrypoints[bl_slot_index].app_offset);
    uint8_t hash[32];
76
    compute_sha256(hash, image, image_size);
Brendan Moran's avatar
Brendan Moran committed
77
78
79
80
81
82
83
84
85
86
87
88
    // no secret information in this hash, so memcmp is fine
    return memcmp(hash, expected_digest, sizeof(hash));

}

int suit_platform_verify_sha256(
    const uint8_t *expected_digest,
    const uint8_t *data,
    size_t data_len)
{
    uint8_t hash[32];

89
    compute_sha256(hash, data, data_len);
Brendan Moran's avatar
Brendan Moran committed
90
91
92
93
    if (0==memcmp(hash, expected_digest, sizeof(hash))) {
        return CBOR_ERR_NONE;
    }
    else {
94
        RETURN_ERROR( SUIT_ERROR_DIGEST_MISMATCH);
Brendan Moran's avatar
Brendan Moran committed
95
96
97
98
    }
}


99
100
101
102
103
104
int suit_platform_verify_digest(int alg, const uint8_t *exp, size_t exp_len, const uint8_t *data, size_t data_len)
{
    switch (alg) {
        // TODO: expected digest length.
        case SUIT_DIGEST_TYPE_SHA256:
            return suit_platform_verify_sha256(exp, data, data_len);
Brendan Moran's avatar
Brendan Moran committed
105
    }
106
107
    RETURN_ERROR(SUIT_ERROR_DIGEST_MISMATCH);
}
Brendan Moran's avatar
Brendan Moran committed
108

109
110
111
int ES256_verify(
                const uint8_t *msg, size_t msg_len,
                const uint8_t *sig, size_t sig_len,
112
                const uint8_t *pub, size_t pub_len)
113
114
115
116
{
    //TODO: SHA
    uint8_t hash[32] = {0};
    compute_sha256(hash, msg, msg_len);
117
    if (uECC_verify(pub, hash, sig)) {
118
119
120
121
122
123
        return CBOR_ERR_NONE;
    }
    else {
        RETURN_ERROR(SUIT_ERR_SIG);
    }
}
Brendan Moran's avatar
Brendan Moran committed
124

125
126
127
128
129
130
131
int COSEAuthVerify(
                const uint8_t *msg, size_t msg_len,
                const uint8_t *sig, size_t sig_len,
                const uint8_t *kid, size_t kid_len,                
                int alg)
{
    int rc;
132
    //TODO: Lookup public key by key-id
133
134
135
136
137
    switch (alg) {
        case COSE_ES256:
            rc = ES256_verify(
                msg, msg_len,
                sig, sig_len,
138
                public_key, public_key_size);
139
140
141
142
            break;
        default:
            SET_ERROR(rc, CBOR_ERR_UNIMPLEMENTED);
            break;
Brendan Moran's avatar
Brendan Moran committed
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
    }
    return rc;
}

int suit_bootloader() {
    int rc = 1;
    size_t max_seq_idx = 0;
    uint64_t max_seq = -1;
    uint8_t ok = 0;

    while (!ok && max_seq) {
        uint64_t new_max_seq = 0;
        ok = 0;
        for (bl_slot_index = 0; bl_slot_index < n_entrypoints; bl_slot_index++) {
            uint64_t seqnum;
            rc = suit_get_seq(
                (const uint8_t *)entrypoints[bl_slot_index].manifest,
                SUIT_BOOTLOADER_HEADER_SIZE,
                &seqnum);
            if (rc == CBOR_ERR_NONE && seqnum < max_seq && seqnum > new_max_seq) {
                new_max_seq = seqnum;
                max_seq_idx = bl_slot_index;
                ok = 1;
            }
        }
        if (ok) {
            bl_slot_index = max_seq_idx;
            rc = suit_do_process_manifest(
                (const uint8_t *)entrypoints[bl_slot_index].manifest,
                SUIT_BOOTLOADER_HEADER_SIZE);
            if (rc != CBOR_ERR_NONE) {
                ok = 0;
            }
        }
        max_seq = new_max_seq;
    }
    return rc;
}