Beispiel #1
1
DH *
dh_new_group_asc(const char *gen, const char *modulus)
{
	DH *dh = NULL;
	BIGNUM *p=NULL, *g=NULL;

	if ((dh = DH_new()) == NULL ||
	    (p = BN_new()) == NULL ||
	    (g = BN_new()) == NULL)
		goto null;
	if (BN_hex2bn(&p, modulus) == 0 ||
	    BN_hex2bn(&g, gen) == 0) {
		goto null;
	}
	if (DH_set0_pqg(dh, p, NULL, g) == 0) {
		goto null;
	}
	p = g = NULL;
	return (dh);
null:
	BN_free(p);
	BN_free(g);
	DH_free(dh);
	return NULL;
}
Beispiel #2
0
tr_dh_ctx_t
tr_dh_new (const uint8_t * prime_num,
           size_t          prime_num_length,
           const uint8_t * generator_num,
           size_t          generator_num_length)
{
  DH * handle = DH_new ();
  BIGNUM * p, * g;

  assert (prime_num != NULL);
  assert (generator_num != NULL);

  p = BN_bin2bn (prime_num, prime_num_length, NULL);
  g = BN_bin2bn (generator_num, generator_num_length, NULL);

  if (!check_pointer (p) || !check_pointer (g) || !DH_set0_pqg (handle, p, NULL, g))
    {
      BN_free (p);
      BN_free (g);
      DH_free (handle);
      handle = NULL;
    }

  return handle;
}
Beispiel #3
0
   bool diffie_hellman::compute_shared_key( const char* buf, uint32_t s ) {
        ssl_dh dh = DH_new();
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
        auto bn_p = BN_bin2bn( (unsigned char*)&p.front(), p.size(), NULL );
        auto bn_pub_key = BN_bin2bn( (unsigned char*)&pub_key.front(), pub_key.size(), NULL );
        auto bn_priv_key = BN_bin2bn( (unsigned char*)&priv_key.front(), priv_key.size(), NULL );
        auto bn_g = BN_bin2bn( (unsigned char*)&g, 1, NULL );
        DH_set0_pqg(dh.obj, bn_p, NULL, bn_g);
        DH_set0_key(dh.obj, bn_pub_key, bn_priv_key);
#else
        dh->p = BN_bin2bn( (unsigned char*)&p.front(), p.size(), NULL );
        dh->pub_key = BN_bin2bn( (unsigned char*)&pub_key.front(), pub_key.size(), NULL );
        dh->priv_key = BN_bin2bn( (unsigned char*)&priv_key.front(), priv_key.size(), NULL );
        dh->g = BN_bin2bn( (unsigned char*)&g, 1, NULL );
#endif

        int check;
        DH_check(dh,&check);
        if( !fc::validate( dh, valid ) )
        {
            return false;
        }

        ssl_bignum pk;
        BN_bin2bn( (unsigned char*)buf, s, pk );
        shared_key.resize( DH_size(dh) ); 
        DH_compute_key( (unsigned char*)&shared_key.front(), pk, dh );

        return true;
   }
