• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

mendersoftware / mender-mcu / 1652801795

03 Feb 2025 08:48AM UTC coverage: 25.939% (+0.3%) from 25.682%
1652801795

push

gitlab-ci

danielskinstad
chore: explicit error for no files in zephyr-image-update-module

Check if the aritfact has a payload file by adding a boolean that's set
when the download artifact flash callback is called.

Ticket: MEN-7804

Signed-off-by: Daniel Skinstad Drabitzius <daniel.drabitzius@northern.tech>

739 of 2849 relevant lines covered (25.94%)

8.56 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/platform/tls/generic/mbedtls/src/mender-tls.c
1
/**
2
 * @file      mender-tls.c
3
 * @brief     Mender TLS interface for mbedTLS platform
4
 *
5
 * Copyright joelguittet and mender-mcu-client contributors
6
 * Copyright Northern.tech AS
7
 *
8
 * Licensed under the Apache License, Version 2.0 (the "License");
9
 * you may not use this file except in compliance with the License.
10
 * You may obtain a copy of the License at
11
 *
12
 *     http://www.apache.org/licenses/LICENSE-2.0
13
 *
14
 * Unless required by applicable law or agreed to in writing, software
15
 * distributed under the License is distributed on an "AS IS" BASIS,
16
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17
 * See the License for the specific language governing permissions and
18
 * limitations under the License.
19
 */
20

21
#include <mbedtls/base64.h>
22
#include <mbedtls/bignum.h>
23
#include <mbedtls/ctr_drbg.h>
24
#include <mbedtls/entropy.h>
25
#ifdef MBEDTLS_ERROR_C
26
#include <mbedtls/error.h>
27
#endif /* MBEDTLS_ERROR_C */
28
#include <mbedtls/pk.h>
29
#include <mbedtls/ecdsa.h>
30
#include <mbedtls/x509.h>
31
#include "mender-alloc.h"
32
#include "mender-log.h"
33
#include "mender-storage.h"
34
#include "mender-tls.h"
35

36
#include "mender-utils.h"
37

38
/**
39
 * @brief Keys buffer length
40
 */
41
#define MENDER_TLS_PRIVATE_KEY_LENGTH (2048)
42
#define MENDER_TLS_PUBLIC_KEY_LENGTH  (768)
43

44
/**
45
 * @brief Signature buffer length (base64 encoded)
46
 * @note base64 produces 4 bytes of output per 3 bytes of input (padded to be
47
 *       divisible), see RFC-4648 or man:EVP_EncodeBlock(3)
48
 */
49
#define MENDER_TLS_SIGNATURE_LENGTH (((MBEDTLS_PK_SIGNATURE_MAX_SIZE + 2) / 3) * 4)
50

51
#ifdef MBEDTLS_ERROR_C
52
#define MBEDTLS_ERR_BUF char err[128]
53

54
/**
55
 * @brief Macro for logging errors coming from mbedtls
56
 * @note  Make sure to declare the buffer using the #MBEDTLS_ERR_BUF macro above
57
 */
58
#define LOG_MBEDTLS_ERROR(msg, ret)                        \
59
    do {                                                   \
60
        mbedtls_strerror(ret, err, sizeof(err));           \
61
        mender_log_error(msg " (-0x%04x: %s)", -ret, err); \
62
    } while (0)
63
#else
64
#define MBEDTLS_ERR_BUF
65
#define LOG_MBEDTLS_ERROR(msg, ret) mender_log_error(msg " (-0x%04x)", -ret)
66
#endif /* MBEDTLS_ERROR_C */
67

68
/**
69
 * @brief Private and public keys of the device
70
 */
71
static unsigned char *mender_tls_private_key        = NULL;
72
static size_t         mender_tls_private_key_length = 0;
73
static unsigned char *mender_tls_public_key         = NULL;
74
static size_t         mender_tls_public_key_length  = 0;
75

76
/**
77
 * @brief Generate authentication keys
78
 * @param pk_context PK context
79
 * @return MENDER_OK if the function succeeds, error code otherwise
80
 */
