Tidy up mbedtls error handling

This commit is contained in:
jaseg 2021-07-19 14:57:18 +02:00
parent 4a97412516
commit aec38e6255

View file

@ -21,6 +21,19 @@
#include "con_usart.h" #include "con_usart.h"
#define LOG_PRINTF con_printf #define LOG_PRINTF con_printf
#define MBEDTLS_CHECK_MSG( fun_call, err_value, msg, ... ) \
do { \
int mbedtls_rc = fun_call; \
if (mbedtls_rc) { \
LOG_PRINTF("Error: " #fun_call ": " msg ": rc=-0x%x\n", __VA_ARGS__ -mbedtls_rc); \
err = err_value; \
goto cleanup; \
} \
} while (false);
#define MBEDTLS_CHECK_VAL(fun_call, err_value) MBEDTLS_CHECK_MSG(fun_call, err_value, "")
#define MBEDTLS_CHECK(fun_call) MBEDTLS_CHECK_VAL(fun_call, CA_ERR_MBEDTLS_ERROR)
static enum ca_error parse_stanza(struct ca_keystore *ks, const char *stanza_head, size_t len, unsigned char file_key[16]); static enum ca_error parse_stanza(struct ca_keystore *ks, const char *stanza_head, size_t len, unsigned char file_key[16]);
static enum ca_error parse_stanza_x25519(struct ca_keystore *ks, size_t nargs, const char **args, size_t body_len, const unsigned char *body, unsigned char file_key[16]); static enum ca_error parse_stanza_x25519(struct ca_keystore *ks, size_t nargs, const char **args, size_t body_len, const unsigned char *body, unsigned char file_key[16]);
@ -35,7 +48,7 @@ void ca_keystore_free(struct ca_keystore *ks) {
} }
enum ca_error ca_keystore_load_x25519_private_key(struct ca_keystore *ks, const unsigned char buf[32]) { enum ca_error ca_keystore_load_x25519_private_key(struct ca_keystore *ks, const unsigned char buf[32]) {
enum ca_error err = CA_ERR_CORRUPTED_STATE;
/* /*
printf("x25519: private key: "); printf("x25519: private key: ");
for (size_t i=0; i<32; i++) { for (size_t i=0; i<32; i++) {
@ -44,22 +57,17 @@ enum ca_error ca_keystore_load_x25519_private_key(struct ca_keystore *ks, const
printf("\n"); printf("\n");
*/ */
int mbedtls_rc = mbedtls_ecp_read_key(MBEDTLS_ECP_DP_CURVE25519, &(ks->x25519_kp), buf, 32); MBEDTLS_CHECK( mbedtls_ecp_read_key(MBEDTLS_ECP_DP_CURVE25519, &(ks->x25519_kp), buf, 32) );
if (mbedtls_rc) {
LOG_PRINTF("Error: mbedtls_ecp_read_key: rc=-0x%x\n", -mbedtls_rc);
return CA_ERR_MBEDTLS_ERROR;
}
/* Reconstruct public key from private key */ /* Reconstruct public key from private key */
mbedtls_rc = mbedtls_ecp_mul(&(ks->x25519_kp.grp), &(ks->x25519_kp.Q), MBEDTLS_CHECK( mbedtls_ecp_mul(&(ks->x25519_kp.grp), &(ks->x25519_kp.Q),
&(ks->x25519_kp.d), &(ks->x25519_kp.grp.G), &(ks->x25519_kp.d), &(ks->x25519_kp.grp.G),
mbedtls_ctr_drbg_random, g_drbg_ctx); mbedtls_ctr_drbg_random, g_drbg_ctx) );
if (mbedtls_rc) {
LOG_PRINTF("Error: mbedtls_ecp_read_key: rc=-0x%x\n", -mbedtls_rc); err = CA_ERR_SUCCESS;
return CA_ERR_MBEDTLS_ERROR;
} cleanup:
return err;
return CA_ERR_SUCCESS;
} }
enum ca_error parse_age_buf(struct ca_keystore *ks, const char *buf, size_t buflen, unsigned char file_key[16]) { enum ca_error parse_age_buf(struct ca_keystore *ks, const char *buf, size_t buflen, unsigned char file_key[16]) {
@ -238,7 +246,6 @@ errout:
} }
enum ca_error parse_stanza_x25519(struct ca_keystore *ks, size_t nargs, const char **args, size_t body_len, const unsigned char *body, unsigned char file_key[16]) { enum ca_error parse_stanza_x25519(struct ca_keystore *ks, size_t nargs, const char **args, size_t body_len, const unsigned char *body, unsigned char file_key[16]) {
int mbedtls_rc = -1;
enum ca_error err = CA_ERR_CORRUPTED_STATE; enum ca_error err = CA_ERR_CORRUPTED_STATE;
/* body length: 16 bytes ciphertext of 128 bit file key + 16 bytes Poly1305 tag */ /* body length: 16 bytes ciphertext of 128 bit file key + 16 bytes Poly1305 tag */
@ -270,19 +277,17 @@ enum ca_error parse_stanza_x25519(struct ca_keystore *ks, size_t nargs, const ch
mbedtls_ecp_point_init(&ecp_ciphertext_pt); mbedtls_ecp_point_init(&ecp_ciphertext_pt);
mbedtls_ecp_group x25519_grp; mbedtls_ecp_group x25519_grp;
mbedtls_ecp_group_init(&x25519_grp); mbedtls_ecp_group_init(&x25519_grp);
mbedtls_rc = mbedtls_ecp_group_load(&x25519_grp, MBEDTLS_ECP_DP_CURVE25519); mbedtls_ecp_point ecp_dec_res_pt;
if (mbedtls_rc) { mbedtls_ecp_point_init(&ecp_dec_res_pt);
LOG_PRINTF("Error: mbedtls_ecp_group_load: rc=-0x%x\n", -mbedtls_rc); mbedtls_chachapoly_context cp_ctx;
err = CA_ERR_KEY_WRAPPING_DECRYPTION_FAILURE; mbedtls_chachapoly_init(&cp_ctx);
goto err_free_grp;
}
mbedtls_rc = mbedtls_ecp_point_read_binary(&x25519_grp, &ecp_ciphertext_pt, ecp_ciphertext, sizeof(ecp_ciphertext)); MBEDTLS_CHECK_VAL( mbedtls_ecp_group_load(&x25519_grp, MBEDTLS_ECP_DP_CURVE25519),
if (mbedtls_rc) { CA_ERR_KEY_WRAPPING_DECRYPTION_FAILURE );
LOG_PRINTF("Error: mbedtls_ecp_point_read_binary: rc=-0x%x\n", -mbedtls_rc);
err = CA_ERR_KEY_WRAPPING_DECRYPTION_FAILURE; MBEDTLS_CHECK_VAL( mbedtls_ecp_point_read_binary(&x25519_grp,
goto err_free_grp; &ecp_ciphertext_pt, ecp_ciphertext, sizeof(ecp_ciphertext)),
} CA_ERR_KEY_WRAPPING_DECRYPTION_FAILURE );
/* /*
printf("x25519: derived_secret: "); printf("x25519: derived_secret: ");
@ -292,23 +297,16 @@ enum ca_error parse_stanza_x25519(struct ca_keystore *ks, size_t nargs, const ch
printf("\n"); printf("\n");
*/ */
mbedtls_ecp_point ecp_dec_res_pt; MBEDTLS_CHECK( mbedtls_ecp_mul(&x25519_grp, &ecp_dec_res_pt,
mbedtls_ecp_point_init(&ecp_dec_res_pt); &(ks->x25519_kp.d), &ecp_ciphertext_pt,
mbedtls_ctr_drbg_random, g_drbg_ctx) );
mbedtls_rc = mbedtls_ecp_mul(&x25519_grp, &ecp_dec_res_pt, &(ks->x25519_kp.d), &ecp_ciphertext_pt,
mbedtls_ctr_drbg_random, g_drbg_ctx);
if (mbedtls_rc) {
LOG_PRINTF("Error: mbedtls_ecp_mul: rc=-0x%x\n", -mbedtls_rc);
err = CA_ERR_MBEDTLS_ERROR;
goto err_free_dec;
}
unsigned char ecp_plaintext_buf[32]; unsigned char ecp_plaintext_buf[32];
size_t ecp_plaintext_len = 0; size_t ecp_plaintext_len = 0;
mbedtls_rc = mbedtls_ecp_point_write_binary(&x25519_grp, &ecp_dec_res_pt, MBEDTLS_CHECK( mbedtls_ecp_point_write_binary(&x25519_grp, &ecp_dec_res_pt,
MBEDTLS_ECP_PF_UNCOMPRESSED, &ecp_plaintext_len, MBEDTLS_ECP_PF_UNCOMPRESSED, &ecp_plaintext_len,
ecp_plaintext_buf, sizeof(ecp_plaintext_buf)); ecp_plaintext_buf, sizeof(ecp_plaintext_buf)) );
/* /*
printf("x25519: key_material: "); printf("x25519: key_material: ");
@ -318,39 +316,28 @@ enum ca_error parse_stanza_x25519(struct ca_keystore *ks, size_t nargs, const ch
printf("\n"); printf("\n");
*/ */
if (mbedtls_rc) {
LOG_PRINTF("Error: mbedtls_ecp_point_write_binary: rc=-0x%x\n", -mbedtls_rc);
err = CA_ERR_MBEDTLS_ERROR;
goto err_free_dec;
}
if (ecp_plaintext_len != 32) { if (ecp_plaintext_len != 32) {
LOG_PRINTF("Error: parse_stanza_x25519: (ecp_plaintext_len == %d) != 32 (bug, should not happen!)\n", ecp_plaintext_len); LOG_PRINTF("Error: parse_stanza_x25519: (ecp_plaintext_len == %d) != 32 (bug, should not happen!)\n", ecp_plaintext_len);
err = CA_ERR_CORRUPTED_STATE; err = CA_ERR_CORRUPTED_STATE;
goto err_free_dec; goto cleanup;
} }
const mbedtls_md_info_t *sha256_md = mbedtls_md_info_from_type(MBEDTLS_MD_SHA256); const mbedtls_md_info_t *sha256_md = mbedtls_md_info_from_type(MBEDTLS_MD_SHA256);
if (!sha256_md) { if (!sha256_md) {
LOG_PRINTF("Error: mbedtls_md_info_from_type: cannot load SHA256\n"); LOG_PRINTF("Error: mbedtls_md_info_from_type: cannot load SHA256\n");
err = CA_ERR_MBEDTLS_ERROR; err = CA_ERR_MBEDTLS_ERROR;
goto err_free_dec; goto cleanup;
} }
unsigned char salt[64]; unsigned char salt[64];
memcpy(salt, ecp_ciphertext, 32); memcpy(salt, ecp_ciphertext, 32);
size_t pbin_olen = 0; size_t pbin_olen = 0;
mbedtls_rc = mbedtls_ecp_point_write_binary(&x25519_grp, &(ks->x25519_kp.Q), MBEDTLS_CHECK( mbedtls_ecp_point_write_binary(&x25519_grp, &(ks->x25519_kp.Q),
MBEDTLS_ECP_PF_UNCOMPRESSED, &pbin_olen, salt+32, 32); MBEDTLS_ECP_PF_UNCOMPRESSED, &pbin_olen, salt+32, 32) );
if (mbedtls_rc) {
LOG_PRINTF("Error: mbedtls_ecp_point_write_binary: rc=-0x%x\n", -mbedtls_rc);
err = CA_ERR_MBEDTLS_ERROR;
goto err_free_dec;
}
if (pbin_olen != 32) { if (pbin_olen != 32) {
LOG_PRINTF("Error: mbedtls_ecp_point_write_binary returned invalid output len: %d != 32\n", pbin_olen); LOG_PRINTF("Error: mbedtls_ecp_point_write_binary returned invalid output len: %d != 32\n", pbin_olen);
err = CA_ERR_CORRUPTED_STATE; err = CA_ERR_CORRUPTED_STATE;
goto err_free_dec; goto cleanup;
} }
/* /*
@ -363,14 +350,10 @@ enum ca_error parse_stanza_x25519(struct ca_keystore *ks, size_t nargs, const ch
const char *info_str = "age-encryption.org/v1/X25519"; const char *info_str = "age-encryption.org/v1/X25519";
unsigned char wrap_key[32]; unsigned char wrap_key[32];
mbedtls_rc = mbedtls_hkdf(sha256_md, salt, sizeof(salt), MBEDTLS_CHECK( mbedtls_hkdf(sha256_md, salt, sizeof(salt),
ecp_plaintext_buf, sizeof(ecp_plaintext_buf), ecp_plaintext_buf, sizeof(ecp_plaintext_buf),
(const unsigned char *)info_str, strlen(info_str), (const unsigned char *)info_str, strlen(info_str),
wrap_key, sizeof(wrap_key)); wrap_key, sizeof(wrap_key)) );
if (mbedtls_rc) {
LOG_PRINTF("Error: mbedtls_hkdf: rc=-0x%x\n", -mbedtls_rc);
return CA_ERR_MBEDTLS_ERROR;
}
/* /*
printf("x25519: key: "); printf("x25519: key: ");
@ -380,40 +363,24 @@ enum ca_error parse_stanza_x25519(struct ca_keystore *ks, size_t nargs, const ch
printf("\n"); printf("\n");
*/ */
mbedtls_chachapoly_context cp_ctx; MBEDTLS_CHECK( mbedtls_chachapoly_setkey(&cp_ctx, wrap_key) );
mbedtls_chachapoly_init(&cp_ctx);
mbedtls_rc = mbedtls_chachapoly_setkey(&cp_ctx, wrap_key);
if (mbedtls_rc) {
LOG_PRINTF("Error: mbedtls_chachapoly_setkey: rc=-0x%x\n", -mbedtls_rc);
err = CA_ERR_MBEDTLS_ERROR;
goto err_free_cp;
}
const unsigned char nonce[12] = { 0 }; const unsigned char nonce[12] = { 0 };
mbedtls_rc = mbedtls_chachapoly_auth_decrypt(&cp_ctx, 16, nonce, NULL, 0, (const unsigned char*)(body + body_len - 16), body, file_key); MBEDTLS_CHECK( mbedtls_chachapoly_auth_decrypt(&cp_ctx, 16, nonce,
if (mbedtls_rc) { NULL, 0, (const unsigned char*)(body + body_len - 16), body, file_key) );
LOG_PRINTF("Error: mbedtls_chachapoly_auth_decrypt: rc=-0x%x\n", -mbedtls_rc);
err = CA_ERR_MBEDTLS_ERROR;
goto err_free_cp;
}
err = CA_ERR_SUCCESS; err = CA_ERR_SUCCESS;
err_free_cp: cleanup:
mbedtls_chachapoly_free(&cp_ctx); mbedtls_chachapoly_free(&cp_ctx);
err_free_dec:
mbedtls_ecp_point_free(&ecp_dec_res_pt); mbedtls_ecp_point_free(&ecp_dec_res_pt);
err_free_grp:
mbedtls_ecp_group_free(&x25519_grp); mbedtls_ecp_group_free(&x25519_grp);
mbedtls_ecp_point_free(&ecp_ciphertext_pt); mbedtls_ecp_point_free(&ecp_ciphertext_pt);
return err; return err;
} }
enum ca_error check_file_key(const unsigned char *buf, size_t buflen, const unsigned char file_key[16]) { enum ca_error check_file_key(const unsigned char *buf, size_t buflen, const unsigned char file_key[16]) {
int mbedtls_rc; enum ca_error err = CA_ERR_CORRUPTED_STATE;
const mbedtls_md_info_t *sha256_md = mbedtls_md_info_from_type(MBEDTLS_MD_SHA256); const mbedtls_md_info_t *sha256_md = mbedtls_md_info_from_type(MBEDTLS_MD_SHA256);
if (!sha256_md) { if (!sha256_md) {
@ -430,23 +397,15 @@ enum ca_error check_file_key(const unsigned char *buf, size_t buflen, const unsi
size_t header_len = found - (const char *)buf; size_t header_len = found - (const char *)buf;
unsigned char check_value[32]; unsigned char check_value[32];
mbedtls_rc = mbedtls_hkdf(sha256_md, (const unsigned char *)"", 0, MBEDTLS_CHECK( mbedtls_hkdf(sha256_md, (const unsigned char *)"", 0,
file_key, 16, file_key, 16,
(const unsigned char *)"header", strlen("header"), (const unsigned char *)"header", strlen("header"),
check_value, sizeof(check_value)); check_value, sizeof(check_value)) );
if (mbedtls_rc) {
LOG_PRINTF("Error: mbedtls_hkdf: rc=-0x%x\n", -mbedtls_rc);
return CA_ERR_MBEDTLS_ERROR;
}
unsigned char hmac_calculated[32]; unsigned char hmac_calculated[32];
mbedtls_rc = mbedtls_md_hmac(sha256_md, check_value, sizeof(check_value), MBEDTLS_CHECK( mbedtls_md_hmac(sha256_md, check_value, sizeof(check_value),
buf, header_len, buf, header_len,
hmac_calculated); hmac_calculated) );
if (mbedtls_rc) {
LOG_PRINTF("Error: mbedtls_md_hmac: rc=-0x%x\n", -mbedtls_rc);
return CA_ERR_MBEDTLS_ERROR;
}
unsigned char mac[32]; unsigned char mac[32];
size_t mac_osize = 0; size_t mac_osize = 0;
@ -465,7 +424,10 @@ enum ca_error check_file_key(const unsigned char *buf, size_t buflen, const unsi
return CA_ERR_MAC_MISMATCH; return CA_ERR_MAC_MISMATCH;
} }
return CA_ERR_SUCCESS; err = CA_ERR_SUCCESS;
cleanup:
return err;
} }
enum ca_error stream_decrypt(unsigned char *out, size_t outlen, size_t *out_written, const unsigned char *in, size_t inlen, const unsigned char file_key[16]) { enum ca_error stream_decrypt(unsigned char *out, size_t outlen, size_t *out_written, const unsigned char *in, size_t inlen, const unsigned char file_key[16]) {
@ -501,6 +463,9 @@ enum ca_error stream_decrypt(unsigned char *out, size_t outlen, size_t *out_writ
return CA_ERR_NOT_ENOUGH_SPACE; return CA_ERR_NOT_ENOUGH_SPACE;
} }
mbedtls_chachapoly_context cp_ctx;
mbedtls_chachapoly_init(&cp_ctx);
/* /*
printf("file key: "); printf("file key: ");
for (size_t i=0; i<16; i++) { for (size_t i=0; i<16; i++) {
@ -511,7 +476,7 @@ enum ca_error stream_decrypt(unsigned char *out, size_t outlen, size_t *out_writ
const mbedtls_md_info_t *sha256_md = mbedtls_md_info_from_type(MBEDTLS_MD_SHA256); const mbedtls_md_info_t *sha256_md = mbedtls_md_info_from_type(MBEDTLS_MD_SHA256);
if (!sha256_md) { if (!sha256_md) {
LOG_PRINTF("Error: mbedtls_md_info_from_type: cannot load SHA256\n"); LOG_PRINTF("Error: mbedtls_md_info_from_type: cannot load SHA256 MD info\n");
return CA_ERR_MBEDTLS_ERROR; return CA_ERR_MBEDTLS_ERROR;
} }
@ -524,14 +489,10 @@ enum ca_error stream_decrypt(unsigned char *out, size_t outlen, size_t *out_writ
*/ */
unsigned char stream_key[32]; unsigned char stream_key[32];
int mbedtls_rc = mbedtls_hkdf(sha256_md, in, 16, MBEDTLS_CHECK( mbedtls_hkdf(sha256_md, in, 16,
file_key, 16, file_key, 16,
(const unsigned char *)"payload", strlen("payload"), (const unsigned char *)"payload", strlen("payload"),
stream_key, sizeof(stream_key)); stream_key, sizeof(stream_key)) );
if (!sha256_md) {
LOG_PRINTF("Error: mbedtls_md_info_from_type: cannot load SHA256\n");
return CA_ERR_MBEDTLS_ERROR;
}
/* /*
printf("stream key: "); printf("stream key: ");
@ -541,14 +502,7 @@ enum ca_error stream_decrypt(unsigned char *out, size_t outlen, size_t *out_writ
printf("\n"); printf("\n");
*/ */
mbedtls_chachapoly_context cp_ctx; MBEDTLS_CHECK( mbedtls_chachapoly_setkey(&cp_ctx, stream_key) );
mbedtls_chachapoly_init(&cp_ctx);
mbedtls_rc = mbedtls_chachapoly_setkey(&cp_ctx, stream_key);
if (mbedtls_rc) {
LOG_PRINTF("Error: mbedtls_chachapoly_setkey: rc=-0x%x\n", -mbedtls_rc);
err = CA_ERR_MBEDTLS_ERROR;
goto err_free_cp;
}
in += 16; in += 16;
size_t block_num = 0; size_t block_num = 0;
@ -578,13 +532,10 @@ enum ca_error stream_decrypt(unsigned char *out, size_t outlen, size_t *out_writ
LOG_PRINTF("inlen=%zu block_len=%zu inp=%p@%zu outp=%p@%zu data_len=%zu tag=%p\n", LOG_PRINTF("inlen=%zu block_len=%zu inp=%p@%zu outp=%p@%zu data_len=%zu tag=%p\n",
inlen, block_len, inp, i, outp, block_num*out_blocksize, data_len, tag); inlen, block_len, inp, i, outp, block_num*out_blocksize, data_len, tag);
*/ */
mbedtls_rc = mbedtls_chachapoly_auth_decrypt(&cp_ctx, MBEDTLS_CHECK_MSG( mbedtls_chachapoly_auth_decrypt(&cp_ctx,
data_len, (unsigned char *)&nonce, NULL, 0, tag, inp, outp); data_len, (unsigned char *)&nonce, NULL, 0, tag, inp, outp),
if (mbedtls_rc) { CA_ERR_MBEDTLS_ERROR,
LOG_PRINTF("Error: mbedtls_chachapoly_auth_decrypt: i=%zx rc=-0x%x\n", i, -mbedtls_rc); "i=%zx", i );
err = CA_ERR_MBEDTLS_ERROR;
goto err_free_cp;
}
*out_written += data_len; *out_written += data_len;
block_num += 1; block_num += 1;
@ -592,7 +543,7 @@ enum ca_error stream_decrypt(unsigned char *out, size_t outlen, size_t *out_writ
err = CA_ERR_SUCCESS; err = CA_ERR_SUCCESS;
err_free_cp: cleanup:
mbedtls_chachapoly_free(&cp_ctx); mbedtls_chachapoly_free(&cp_ctx);
return err; return err;