Beispiel #4
0
Datei: dh.c Projekt: KennethL/otp
ERL_NIF_TERM dh_compute_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{/* (OthersPublicKey, MyPrivateKey, DHParams=[P,G]) */
    BIGNUM *other_pub_key = NULL,
        *dh_p = NULL,
        *dh_g = NULL;
    DH *dh_priv = DH_new();

    /* Check the arguments and get
          my private key (dh_priv),
          the peer's public key (other_pub_key),
          the parameters p & q
    */

    {
        BIGNUM *dummy_pub_key = NULL,
               *priv_key = NULL;
        ERL_NIF_TERM head, tail;

        if (!get_bn_from_bin(env, argv[0], &other_pub_key)
            || !get_bn_from_bin(env, argv[1], &priv_key)
            || !enif_get_list_cell(env, argv[2], &head, &tail)
            || !get_bn_from_bin(env, head, &dh_p)
            || !enif_get_list_cell(env, tail, &head, &tail)
            || !get_bn_from_bin(env, head, &dh_g)
            || !enif_is_empty_list(env, tail)

            /* Note: DH_set0_key() does not allow setting only the
             * private key, although DH_compute_key() does not use the
             * public key. Work around this limitation by setting
             * the public key to a copy of the private key.
             */
            || !(dummy_pub_key = BN_dup(priv_key))
            || !DH_set0_key(dh_priv, dummy_pub_key, priv_key)
            || !DH_set0_pqg(dh_priv, dh_p, NULL, dh_g)
            ) {
            if (dh_p) BN_free(dh_p);
            if (dh_g) BN_free(dh_g);
            if (other_pub_key) BN_free(other_pub_key);
            if (dummy_pub_key) BN_free(dummy_pub_key);
            if (priv_key) BN_free(priv_key);
            return enif_make_badarg(env);
        }
    }
    {
        ErlNifBinary ret_bin;
        int size;

        enif_alloc_binary(DH_size(dh_priv), &ret_bin);
        size = DH_compute_key(ret_bin.data, other_pub_key, dh_priv);
        BN_free(other_pub_key);
        DH_free(dh_priv);
        if (size<=0) {
            enif_release_binary(&ret_bin);
            return atom_error;
        }

        if (size != ret_bin.size) enif_realloc_binary(&ret_bin, size);
        return enif_make_binary(env, &ret_bin);
    }
}
Beispiel #5
0
static int s2n_set_p_g_Ys_dh_params(struct s2n_dh_params *dh_params, struct s2n_blob *p, struct s2n_blob *g, struct s2n_blob *Ys)
{
    BIGNUM *bn_p = BN_bin2bn((const unsigned char *)p->data, p->size, NULL);
    BIGNUM *bn_g = BN_bin2bn((const unsigned char *)g->data, g->size, NULL);
    BIGNUM *bn_Ys = BN_bin2bn((const unsigned char *)Ys->data, Ys->size, NULL);

    #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined LIBRESSL_VERSION_NUMBER
        dh_params->dh->p = bn_p;
        dh_params->dh->g = bn_g;
        dh_params->dh->pub_key = bn_Ys;
    #else
        if (DH_set0_pqg(dh_params->dh, bn_p, NULL, bn_g) == 0) {
            /* Per https://www.openssl.org/docs/man1.1.0/crypto/DH_get0_pqg.html:
             * values that have been passed in should not be freed directly after this function has been called
             */
            S2N_ERROR(S2N_ERR_DH_PARAMS_CREATE);
        }

        if (DH_set0_key(dh_params->dh, bn_Ys, NULL) == 0) {
            /* Same as DH_set0_pqg */
            S2N_ERROR(S2N_ERR_DH_PARAMS_CREATE);
        }
    #endif

    return 0;
}
Beispiel #6
0
// Create the OpenSSL representation of the key
void OSSLDHPublicKey::createOSSLKey()
{
	if (dh != NULL) return;

	dh = DH_new();
	if (dh == NULL)
	{
		ERROR_MSG("Could not create DH object");
		return;
	}

	// Use the OpenSSL implementation and not any engine
#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)

#ifdef WITH_FIPS
	if (FIPS_mode())
		DH_set_method(dh, FIPS_dh_openssl());
	else
		DH_set_method(dh, DH_OpenSSL());
#else
	DH_set_method(dh, DH_OpenSSL());
#endif

#else
	DH_set_method(dh, DH_OpenSSL());
#endif

	BIGNUM* bn_p = OSSL::byteString2bn(p);
	BIGNUM* bn_g = OSSL::byteString2bn(g);
	BIGNUM* bn_pub_key = OSSL::byteString2bn(y);

	DH_set0_pqg(dh, bn_p, NULL, bn_g);
	DH_set0_key(dh, bn_pub_key, NULL);
}
Beispiel #7
0
static void setup_dh(SSL_CTX *ctx)
{
	DH *dh;
	BIGNUM *p;
	BIGNUM *g;

	dh = DH_new();
	if (dh == NULL) {
		return;
	}

	p = BN_bin2bn(dh3072_p, sizeof(dh3072_p), NULL);
	g = BN_bin2bn(dh3072_g, sizeof(dh3072_g), NULL);

	if (p == NULL || g == NULL) {
		DH_free(dh);
		return;
	}

#if (OPENSSL_VERSION_NUMBER >= 0x1010000fL)
	/* libssl >= v1.1.0 */
	DH_set0_pqg(dh, p, NULL, g);
#else
	dh->p = p;
	dh->g = g;
#endif


   SSL_CTX_set_options(ctx, SSL_OP_SINGLE_DH_USE);
   SSL_CTX_set_tmp_dh(ctx, dh);

   DH_free(dh);
}
Beispiel #8
0
static DH *
get_rfc5114_modp(int num)
{
    DH *ret = NULL;
    BIGNUM *p = NULL, *g = NULL, *q = NULL;
    int check = 0;

    ret = DH_new();
    if (!ret)
        goto err;

    switch(num) {
        case 0:
            p = BN_bin2bn(rfc_5114_modp_1_p, sizeof(rfc_5114_modp_1_p), p);
            g = BN_bin2bn(rfc_5114_modp_1_g, sizeof(rfc_5114_modp_1_g), g);
            q = BN_bin2bn(rfc_5114_modp_1_q, sizeof(rfc_5114_modp_1_q), q);
            break;
        case 1:
            p = BN_bin2bn(rfc_5114_modp_2_p, sizeof(rfc_5114_modp_2_p), p);
            g = BN_bin2bn(rfc_5114_modp_2_g, sizeof(rfc_5114_modp_2_g), g);
            q = BN_bin2bn(rfc_5114_modp_2_q, sizeof(rfc_5114_modp_2_q), q);
            break;
        case 2:
            p = BN_bin2bn(rfc_5114_modp_3_p, sizeof(rfc_5114_modp_3_p), p);
            g = BN_bin2bn(rfc_5114_modp_3_g, sizeof(rfc_5114_modp_3_g), g);
            q = BN_bin2bn(rfc_5114_modp_3_q, sizeof(rfc_5114_modp_3_q), q);
            break;
        default:
            log_err("Invalid arguments");
            goto err;
    }

    if (!p || !g || !q)
        goto err;

    if (!DH_set0_pqg(ret, p, q, g))
       goto err;

    /* Perform some checks. OpenSSL only knows generators 2 and 5, so the
     * DH_UNABLE_TO_CHECK_GENERATOR will be set, but the prime should be safe
     * nevertheless */
    if (!DH_check(ret, &check)) goto err;
    if (check & DH_CHECK_P_NOT_PRIME)
        goto err;

    return ret;

err:
    if (ret)
        DH_free(ret);
    if (p)
        BN_free(p);
    if (g)
        BN_free(g);
    if (q)
        BN_free(q);
    return NULL;
}
Beispiel #9
0
DH *DSA_dup_DH(const DSA *r)
{
    /*
     * DSA has p, q, g, optional pub_key, optional priv_key. DH has p,
     * optional length, g, optional pub_key, optional priv_key, optional q.
     */

    DH *ret = NULL;
    BIGNUM *p = NULL, *q = NULL, *g = NULL, *pub_key = NULL, *priv_key = NULL;

    if (r == NULL)
        goto err;
    ret = DH_new();
    if (ret == NULL)
        goto err;
    if (r->p != NULL || r->g != NULL || r->q != NULL) {
        if (r->p == NULL || r->g == NULL || r->q == NULL) {
            /* Shouldn't happen */
            goto err;
        }
        p = BN_dup(r->p);
        g = BN_dup(r->g);
        q = BN_dup(r->q);
        if (p == NULL || g == NULL || q == NULL || !DH_set0_pqg(ret, p, q, g))
            goto err;
        p = g = q = NULL;
    }

    if (r->pub_key != NULL) {
        pub_key = BN_dup(r->pub_key);
        if (pub_key == NULL)
            goto err;
        if (r->priv_key != NULL) {
            priv_key = BN_dup(r->priv_key);
            if (priv_key == NULL)
                goto err;
        }
        if (!DH_set0_key(ret, pub_key, priv_key))
            goto err;
    } else if (r->priv_key != NULL) {
        /* Shouldn't happen */
        goto err;
    }

    return ret;

 err:
    BN_free(p);
    BN_free(g);
    BN_free(q);
    BN_free(pub_key);
    BN_free(priv_key);
    DH_free(ret);
    return NULL;
}
Beispiel #10
0
DH *
DHparams_dup_with_q(DH *dh)
{
    const BIGNUM *p, *q, *g;

    DH *dup = DHparams_dup(dh);
    DH_get0_pqg(dh, &p, &q, &g);
    DH_set0_pqg(dup, BN_dup(p), BN_dup(q), BN_dup(g));

    return dup;
}
Beispiel #11
0
DH *
dh_new_group(BIGNUM *gen, BIGNUM *modulus)
{
	DH *dh;

	if ((dh = DH_new()) == NULL)
		return NULL;
	if (DH_set0_pqg(dh, modulus, NULL, gen) == 0)
		return NULL;

	return (dh);
}
Beispiel #12
0
DH *get_dh2048()
{
    static unsigned char dhp_2048[] = {
	0x89, 0x9D, 0x84, 0xB8, 0x3A, 0x2D, 0xD4, 0xF7, 0x41, 0x5A, 
	0xBB, 0x27, 0x00, 0x69, 0xAE, 0xB4, 0xAC, 0x5E, 0xD8, 0xEB, 
	0xAE, 0x3D, 0x0E, 0x1A, 0x05, 0xD5, 0xE5, 0xEF, 0x2B, 0x8E, 
	0x4F, 0xF3, 0x65, 0x3C, 0xE3, 0x40, 0x6B, 0xFB, 0xA7, 0x24, 
	0x58, 0x85, 0xE4, 0xFA, 0x86, 0x0D, 0xED, 0x8D, 0xBF, 0xA0, 
	0x4D, 0x58, 0xC9, 0x30, 0x26, 0x3B, 0xF0, 0x1E, 0xAF, 0x15, 
	0x6F, 0x4E, 0x71, 0x2D, 0xF1, 0x67, 0xED, 0x44, 0x8C, 0x04, 
	0x04, 0x23, 0xE4, 0xA8, 0x5B, 0x7B, 0x28, 0x32, 0x0D, 0x67, 
	0xBB, 0x7E, 0xE5, 0x1B, 0x58, 0x6F, 0x0C, 0x3C, 0x0A, 0x8A, 
	0x3E, 0xC8, 0x8A, 0x10, 0xCA, 0x74, 0x94, 0x6E, 0xC8, 0xC0, 
	0x52, 0x9C, 0xE5, 0x45, 0xE7, 0x0A, 0x78, 0x9B, 0x30, 0x60, 
	0x70, 0xEA, 0xF2, 0xEF, 0xB6, 0xD5, 0x28, 0x2F, 0xA1, 0x92, 
	0xA6, 0x94, 0x45, 0x03, 0x5A, 0x8F, 0xF3, 0x17, 0x93, 0x99, 
	0x28, 0x1B, 0x9C, 0xE1, 0x3F, 0x96, 0x4E, 0x95, 0x62, 0x72, 
	0x79, 0x8E, 0xD9, 0xE6, 0x42, 0xEF, 0xF5, 0x46, 0xBF, 0xB3, 
	0x2B, 0x23, 0x5D, 0xEF, 0x11, 0x18, 0x81, 0x85, 0xBB, 0xD9, 
	0xD1, 0x32, 0x96, 0xEE, 0x98, 0x8C, 0x14, 0x6E, 0x57, 0x68, 
	0xAD, 0x5B, 0xE0, 0xF4, 0x7A, 0x75, 0x9E, 0x8D, 0xB0, 0x18, 
	0x9A, 0xFD, 0x1E, 0x0C, 0xD9, 0x23, 0x4B, 0xF1, 0xF3, 0x92, 
	0xD8, 0x23, 0x41, 0xE0, 0xEC, 0x94, 0xDE, 0xF3, 0x34, 0x87, 
	0xF6, 0x87, 0x35, 0xF4, 0x48, 0x9B, 0xB7, 0x3B, 0x4E, 0xCD, 
	0x1A, 0x8D, 0xFC, 0x5A, 0xD1, 0x39, 0x41, 0x33, 0x66, 0xE2, 
	0x06, 0xEE, 0x2C, 0x1B, 0x5F, 0x5C, 0xB2, 0xF2, 0xB3, 0xBA, 
	0xA3, 0x58, 0x8B, 0xF2, 0xD2, 0x9A, 0xAF, 0x03, 0xA2, 0x84, 
	0x7D, 0xA1, 0xAA, 0x23, 0x3A, 0x7B, 0xE2, 0xF8, 0xAF, 0xA6, 
	0xE3, 0x5B, 0xCE, 0x25, 0x68, 0x7B
    };
    static unsigned char dhg_2048[] = {
	0x02
    };
    DH *dh = DH_new();
    BIGNUM *dhp_bn, *dhg_bn;

    if (dh == NULL)
        return NULL;
    dhp_bn = BN_bin2bn(dhp_2048, sizeof (dhp_2048), NULL);
    dhg_bn = BN_bin2bn(dhg_2048, sizeof (dhg_2048), NULL);
    if (dhp_bn == NULL || dhg_bn == NULL
            || !DH_set0_pqg(dh, dhp_bn, NULL, dhg_bn)) {
        DH_free(dh);
        BN_free(dhp_bn);
        BN_free(dhg_bn);
        return NULL;
    }
    return dh;
}
Beispiel #13
0
   bool diffie_hellman::validate()
   {
        if( !p.size() ) 
            return valid = false;
        ssl_dh dh = DH_new();
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
        const auto bn_p = BN_bin2bn( (unsigned char*)&p.front(), p.size(), NULL );
        const auto bn_g = BN_bin2bn( (unsigned char*)&g, 1, NULL );
        DH_set0_pqg(dh.obj, bn_p, NULL, bn_g);
#else
        dh->p = BN_bin2bn( (unsigned char*)&p.front(), p.size(), NULL );
        dh->g = BN_bin2bn( (unsigned char*)&g, 1, NULL );
#endif
        return fc::validate( dh, valid );
   }