81
static mender_err_t mender_tls_generate_authentication_keys(mbedtls_pk_context *pk_context);
82

83
/**
84
 * @brief Get user provided authentication keys
85
 * @param pk_context PK context
86
 * @param user_provided_key Buffer of user provided key
87
 * @param user_provided_key_length Length of buffer of user provided key
88
 * @return MENDER_OK if the function succeeds, error code otherwise
89
 */
90
static mender_err_t mender_tls_user_provided_authentication_keys(mbedtls_pk_context *pk_context,
91
                                                                 const char         *user_provided_key,
92
                                                                 size_t              user_provided_key_length);
93

94
/**
95
 * @brief Generate authentication keys
96
 * @param private_key Private key generated
97
 * @param private_key_length Private key length
98
 * @param public_key Public key generated
99
 * @param public_key_length Public key length
100
 * @param user_provided_key Path to user-provided key
101
 * @param user_provided_key_length Length of buffer of user provided key
102
 * @return MENDER_OK if the function succeeds, error code otherwise
103
 */
104
static mender_err_t mender_tls_get_authentication_keys(unsigned char **private_key,
105
                                                       size_t         *private_key_length,
106
                                                       unsigned char **public_key,
107
                                                       size_t         *public_key_length,
108
                                                       const char     *user_provided_key,
109
                                                       size_t          user_provided_key_length);
110

111
/**
112
 * @brief Write a buffer of PEM information from a DER encoded buffer
113
 * @note This function is derived from mbedtls_pem_write_buffer with const header and footer
114
 * @param der_data The DER data to encode
115
 * @param der_len The length of the DER data
116
 * @param buf The buffer to write to
117
 * @param buf_len The length of the output buffer
118
 * @param olen The address at which to store the total length written or required output buffer length is not enough
119
 * @return MENDER_OK if the function succeeds, error code otherwise
120
 */
121
static mender_err_t mender_tls_pem_write_buffer(const unsigned char *der_data, size_t der_len, char *buf, size_t buf_len, size_t *olen);
122

123
mender_err_t
124
mender_tls_init(void) {
×
125

126
    /* Nothing to do */
127
    return MENDER_OK;
×
128
}
129

