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

mendersoftware / mender-mcu / 1559779716

25 Nov 2024 06:45PM UTC coverage: 9.39% (-0.03%) from 9.418%
1559779716

push

gitlab-ci

danielskinstad
fix: fail deployment when it's aborted

Changelog: Title
Ticket: MEN-7693

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

0 of 16 new or added lines in 3 files covered. (0.0%)

472 existing lines in 5 files now uncovered.

251 of 2673 relevant lines covered (9.39%)

0.67 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-log.h"
32
#include "mender-storage.h"
33
#include "mender-tls.h"
34

35
#include "mender-utils.h"
36

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

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

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

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

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

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

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

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

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

122
mender_err_t
123
mender_tls_init(void) {
×
124

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

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

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

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

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

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

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

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

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

176
        free(user_provided_key);
×
177
        return MENDER_OK;
×
178
    }
179

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

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

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

223
    return MENDER_OK;
×
224
}
225

226
mender_err_t
UNCOV
227
mender_tls_get_public_key_pem(char **public_key) {
×
228

UNCOV
229
    assert(NULL != public_key);
×
230
    mender_err_t ret;
231

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

244
    /* Convert public key from DER to PEM format */
UNCOV
245
    if (MENDER_OK != (ret = mender_tls_pem_write_buffer(mender_tls_public_key, mender_tls_public_key_length, *public_key, olen, &olen))) {
×
UNCOV
246
        mender_log_error("Unable to convert public key");
×
UNCOV
247
        return ret;
×
248
    }
249

250
    return MENDER_OK;
×
251
}
252

253
mender_err_t
UNCOV
254
mender_tls_sign_payload(char *payload, char **signature, size_t *signature_length) {
×
255

UNCOV
256
    assert(NULL != payload);
×
257
    assert(NULL != signature);
×
UNCOV
258
    assert(NULL != signature_length);
×
259
    int                       ret;
260
    mbedtls_pk_context       *pk_context = NULL;
×
261
    mbedtls_ctr_drbg_context *ctr_drbg   = NULL;
×
UNCOV
262
    mbedtls_entropy_context  *entropy    = NULL;
×
263
    unsigned char            *sig        = NULL;
×
264
    size_t                    sig_length;
265
    MBEDTLS_ERR_BUF;
266

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

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

293
    /* Parse private key (IMPORTANT NOTE: length must include the ending \0 character) */
294
#if MBEDTLS_VERSION_NUMBER >= 0x03000000
UNCOV
295
    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))) {
×
296
#else
297
    if (0 != (ret = mbedtls_pk_parse_key(pk_context, mender_tls_private_key, mender_tls_private_key_length, NULL, 0))) {
298
#endif /* MBEDTLS_VERSION_NUMBER >= 0x03000000 */
UNCOV
299
        LOG_MBEDTLS_ERROR("Unable to parse private key", ret);
×
UNCOV
300
        goto END;
×
301
    }
302

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

310
    /* Compute signature */
UNCOV
311
    if (NULL == (sig = (unsigned char *)malloc(MBEDTLS_PK_SIGNATURE_MAX_SIZE))) {
×
UNCOV
312
        mender_log_error("Unable to allocate memory");
×
UNCOV
313
        ret = -1;
×
314
        goto END;
×
315
    }
316
    sig_length = MBEDTLS_PK_SIGNATURE_MAX_SIZE;
×
317
#if MBEDTLS_VERSION_NUMBER >= 0x03000000
UNCOV
318
    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))) {
×
319
#else
320
    if (0 != (ret = mbedtls_pk_sign(pk_context, MBEDTLS_MD_SHA256, digest, sizeof(digest), sig, &sig_length, mbedtls_ctr_drbg_random, ctr_drbg))) {
321
#endif /* MBEDTLS_VERSION_NUMBER >= 0x03000000 */
UNCOV
322
        LOG_MBEDTLS_ERROR("Unable to compute signature", ret);
×
UNCOV
323
        goto END;
×
324
    }
325

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

343
END:
×
344

345
    /* Release mbedtls */
346
    mbedtls_entropy_free(entropy);
×
UNCOV
347
    free(entropy);
×
UNCOV
348
    mbedtls_ctr_drbg_free(ctr_drbg);
×
349
    free(ctr_drbg);
×
350
    mbedtls_pk_free(pk_context);
×
351
    free(pk_context);
×
352

353
    /* Release memory */
354
    free(sig);
×
355

UNCOV
356
    return (0 != ret) ? MENDER_FAIL : MENDER_OK;
×
357
}
358