Beispiel #14
0
/**
  Sets generator and prime parameters for DH.

  Given generator g, and prime number p, this function and sets DH
  context accordingly.

  If DhContext is NULL, then return FALSE.
  If Prime is NULL, then return FALSE.

  @param[in, out]  DhContext    Pointer to the DH context.
  @param[in]       Generator    Value of generator.
  @param[in]       PrimeLength  Length in bits of prime to be generated.
  @param[in]       Prime        Pointer to the prime number.

  @retval TRUE   DH parameter setting succeeded.
  @retval FALSE  Value of Generator is not supported.
  @retval FALSE  Value of Generator is not suitable for the Prime.
  @retval FALSE  Value of Prime is not a prime number.
  @retval FALSE  Value of Prime is not a safe prime number.

**/
BOOLEAN
EFIAPI
DhSetParameter (
  IN OUT  VOID         *DhContext,
  IN      UINTN        Generator,
  IN      UINTN        PrimeLength,
  IN      CONST UINT8  *Prime
  )
{
  DH      *Dh;
  BIGNUM  *BnP;
  BIGNUM  *BnG;

  //
  // Check input parameters.
  //
  if (DhContext == NULL || Prime == NULL || PrimeLength > INT_MAX) {
    return FALSE;
  }

  if (Generator != DH_GENERATOR_2 && Generator != DH_GENERATOR_5) {
    return FALSE;
  }

  //
  // Set the generator and prime parameters for DH object.
  //
  Dh  = (DH *)DhContext;
  BnP = BN_bin2bn ((const unsigned char *)Prime, (int)(PrimeLength / 8), NULL);
  BnG = BN_bin2bn ((const unsigned char *)&Generator, 1, NULL);
  if ((BnP == NULL) || (BnG == NULL) || !DH_set0_pqg (Dh, BnP, NULL, BnG)) {
    goto Error;
  }

  return TRUE;

Error:
  BN_free (BnP);
  BN_free (BnG);

  return FALSE;
}
Beispiel #15
0
   bool diffie_hellman::generate_pub_key()
   {
        if( !p.size() ) 
            return valid = false;
        ssl_dh dh = DH_new();
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
        const auto bn_p = BN_bin2bn( (unsigned char*)&p.front(), p.size(), NULL );
        const auto bn_g = BN_bin2bn( (unsigned char*)&g, 1, NULL );
        DH_set0_pqg(dh.obj, bn_p, NULL, bn_g);
#else
        dh->p = BN_bin2bn( (unsigned char*)&p.front(), p.size(), NULL );
        dh->g = BN_bin2bn( (unsigned char*)&g, 1, NULL );
#endif

        if( !fc::validate( dh, valid ) )
        {
            return false;
        }
        DH_generate_key(dh);

#if OPENSSL_VERSION_NUMBER >= 0x10100000L
        ssl_bignum bn_pub_key;
        ssl_bignum bn_priv_key;
        DH_get0_key(dh.obj, (const BIGNUM**)&bn_pub_key.obj, (const BIGNUM**)&bn_priv_key.obj);
        pub_key.resize( BN_num_bytes( bn_pub_key ) );
        priv_key.resize( BN_num_bytes( bn_priv_key ) );
        if( pub_key.size() )
            BN_bn2bin( bn_pub_key.obj, (unsigned char*)&pub_key.front()  );
        if( priv_key.size() )
            BN_bn2bin( bn_priv_key.obj, (unsigned char*)&priv_key.front()  );
#else
        pub_key.resize( BN_num_bytes( dh->pub_key ) );
        priv_key.resize( BN_num_bytes( dh->priv_key ) );
        if( pub_key.size() )
            BN_bn2bin( dh->pub_key, (unsigned char*)&pub_key.front()  );
        if( priv_key.size() )
            BN_bn2bin( dh->priv_key, (unsigned char*)&priv_key.front()  );
#endif

        return true;
   }
Beispiel #16
0
int network_init(server *srv) {
	buffer *b;
	size_t i, j;
	network_backend_t backend;

#if OPENSSL_VERSION_NUMBER >= 0x0090800fL
#ifndef OPENSSL_NO_ECDH
	EC_KEY *ecdh;
	int nid;
#endif
#endif

#ifdef USE_OPENSSL
# ifndef OPENSSL_NO_DH
	DH *dh;
# endif
	BIO *bio;

       /* 1024-bit MODP Group with 160-bit prime order subgroup (RFC5114)
	* -----BEGIN DH PARAMETERS-----
	* MIIBDAKBgQCxC4+WoIDgHd6S3l6uXVTsUsmfvPsGo8aaap3KUtI7YWBz4oZ1oj0Y
	* mDjvHi7mUsAT7LSuqQYRIySXXDzUm4O/rMvdfZDEvXCYSI6cIZpzck7/1vrlZEc4
	* +qMaT/VbzMChUa9fDci0vUW/N982XBpl5oz9p21NpwjfH7K8LkpDcQKBgQCk0cvV
	* w/00EmdlpELvuZkF+BBN0lisUH/WQGz/FCZtMSZv6h5cQVZLd35pD1UE8hMWAhe0
	* sBuIal6RVH+eJ0n01/vX07mpLuGQnQ0iY/gKdqaiTAh6CR9THb8KAWm2oorWYqTR
	* jnOvoy13nVkY0IvIhY9Nzvl8KiSFXm7rIrOy5QICAKA=
	* -----END DH PARAMETERS-----
	*/

	static const unsigned char dh1024_p[]={
		0xB1,0x0B,0x8F,0x96,0xA0,0x80,0xE0,0x1D,0xDE,0x92,0xDE,0x5E,
		0xAE,0x5D,0x54,0xEC,0x52,0xC9,0x9F,0xBC,0xFB,0x06,0xA3,0xC6,
		0x9A,0x6A,0x9D,0xCA,0x52,0xD2,0x3B,0x61,0x60,0x73,0xE2,0x86,
		0x75,0xA2,0x3D,0x18,0x98,0x38,0xEF,0x1E,0x2E,0xE6,0x52,0xC0,
		0x13,0xEC,0xB4,0xAE,0xA9,0x06,0x11,0x23,0x24,0x97,0x5C,0x3C,
		0xD4,0x9B,0x83,0xBF,0xAC,0xCB,0xDD,0x7D,0x90,0xC4,0xBD,0x70,
		0x98,0x48,0x8E,0x9C,0x21,0x9A,0x73,0x72,0x4E,0xFF,0xD6,0xFA,
		0xE5,0x64,0x47,0x38,0xFA,0xA3,0x1A,0x4F,0xF5,0x5B,0xCC,0xC0,
		0xA1,0x51,0xAF,0x5F,0x0D,0xC8,0xB4,0xBD,0x45,0xBF,0x37,0xDF,
		0x36,0x5C,0x1A,0x65,0xE6,0x8C,0xFD,0xA7,0x6D,0x4D,0xA7,0x08,
		0xDF,0x1F,0xB2,0xBC,0x2E,0x4A,0x43,0x71,
	};

	static const unsigned char dh1024_g[]={
		0xA4,0xD1,0xCB,0xD5,0xC3,0xFD,0x34,0x12,0x67,0x65,0xA4,0x42,
		0xEF,0xB9,0x99,0x05,0xF8,0x10,0x4D,0xD2,0x58,0xAC,0x50,0x7F,
		0xD6,0x40,0x6C,0xFF,0x14,0x26,0x6D,0x31,0x26,0x6F,0xEA,0x1E,
		0x5C,0x41,0x56,0x4B,0x77,0x7E,0x69,0x0F,0x55,0x04,0xF2,0x13,
		0x16,0x02,0x17,0xB4,0xB0,0x1B,0x88,0x6A,0x5E,0x91,0x54,0x7F,
		0x9E,0x27,0x49,0xF4,0xD7,0xFB,0xD7,0xD3,0xB9,0xA9,0x2E,0xE1,
		0x90,0x9D,0x0D,0x22,0x63,0xF8,0x0A,0x76,0xA6,0xA2,0x4C,0x08,
		0x7A,0x09,0x1F,0x53,0x1D,0xBF,0x0A,0x01,0x69,0xB6,0xA2,0x8A,
		0xD6,0x62,0xA4,0xD1,0x8E,0x73,0xAF,0xA3,0x2D,0x77,0x9D,0x59,
		0x18,0xD0,0x8B,0xC8,0x85,0x8F,0x4D,0xCE,0xF9,0x7C,0x2A,0x24,
		0x85,0x5E,0x6E,0xEB,0x22,0xB3,0xB2,0xE5,
	};
#endif

	struct nb_map {
		network_backend_t nb;
		const char *name;
	} network_backends[] = {
		/* lowest id wins */
#if defined USE_SENDFILE
		{ NETWORK_BACKEND_SENDFILE,   "sendfile" },
#endif
#if defined USE_LINUX_SENDFILE
		{ NETWORK_BACKEND_SENDFILE,   "linux-sendfile" },
#endif
#if defined USE_FREEBSD_SENDFILE
		{ NETWORK_BACKEND_SENDFILE,   "freebsd-sendfile" },
#endif
#if defined USE_SOLARIS_SENDFILEV
		{ NETWORK_BACKEND_SENDFILE,   "solaris-sendfilev" },
#endif
#if defined USE_WRITEV
		{ NETWORK_BACKEND_WRITEV,     "writev" },
#endif
		{ NETWORK_BACKEND_WRITE,      "write" },
		{ NETWORK_BACKEND_UNSET,       NULL }
	};

#ifdef USE_OPENSSL
	/* load SSL certificates */
	for (i = 0; i < srv->config_context->used; i++) {
		specific_config *s = srv->config_storage[i];
#ifndef SSL_OP_NO_COMPRESSION
# define SSL_OP_NO_COMPRESSION 0
#endif
		long ssloptions =
			SSL_OP_ALL | SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION | SSL_OP_NO_COMPRESSION;

		if (buffer_string_is_empty(s->ssl_pemfile) && buffer_string_is_empty(s->ssl_ca_file)) continue;

		if (srv->ssl_is_init == 0) {
			SSL_load_error_strings();
			SSL_library_init();
			OpenSSL_add_all_algorithms();
			srv->ssl_is_init = 1;

			if (0 == RAND_status()) {
				log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
						"not enough entropy in the pool");
				return -1;
			}
		}

		if (!buffer_string_is_empty(s->ssl_pemfile)) {
#ifdef OPENSSL_NO_TLSEXT
			data_config *dc = (data_config *)srv->config_context->data[i];
			if (COMP_HTTP_HOST == dc->comp) {
				log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
						"can't use ssl.pemfile with $HTTP[\"host\"], openssl version does not support TLS extensions");
				return -1;
			}
#endif
			if (network_openssl_load_pemfile(srv, i)) return -1;
		}


		if (!buffer_string_is_empty(s->ssl_ca_file)) {
			s->ssl_ca_file_cert_names = SSL_load_client_CA_file(s->ssl_ca_file->ptr);
			if (NULL == s->ssl_ca_file_cert_names) {
				log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:",
						ERR_error_string(ERR_get_error(), NULL), s->ssl_ca_file);
			}
		}

		if (buffer_string_is_empty(s->ssl_pemfile) || !s->ssl_enabled) continue;

		if (NULL == (s->ssl_ctx = SSL_CTX_new(SSLv23_server_method()))) {
			log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
					ERR_error_string(ERR_get_error(), NULL));
			return -1;
		}

		/* completely useless identifier; required for client cert verification to work with sessions */
		if (0 == SSL_CTX_set_session_id_context(s->ssl_ctx, (const unsigned char*) CONST_STR_LEN("lighttpd"))) {
			log_error_write(srv, __FILE__, __LINE__, "ss:s", "SSL:",
				"failed to set session context",
				ERR_error_string(ERR_get_error(), NULL));
			return -1;
		}

		if (s->ssl_empty_fragments) {
#ifdef SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS
			ssloptions &= ~SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS;
#else
			ssloptions &= ~0x00000800L; /* hardcode constant */
			log_error_write(srv, __FILE__, __LINE__, "ss", "WARNING: SSL:",
					"'insert empty fragments' not supported by the openssl version used to compile lighttpd with");
#endif
		}

		SSL_CTX_set_options(s->ssl_ctx, ssloptions);
		SSL_CTX_set_info_callback(s->ssl_ctx, ssl_info_callback);

		if (!s->ssl_use_sslv2) {
			/* disable SSLv2 */
			if ((SSL_OP_NO_SSLv2 & SSL_CTX_set_options(s->ssl_ctx, SSL_OP_NO_SSLv2)) != SSL_OP_NO_SSLv2) {
				log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
						ERR_error_string(ERR_get_error(), NULL));
				return -1;
			}
		}

		if (!s->ssl_use_sslv3) {
			/* disable SSLv3 */
			if ((SSL_OP_NO_SSLv3 & SSL_CTX_set_options(s->ssl_ctx, SSL_OP_NO_SSLv3)) != SSL_OP_NO_SSLv3) {
				log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
						ERR_error_string(ERR_get_error(), NULL));
				return -1;
			}
		}

		if (!buffer_string_is_empty(s->ssl_cipher_list)) {
			/* Disable support for low encryption ciphers */
			if (SSL_CTX_set_cipher_list(s->ssl_ctx, s->ssl_cipher_list->ptr) != 1) {
				log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
						ERR_error_string(ERR_get_error(), NULL));
				return -1;
			}

			if (s->ssl_honor_cipher_order) {
				SSL_CTX_set_options(s->ssl_ctx, SSL_OP_CIPHER_SERVER_PREFERENCE);
			}
		}

