diff --git a/sbin/dumpon/dumpon.c b/sbin/dumpon/dumpon.c --- a/sbin/dumpon/dumpon.c +++ b/sbin/dumpon/dumpon.c @@ -76,10 +76,10 @@ #include #ifdef HAVE_CRYPTO +#include #include #include #include -#include #endif static int verbose; @@ -229,50 +229,52 @@ } #ifdef HAVE_CRYPTO + +#define KERNELDUMP_RSA_ENCKEY_MIN_SIZE 256 + static void _genkey(const char *pubkeyfile, struct diocskerneldump_arg *kdap) { + EVP_PKEY_CTX *pubkey_ctx; + EVP_PKEY *pubkey; FILE *fp; - RSA *pubkey; assert(pubkeyfile != NULL); assert(kdap != NULL); fp = NULL; pubkey = NULL; + pubkey_ctx = NULL; fp = fopen(pubkeyfile, "r"); if (fp == NULL) err(1, "Unable to open %s", pubkeyfile); - /* - * Obsolescent OpenSSL only knows about /dev/random, and needs to - * pre-seed before entering cap mode. For whatever reason, - * RSA_pub_encrypt uses the internal PRNG. - */ -#if OPENSSL_VERSION_NUMBER < 0x10100000L - { - unsigned char c[1]; - RAND_bytes(c, 1); - } -#endif - if (caph_enter() < 0) err(1, "Unable to enter capability mode"); - pubkey = RSA_new(); + pubkey = EVP_PKEY_new(); if (pubkey == NULL) { errx(1, "Unable to allocate an RSA structure: %s", ERR_error_string(ERR_get_error(), NULL)); } - pubkey = PEM_read_RSA_PUBKEY(fp, &pubkey, NULL, NULL); + pubkey = PEM_read_PUBKEY(fp, &pubkey, NULL, NULL); fclose(fp); fp = NULL; if (pubkey == NULL) errx(1, "Unable to read data from %s: %s", pubkeyfile, ERR_error_string(ERR_get_error(), NULL)); + pubkey_ctx = EVP_PKEY_CTX_new(pubkey, NULL); + if (pubkey_ctx == NULL) + errx(1, "Unable to allocate an public key context structure: %s", + ERR_error_string(ERR_get_error(), NULL)); + + if (EVP_PKEY_encrypt_init(pubkey_ctx) <= 0) + errx(1, "EVP_PKEY_encrypt_init failed: %s", + ERR_error_string(ERR_get_error(), NULL)); + /* * RSA keys under ~1024 bits are trivially factorable (2018). OpenSSL * provides an API for RSA keys to estimate the symmetric-cipher @@ -288,18 +290,16 @@ * of 'd' (i.e., the supplied key is a public key rather than a full * keypair). */ -#if OPENSSL_VERSION_NUMBER >= 0x10100000L - if (RSA_security_bits(pubkey) < 112) -#else - if (RSA_size(pubkey) * 8 < 2048) -#endif - errx(1, "Small RSA keys (you provided: %db) can be " - "factored cheaply. Please generate a larger key.", - RSA_size(pubkey) * 8); - - kdap->kda_encryptedkeysize = RSA_size(pubkey); + if (EVP_PKEY_security_bits(pubkey) < KERNELDUMP_RSA_ENCKEY_MIN_SIZE) + errx(1, "Small RSA keys can be factored cheaply. " + "Please generate a key larger than %d (a %d bit key was " + "provided).", + KERNELDUMP_RSA_ENCKEY_MIN_SIZE, + EVP_PKEY_security_bits(pubkey)); + + kdap->kda_encryptedkeysize = EVP_PKEY_size(pubkey); if (kdap->kda_encryptedkeysize > KERNELDUMP_ENCKEY_MAX_SIZE) { - errx(1, "Public key has to be at most %db long.", + errx(1, "Public key must be %d bits or less.", 8 * KERNELDUMP_ENCKEY_MAX_SIZE); } @@ -318,13 +318,25 @@ "with compression."); arc4random_buf(kdap->kda_key, sizeof(kdap->kda_key)); - if (RSA_public_encrypt(sizeof(kdap->kda_key), kdap->kda_key, - kdap->kda_encryptedkey, pubkey, - RSA_PKCS1_OAEP_PADDING) != (int)kdap->kda_encryptedkeysize) { + + if (EVP_PKEY_CTX_set_rsa_padding(pubkey_ctx, + RSA_PKCS1_OAEP_PADDING) <= 0) { + errx(1, "Could not set encryption padding: %s", + ERR_error_string(ERR_get_error(), NULL)); + } + /* + * NOTE: this uses an intermediate variable (`outlen`) to avoid + * -Wcast-align complaints. + */ + size_t outlen = kdap->kda_encryptedkeysize; + if (EVP_PKEY_encrypt(pubkey_ctx, kdap->kda_encryptedkey, &outlen, + kdap->kda_key, sizeof(kdap->kda_key)) < 0) { errx(1, "Unable to encrypt the one-time key: %s", ERR_error_string(ERR_get_error(), NULL)); } - RSA_free(pubkey); + + EVP_PKEY_free(pubkey); + EVP_PKEY_CTX_free(pubkey_ctx); } /*