359
mender_err_t
UNCOV
360
mender_tls_exit(void) {
×
361

362
    /* Release memory */
363
    FREE_AND_NULL(mender_tls_private_key);
×
UNCOV
364
    mender_tls_private_key_length = 0;
×
UNCOV
365
    FREE_AND_NULL(mender_tls_public_key);
×
366
    mender_tls_public_key_length = 0;
×
367

368
    return MENDER_OK;
×
369
}
370

371
static mender_err_t
UNCOV
372
mender_tls_generate_authentication_keys(mbedtls_pk_context *pk_context) {
×
373

UNCOV
374
    mbedtls_ctr_drbg_context     *ctr_drbg   = NULL;
×
375
    mbedtls_entropy_context      *entropy    = NULL;
×
UNCOV
376
    const mbedtls_ecp_curve_info *curve_info = NULL;
×
377
    int                           ret;
378
    MBEDTLS_ERR_BUF;
379

UNCOV
380
    if (NULL == (ctr_drbg = (mbedtls_ctr_drbg_context *)malloc(sizeof(mbedtls_ctr_drbg_context)))) {
×
UNCOV
381
        mender_log_error("Unable to allocate memory");
×
UNCOV
382
        ret = -1;
×
383
        goto END;
×
384
    }
385
    mbedtls_ctr_drbg_init(ctr_drbg);
×
386
    if (NULL == (entropy = (mbedtls_entropy_context *)malloc(sizeof(mbedtls_entropy_context)))) {
×
UNCOV
387
        mender_log_error("Unable to allocate memory");
×
388
        ret = -1;
×
389
        goto END;
×
390
    }
391
    mbedtls_entropy_init(entropy);
×
392

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

399
    /* PK setup */
UNCOV
400
    if (0 != (ret = mbedtls_pk_setup(pk_context, mbedtls_pk_info_from_type(MBEDTLS_PK_ECKEY)))) {
×
UNCOV
401
        LOG_MBEDTLS_ERROR("Unable to setup pk", ret);
×
UNCOV
402
        goto END;
×
403
    }
404

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

417
    /* Generate key pair */
UNCOV
418
    if (0 != (ret = mbedtls_ecdsa_genkey(mbedtls_pk_ec(*pk_context), curve_info->grp_id, mbedtls_ctr_drbg_random, ctr_drbg))) {
×
UNCOV
419
        LOG_MBEDTLS_ERROR("Unable to generate key", ret);
×
UNCOV
420
        goto END;
×
421
    }
422

423
END:
×
424
    /* Release mbedtls */
UNCOV
425
    mbedtls_entropy_free(entropy);
×
426
    free(entropy);
×
UNCOV
427
    mbedtls_ctr_drbg_free(ctr_drbg);
×
428
    free(ctr_drbg);
×
429

430
    return (0 != ret) ? MENDER_FAIL : MENDER_OK;
×
431
}
432

433
static mender_err_t
UNCOV
434
mender_tls_user_provided_authentication_keys(mbedtls_pk_context *pk_context, const char *user_provided_key, size_t user_provided_key_length) {
×
435

UNCOV
436
    assert(NULL != user_provided_key);
×
437
    assert(0 != user_provided_key_length);
×
438

439
    mbedtls_ctr_drbg_context *ctr_drbg = NULL;
×
440
    mbedtls_entropy_context  *entropy  = NULL;
×
441
    int                       ret;
442
    MBEDTLS_ERR_BUF;
443

UNCOV
444
    if (NULL == (ctr_drbg = (mbedtls_ctr_drbg_context *)malloc(sizeof(mbedtls_ctr_drbg_context)))) {
×
UNCOV
445
        mender_log_error("Unable to allocate memory");
×
UNCOV
446
        ret = -1;
×
447
        goto END;
×
448
    }
449
    mbedtls_ctr_drbg_init(ctr_drbg);
×
450
    if (NULL == (entropy = (mbedtls_entropy_context *)malloc(sizeof(mbedtls_entropy_context)))) {
×
UNCOV
451
        mender_log_error("Unable to allocate memory");
×
452
        ret = -1;
×
453
        goto END;
×
454
    }
455
    mbedtls_entropy_init(entropy);
×
456

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

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

475
END:
×
476
    /* Release mbedtls */
UNCOV
477
    mbedtls_entropy_free(entropy);
×
478
    free(entropy);
×
UNCOV
479
    mbedtls_ctr_drbg_free(ctr_drbg);
×
480
    free(ctr_drbg);
×
481

482
    return (0 != ret) ? MENDER_FAIL : MENDER_OK;
×
483
}
484