#ifndef OPENSSL_NO_DH
		/* Support for Diffie-Hellman key exchange */
		if (!buffer_string_is_empty(s->ssl_dh_file)) {
			/* DH parameters from file */
			bio = BIO_new_file((char *) s->ssl_dh_file->ptr, "r");
			if (bio == NULL) {
				log_error_write(srv, __FILE__, __LINE__, "ss", "SSL: Unable to open file", s->ssl_dh_file->ptr);
				return -1;
			}
			dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
			BIO_free(bio);
			if (dh == NULL) {
				log_error_write(srv, __FILE__, __LINE__, "ss", "SSL: PEM_read_bio_DHparams failed", s->ssl_dh_file->ptr);
				return -1;
			}
		} else {
			BIGNUM *dh_p, *dh_g;
			/* Default DH parameters from RFC5114 */
			dh = DH_new();
			if (dh == NULL) {
				log_error_write(srv, __FILE__, __LINE__, "s", "SSL: DH_new () failed");
				return -1;
			}
			dh_p = BN_bin2bn(dh1024_p,sizeof(dh1024_p), NULL);
			dh_g = BN_bin2bn(dh1024_g,sizeof(dh1024_g), NULL);
			if ((dh_p == NULL) || (dh_g == NULL)) {
				DH_free(dh);
				log_error_write(srv, __FILE__, __LINE__, "s", "SSL: BN_bin2bn () failed");
				return -1;
			}
		      #if OPENSSL_VERSION_NUMBER < 0x10100000L \
			|| defined(LIBRESSL_VERSION_NUMBER)
			dh->p = dh_p;
			dh->g = dh_g;
			dh->length = 160;
		      #else
			DH_set0_pqg(dh, dh_p, NULL, dh_g);
			DH_set_length(dh, 160);
		      #endif
		}
		SSL_CTX_set_tmp_dh(s->ssl_ctx,dh);
		SSL_CTX_set_options(s->ssl_ctx,SSL_OP_SINGLE_DH_USE);
		DH_free(dh);
#else
		if (!buffer_string_is_empty(s->ssl_dh_file)) {
			log_error_write(srv, __FILE__, __LINE__, "ss", "SSL: openssl compiled without DH support, can't load parameters from", s->ssl_dh_file->ptr);
		}
#endif

#if OPENSSL_VERSION_NUMBER >= 0x0090800fL
#ifndef OPENSSL_NO_ECDH
		/* Support for Elliptic-Curve Diffie-Hellman key exchange */
		if (!buffer_string_is_empty(s->ssl_ec_curve)) {
			/* OpenSSL only supports the "named curves" from RFC 4492, section 5.1.1. */
			nid = OBJ_sn2nid((char *) s->ssl_ec_curve->ptr);
			if (nid == 0) {
				log_error_write(srv, __FILE__, __LINE__, "ss", "SSL: Unknown curve name", s->ssl_ec_curve->ptr);
				return -1;
			}
		} else {
			/* Default curve */
			nid = OBJ_sn2nid("prime256v1");
		}
		ecdh = EC_KEY_new_by_curve_name(nid);
		if (ecdh == NULL) {
			log_error_write(srv, __FILE__, __LINE__, "ss", "SSL: Unable to create curve", s->ssl_ec_curve->ptr);
			return -1;
		}
		SSL_CTX_set_tmp_ecdh(s->ssl_ctx,ecdh);
		SSL_CTX_set_options(s->ssl_ctx,SSL_OP_SINGLE_ECDH_USE);
		EC_KEY_free(ecdh);
#endif
#endif

		/* load all ssl.ca-files specified in the config into each SSL_CTX to be prepared for SNI */
		for (j = 0; j < srv->config_context->used; j++) {
			specific_config *s1 = srv->config_storage[j];

			if (!buffer_string_is_empty(s1->ssl_ca_file)) {
				if (1 != SSL_CTX_load_verify_locations(s->ssl_ctx, s1->ssl_ca_file->ptr, NULL)) {
					log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:",
							ERR_error_string(ERR_get_error(), NULL), s1->ssl_ca_file);
					return -1;
				}
			}
		}

		if (s->ssl_verifyclient) {
			if (NULL == s->ssl_ca_file_cert_names) {
				log_error_write(srv, __FILE__, __LINE__, "s",
					"SSL: You specified ssl.verifyclient.activate but no ca_file"
				);
				return -1;
			}
			SSL_CTX_set_client_CA_list(s->ssl_ctx, SSL_dup_CA_list(s->ssl_ca_file_cert_names));
			SSL_CTX_set_verify(
				s->ssl_ctx,
				SSL_VERIFY_PEER | (s->ssl_verifyclient_enforce ? SSL_VERIFY_FAIL_IF_NO_PEER_CERT : 0),
				NULL
			);
			SSL_CTX_set_verify_depth(s->ssl_ctx, s->ssl_verifyclient_depth);
		}

		if (SSL_CTX_use_certificate(s->ssl_ctx, s->ssl_pemfile_x509) < 0) {
			log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:",
					ERR_error_string(ERR_get_error(), NULL), s->ssl_pemfile);
			return -1;
		}

		if (SSL_CTX_use_PrivateKey(s->ssl_ctx, s->ssl_pemfile_pkey) < 0) {
			log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:",
					ERR_error_string(ERR_get_error(), NULL), s->ssl_pemfile);
			return -1;
		}

		if (SSL_CTX_check_private_key(s->ssl_ctx) != 1) {
			log_error_write(srv, __FILE__, __LINE__, "sssb", "SSL:",
					"Private key does not match the certificate public key, reason:",
					ERR_error_string(ERR_get_error(), NULL),
					s->ssl_pemfile);
			return -1;
		}
		SSL_CTX_set_default_read_ahead(s->ssl_ctx, 1);
		SSL_CTX_set_mode(s->ssl_ctx, SSL_CTX_get_mode(s->ssl_ctx) | SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);

# ifndef OPENSSL_NO_TLSEXT
		if (!SSL_CTX_set_tlsext_servername_callback(s->ssl_ctx, network_ssl_servername_callback) ||
		    !SSL_CTX_set_tlsext_servername_arg(s->ssl_ctx, srv)) {
			log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
					"failed to initialize TLS servername callback, openssl library does not support TLS servername extension");
			return -1;
		}
# endif
	}
#endif

	b = buffer_init();

	buffer_copy_buffer(b, srv->srvconf.bindhost);
	buffer_append_string_len(b, CONST_STR_LEN(":"));
	buffer_append_int(b, srv->srvconf.port);

	if (0 != network_server_init(srv, b, srv->config_storage[0])) {
		buffer_free(b);
		return -1;
	}
	buffer_free(b);

#ifdef USE_OPENSSL
	srv->network_ssl_backend_write = network_write_chunkqueue_openssl;
