From 4bf552c1e35782d4ff1e174aea24d547a25387f3 Mon Sep 17 00:00:00 2001 From: Aveen Ismail Date: Tue, 3 Sep 2024 16:22:37 +0200 Subject: [PATCH] Handle errors when signing SSH certificates --- common/util.c | 40 +++++++++++++++++++++++++++++++--------- examples/ssh.c | 6 +++--- src/commands.c | 42 ++++++++++++++++++++++++++++++------------ 3 files changed, 64 insertions(+), 24 deletions(-) diff --git a/common/util.c b/common/util.c index ac43385b8..e63d74768 100644 --- a/common/util.c +++ b/common/util.c @@ -91,8 +91,14 @@ bool read_ed25519_key(uint8_t *in, size_t in_len, uint8_t *out, BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL); BIO_push(b64, bio); - (void) BIO_write(bio, in + 28, in_len - 28 - 25); - (void) BIO_flush(bio); + if (BIO_write(bio, in + 28, in_len - 28 - 25) <= 0) { + BIO_free_all(b64); + return false; + } + if(BIO_flush(bio) != 1) { + BIO_free_all(b64); + return false; + } ret = BIO_read(b64, decoded, decoded_len); BIO_free_all(b64); @@ -167,7 +173,9 @@ bool read_private_key(uint8_t *buf, size_t len, yh_algorithm *algo, return false; } - (void) BIO_write(bio, buf, len); + if(BIO_write(bio, buf, len) <= 0) { + return false; + } private_key = PEM_read_bio_PrivateKey(bio, NULL, NULL, /*password*/ NULL); BIO_free_all(bio); @@ -372,7 +380,9 @@ bool read_public_key(uint8_t *buf, size_t len, yh_algorithm *algo, return false; } - (void) BIO_write(bio, buf, len); + if(BIO_write(bio, buf, len) <= 0) { + return false; + } EVP_PKEY *pubkey = PEM_read_bio_PUBKEY(bio, NULL, NULL, NULL); BIO_free_all(bio); @@ -639,8 +649,14 @@ bool base64_decode(const char *in, uint8_t *out, size_t *len) { BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL); BIO_push(b64, bio); - (void) BIO_write(bio, in, strlen(in)); - (void) BIO_flush(bio); + if(BIO_write(bio, in, strlen(in)) <= 0) { + BIO_free_all(b64); + return false; + } + if(BIO_flush(bio) != 1) { + BIO_free_all(b64); + return false; + } ret = BIO_read(b64, out, *len); BIO_free_all(b64); @@ -677,9 +693,15 @@ bool write_file(const uint8_t *buf, size_t buf_len, FILE *fp, format_t format) { bio = BIO_push(b64, bio); (void) BIO_set_flags(bio, BIO_FLAGS_BASE64_NO_NL); - (void) BIO_write(bio, buf, buf_len); - (void) BIO_flush(bio); - (void) BIO_get_mem_ptr(bio, &bufferPtr); + if(BIO_write(bio, buf, buf_len) <= 0) { + return false; + } + if(BIO_flush(bio) != 1) { + return false; + } + if(BIO_get_mem_ptr(bio, &bufferPtr) != 1) { + return false; + } p = (uint8_t *) bufferPtr->data; length = bufferPtr->length; } else if (format == _hex) { diff --git a/examples/ssh.c b/examples/ssh.c index 8abb9c1f4..015312d13 100644 --- a/examples/ssh.c +++ b/examples/ssh.c @@ -281,9 +281,9 @@ int main(void) { fprintf(stdout, "ssh-rsa-cert-v01@openssh.com "); (void) BIO_set_flags(bio, BIO_FLAGS_BASE64_NO_NL); - (void) BIO_write(bio, ssh_req + 4 + 256, - ssh_req_len + ssh_cert_len - 4 - 256); - (void) BIO_flush(bio); + assert(BIO_write(bio, ssh_req + 4 + 256, + ssh_req_len + ssh_cert_len - 4 - 256) > 0); + assert(BIO_flush(bio) == 1); fprintf(stdout, "\n"); BIO_free_all(bio); diff --git a/src/commands.c b/src/commands.c index dacc03cdd..df3bf3f17 100644 --- a/src/commands.c +++ b/src/commands.c @@ -2452,7 +2452,10 @@ static bool read_rsa_pubkey(const uint8_t *buf, size_t len, if ((bio = BIO_new(BIO_s_mem())) == NULL) return false; - (void) BIO_write(bio, buf, len); + if(BIO_write(bio, buf, len) <= 0) { + fprintf(stderr, "%s: Failed to read RSA public key\n", __func__); + return false; + } RSA *rsa = NULL; EVP_PKEY *pubkey = PEM_read_bio_PUBKEY(bio, NULL, NULL, NULL); @@ -3082,6 +3085,7 @@ int yh_com_sign_ssh_certificate(yubihsm_context *ctx, Argument *argv, uint8_t data[YH_MSG_BUF_SIZE + 1024] = {0}; size_t response_len = sizeof(data); + size_t in_len = 4 + 256; // 4 bytes time stamp + 256 bytes signature if (argv[4].len > YH_MSG_BUF_SIZE) { fprintf(stderr, "Failed to sign ssh certificate: %s\n", @@ -3095,7 +3099,7 @@ int yh_com_sign_ssh_certificate(yubihsm_context *ctx, Argument *argv, yh_rc yrc = yh_util_sign_ssh_certificate(argv[0].e, argv[1].w, argv[2].w, argv[3].a, data, argv[4].len, data + argv[4].len, &response_len); - if (yrc != YHR_SUCCESS) { + if (yrc != YHR_SUCCESS || response_len <= 0) { fprintf(stderr, "Failed to get certificate signature: %s\n", yh_strerror(yrc)); return -1; @@ -3116,12 +3120,23 @@ int yh_com_sign_ssh_certificate(yubihsm_context *ctx, Argument *argv, BUF_MEM *bufferPtr = 0; + int ret = 0; (void) BIO_set_flags(bio, BIO_FLAGS_BASE64_NO_NL); - (void) BIO_write(bio, data + 4 + 256, - argv[4].len + response_len - 4 - - 256); // TODO(adma): FIXME, unmagify - (void) BIO_flush(bio); - (void) BIO_get_mem_ptr(bio, &bufferPtr); + if (BIO_write(bio, data + in_len, argv[4].len + response_len - in_len) <= 0) { + fprintf(stderr, "Failed to sign SSH certificate.\n"); + ret = -1; + goto clean_bio; + } + if(BIO_flush(bio) != 1) { + fprintf(stderr, "Failed to sign SSH certificate.\n"); + ret = -1; + goto clean_bio; + } + if(BIO_get_mem_ptr(bio, &bufferPtr) != 1) { + fprintf(stderr, "Failed to sign SSH certificate.\n"); + ret = -1; + goto clean_bio; + } const char *ssh_cert_str = "ssh-rsa-cert-v01@openssh.com "; // TODO(adma): ECDSA @@ -3130,24 +3145,27 @@ int yh_com_sign_ssh_certificate(yubihsm_context *ctx, Argument *argv, strlen(ssh_cert_str) || ferror(ctx->out)) { fprintf(stderr, "Unable to write data to file\n"); - return -1; + ret = -1; + goto clean_bio; } if (fwrite(bufferPtr->data, 1, bufferPtr->length, ctx->out) != bufferPtr->length || ferror(ctx->out)) { fprintf(stderr, "Unable to write data to file\n"); - return -1; + ret = -1; + goto clean_bio; } if (fwrite("\n", 1, 1, ctx->out) != 1 || ferror(ctx->out)) { fprintf(stderr, "Unable to write data to file\n"); - return -1; + ret = -1; } - (void) BIO_free_all(bio); // TODO: fix this leak. +clean_bio: + (void) BIO_free_all(bio); - return 0; + return ret; } static void time_elapsed(struct timeval *after, struct timeval *before,