485
static mender_err_t
UNCOV
486
mender_tls_get_authentication_keys(unsigned char **private_key,
×
487
                                   size_t         *private_key_length,
488
                                   unsigned char **public_key,
489
                                   size_t         *public_key_length,
490
                                   const char     *user_provided_key,
491
                                   size_t          user_provided_key_length) {
492

UNCOV
493
    assert(NULL != private_key);
×
UNCOV
494
    assert(NULL != private_key_length);
×
UNCOV
495
    assert(NULL != public_key);
×
496
    assert(NULL != public_key_length);
×
497

498
    int                 ret;
499
    mbedtls_pk_context *pk_context = NULL;
×
500
    unsigned char      *tmp;
501
    MBEDTLS_ERR_BUF;
502

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

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

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

570
END:
×
571

572
    /* Release mbedtls */
573
    mbedtls_pk_free(pk_context);
×
UNCOV
574
    free(pk_context);
×
575

576
    return (0 != ret) ? MENDER_FAIL : MENDER_OK;
×
577
}
578

579
static mender_err_t
UNCOV
580
mender_tls_pem_write_buffer(const unsigned char *der_data, size_t der_len, char *buf, size_t buf_len, size_t *olen) {
×
581

582
#define PEM_BEGIN_PUBLIC_KEY "-----BEGIN PUBLIC KEY-----"
583
#define PEM_END_PUBLIC_KEY   "-----END PUBLIC KEY-----"
584

UNCOV
585
    mender_err_t   ret        = MENDER_OK;
×
UNCOV
586
    unsigned char *encode_buf = NULL;
×
UNCOV
587
    unsigned char *p          = (unsigned char *)buf;
×
588

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

598
    /* Compute length required to format PEM */
UNCOV
599
    size_t add_len = strlen(PEM_BEGIN_PUBLIC_KEY) + 1 + strlen(PEM_END_PUBLIC_KEY) + ((use_len / 64) + 1);
×
600

601
    /* Check buffer length */
602
    if (use_len + add_len > buf_len) {
×
UNCOV
603
        *olen = use_len + add_len;
×
UNCOV
604
        ret   = MENDER_FAIL;
×
605
        goto END;
×
606
    }
607

608
    /* Check buffer */
UNCOV
609
    if (NULL == p) {
×
UNCOV
610
        ret = MENDER_FAIL;
×
UNCOV
611
        goto END;
×
612
    }
613

614
    /* Allocate memory to store PEM data */
UNCOV
615
    if (NULL == (encode_buf = (unsigned char *)malloc(use_len))) {
×
UNCOV
616
        mender_log_error("Unable to allocate memory");
×
UNCOV
617
        ret = MENDER_FAIL;
×
618
        goto END;
×
619
    }
620

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

628
    /* Copy header */
UNCOV
629
    memcpy(p, PEM_BEGIN_PUBLIC_KEY, strlen(PEM_BEGIN_PUBLIC_KEY));
×
UNCOV
630
    p += strlen(PEM_BEGIN_PUBLIC_KEY);
×
UNCOV
631
    *p++ = '\n';
×
632

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

644
    /* Copy footer */
UNCOV
645
    memcpy(p, PEM_END_PUBLIC_KEY, strlen(PEM_END_PUBLIC_KEY));
×
UNCOV
646
    p += strlen(PEM_END_PUBLIC_KEY);
×
UNCOV
647
    *p++ = '\0';
×
648

649
    /* Compute output length */
650
    *olen = p - (unsigned char *)buf;
×
651

652
    /* Clean any remaining data previously written to the buffer */
653
    memset(buf + *olen, 0, buf_len - *olen);
×
654

UNCOV
655
END:
×
656

657
    /* Release memory */
658
    free(encode_buf);
×
659

UNCOV
660
    return ret;
×
661
}
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