#endif

	/* get a usefull default */
	backend = network_backends[0].nb;

	/* match name against known types */
	if (!buffer_string_is_empty(srv->srvconf.network_backend)) {
		for (i = 0; network_backends[i].name; i++) {
			/**/
			if (buffer_is_equal_string(srv->srvconf.network_backend, network_backends[i].name, strlen(network_backends[i].name))) {
				backend = network_backends[i].nb;
				break;
			}
		}
		if (NULL == network_backends[i].name) {
			/* we don't know it */

			log_error_write(srv, __FILE__, __LINE__, "sb",
					"server.network-backend has a unknown value:",
					srv->srvconf.network_backend);

			return -1;
		}
	}

	switch(backend) {
	case NETWORK_BACKEND_WRITE:
		srv->network_backend_write = network_write_chunkqueue_write;
		break;
#if defined(USE_WRITEV)
	case NETWORK_BACKEND_WRITEV:
		srv->network_backend_write = network_write_chunkqueue_writev;
		break;
#endif
#if defined(USE_SENDFILE)
	case NETWORK_BACKEND_SENDFILE:
		srv->network_backend_write = network_write_chunkqueue_sendfile;
		break;
#endif
	default:
		return -1;
	}

	/* check for $SERVER["socket"] */
	for (i = 1; i < srv->config_context->used; i++) {
		data_config *dc = (data_config *)srv->config_context->data[i];
		specific_config *s = srv->config_storage[i];

		/* not our stage */
		if (COMP_SERVER_SOCKET != dc->comp) continue;

		if (dc->cond != CONFIG_COND_EQ) continue;

		/* check if we already know this socket,
		 * if yes, don't init it */
		for (j = 0; j < srv->srv_sockets.used; j++) {
			if (buffer_is_equal(srv->srv_sockets.ptr[j]->srv_token, dc->string)) {
				break;
			}
		}

		if (j == srv->srv_sockets.used) {
			if (0 != network_server_init(srv, dc->string, s)) return -1;
		}
	}

	return 0;
}
Beispiel #17
0
    SSL_CTX *