130
mender_err_t
131
mender_tls_init_authentication_keys(mender_err_t (*get_user_provided_keys)(char **user_provided_key, size_t *user_provided_key_length), bool recommissioning) {
×
132

133
    /* Release memory */
134
    FREE_AND_NULL(mender_tls_private_key);
×
135
    mender_tls_private_key_length = 0;
×
136
    FREE_AND_NULL(mender_tls_public_key);
×
137
    mender_tls_public_key_length = 0;
×
138

139
    /* Check if recommissioning is forced */
140
    if (recommissioning) {
×
141
        /* Erase authentication keys */
142
        mender_log_debug("Deleting authentication keys");
143
        if (MENDER_OK != mender_storage_delete_authentication_keys()) {
×
144
            mender_log_warning("Unable to delete authentication keys");
×
145
        }
146
    }
147

148
    /* Get user provided key (callback is optional) */
149
    if (NULL != get_user_provided_keys) {
×
150
        char  *user_provided_key        = NULL;
×
151
        size_t user_provided_key_length = 0;
×
152

153
        mender_log_debug("Retrieving user provided authentication keys");
154

155
        if (MENDER_OK != get_user_provided_keys(&user_provided_key, &user_provided_key_length)) {
×
156
            mender_log_error("Unable to get user provided authentication key");
×
157
            return MENDER_FAIL;
×
158
        }
159

160
        if ((NULL == user_provided_key) || (0 == user_provided_key_length)) {
×
161
            mender_log_error("User provided authentication key is empty");
×
162
            return MENDER_FAIL;
×
163
        }
164

165
        if (MENDER_OK
×
166
            != mender_tls_get_authentication_keys(&mender_tls_private_key,
×
167
                                                  &mender_tls_private_key_length,
168
                                                  &mender_tls_public_key,
169
                                                  &mender_tls_public_key_length,
170
                                                  user_provided_key,
171
                                                  user_provided_key_length)) {
172
            mender_log_error("Unable to get user provided authentication key");
×
173
            mender_free(user_provided_key);
×
174
            return MENDER_FAIL;
×
175
        }
176

177
        mender_free(user_provided_key);
×
178
        return MENDER_OK;
×
179
    }
180

181
    /* Get keys from store */
182
    mender_log_debug("Trying to read authentication keys from store");
183
    switch (mender_storage_get_authentication_keys(
×
184
        &mender_tls_private_key, &mender_tls_private_key_length, &mender_tls_public_key, &mender_tls_public_key_length)) {
185
        case MENDER_OK:
×
186
            /* Keys found! */
187
            return MENDER_OK;
×
188
        case MENDER_NOT_FOUND:
×
189
            mender_log_debug("Authentication keys not found in store");
190
            break;
×
191
        case MENDER_DONE:
×
192
            /* fallthrough */
193
        case MENDER_NOT_IMPLEMENTED:
194
            assert(false && "Unexpected return value");
×
195
            /* fallthrough */
196
        case MENDER_LOOP_DETECTED:
197
            assert(false && "Unexpected return value");
×
198
            /* fallthrough */
199
        case MENDER_LOCK_FAILED:
200
            assert(false && "Unexpected return value");
×
201
            /* fallthrough */
202
        case MENDER_ABORTED:
203
            assert(false && "Unexpected return value");
×
204
            /* fallthrough */
205
        case MENDER_FAIL:
206
            mender_log_error("Unable to get authentication keys from store");
×
207
            return MENDER_FAIL;
×
208
    }
209

210
    /* We failed to get keys from store. Hence, we need to generate them */
211
    mender_log_info("Generating authentication keys");
×
212
    if (MENDER_OK
×
213
        != mender_tls_get_authentication_keys(
×
214
            &mender_tls_private_key, &mender_tls_private_key_length, &mender_tls_public_key, &mender_tls_public_key_length, NULL, 0)) {
215
        mender_log_error("Unable to generate authentication keys");
×
216
        return MENDER_FAIL;
×
217
    }
218

219
    /* Store newly generated keys */
220
    mender_log_debug("Writing authentication keys to store");
221
    if (MENDER_OK
×
222
        != mender_storage_set_authentication_keys(mender_tls_private_key, mender_tls_private_key_length, mender_tls_public_key, mender_tls_public_key_length)) {
×
223
        mender_log_error("Unable to store authentication keys");
×
224
        return MENDER_FAIL;
×
225
    }
226

227
    return MENDER_OK;
×
228
}
229

230
mender_err_t
231
mender_tls_get_public_key_pem(char **public_key) {
×
232

233
    assert(NULL != public_key);
×
234
    mender_err_t ret;
235

236
    /* Compute size of the public key */
237
    size_t olen = 0;
×
238
    mender_tls_pem_write_buffer(mender_tls_public_key, mender_tls_public_key_length, NULL, 0, &olen);
×
239
    if (0 == olen) {
×
240
        mender_log_error("Unable to compute public key size");
×
241
        return MENDER_FAIL;
×
242
    }
243
    if (NULL == (*public_key = (char *)mender_malloc(olen))) {
×
244
        mender_log_error("Unable to allocate memory");
×
245
        return MENDER_FAIL;
×
246
    }
247

248
    /* Convert public key from DER to PEM format */
249
    if (MENDER_OK != (ret = mender_tls_pem_write_buffer(mender_tls_public_key, mender_tls_public_key_length, *public_key, olen, &olen))) {
×
250
        mender_log_error("Unable to convert public key");
×
251
        return ret;
×
252
    }
253

254
    return MENDER_OK;
×
255
}
256

