diff --git a/examples/rsa-decrypt.c b/examples/rsa-decrypt.c index 10c63dbe33b04b2701e3aa0ebd10dba8e192b67a..8dfd38f9594b1649fc979befebc1e274f3f46b12 100644 --- a/examples/rsa-decrypt.c +++ b/examples/rsa-decrypt.c @@ -103,56 +103,83 @@ struct process_ctx struct yarrow256_ctx yarrow; }; +#define BUF_SIZE (100 * AES_BLOCK_SIZE) + +/* Trailing data that needs special processing */ +#define BUF_FINAL (AES_BLOCK_SIZE + SHA1_DIGEST_SIZE) + static int process_file(struct rsa_session *ctx, FILE *in, FILE *out) { - uint8_t buffer[AES_BLOCK_SIZE * 100]; - unsigned leftover; + uint8_t buffer[BUF_SIZE + BUF_FINAL]; + uint8_t digest[SHA1_DIGEST_SIZE]; + size_t size; unsigned padding; - /* FIXME: Cut'n'paste code, not working yet */ - abort(); - for (padding = leftover = 0; padding == 0;) + size = fread(buffer, 1, BUF_FINAL, in); + if (size < BUF_FINAL || ferror(in)) + { + werror("Reading input failed: %s\n", strerror(errno)); + return 0; + } + + do { - size_t size = fread(buffer, 1, sizeof(buffer), in); + size = fread(buffer + BUF_FINAL, 1, BUF_SIZE, in); + if (ferror(in)) { werror("Reading input failed: %s\n", strerror(errno)); return 0; } - hmac_sha1_update(&ctx->hmac, size, buffer); - if (size < sizeof(buffer)) + if (size % AES_BLOCK_SIZE != 0) { - /* Setting padding != ends the loop */ - leftover = size % AES_BLOCK_SIZE; - padding = AES_BLOCK_SIZE - leftover; - size -= leftover; + werror("Unexpected EOF on input.\n"); + return 0; + } - if (!size) - break; + if (size) + { + CBC_DECRYPT(&ctx->aes, aes_decrypt, size, buffer, buffer); + hmac_sha1_update(&ctx->hmac, size, buffer); + if (!write_string(out, size, buffer)) + { + werror("Writing output failed: %s\n", strerror(errno)); + return 0; + } + memmove(buffer, buffer + size, BUF_FINAL); } + } + while (size == BUF_SIZE); - CBC_DECRYPT(&ctx->aes, aes_encrypt, size, buffer, buffer); - if (!write_string(out, size, buffer)) + /* Decrypt final block */ + CBC_DECRYPT(&ctx->aes, aes_decrypt, AES_BLOCK_SIZE, buffer, buffer); + padding = buffer[AES_BLOCK_SIZE - 1]; + if (padding > AES_BLOCK_SIZE) + { + werror("Decryption failed: Invalid padding.\n"); + return 0; + } + + if (padding < AES_BLOCK_SIZE) + { + unsigned leftover = AES_BLOCK_SIZE - padding; + hmac_sha1_update(&ctx->hmac, leftover, buffer); + if (!write_string(out, leftover, buffer)) { werror("Writing output failed: %s\n", strerror(errno)); return 0; } } - if (padding > 1) - yarrow256_random(&ctx->yarrow, padding - 1, buffer + leftover); - - buffer[AES_BLOCK_SIZE - 1] = padding; - CBC_ENCRYPT(&ctx->aes, aes_encrypt, AES_BLOCK_SIZE, buffer, buffer); - hmac_sha1_digest(&ctx->hmac, SHA1_DIGEST_SIZE, buffer + AES_BLOCK_SIZE); - if (!write_string(out, AES_BLOCK_SIZE + SHA1_DIGEST_SIZE, buffer)) + hmac_sha1_digest(&ctx->hmac, SHA1_DIGEST_SIZE, digest); + if (memcmp(digest, buffer + AES_BLOCK_SIZE, SHA1_DIGEST_SIZE) != 0) { - werror("Writing output failed: %s\n", strerror(errno)); + werror("Decryption failed: Invalid mac.\n"); return 0; } - + return 1; } @@ -165,6 +192,8 @@ main(int argc, char **argv) unsigned length; mpz_t x; + + mpz_init(x); if (argc != 2) { @@ -193,12 +222,13 @@ main(int argc, char **argv) } length = sizeof(session.key); - if (!rsa_decrypt(&key, &length, session.key, x)) + if (!rsa_decrypt(&key, &length, session.key, x) || length != sizeof(session.key)) { werror("Failed to decrypt rsa header in input file.\n"); return EXIT_FAILURE; } - + mpz_clear(x); + rsa_session_set_decrypt_key(&ctx, &session); if (!process_file(&ctx,