tls_server_setup( int authlevel, const char *caFile,
	const char *caDir, const char *cert, const char *privatekey,
	const char *ciphers )
{
    SSL_CTX		*ssl_ctx;
    int                 ssl_mode = 0;
    static unsigned char dh4096_p[ ] = {
	0x91, 0x6B, 0xA1, 0x6D, 0xC7, 0xE7, 0x1C, 0x21, 0x69, 0xCE, 0x7C, 0x3D,
	0x72, 0x28, 0x01, 0x56, 0xAE, 0x71, 0xFE, 0xEF, 0x29, 0x4B, 0xDC, 0xD1,
	0x23, 0x37, 0x9E, 0xA5, 0x80, 0x45, 0xEF, 0x51, 0x7A, 0x65, 0x77, 0x41,
	0x90, 0x5D, 0xEA, 0xAB, 0x52, 0x39, 0xF0, 0xE1, 0xA9, 0x77, 0xA1, 0xCD,
	0x14, 0xB1, 0x8B, 0x07, 0x4F, 0xC5, 0x44, 0xD9, 0x2F, 0x7A, 0x74, 0xFD,
	0xBB, 0xEA, 0x6C, 0x4A, 0x22, 0xD0, 0x78, 0xCA, 0xCF, 0x51, 0x04, 0x0E,
	0x88, 0x44, 0x65, 0x41, 0xD9, 0x10, 0x6A, 0x11, 0x66, 0x21, 0x0E, 0xE7,
	0x9B, 0x39, 0x36, 0xF6, 0x59, 0x15, 0x83, 0xFB, 0x57, 0x51, 0x02, 0xE2,
	0x95, 0xBE, 0x85, 0xDA, 0x78, 0x40, 0xC1, 0x9A, 0x0A, 0xE6, 0x43, 0x95,
	0xD8, 0x7A, 0x30, 0x50, 0x15, 0x9F, 0x37, 0x5E, 0xAA, 0x27, 0x50, 0xA4,
	0x15, 0x1C, 0x6E, 0xFE, 0x3B, 0xA5, 0xD9, 0xF6, 0x0F, 0xE3, 0xA5, 0xFF,
	0xE7, 0xDA, 0xD9, 0x68, 0x64, 0x40, 0xF3, 0x54, 0x32, 0x84, 0xF3, 0x12,
	0xC4, 0xD3, 0x77, 0x25, 0x00, 0x60, 0x0D, 0x95, 0xEA, 0x16, 0xE0, 0x51,
	0x91, 0x8F, 0xF4, 0x40, 0x1B, 0x8A, 0x2D, 0x84, 0x0E, 0xAC, 0x53, 0x58,
	0x08, 0x4E, 0x52, 0xC8, 0xE4, 0x6E, 0xA1, 0xCB, 0xA6, 0xF8, 0x3B, 0xE0,
	0x1F, 0x35, 0xA6, 0x37, 0x6A, 0x62, 0x61, 0xDE, 0x6D, 0x5A, 0x70, 0x70,
	0x71, 0xC9, 0x24, 0x41, 0x70, 0x7C, 0xCD, 0x3F, 0xD9, 0x38, 0xDB, 0x7B,
	0x26, 0xFA, 0xB5, 0x6B, 0xAC, 0xF0, 0x2D, 0x45, 0xD8, 0x55, 0x68, 0xCB,
	0x89, 0x04, 0x1F, 0xA0, 0xAD, 0x6F, 0xCB, 0x05, 0x04, 0xB3, 0x26, 0xF4,
	0x53, 0x02, 0x9E, 0xB8, 0x76, 0x8D, 0xC6, 0xE8, 0x12, 0x24, 0x38, 0x4E,
	0x46, 0x27, 0x30, 0xAE, 0x55, 0x1A, 0xD0, 0xDB, 0xCE, 0x4C, 0x35, 0xFA,
	0x7D, 0x9D, 0x40, 0x3E, 0x66, 0x7A, 0xBA, 0xEA, 0x78, 0x6C, 0x6E, 0x47,
	0x81, 0xBD, 0xB0, 0x57, 0x5D, 0x1C, 0x94, 0xCC, 0x4F, 0x08, 0xF3, 0x5E,
	0xB1, 0x6E, 0x0B, 0xD5, 0x55, 0x45, 0x3F, 0x8B, 0xFD, 0x01, 0x4E, 0x01,
	0x21, 0x34, 0x20, 0xA8, 0x49, 0xB0, 0x75, 0x40, 0xB4, 0x55, 0x17, 0x3A,
	0x55, 0x1E, 0xBA, 0xF2, 0x31, 0x1D, 0x89, 0x81, 0x7A, 0xB3, 0x87, 0xC9,
	0xFB, 0xBB, 0x8A, 0x26, 0x66, 0x99, 0x19, 0x7E, 0x3C, 0xB1, 0x6A, 0x9A,
	0x4A, 0xDC, 0xE9, 0x3C, 0xF0, 0x7C, 0x29, 0xC9, 0xA1, 0xE1, 0x78, 0x3A,
	0x73, 0x8F, 0xEF, 0x2B, 0x33, 0xDF, 0x0C, 0x53, 0xCE, 0x98, 0x91, 0x7C,
	0xE3, 0xC9, 0xE2, 0x26, 0xD8, 0x2F, 0x1A, 0x69, 0xCA, 0xB8, 0x64, 0x3B,
	0x43, 0x38, 0xBB, 0xFA, 0x89, 0x59, 0xE0, 0x3C, 0xDA, 0xED, 0x93, 0x65,
	0x8B, 0x12, 0xED, 0xDB, 0x6F, 0x8F, 0xC5, 0xFE, 0x9C, 0xEB, 0x88, 0xD2,
	0xAB, 0x89, 0xAF, 0xAF, 0x60, 0xFF, 0xFC, 0x40, 0x69, 0x3C, 0xD0, 0x22,
	0x02, 0xB8, 0x2C, 0x1D, 0x9A, 0x26, 0x19, 0x33, 0xCB, 0x5A, 0x9D, 0x91,
	0xDD, 0x05, 0x39, 0x68, 0xBA, 0x15, 0x2B, 0x14, 0xFD, 0x5D, 0xB8, 0x87,
	0x90, 0xAF, 0xAA, 0x5F, 0x54, 0xC7, 0x43, 0x04, 0xF4, 0xE1, 0x49, 0x91,
	0x42, 0x27, 0x23, 0xCC, 0x5A, 0xFC, 0xF1, 0xA6, 0x2A, 0x39, 0x19, 0xC1,
	0x31, 0xBF, 0xE5, 0x89, 0x8C, 0x48, 0xA7, 0xCE, 0x0E, 0x67, 0x18, 0xA1,
	0x07, 0x8E, 0xBD, 0xFE, 0x2A, 0x9F, 0xF0, 0xA3, 0x19, 0xAA, 0xBC, 0xD7,
	0x6D, 0x43, 0x1C, 0x3D, 0x31, 0xBA, 0x9B, 0xD4, 0xF7, 0xDF, 0x2C, 0x7F,
	0x37, 0x7B, 0xD9, 0x7B, 0xDE, 0x62, 0x5C, 0xDE, 0x21, 0x38, 0x4D, 0xB7,
	0x4A, 0x45, 0x04, 0x7D, 0x76, 0x4A, 0x93, 0xFE, 0x8E, 0x49, 0x04, 0xD0,
	0xAD, 0x99, 0xCD, 0xF0, 0x86, 0x24, 0x5E, 0x73, };
    static unsigned char    dh4096_g[ ] = { 0x02, };
    DH			*dh = NULL;

    /* OpenSSL 1.1.0 added auto-init */
#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
    SSL_load_error_strings();
    SSL_library_init();
#endif /* OpenSSL < 1.1.0 */

    if (( ssl_ctx = SSL_CTX_new( SSLv23_server_method())) == NULL ) {
	syslog( LOG_ERR, "Liberror: tls_server_setup SSL_CTX_new: %s",
		ERR_error_string( ERR_get_error(), NULL ));
	return( NULL );
    }

    if (( dh = DH_new( )) == NULL ) {
	syslog( LOG_ERR, "Liberror: tls_server_setup DH_new: %s",
		ERR_error_string( ERR_get_error(), NULL ));
	goto error;
    }

#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER)
    if ( DH_set0_pqg( dh,
	    BN_bin2bn( dh4096_p, sizeof( dh4096_p ), NULL ),
	    NULL,
	    BN_bin2bn( dh4096_g, sizeof( dh4096_g ), NULL )) != 1 ) {
	syslog( LOG_ERR, "Liberror: tls_server_setup DH_set0_pqg: %s",
		ERR_error_string( ERR_get_error(), NULL ));
    }
#else
    dh->p = BN_bin2bn( dh4096_p, sizeof( dh4096_p ), NULL );
    dh->g = BN_bin2bn( dh4096_g, sizeof( dh4096_g ), NULL );
    if (( dh->p == NULL ) || ( dh->g == NULL )) {
	syslog( LOG_ERR, "Liberror: tls_server_setup BN_bin2bn: %s",
		ERR_error_string( ERR_get_error(), NULL ));
        goto error;
    }
#endif /* OpenSSL 1.1.0 */

    if ( SSL_CTX_set_tmp_dh( ssl_ctx, dh ) != 1 ) {
	syslog( LOG_ERR, "Liberror: tls_server_setup SSL_CTX_set_tmp_dh: %s",
		ERR_error_string( ERR_get_error(), NULL ));
	goto error;
    }

    /* Disable SSLv2 and SSLv3, prefer server cipher ordering */
    SSL_CTX_set_options( ssl_ctx,
	    SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 |
	    SSL_OP_CIPHER_SERVER_PREFERENCE );

    if ( ciphers == NULL ) {
	SSL_CTX_set_cipher_list( ssl_ctx,
		"EECDH+CHACHA20:EECDH+AES128:RSA+AES128:EECDH+AES256:"
		"RSA+AES256:DH+CHACHA20:DH+AES128:DH+AES256:!MD5" );
    } else {
	SSL_CTX_set_cipher_list( ssl_ctx, ciphers );
    }

    if ( SSL_CTX_use_PrivateKey_file( ssl_ctx, privatekey,
	    SSL_FILETYPE_PEM ) != 1 ) {
	syslog( LOG_ERR, "Liberror: tls_server_setup "
		"SSL_CTX_use_PrivateKey_file: %s: %s",
		privatekey, ERR_error_string( ERR_get_error(), NULL ));
	goto error;
    }
    if ( SSL_CTX_use_certificate_chain_file( ssl_ctx, cert ) != 1 ) {
	syslog( LOG_ERR, "Liberror: tls_server_setup "
		"SSL_CTX_use_certificate_chain_file: %s: %s",
		cert, ERR_error_string( ERR_get_error(), NULL ));
	goto error;
    }
    /* Verify that private key matches cert */
    if ( SSL_CTX_check_private_key( ssl_ctx ) != 1 ) {
	syslog( LOG_ERR, "Liberror: tls_server_setup "
		"SSL_CTX_check_private_key: %s",
		ERR_error_string( ERR_get_error(), NULL ));
	goto error;
    }

    /* Load CA */
    if ( caFile != NULL ) {
	if ( SSL_CTX_load_verify_locations( ssl_ctx, caFile, NULL ) != 1 ) {
	    syslog( LOG_ERR, "Liberror: tls_server_setup "
		    "SSL_CTX_load_verify_locations: %s: %s",
		    caFile, ERR_error_string( ERR_get_error(), NULL ));
	    goto error;
	}
    }
    if ( caDir != NULL ) {
	if ( SSL_CTX_load_verify_locations( ssl_ctx, NULL, caDir ) != 1 ) {
	    syslog( LOG_ERR, "Liberror: tls_server_setup "
		    "SSL_CTX_load_verify_locations: %s: %s",
		    caDir, ERR_error_string( ERR_get_error(), NULL ));
	    goto error;
	}
    }

    /* Set level of security expecations */
    if ( authlevel <= 1 ) {
	ssl_mode = SSL_VERIFY_NONE;
    } else {
	/* authlevel == 2 */
	ssl_mode = SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
    }
    SSL_CTX_set_verify( ssl_ctx, ssl_mode, NULL );

#ifndef OPENSSL_NO_ECDH
    /* Do not reuse the same ECDH key pair */
    SSL_CTX_set_options(ssl_ctx, SSL_OP_SINGLE_ECDH_USE);

#if defined(OPENSSL_IS_BORINGSSL) || (OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER))
    /* OpenSSL >= 1.1.0 automatically enables automatic handling of parameter
     * selection and makes SSL_CTX_set_ecdh_auto a noop, so we don't want
     * to do anything.
     */
#elif OPENSSL_VERSION_NUMBER >= 0x10002000L
    /* OpenSSL >= 1.0.2 automatically handles parameter selection */
    SSL_CTX_set_ecdh_auto(ssl_ctx, 1);

#elif OPENSSL_VERSION_NUMBER >= 0x10000000L
    /* Manually select the curve. This selection is compliant with RFC 6460
     * when AES-256 cipher suites are in use, but noncompliant when AES-128
     * cipher suites are used. Oh, well. */
    EC_KEY *ecdh;
    if (( ecdh = EC_KEY_new_by_curve_name( NID_secp384r1 )) != NULL ) {
	SSL_CTX_set_tmp_ecdh(ssl_ctx, ecdh);
	EC_KEY_free(ecdh);
    } else {
	syslog( LOG_ERR, "Liberror: tls_server_setup EC_KEY_new failed: %s",
		ERR_error_string( ERR_get_error(), NULL ));
    }
#endif /* openssl 1.0 - 1.0.1 */
#endif /* OPENSSL_NO_ECDH */

    return( ssl_ctx );

    error:
    SSL_CTX_free( ssl_ctx );
    if ( dh != NULL ) {
	DH_free( dh );
    }
    return( NULL );
}
Beispiel #18
0
static DH *
get_dh2048(void)
{
  static const uint8_t dh2048_p[] = {
    0x8C, 0x9A, 0x5A, 0x28, 0xBF, 0x13, 0x24, 0xC0, 0xD3, 0x7A, 0x73, 0xC3,
    0x87, 0x5B, 0x80, 0x81, 0xE8, 0xF3, 0x7B, 0xF6, 0xF7, 0x18, 0x71, 0xF9,
    0xBB, 0x5B, 0x88, 0x21, 0xAB, 0x63, 0xF6, 0x82, 0xA6, 0xEC, 0xD7, 0x04,
    0x25, 0xDC, 0x64, 0x75, 0x00, 0x49, 0x2C, 0x13, 0x04, 0x4F, 0xCF, 0xF9,
    0x06, 0xE0, 0x4D, 0x23, 0xB8, 0x7C, 0xD8, 0x29, 0x59, 0x6F, 0x69, 0xCC,
    0x41, 0x1F, 0x45, 0xF8, 0x25, 0xC8, 0x72, 0xF4, 0xC8, 0x37, 0x3C, 0x30,
    0xC2, 0x5A, 0xF3, 0x14, 0x43, 0x98, 0x4F, 0x99, 0x12, 0xBC, 0x68, 0x7E,
    0x20, 0x24, 0xAA, 0x8B, 0xBA, 0x87, 0x32, 0xBC, 0x4B, 0xF3, 0x16, 0x25,
    0xEE, 0xE5, 0xEB, 0x47, 0xED, 0xB2, 0x7D, 0x8F, 0x4F, 0xC8, 0xFB, 0x58,
    0x3D, 0x2E, 0xF6, 0x54, 0xF4, 0xDA, 0xD1, 0x88, 0x6A, 0xD8, 0xBC, 0x32,
    0xEC, 0xDA, 0xF1, 0xBC, 0xAF, 0x16, 0x90, 0xCD, 0xEE, 0x5F, 0x92, 0x0B,
    0xCE, 0xB9, 0x26, 0xCF, 0x18, 0xAE, 0x8C, 0x9B, 0x06, 0x0B, 0x83, 0x4D,
    0x99, 0x31, 0x98, 0x3B, 0x29, 0xE1, 0x16, 0x6A, 0xA4, 0x5E, 0xE8, 0x10,
    0x5F, 0x5B, 0x72, 0x3A, 0xA1, 0xD9, 0x89, 0x70, 0x61, 0xD9, 0xC2, 0x25,
    0x53, 0x5C, 0x44, 0x10, 0x27, 0xD7, 0xF2, 0x68, 0x75, 0x3F, 0xA3, 0xA7,
    0xCF, 0x02, 0x03, 0x49, 0xB4, 0xE4, 0xAF, 0x08, 0xEA, 0xAE, 0x97, 0x07,
    0x36, 0xC8, 0xD5, 0x24, 0xC6, 0x51, 0x8B, 0x91, 0x9A, 0x14, 0x91, 0x67,
    0x6A, 0xC0, 0xC3, 0x0E, 0x7C, 0xD8, 0x1F, 0xD2, 0x31, 0x07, 0x59, 0x5D,
    0x1D, 0xBD, 0x8E, 0xAE, 0xD7, 0x01, 0xBA, 0xDE, 0x0B, 0xDA, 0xA6, 0xBC,
    0x9A, 0xD1, 0x39, 0x59, 0x8F, 0xE5, 0x72, 0x65, 0x0F, 0x2A, 0x2D, 0x90,
    0x56, 0xE9, 0xDA, 0xF5, 0x4A, 0x26, 0xD3, 0xB3, 0x56, 0x19, 0x84, 0x00,
    0x3A, 0x11, 0x78, 0x83,
  };
  static const uint8_t dh2048_g[] = {
    0x02,
  };
  DH *dh;

  if ((dh = DH_new()) == NULL)
    return NULL;

#ifdef HAVE_DH_SET0_PQG
  BIGNUM *p, *g;
  p = BN_bin2bn(dh2048_p, sizeof(dh2048_p), NULL);
  if (!p) {
    lock_file(stderr);
    fputs("Error in BN_bin2bn 1!\n", stderr);
    unlock_file(stderr);
    DH_free(dh);
    return NULL;
  }

  g = BN_bin2bn(dh2048_g, sizeof(dh2048_g), NULL);
  if (!g) {
    lock_file(stderr);
    fputs("Error in BN_bin2bn 2!\n", stderr);
    unlock_file(stderr);
    BN_free(p);
    DH_free(dh);
    return NULL;
  }

  DH_set0_pqg(dh, p, NULL, g);
#else
  dh->p = BN_bin2bn(dh2048_p, sizeof(dh2048_p), NULL);
  if (!dh->p) {
    lock_file(stderr);
    fputs("Error in BN_bin2bn 1!\n", stderr);
    unlock_file(stderr);
    DH_free(dh);
    return NULL;
  }

  dh->g = BN_bin2bn(dh2048_g, sizeof(dh2048_g), NULL);
  if (!dh->g) {
    lock_file(stderr);
    fputs("Error in BN_bin2bn 2!\n", stderr);
    unlock_file(stderr);
    DH_free(dh);
    return NULL;
  }
#endif

  return dh;
}
Beispiel #19
0
Datei: dh.c Projekt: KennethL/otp
ERL_NIF_TERM dh_generate_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{/* (PrivKey|undefined, DHParams=[P,G], Mpint, Len|0) */
    DH *dh_params = NULL;
    int mpint; /* 0 or 4 */

    {
        ERL_NIF_TERM head, tail;
        BIGNUM
            *dh_p = NULL,
            *dh_g = NULL,
            *priv_key_in = NULL;
        unsigned long
            len = 0;

        if (!(get_bn_from_bin(env, argv[0], &priv_key_in)
              || argv[0] == atom_undefined)
            || !enif_get_list_cell(env, argv[1], &head, &tail)
            || !get_bn_from_bin(env, head, &dh_p)
            || !enif_get_list_cell(env, tail, &head, &tail)
            || !get_bn_from_bin(env, head, &dh_g)
            || !enif_is_empty_list(env, tail)
            || !enif_get_int(env, argv[2], &mpint) || (mpint & ~4)
            || !enif_get_ulong(env, argv[3], &len)

            /* Load dh_params with values to use by the generator.
               Mem mgmnt transfered from dh_p etc to dh_params */
            || !(dh_params = DH_new())
            || (priv_key_in && !DH_set0_key(dh_params, NULL, priv_key_in))
            || !DH_set0_pqg(dh_params, dh_p, NULL, dh_g)
            ) {
            if (priv_key_in) BN_free(priv_key_in);
            if (dh_p) BN_free(dh_p);
            if (dh_g) BN_free(dh_g);
            if (dh_params) DH_free(dh_params);
            return enif_make_badarg(env);
        }

        if (len) {
            if (len < BN_num_bits(dh_p))
                DH_set_length(dh_params, len);
            else {
                if (priv_key_in) BN_free(priv_key_in);
                if (dh_p) BN_free(dh_p);
                if (dh_g) BN_free(dh_g);
                if (dh_params) DH_free(dh_params);
                return enif_make_badarg(env);
            }
        }
    }

#ifdef HAS_EVP_PKEY_CTX
    {
        EVP_PKEY_CTX *ctx;
        EVP_PKEY *dhkey, *params;
        int success;

        params = EVP_PKEY_new();
        success = EVP_PKEY_set1_DH(params, dh_params);   /* set the key referenced by params to dh_params... */
        DH_free(dh_params);                              /* ...dh_params (and params) must be freed */
        if (!success) return atom_error;

        ctx = EVP_PKEY_CTX_new(params, NULL);
        EVP_PKEY_free(params);
        if (!ctx) {
            return atom_error;
        }

        if (!EVP_PKEY_keygen_init(ctx)) {
            /* EVP_PKEY_CTX_free(ctx); */
            return atom_error;
        }

        dhkey = EVP_PKEY_new();
        if (!EVP_PKEY_keygen(ctx, &dhkey)) {         /* "performs a key generation operation, the ... */
                                                     /*... generated key is written to ppkey." (=last arg) */
             /* EVP_PKEY_CTX_free(ctx); */
             /* EVP_PKEY_free(dhkey); */
             return atom_error;
        }

        dh_params = EVP_PKEY_get1_DH(dhkey); /* return the referenced key. dh_params and dhkey must be freed */
        EVP_PKEY_free(dhkey);
        if (!dh_params) {
            /* EVP_PKEY_CTX_free(ctx); */
            return atom_error;
        }
        EVP_PKEY_CTX_free(ctx);
    }
#else
    if (!DH_generate_key(dh_params)) return atom_error;
#endif
    {
        unsigned char *pub_ptr, *prv_ptr;
        int pub_len, prv_len;
        ERL_NIF_TERM ret_pub, ret_prv;
        const BIGNUM *pub_key_gen, *priv_key_gen;

        DH_get0_key(dh_params,
                    &pub_key_gen, &priv_key_gen); /* Get pub_key_gen and priv_key_gen.
                                                     "The values point to the internal representation of
                                                     the public key and private key values. This memory
                                                     should not be freed directly." says man */
        pub_len = BN_num_bytes(pub_key_gen);
        prv_len = BN_num_bytes(priv_key_gen);
        pub_ptr = enif_make_new_binary(env, pub_len+mpint, &ret_pub);
        prv_ptr = enif_make_new_binary(env, prv_len+mpint, &ret_prv);
        if (mpint) {
            put_int32(pub_ptr, pub_len); pub_ptr += 4;
            put_int32(prv_ptr, prv_len); prv_ptr += 4;
        }
        BN_bn2bin(pub_key_gen, pub_ptr);
        BN_bn2bin(priv_key_gen, prv_ptr);
        ERL_VALGRIND_MAKE_MEM_DEFINED(pub_ptr, pub_len);
        ERL_VALGRIND_MAKE_MEM_DEFINED(prv_ptr, prv_len);

        DH_free(dh_params);

        return enif_make_tuple2(env, ret_pub, ret_prv);
    }
}
Beispiel #20
0
static int dh_test(void)
{
    BN_GENCB *_cb = NULL;
    DH *a = NULL;
    DH *b = NULL;
    const BIGNUM *ap = NULL, *ag = NULL, *apub_key = NULL;
    const BIGNUM *bpub_key = NULL;
    BIGNUM *bp = NULL, *bg = NULL;
    unsigned char *abuf = NULL;
    unsigned char *bbuf = NULL;
    int i, alen, blen, aout, bout;
    int ret = 0;

    RAND_seed(rnd_seed, sizeof rnd_seed);

    if (!TEST_ptr(_cb = BN_GENCB_new()))
        goto err;
    BN_GENCB_set(_cb, &cb, NULL);
    if (!TEST_ptr(a = DH_new())
            || !TEST_true(DH_generate_parameters_ex(a, 64,
                                                    DH_GENERATOR_5, _cb)))
        goto err;

    if (!DH_check(a, &i))
        goto err;
    if (!TEST_false(i & DH_CHECK_P_NOT_PRIME)
            || !TEST_false(i & DH_CHECK_P_NOT_SAFE_PRIME)
            || !TEST_false(i & DH_UNABLE_TO_CHECK_GENERATOR)
            || !TEST_false(i & DH_NOT_SUITABLE_GENERATOR))
        goto err;

    DH_get0_pqg(a, &ap, NULL, &ag);

    if (!TEST_ptr(b = DH_new()))
        goto err;

    if (!TEST_ptr(bp = BN_dup(ap))
            || !TEST_ptr(bg = BN_dup(ag))
            || !TEST_true(DH_set0_pqg(b, bp, NULL, bg)))
        goto err;
    bp = bg = NULL;

    if (!DH_generate_key(a))
        goto err;
    DH_get0_key(a, &apub_key, NULL);

    if (!DH_generate_key(b))
        goto err;
    DH_get0_key(b, &bpub_key, NULL);

    alen = DH_size(a);
    if (!TEST_ptr(abuf = OPENSSL_malloc(alen))
            || !TEST_true((aout = DH_compute_key(abuf, bpub_key, a)) != -1))
        goto err;

    blen = DH_size(b);
    if (!TEST_ptr(bbuf = OPENSSL_malloc(blen))
            || !TEST_true((bout = DH_compute_key(bbuf, apub_key, b)) != -1))
        goto err;

    if (!TEST_true(aout >= 4)
            || !TEST_mem_eq(abuf, aout, bbuf, bout))
        goto err;

    ret = 1;

 err:
    OPENSSL_free(abuf);
    OPENSSL_free(bbuf);
    DH_free(b);
    DH_free(a);
    BN_free(bp);
    BN_free(bg);
    BN_GENCB_free(_cb);
    return ret;
}
Beispiel #21
0
int main(int argc, char *argv[])
{
    BN_GENCB *_cb = NULL;
    DH *a = NULL;
    DH *b = NULL;
    BIGNUM *ap = NULL, *ag = NULL, *bp = NULL, *bg = NULL, *apub_key = NULL;
    BIGNUM *bpub_key = NULL, *priv_key = NULL;
    char buf[12] = {0};
    unsigned char *abuf = NULL;
    unsigned char *bbuf = NULL;
    int i, alen, blen, aout, bout;
    int ret = 1;
    BIO *out = NULL;

    CRYPTO_set_mem_debug(1);
    CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON);

    RAND_seed(rnd_seed, sizeof rnd_seed);

    out = BIO_new(BIO_s_file());
    if (out == NULL)
        EXIT(1);
    BIO_set_fp(out, stdout, BIO_NOCLOSE | BIO_FP_TEXT);

    _cb = BN_GENCB_new();
    if (_cb == NULL)
        goto err;
    BN_GENCB_set(_cb, &cb, out);
    if (((a = DH_new()) == NULL)
        || (!DH_generate_parameters_ex(a, 64, DH_GENERATOR_5, _cb)))
        goto err;

    if (!DH_check(a, &i))
        goto err;
    if (i & DH_CHECK_P_NOT_PRIME)
        BIO_puts(out, "p value is not prime\n");
    if (i & DH_CHECK_P_NOT_SAFE_PRIME)
        BIO_puts(out, "p value is not a safe prime\n");
    if (i & DH_UNABLE_TO_CHECK_GENERATOR)
        BIO_puts(out, "unable to check the generator value\n");
    if (i & DH_NOT_SUITABLE_GENERATOR)
        BIO_puts(out, "the g value is not a generator\n");

    DH_get0_pqg(a, &ap, NULL, &ag);
    BIO_puts(out, "\np    =");
    BN_print(out, ap);
    BIO_puts(out, "\ng    =");
    BN_print(out, ag);
    BIO_puts(out, "\n");

    b = DH_new();
    if (b == NULL)
        goto err;

    bp = BN_dup(ap);
    bg = BN_dup(ag);
    if ((bp == NULL) || (bg == NULL) || !DH_set0_pqg(b, bp, NULL, bg))
        goto err;
    bp = bg = NULL;

    if (!DH_generate_key(a))
        goto err;
    DH_get0_key(a, &apub_key, &priv_key);
    BIO_puts(out, "pri 1=");
    BN_print(out, priv_key);
    BIO_puts(out, "\npub 1=");
    BN_print(out, apub_key);
    BIO_puts(out, "\n");

    if (!DH_generate_key(b))
        goto err;
    DH_get0_key(b, &bpub_key, &priv_key);
    BIO_puts(out, "pri 2=");
    BN_print(out, priv_key);
    BIO_puts(out, "\npub 2=");
    BN_print(out, bpub_key);
    BIO_puts(out, "\n");

    alen = DH_size(a);
    abuf = OPENSSL_malloc(alen);
    if (abuf == NULL)
        goto err;

    aout = DH_compute_key(abuf, bpub_key, a);

    BIO_puts(out, "key1 =");
    for (i = 0; i < aout; i++) {
        sprintf(buf, "%02X", abuf[i]);
        BIO_puts(out, buf);
    }
    BIO_puts(out, "\n");

    blen = DH_size(b);
    bbuf = OPENSSL_malloc(blen);
    if (bbuf == NULL)
        goto err;

    bout = DH_compute_key(bbuf, apub_key, b);

    BIO_puts(out, "key2 =");
    for (i = 0; i < bout; i++) {
        sprintf(buf, "%02X", bbuf[i]);
        BIO_puts(out, buf);
    }
    BIO_puts(out, "\n");
    if ((aout < 4) || (bout != aout) || (memcmp(abuf, bbuf, aout) != 0)) {
        fprintf(stderr, "Error in DH routines\n");
        ret = 1;
    } else
        ret = 0;
    if (!run_rfc5114_tests())
        ret = 1;
 err:
    (void)BIO_flush(out);
    ERR_print_errors_fp(stderr);

    OPENSSL_free(abuf);
    OPENSSL_free(bbuf);
    DH_free(b);
    DH_free(a);
    BN_free(bp);
    BN_free(bg);
    BN_GENCB_free(_cb);
    BIO_free(out);