257
mender_err_t
258
mender_tls_sign_payload(char *payload, char **signature, size_t *signature_length) {
×
259

260
    assert(NULL != payload);
×
261
    assert(NULL != signature);
×
262
    assert(NULL != signature_length);
×
263
    int                       ret;
264
    mbedtls_pk_context       *pk_context = NULL;
×
265
    mbedtls_ctr_drbg_context *ctr_drbg   = NULL;
×
266
    mbedtls_entropy_context  *entropy    = NULL;
×
267
    unsigned char            *sig        = NULL;
×
268
    size_t                    sig_length;
269
    MBEDTLS_ERR_BUF;
270

271
    /* Initialize mbedtls */
272
    if (NULL == (pk_context = (mbedtls_pk_context *)mender_malloc(sizeof(mbedtls_pk_context)))) {
×
273
        mender_log_error("Unable to allocate memory");
×
274
        ret = -1;
×
275
        goto END;
×
276
    }
277
    mbedtls_pk_init(pk_context);
×
278
    if (NULL == (ctr_drbg = (mbedtls_ctr_drbg_context *)mender_malloc(sizeof(mbedtls_ctr_drbg_context)))) {
×
279
        mender_log_error("Unable to allocate memory");
×
280
        ret = -1;
×
281
        goto END;
×
282
    }
283
    mbedtls_ctr_drbg_init(ctr_drbg);
×
284
    if (NULL == (entropy = (mbedtls_entropy_context *)mender_malloc(sizeof(mbedtls_entropy_context)))) {
×
285
        mender_log_error("Unable to allocate memory");
×
286
        ret = -1;
×
287
        goto END;
×
288
    }
289
    mbedtls_entropy_init(entropy);
×
290

291
    /* Setup CRT DRBG */
292
    if (0 != (ret = mbedtls_ctr_drbg_seed(ctr_drbg, mbedtls_entropy_func, entropy, (const unsigned char *)"mender", strlen("mender")))) {
×
293
        LOG_MBEDTLS_ERROR("Unable to initialize ctr drbg", ret);
×
294
        goto END;
×
295
    }
296

297
    /* Parse private key (IMPORTANT NOTE: length must include the ending \0 character) */
298
#if MBEDTLS_VERSION_NUMBER >= 0x03000000
299
    if (0 != (ret = mbedtls_pk_parse_key(pk_context, mender_tls_private_key, mender_tls_private_key_length, NULL, 0, mbedtls_ctr_drbg_random, ctr_drbg))) {
×
300
#else
301
    if (0 != (ret = mbedtls_pk_parse_key(pk_context, mender_tls_private_key, mender_tls_private_key_length, NULL, 0))) {
302
#endif /* MBEDTLS_VERSION_NUMBER >= 0x03000000 */
303
        LOG_MBEDTLS_ERROR("Unable to parse private key", ret);
×
304
        goto END;
×
305
    }
306

307
    /* Generate digest */
308
    uint8_t digest[32];
309
    if (0 != (ret = mbedtls_md(mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), (unsigned char *)payload, strlen(payload), digest))) {
×
310
        LOG_MBEDTLS_ERROR("Unable to generate digest", ret);
×
311
        goto END;
×
312
    }
313

314
    /* Compute signature */
315
    if (NULL == (sig = (unsigned char *)mender_malloc(MBEDTLS_PK_SIGNATURE_MAX_SIZE))) {
×
316
        mender_log_error("Unable to allocate memory");
×
317
        ret = -1;
×
318
        goto END;
×
319
    }
320
    sig_length = MBEDTLS_PK_SIGNATURE_MAX_SIZE;
×
321
#if MBEDTLS_VERSION_NUMBER >= 0x03000000
322
    if (0 != (ret = mbedtls_pk_sign(pk_context, MBEDTLS_MD_SHA256, digest, sizeof(digest), sig, sig_length, &sig_length, mbedtls_ctr_drbg_random, ctr_drbg))) {
×
323
#else
324
    if (0 != (ret = mbedtls_pk_sign(pk_context, MBEDTLS_MD_SHA256, digest, sizeof(digest), sig, &sig_length, mbedtls_ctr_drbg_random, ctr_drbg))) {
325
#endif /* MBEDTLS_VERSION_NUMBER >= 0x03000000 */
326
        LOG_MBEDTLS_ERROR("Unable to compute signature", ret);
×
327
        goto END;
×
328
    }
329

330
    /* Encode signature to base64 (1 extra byte for the NUL character) */
331
    if (NULL == (*signature = (char *)mender_malloc(MENDER_TLS_SIGNATURE_LENGTH + 1))) {
×
332
        mender_log_error("Unable to allocate memory");
×
333
        ret = -1;
×
334
        goto END;
×
335
    }
336
    *signature_length = MENDER_TLS_SIGNATURE_LENGTH + 1;
×
337
    if (0 != (ret = mbedtls_base64_encode((unsigned char *)*signature, *signature_length, signature_length, sig, sig_length))) {
×
338
        LOG_MBEDTLS_ERROR("Unable to encode signature", ret);
×
339
        if (MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL == ret) {
×
340
            mender_log_error("This is a bug, please report it");
×
341
        }
342
        FREE_AND_NULL(*signature);
×
343
        *signature_length = 0;
×
344
        goto END;
×
345
    }
346

347
END:
×
348

349
    /* Release mbedtls */
350
    mbedtls_entropy_free(entropy);
×
351
    mender_free(entropy);
×
352
    mbedtls_ctr_drbg_free(ctr_drbg);
×
353
    mender_free(ctr_drbg);
×
354
    mbedtls_pk_free(pk_context);
×
355
    mender_free(pk_context);
×
356

357
    /* Release memory */
358
    mender_free(sig);
×
359

360
    return (0 != ret) ? MENDER_FAIL : MENDER_OK;
×
361
}
362

363
mender_err_t
364
mender_tls_exit(void) {
×
365

366
    /* Release memory */
367
    FREE_AND_NULL(mender_tls_private_key);
×
368
    mender_tls_private_key_length = 0;
×
369
    FREE_AND_NULL(mender_tls_public_key);
×
370
    mender_tls_public_key_length = 0;
×
371

372
    return MENDER_OK;
×
373
}
374

375
static mender_err_t
376
mender_tls_generate_authentication_keys(mbedtls_pk_context *pk_context) {
×
377

378
    mbedtls_ctr_drbg_context     *ctr_drbg   = NULL;
×
379
    mbedtls_entropy_context      *entropy    = NULL;
×
380
    const mbedtls_ecp_curve_info *curve_info = NULL;
×
381
    int                           ret;
382
    MBEDTLS_ERR_BUF;
383

384
    if (NULL == (ctr_drbg = (mbedtls_ctr_drbg_context *)mender_malloc(sizeof(mbedtls_ctr_drbg_context)))) {
×
385
        mender_log_error("Unable to allocate memory");
×
386
        ret = -1;
×
387
        goto END;
×
388
    }
389
    mbedtls_ctr_drbg_init(ctr_drbg);
×
390
    if (NULL == (entropy = (mbedtls_entropy_context *)mender_malloc(sizeof(mbedtls_entropy_context)))) {
×
391
        mender_log_error("Unable to allocate memory");
×
392
        ret = -1;
×
393
        goto END;
×
394
    }
395
    mbedtls_entropy_init(entropy);
×
396

397
    /* Setup CRT DRBG */
398
    if (0 != (ret = mbedtls_ctr_drbg_seed(ctr_drbg, mbedtls_entropy_func, entropy, (const unsigned char *)"mender", strlen("mender")))) {
×
399
        LOG_MBEDTLS_ERROR("Unable to initialize ctr drbg", ret);
×
400
        goto END;
×
401
    }
402

403
    /* PK setup */
404
    if (0 != (ret = mbedtls_pk_setup(pk_context, mbedtls_pk_info_from_type(MBEDTLS_PK_ECKEY)))) {
×
405
        LOG_MBEDTLS_ERROR("Unable to setup pk", ret);
×
406
        goto END;
×
407
    }
408

409
    /* Find a supported curve */
410
    for (curve_info = mbedtls_ecp_curve_list(); MBEDTLS_ECP_DP_NONE != curve_info->grp_id; curve_info++) {
×
411
        if (1 == mbedtls_ecdsa_can_do(curve_info->grp_id)) {
×
412
            mender_log_debug("Found supported ECDSA curve: %s", curve_info->name);
413
            break;
×
414
        }
415
    }
416
    if (MBEDTLS_ECP_DP_NONE == curve_info->grp_id) {
×
417
        mender_log_error("Unable to find a ECDSA valid curve");
×
418
        goto END;
×
419
    }
420

421
    /* Generate key pair */
422
    if (0 != (ret = mbedtls_ecdsa_genkey(mbedtls_pk_ec(*pk_context), curve_info->grp_id, mbedtls_ctr_drbg_random, ctr_drbg))) {
×
423
        LOG_MBEDTLS_ERROR("Unable to generate key", ret);
×
424
        goto END;
×
425
    }
426

427
END:
×
428
    /* Release mbedtls */
429
    mbedtls_entropy_free(entropy);
×
430
    mender_free(entropy);
×
431
    mbedtls_ctr_drbg_free(ctr_drbg);
×
432
    mender_free(ctr_drbg);
×
433

434
    return (0 != ret) ? MENDER_FAIL : MENDER_OK;
×
435
}
436

437
static mender_err_t
438
mender_tls_user_provided_authentication_keys(mbedtls_pk_context *pk_context, const char *user_provided_key, size_t user_provided_key_length) {
×
439

440
    assert(NULL != user_provided_key);
×
441
    assert(0 != user_provided_key_length);
×
442

443
    mbedtls_ctr_drbg_context *ctr_drbg = NULL;
×
444
    mbedtls_entropy_context  *entropy  = NULL;
×
445
    int                       ret;
446
    MBEDTLS_ERR_BUF;
447

448
    if (NULL == (ctr_drbg = (mbedtls_ctr_drbg_context *)mender_malloc(sizeof(mbedtls_ctr_drbg_context)))) {
×
449
        mender_log_error("Unable to allocate memory");
×
450
        ret = -1;
×
451
        goto END;
×
452
    }
453
    mbedtls_ctr_drbg_init(ctr_drbg);
×
454
    if (NULL == (entropy = (mbedtls_entropy_context *)mender_malloc(sizeof(mbedtls_entropy_context)))) {
×
455
        mender_log_error("Unable to allocate memory");
×
456
        ret = -1;
×
457
        goto END;
×
458
    }
459
    mbedtls_entropy_init(entropy);
×
460

461
    /* Setup CRT DRBG */
462
    if (0 != (ret = mbedtls_ctr_drbg_seed(ctr_drbg, mbedtls_entropy_func, entropy, (const unsigned char *)"mender", strlen("mender")))) {
×
463
        LOG_MBEDTLS_ERROR("Unable to initialize ctr drbg", ret);
×
464
        goto END;
×
465
    }
466

467
    /* Load and parse the private key buffer */
468
#if MBEDTLS_VERSION_NUMBER >= 0x03000000
469
    if (0
×
470
        != (ret = mbedtls_pk_parse_key(
×
471
                pk_context, (const unsigned char *)user_provided_key, user_provided_key_length, NULL, 0, mbedtls_ctr_drbg_random, ctr_drbg))) {
472
#else
473
    if (0 != (ret = mbedtls_pk_parse_key(pk_context, (const unsigned char *)user_provided_key, user_provided_key_length, NULL, 0))) {
474
#endif /* MBEDTLS_VERSION_NUMBER >= 0x03000000 */
475
        LOG_MBEDTLS_ERROR("Unable to parse private key", ret);
×
476
        goto END;
×
477
    }
478

479
END:
×
480
    /* Release mbedtls */
481
    mbedtls_entropy_free(entropy);
×
482
    mender_free(entropy);
×
483
    mbedtls_ctr_drbg_free(ctr_drbg);
×
484
    mender_free(ctr_drbg);
×
485

486
    return (0 != ret) ? MENDER_FAIL : MENDER_OK;
×
487
}
488

489
static mender_err_t
490
mender_tls_get_authentication_keys(unsigned char **private_key,
×
491
                                   size_t         *private_key_length,
492
                                   unsigned char **public_key,
493
                                   size_t         *public_key_length,
494
                                   const char     *user_provided_key,
495
                                   size_t          user_provided_key_length) {
496

497
    assert(NULL != private_key);
×
498
    assert(NULL != private_key_length);
×
499
    assert(NULL != public_key);
×
500
    assert(NULL != public_key_length);
×
501

502
    int                 ret;
503
    mbedtls_pk_context *pk_context = NULL;
×
504
    unsigned char      *tmp;
505
    MBEDTLS_ERR_BUF;
506

507
    /* Initialize mbedtls */
508
    if (NULL == (pk_context = (mbedtls_pk_context *)mender_malloc(sizeof(mbedtls_pk_context)))) {
×
509
        mender_log_error("Unable to allocate memory");
×
510
        ret = -1;
×
511
        goto END;
×
512
    }
513
    mbedtls_pk_init(pk_context);
×
514
    /* Get user provided key, else generate key  */
515
    if (NULL != user_provided_key) {
×
516
        if (MENDER_OK != mender_tls_user_provided_authentication_keys(pk_context, user_provided_key, user_provided_key_length)) {
×
517
            ret = -1;
×
518
            goto END;
×
519
        }
520
    } else {
521
        /* Generate key */
522
        if (MENDER_OK != mender_tls_generate_authentication_keys(pk_context)) {
×
523
            ret = -1;
×
524
            goto END;
×
525
        }
526
    }
527

528
    /* Export private key */
529
    if (NULL == (*private_key = (unsigned char *)mender_malloc(MENDER_TLS_PRIVATE_KEY_LENGTH))) {
×
530
        mender_log_error("Unable to allocate memory");
×
531
        ret = -1;
×
532
        goto END;
×
533
    }
534
    if ((ret = mbedtls_pk_write_key_der(pk_context, *private_key, MENDER_TLS_PRIVATE_KEY_LENGTH)) < 0) {
×
535
        LOG_MBEDTLS_ERROR("Unable to write private key to PEM format", ret);
×
536
        FREE_AND_NULL(*private_key);
×
537
        goto END;
×
538
    }
539
    *private_key_length = (size_t)ret;
×
540
    memcpy(*private_key, *private_key + MENDER_TLS_PRIVATE_KEY_LENGTH - *private_key_length, *private_key_length);
×
541
    if (NULL == (tmp = mender_realloc(*private_key, *private_key_length))) {
×
542
        mender_log_error("Unable to allocate memory");
×
543
        FREE_AND_NULL(*private_key);
×
544
        ret = -1;
×
545
        goto END;
×
546
    }
547
    *private_key = tmp;
×
548

549
    /* Export public key */
550
    if (NULL == (*public_key = (unsigned char *)mender_malloc(MENDER_TLS_PUBLIC_KEY_LENGTH))) {
×
551
        mender_log_error("Unable to allocate memory");
×
552
        FREE_AND_NULL(*private_key);
×
553
        ret = -1;
×
554
        goto END;
×
555
    }
556
    if ((ret = mbedtls_pk_write_pubkey_der(pk_context, *public_key, MENDER_TLS_PUBLIC_KEY_LENGTH)) < 0) {
×
557
        LOG_MBEDTLS_ERROR("Unable to write public key to PEM format", ret);
×
558
        FREE_AND_NULL(*private_key);
×
559
        FREE_AND_NULL(*public_key);
×
560
        goto END;
×
561
    }
562
    *public_key_length = (size_t)ret;
×
563
    memcpy(*public_key, *public_key + MENDER_TLS_PUBLIC_KEY_LENGTH - *public_key_length, *public_key_length);
×
564
    if (NULL == (tmp = mender_realloc(*public_key, *public_key_length))) {
×
565
        mender_log_error("Unable to allocate memory");
×
566
        FREE_AND_NULL(*private_key);
×
567
        FREE_AND_NULL(*public_key);
×
568
        ret = -1;
×
569
        goto END;
×
570
    }
571
    *public_key = tmp;
×
572
    ret         = 0;
×
573

574
END:
×
575

576
    /* Release mbedtls */
577
    mbedtls_pk_free(pk_context);
×
578
    mender_free(pk_context);
×
579

580
    return (0 != ret) ? MENDER_FAIL : MENDER_OK;
×
581
}
582

583
static mender_err_t
584
mender_tls_pem_write_buffer(const unsigned char *der_data, size_t der_len, char *buf, size_t buf_len, size_t *olen) {
×
585

586
#define PEM_BEGIN_PUBLIC_KEY "-----BEGIN PUBLIC KEY-----"
587
#define PEM_END_PUBLIC_KEY   "-----END PUBLIC KEY-----"
588

589
    mender_err_t   ret        = MENDER_OK;
×
590
    unsigned char *encode_buf = NULL;
×
591
    unsigned char *p          = (unsigned char *)buf;
×
592

593
    /* Compute length required to convert DER data */
594
    size_t use_len = 0;
×
595
    mbedtls_base64_encode(NULL, 0, &use_len, der_data, der_len);
×
596
    if (0 == use_len) {
×
597
        mender_log_error("Unable to compute length");
×
598
        ret = MENDER_FAIL;
×
599
        goto END;
×
600
    }
601

602
    /* Compute length required to format PEM */
603
    size_t add_len = strlen(PEM_BEGIN_PUBLIC_KEY) + 1 + strlen(PEM_END_PUBLIC_KEY) + ((use_len / 64) + 1);
×
604

605
    /* Check buffer length */
606
    if (use_len + add_len > buf_len) {
×
607
        *olen = use_len + add_len;
×
608
        ret   = MENDER_FAIL;
×
609
        goto END;
×
610
    }
611

612
    /* Check buffer */
613
    if (NULL == p) {
×
614
        ret = MENDER_FAIL;
×
615
        goto END;
×
616
    }
617

618
    /* Allocate memory to store PEM data */
619
    if (NULL == (encode_buf = (unsigned char *)mender_malloc(use_len))) {
×
620
        mender_log_error("Unable to allocate memory");
×
621
        ret = MENDER_FAIL;
×
622
        goto END;
×
623
    }
624

625
    /* Convert DER data */
626
    if (0 != mbedtls_base64_encode(encode_buf, use_len, &use_len, der_data, der_len)) {
×
627
        mender_log_error("Unable to convert data to base64 format");
×
628
        ret = MENDER_FAIL;
×
629
        goto END;
×
630
    }
631

632
    /* Copy header */
633
    memcpy(p, PEM_BEGIN_PUBLIC_KEY, strlen(PEM_BEGIN_PUBLIC_KEY));
×
634
    p += strlen(PEM_BEGIN_PUBLIC_KEY);
×
635
    *p++ = '\n';
×
636

637
    /* Copy PEM data */
638
    unsigned char *c = encode_buf;
×
639
    while (use_len) {
×
640
        size_t len = (use_len > 64) ? 64 : use_len;
×
641
        memcpy(p, c, len);
×
642
        use_len -= len;
×
643
        p += len;
×
644
        c += len;
×
645
        *p++ = '\n';
×
646
    }
647

648
    /* Copy footer */
649
    memcpy(p, PEM_END_PUBLIC_KEY, strlen(PEM_END_PUBLIC_KEY));
×
650
    p += strlen(PEM_END_PUBLIC_KEY);
×
651
    *p++ = '\0';
×
652

653
    /* Compute output length */
654
    *olen = p - (unsigned char *)buf;
×
655

656
    /* Clean any remaining data previously written to the buffer */
657
    memset(buf + *olen, 0, buf_len - *olen);
×
658

659
END:
×
660

661
    /* Release memory */
662
    mender_free(encode_buf);
×
663

664
    return ret;
×
665
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc