123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279 |
- #include <assert.h>
- #include <stddef.h>
- #include <openssl/bn.h>
- #include <openssl/crypto.h>
- #include <openssl/err.h>
- #include <openssl/evp.h>
- #include <openssl/opensslv.h>
- #include <openssl/rsa.h>
- #include "warnp.h"
- #include "crypto_compat.h"
- #ifndef OPENSSL_VERSION_NUMBER
- #error "OPENSSL_VERSION_NUMBER must be defined"
- #endif
- /* LibreSSL compatibility. */
- #ifdef LIBRESSL_VERSION_NUMBER
- /* LibreSSL claims to be OpenSSL 2.0; ignore that. */
- #undef OPENSSL_VERSION_NUMBER
- #if LIBRESSL_VERSION_NUMBER >= 0x2070000fL
- /* Compatibility for LibreSSL 2.7.0+: pretend to be OpenSSL 1.1.0. */
- #define OPENSSL_VERSION_NUMBER 0x1010000fL
- #else
- /* Compatibility for LibreSSL before 2.7.0: pretend to be OpenSSL 1.0.1g. */
- #define OPENSSL_VERSION_NUMBER 0x1000107fL
- #endif
- #endif /* LIBRESSL_VERSION_NUMBER */
- /**
- * crypto_compat_RSA_valid_size(key):
- * Return nonzero if ${key} has a valid size, and zero for an invalid size.
- */
- int
- crypto_compat_RSA_valid_size(const RSA * const key)
- {
- /* Sanity checks. */
- assert(key != NULL);
- #if OPENSSL_VERSION_NUMBER < 0x10100000L
- assert(key->n != NULL);
- return ((RSA_size(key) == 256) && (BN_num_bits(key->n) == 2048));
- #else
- return ((RSA_size(key) == 256) && (RSA_bits(key) == 2048));
- #endif
- }
- /**
- * crypto_compat_RSA_import(key, n, e, d, p, q, dmp1, dmq1, iqmp):
- * Import the given BIGNUMs into the RSA ${key}. If this function fails,
- * free any any BIGNUMs which have not been imported into the ${key}, but do
- * not free the ${key} itself.
- */
- int
- crypto_compat_RSA_import(RSA * key, BIGNUM * n, BIGNUM * e, BIGNUM * d,
- BIGNUM * p, BIGNUM * q, BIGNUM * dmp1, BIGNUM * dmq1, BIGNUM * iqmp)
- {
- /* Sanity checks. */
- assert(key != NULL);
- assert((n != NULL) && (e != NULL));
- /* All the private-key-related variables are NULL, or they're not. */
- if (d == NULL) {
- assert((p == NULL) && (q == NULL) && (dmp1 == NULL)
- && (dmq1 == NULL) && (iqmp == NULL));
- } else {
- assert((p != NULL) && (q != NULL) && (dmp1 != NULL)
- && (dmq1 != NULL) && (iqmp != NULL));
- }
- /* Put values into RSA key. */
- #if OPENSSL_VERSION_NUMBER < 0x10100000L
- key->n = n;
- key->e = e;
- if (d != NULL) {
- /* Private key. */
- key->d = d;
- key->p = p;
- key->q = q;
- key->dmp1 = dmp1;
- key->dmq1 = dmq1;
- key->iqmp = iqmp;
- }
- #else
- /* Do we have a public key, or private key? */
- if (d == NULL) {
- /* We could use d here, but using NULL makes it more clear. */
- if (RSA_set0_key(key, n, e, NULL) != 1)
- goto err3;
- } else {
- /* Private key. */
- if (RSA_set0_key(key, n, e, d) != 1)
- goto err3;
- if (RSA_set0_factors(key, p, q) != 1)
- goto err2;
- if (RSA_set0_crt_params(key, dmp1, dmq1, iqmp) != 1)
- goto err1;
- }
- #endif
- /* Success! */
- return (0);
- #if OPENSSL_VERSION_NUMBER < 0x10100000L
- #else
- err3:
- BN_free(n);
- BN_free(e);
- BN_clear_free(d);
- err2:
- BN_clear_free(p);
- BN_clear_free(q);
- err1:
- BN_clear_free(dmp1);
- BN_clear_free(dmq1);
- BN_clear_free(iqmp);
- /* Failure! */
- return (-1);
- #endif
- }
- /**
- * crypto_compat_RSA_export(key, n, e, d, p, q, dmp1, dmq1, iqmp):
- * Export values from the given RSA ${key} into the BIGNUMs. ${n} and ${e}
- * must be non-NULL; the other values may be NULL if desired, and will
- * therefore not be exported.
- */
- int
- crypto_compat_RSA_export(RSA * key, const BIGNUM ** n, const BIGNUM ** e,
- const BIGNUM ** d, const BIGNUM ** p, const BIGNUM ** q,
- const BIGNUM ** dmp1, const BIGNUM ** dmq1, const BIGNUM ** iqmp)
- {
- /* Sanity checks. */
- assert(key != NULL);
- assert((n != NULL) && (e != NULL));
- /* All the private-key-related variables are NULL, or they're not. */
- if (d == NULL) {
- assert((p == NULL) && (q == NULL) && (dmp1 == NULL)
- && (dmq1 == NULL) && (iqmp == NULL));
- } else {
- assert((p != NULL) && (q != NULL) && (dmp1 != NULL)
- && (dmq1 != NULL) && (iqmp != NULL));
- }
- /* Get values from RSA key. */
- #if OPENSSL_VERSION_NUMBER < 0x10100000L
- *n = key->n;
- *e = key->e;
- if (d != NULL) {
- /* Private key. */
- *d = key->d;
- *p = key->p;
- *q = key->q;
- *dmp1 = key->dmp1;
- *dmq1 = key->dmq1;
- *iqmp = key->iqmp;
- }
- #else
- /* Do we have a public key, or private key? */
- if (d == NULL) {
- /* We could use d here, but using NULL makes it more clear. */
- RSA_get0_key(key, n, e, NULL);
- } else {
- /* Private key. */
- RSA_get0_key(key, n, e, d);
- RSA_get0_factors(key, p, q);
- RSA_get0_crt_params(key, dmp1, dmq1, iqmp);
- }
- #endif
- /* Success! */
- return (0);
- }
- /**
- * crypto_compat_RSA_generate_key(void):
- * Generate a key pair.
- */
- RSA *
- crypto_compat_RSA_generate_key(void)
- {
- RSA * key;
- #if OPENSSL_VERSION_NUMBER < 0x00908000L
- /* Generate key. */
- if ((key = RSA_generate_key(2048, 65537, NULL, NULL)) == NULL) {
- warn0("%s", ERR_error_string(ERR_get_error(), NULL));
- goto err0;
- }
- /* Success! */
- return (key);
- #else
- BIGNUM * e;
- /* Set up parameter. */
- if ((e = BN_new()) == NULL) {
- warn0("%s", ERR_error_string(ERR_get_error(), NULL));
- goto err0;
- }
- BN_set_word(e, 65537);
- /* Generate key. */
- if ((key = RSA_new()) == NULL) {
- warn0("%s", ERR_error_string(ERR_get_error(), NULL));
- goto err1;
- }
- if (RSA_generate_key_ex(key, 2048, e, NULL) != 1) {
- warn0("%s", ERR_error_string(ERR_get_error(), NULL));
- goto err2;
- }
- /* Clean up. */
- BN_free(e);
- /* Success! */
- return (key);
- err2:
- RSA_free(key);
- err1:
- BN_free(e);
- #endif
- err0:
- /* Failure! */
- return (NULL);
- }
- /**
- * crypto_compat_free(void):
- * Free the shared memory allocated by OpenSSL.
- */
- void
- crypto_compat_free(void)
- {
- #if !defined(LIBRESSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER > 0x1010000fL
- /* OpenSSL 1.1.0 and higher: do nothing; the library uses atexit(). */
- #elif defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER > 0x3070100fL
- /* LibreSSL 3.7.1 and higher. */
- OPENSSL_cleanup();
- #elif defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER > 0x3060000fL
- /* LibreSSL 3.6.0 to 3.7.0. */
- OPENSSL_cleanup();
- CRYPTO_cleanup_all_ex_data();
- #else
- /* Earlier versions of OpenSSL and LibreSSL. */
- /* Free OpenSSL error queue. */
- #if OPENSSL_VERSION_NUMBER < 0x10000000L
- ERR_remove_state(0);
- #elif OPENSSL_VERSION_NUMBER < 0x10100000L
- ERR_remove_thread_state(NULL);
- #endif
- /* Free OpenSSL error strings. */
- ERR_free_strings();
- #if LIBRESSL_VERSION_NUMBER >= 0x2070000fL
- /* Additional cleaning needed for LibreSSL 2.7.0 to 3.5.x. */
- EVP_cleanup();
- #endif
- /* A more general OpenSSL cleanup function. */
- CRYPTO_cleanup_all_ex_data();
- #endif
- }
|