#ifndef OPENSSL_NO_CRYPTO_MDEBUG
    if (CRYPTO_mem_leaks_fp(stderr) <= 0)
        ret = 1;
#endif

    EXIT(ret);
}
Beispiel #22
0
void Context::initDH(const std::string& dhParamsFile)
{
#ifndef OPENSSL_NO_DH
    // 1024-bit MODP Group with 160-bit prime order subgroup (RFC5114)
	// -----BEGIN DH PARAMETERS-----
	// MIIBDAKBgQCxC4+WoIDgHd6S3l6uXVTsUsmfvPsGo8aaap3KUtI7YWBz4oZ1oj0Y
	// mDjvHi7mUsAT7LSuqQYRIySXXDzUm4O/rMvdfZDEvXCYSI6cIZpzck7/1vrlZEc4
	// +qMaT/VbzMChUa9fDci0vUW/N982XBpl5oz9p21NpwjfH7K8LkpDcQKBgQCk0cvV
	// w/00EmdlpELvuZkF+BBN0lisUH/WQGz/FCZtMSZv6h5cQVZLd35pD1UE8hMWAhe0
	// sBuIal6RVH+eJ0n01/vX07mpLuGQnQ0iY/gKdqaiTAh6CR9THb8KAWm2oorWYqTR
	// jnOvoy13nVkY0IvIhY9Nzvl8KiSFXm7rIrOy5QICAKA=
	// -----END DH PARAMETERS-----
	//

	static const unsigned char dh1024_p[] = 
	{
		0xB1,0x0B,0x8F,0x96,0xA0,0x80,0xE0,0x1D,0xDE,0x92,0xDE,0x5E,
		0xAE,0x5D,0x54,0xEC,0x52,0xC9,0x9F,0xBC,0xFB,0x06,0xA3,0xC6,
		0x9A,0x6A,0x9D,0xCA,0x52,0xD2,0x3B,0x61,0x60,0x73,0xE2,0x86,
		0x75,0xA2,0x3D,0x18,0x98,0x38,0xEF,0x1E,0x2E,0xE6,0x52,0xC0,
		0x13,0xEC,0xB4,0xAE,0xA9,0x06,0x11,0x23,0x24,0x97,0x5C,0x3C,
		0xD4,0x9B,0x83,0xBF,0xAC,0xCB,0xDD,0x7D,0x90,0xC4,0xBD,0x70,
		0x98,0x48,0x8E,0x9C,0x21,0x9A,0x73,0x72,0x4E,0xFF,0xD6,0xFA,
		0xE5,0x64,0x47,0x38,0xFA,0xA3,0x1A,0x4F,0xF5,0x5B,0xCC,0xC0,
		0xA1,0x51,0xAF,0x5F,0x0D,0xC8,0xB4,0xBD,0x45,0xBF,0x37,0xDF,
		0x36,0x5C,0x1A,0x65,0xE6,0x8C,0xFD,0xA7,0x6D,0x4D,0xA7,0x08,
		0xDF,0x1F,0xB2,0xBC,0x2E,0x4A,0x43,0x71,
	};

	static const unsigned char dh1024_g[] = 
	{
		0xA4,0xD1,0xCB,0xD5,0xC3,0xFD,0x34,0x12,0x67,0x65,0xA4,0x42,
		0xEF,0xB9,0x99,0x05,0xF8,0x10,0x4D,0xD2,0x58,0xAC,0x50,0x7F,
		0xD6,0x40,0x6C,0xFF,0x14,0x26,0x6D,0x31,0x26,0x6F,0xEA,0x1E,
		0x5C,0x41,0x56,0x4B,0x77,0x7E,0x69,0x0F,0x55,0x04,0xF2,0x13,
		0x16,0x02,0x17,0xB4,0xB0,0x1B,0x88,0x6A,0x5E,0x91,0x54,0x7F,
		0x9E,0x27,0x49,0xF4,0xD7,0xFB,0xD7,0xD3,0xB9,0xA9,0x2E,0xE1,
		0x90,0x9D,0x0D,0x22,0x63,0xF8,0x0A,0x76,0xA6,0xA2,0x4C,0x08,
		0x7A,0x09,0x1F,0x53,0x1D,0xBF,0x0A,0x01,0x69,0xB6,0xA2,0x8A,
		0xD6,0x62,0xA4,0xD1,0x8E,0x73,0xAF,0xA3,0x2D,0x77,0x9D,0x59,
		0x18,0xD0,0x8B,0xC8,0x85,0x8F,0x4D,0xCE,0xF9,0x7C,0x2A,0x24,
		0x85,0x5E,0x6E,0xEB,0x22,0xB3,0xB2,0xE5,
	};

	DH* dh = 0;
	if (!dhParamsFile.empty()) 
	{
		BIO* bio = BIO_new_file(dhParamsFile.c_str(), "r");
		if (!bio) 
		{
			std::string msg = Utility::getLastError();
			throw SSLContextException(std::string("Error opening Diffie-Hellman parameters file ") + dhParamsFile, msg);
		}
		dh = PEM_read_bio_DHparams(bio, 0, 0, 0);
		BIO_free(bio);
		if (!dh) 
		{
			std::string msg = Utility::getLastError();
			throw SSLContextException(std::string("Error reading Diffie-Hellman parameters from file ") + dhParamsFile, msg);
		}
	} 
	else 
	{
		dh = DH_new();
		if (!dh) 
		{
			std::string msg = Utility::getLastError();
			throw SSLContextException("Error creating Diffie-Hellman parameters", msg);
		}
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
		BIGNUM* p = BN_bin2bn(dh1024_p, sizeof(dh1024_p), 0);
		BIGNUM* g = BN_bin2bn(dh1024_g, sizeof(dh1024_g), 0);
		DH_set0_pqg(dh, p, 0, g);
		DH_set_length(dh, 160);
		if (!p || !g)
		{
			DH_free(dh);
			throw SSLContextException("Error creating Diffie-Hellman parameters");
		}
#else
		dh->p = BN_bin2bn(dh1024_p, sizeof(dh1024_p), 0);
		dh->g = BN_bin2bn(dh1024_g, sizeof(dh1024_g), 0);
		dh->length = 160;
		if ((!dh->p) || (!dh->g)) 
		{
			DH_free(dh);
			throw SSLContextException("Error creating Diffie-Hellman parameters");
		}
#endif
	}
	SSL_CTX_set_tmp_dh(_pSSLContext, dh);
	SSL_CTX_set_options(_pSSLContext, SSL_OP_SINGLE_DH_USE);
	DH_free(dh);
#else
	if (!dhParamsFile.empty())
		throw SSLContextException("OpenSSL does not support DH");
#endif
}