/** Initialize the SSL context. * \return pointer to SSL context object. */ SSL_CTX * ssl_init(char *private_key_file, char *ca_file, int req_client_cert) { const SSL_METHOD *meth; /* If this const gives you a warning, you're using an old version of OpenSSL. */ unsigned char context[128]; DH *dh; unsigned int reps = 1; if (!bio_err) { if (!SSL_library_init()) return NULL; SSL_load_error_strings(); /* Error write context */ bio_err = BIO_new_fp(stderr, BIO_NOCLOSE); } do_rawlog(LT_ERR, "Seeding OpenSSL random number pool."); while (!RAND_status()) { /* At this point, a system with /dev/urandom or a EGD file in the usual places will have enough entropy. Otherwise, be lazy and use random numbers until it's satisfied. */ uint32_t gibberish[4]; int n; for (n = 0; n < 4; n++) gibberish[n] = gen_rand32(); RAND_seed(gibberish, sizeof gibberish); reps += 1; } do_rawlog(LT_ERR, "Seeded after %u %s.", reps, reps > 1 ? "cycles" : "cycle"); /* Set up SIGPIPE handler here? */ /* Create context */ meth = SSLv23_server_method(); ctx = SSL_CTX_new(meth); /* Load keys/certs */ if (private_key_file && *private_key_file) { if (!SSL_CTX_use_certificate_chain_file(ctx, private_key_file)) { ssl_errordump ("Unable to load server certificate - only anonymous ciphers supported."); } if (!SSL_CTX_use_PrivateKey_file(ctx, private_key_file, SSL_FILETYPE_PEM)) { ssl_errordump ("Unable to load private key - only anonymous ciphers supported."); } } /* Load trusted CAs */ if (ca_file && *ca_file) { if (!SSL_CTX_load_verify_locations(ctx, ca_file, NULL)) { ssl_errordump("Unable to load CA certificates"); } else { if (req_client_cert) SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, client_verify_callback); else SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, client_verify_callback); #if (OPENSSL_VERSION_NUMBER < 0x0090600fL) SSL_CTX_set_verify_depth(ctx, 1); #endif } } SSL_CTX_set_options(ctx, SSL_OP_SINGLE_DH_USE | SSL_OP_ALL); SSL_CTX_set_mode(ctx, SSL_MODE_ENABLE_PARTIAL_WRITE | SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER); /* Set up DH callback */ dh = get_dh1024(); SSL_CTX_set_tmp_dh(ctx, dh); /* The above function makes a private copy of this */ DH_free(dh); /* Set the cipher list to the usual default list, except that * we'll allow anonymous diffie-hellman, too. */ SSL_CTX_set_cipher_list(ctx, "ALL:ADH:RC4+RSA:+SSLv2:@STRENGTH"); /* Set up session cache if we can */ strncpy((char *) context, MUDNAME, 128); SSL_CTX_set_session_id_context(ctx, context, u_strlen(context)); /* Load hash algorithms */ OpenSSL_add_all_digests(); return ctx; }
static int __ssl_setup(struct ast_tls_config *cfg, int client) { #ifndef DO_SSL cfg->enabled = 0; return 0; #else int disable_ssl = 0; long ssl_opts = 0; if (!cfg->enabled) { return 0; } /* Get rid of an old SSL_CTX since we're about to * allocate a new one */ if (cfg->ssl_ctx) { SSL_CTX_free(cfg->ssl_ctx); cfg->ssl_ctx = NULL; } if (client) { #if !defined(OPENSSL_NO_SSL2) && (OPENSSL_VERSION_NUMBER < 0x10100000L) if (ast_test_flag(&cfg->flags, AST_SSL_SSLV2_CLIENT)) { ast_log(LOG_WARNING, "Usage of SSLv2 is discouraged due to known vulnerabilities. Please use 'tlsv1' or leave the TLS method unspecified!\n"); cfg->ssl_ctx = SSL_CTX_new(SSLv2_client_method()); } else #endif #ifndef OPENSSL_NO_SSL3_METHOD if (ast_test_flag(&cfg->flags, AST_SSL_SSLV3_CLIENT)) { ast_log(LOG_WARNING, "Usage of SSLv3 is discouraged due to known vulnerabilities. Please use 'tlsv1' or leave the TLS method unspecified!\n"); cfg->ssl_ctx = SSL_CTX_new(SSLv3_client_method()); } else #endif if (ast_test_flag(&cfg->flags, AST_SSL_TLSV1_CLIENT)) { cfg->ssl_ctx = SSL_CTX_new(TLSv1_client_method()); } else { disable_ssl = 1; cfg->ssl_ctx = SSL_CTX_new(SSLv23_client_method()); } } else { disable_ssl = 1; cfg->ssl_ctx = SSL_CTX_new(SSLv23_server_method()); } if (!cfg->ssl_ctx) { ast_debug(1, "Sorry, SSL_CTX_new call returned null...\n"); cfg->enabled = 0; return 0; } /* Due to the POODLE vulnerability, completely disable * SSLv2 and SSLv3 if we are not explicitly told to use * them. SSLv23_*_method supports TLSv1+. */ if (disable_ssl) { ssl_opts |= SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3; } if (ast_test_flag(&cfg->flags, AST_SSL_SERVER_CIPHER_ORDER)) { ssl_opts |= SSL_OP_CIPHER_SERVER_PREFERENCE; } if (ast_test_flag(&cfg->flags, AST_SSL_DISABLE_TLSV1)) { ssl_opts |= SSL_OP_NO_TLSv1; } #if defined(HAVE_SSL_OP_NO_TLSV1_1) && defined(HAVE_SSL_OP_NO_TLSV1_2) if (ast_test_flag(&cfg->flags, AST_SSL_DISABLE_TLSV11)) { ssl_opts |= SSL_OP_NO_TLSv1_1; } if (ast_test_flag(&cfg->flags, AST_SSL_DISABLE_TLSV12)) { ssl_opts |= SSL_OP_NO_TLSv1_2; } #else ast_log(LOG_WARNING, "Your version of OpenSSL leaves you potentially vulnerable " "to the SSL BEAST attack. Please upgrade to OpenSSL 1.0.1 or later\n"); #endif SSL_CTX_set_options(cfg->ssl_ctx, ssl_opts); SSL_CTX_set_verify(cfg->ssl_ctx, ast_test_flag(&cfg->flags, AST_SSL_VERIFY_CLIENT) ? SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT : SSL_VERIFY_NONE, NULL); if (!ast_strlen_zero(cfg->certfile)) { char *tmpprivate = ast_strlen_zero(cfg->pvtfile) ? cfg->certfile : cfg->pvtfile; if (SSL_CTX_use_certificate_chain_file(cfg->ssl_ctx, cfg->certfile) == 0) { if (!client) { /* Clients don't need a certificate, but if its setup we can use it */ ast_log(LOG_ERROR, "TLS/SSL error loading cert file. <%s>\n", cfg->certfile); cfg->enabled = 0; SSL_CTX_free(cfg->ssl_ctx); cfg->ssl_ctx = NULL; return 0; } } if ((SSL_CTX_use_PrivateKey_file(cfg->ssl_ctx, tmpprivate, SSL_FILETYPE_PEM) == 0) || (SSL_CTX_check_private_key(cfg->ssl_ctx) == 0 )) { if (!client) { /* Clients don't need a private key, but if its setup we can use it */ ast_log(LOG_ERROR, "TLS/SSL error loading private key file. <%s>\n", tmpprivate); cfg->enabled = 0; SSL_CTX_free(cfg->ssl_ctx); cfg->ssl_ctx = NULL; return 0; } } if (!client) { size_t certfile_len = strlen(cfg->certfile); /* expects a file name which contains _rsa. like asterisk_rsa.pem * ignores any 3-character file-extension like .pem, .cer, .crt */ if (certfile_len >= 8 && !strncmp(cfg->certfile + certfile_len - 8, "_rsa.", 5)) { __ssl_setup_certs(cfg, certfile_len, "_ecc.", "ECC"); __ssl_setup_certs(cfg, certfile_len, "_dsa.", "DSA"); } } } if (!ast_strlen_zero(cfg->cipher)) { if (SSL_CTX_set_cipher_list(cfg->ssl_ctx, cfg->cipher) == 0 ) { if (!client) { ast_log(LOG_ERROR, "TLS/SSL cipher error <%s>\n", cfg->cipher); cfg->enabled = 0; SSL_CTX_free(cfg->ssl_ctx); cfg->ssl_ctx = NULL; return 0; } } } if (!ast_strlen_zero(cfg->cafile) || !ast_strlen_zero(cfg->capath)) { if (SSL_CTX_load_verify_locations(cfg->ssl_ctx, S_OR(cfg->cafile, NULL), S_OR(cfg->capath,NULL)) == 0) { ast_log(LOG_ERROR, "TLS/SSL CA file(%s)/path(%s) error\n", cfg->cafile, cfg->capath); } } #ifdef HAVE_OPENSSL_EC if (!ast_strlen_zero(cfg->pvtfile)) { BIO *bio = BIO_new_file(cfg->pvtfile, "r"); if (bio != NULL) { DH *dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL); if (dh != NULL) { if (SSL_CTX_set_tmp_dh(cfg->ssl_ctx, dh)) { long options = SSL_OP_CIPHER_SERVER_PREFERENCE | SSL_OP_SINGLE_DH_USE | SSL_OP_SINGLE_ECDH_USE; options = SSL_CTX_set_options(cfg->ssl_ctx, options); ast_verb(2, "TLS/SSL DH initialized, PFS cipher-suites enabled\n"); } DH_free(dh); } BIO_free(bio); } } #ifndef SSL_CTRL_SET_ECDH_AUTO #define SSL_CTRL_SET_ECDH_AUTO 94 #endif /* SSL_CTX_set_ecdh_auto(cfg->ssl_ctx, on); requires OpenSSL 1.0.2 which wraps: */ if (SSL_CTX_ctrl(cfg->ssl_ctx, SSL_CTRL_SET_ECDH_AUTO, 1, NULL)) { ast_verb(2, "TLS/SSL ECDH initialized (automatic), faster PFS ciphers enabled\n"); } else { /* enables AES-128 ciphers, to get AES-256 use NID_secp384r1 */ EC_KEY *ecdh = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1); if (ecdh != NULL) { if (SSL_CTX_set_tmp_ecdh(cfg->ssl_ctx, ecdh)) { ast_verb(2, "TLS/SSL ECDH initialized (secp256r1), faster PFS cipher-suites enabled\n"); } EC_KEY_free(ecdh); } } #endif /* #ifdef HAVE_OPENSSL_EC */ ast_verb(2, "TLS/SSL certificate ok\n"); /* We should log which one that is ok. This message doesn't really make sense in production use */ return 1; #endif }
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); } }
int input_kex_dh_init(int type, u_int32_t seq, void *ctxt) { struct ssh *ssh = ctxt; struct kex *kex = ssh->kex; BIGNUM *shared_secret = NULL, *dh_client_pub = NULL; struct sshkey *server_host_public, *server_host_private; u_char *kbuf = NULL, *signature = NULL, *server_host_key_blob = NULL; u_char hash[SSH_DIGEST_MAX_LENGTH]; size_t sbloblen, slen; size_t klen = 0, hashlen; int kout, r; if (kex->load_host_public_key == NULL || kex->load_host_private_key == NULL) { r = SSH_ERR_INVALID_ARGUMENT; goto out; } server_host_public = kex->load_host_public_key(kex->hostkey_type, kex->hostkey_nid, ssh); server_host_private = kex->load_host_private_key(kex->hostkey_type, kex->hostkey_nid, ssh); if (server_host_public == NULL) { r = SSH_ERR_NO_HOSTKEY_LOADED; goto out; } /* key, cert */ if ((dh_client_pub = BN_new()) == NULL) { r = SSH_ERR_ALLOC_FAIL; goto out; } if ((r = sshpkt_get_bignum2(ssh, dh_client_pub)) != 0 || (r = sshpkt_get_end(ssh)) != 0) goto out; #ifdef DEBUG_KEXDH fprintf(stderr, "dh_client_pub= "); BN_print_fp(stderr, dh_client_pub); fprintf(stderr, "\n"); debug("bits %d", BN_num_bits(dh_client_pub)); #endif #ifdef DEBUG_KEXDH DHparams_print_fp(stderr, kex->dh); fprintf(stderr, "pub= "); BN_print_fp(stderr, kex->dh->pub_key); fprintf(stderr, "\n"); #endif if (!dh_pub_is_valid(kex->dh, dh_client_pub)) { sshpkt_disconnect(ssh, "bad client public DH value"); r = SSH_ERR_MESSAGE_INCOMPLETE; goto out; } klen = DH_size(kex->dh); if ((kbuf = malloc(klen)) == NULL || (shared_secret = BN_new()) == NULL) { r = SSH_ERR_ALLOC_FAIL; goto out; } if ((kout = DH_compute_key(kbuf, dh_client_pub, kex->dh)) < 0 || BN_bin2bn(kbuf, kout, shared_secret) == NULL) { r = SSH_ERR_LIBCRYPTO_ERROR; goto out; } #ifdef DEBUG_KEXDH dump_digest("shared secret", kbuf, kout); #endif if ((r = sshkey_to_blob(server_host_public, &server_host_key_blob, &sbloblen)) != 0) goto out; /* calc H */ hashlen = sizeof(hash); if ((r = kex_dh_hash( kex->client_version_string, kex->server_version_string, sshbuf_ptr(kex->peer), sshbuf_len(kex->peer), sshbuf_ptr(kex->my), sshbuf_len(kex->my), server_host_key_blob, sbloblen, dh_client_pub, kex->dh->pub_key, shared_secret, hash, &hashlen)) != 0) goto out; /* save session id := H */ if (kex->session_id == NULL) { kex->session_id_len = hashlen; kex->session_id = malloc(kex->session_id_len); if (kex->session_id == NULL) { r = SSH_ERR_ALLOC_FAIL; goto out; } memcpy(kex->session_id, hash, kex->session_id_len); } /* sign H */ if ((r = kex->sign(server_host_private, server_host_public, &signature, &slen, hash, hashlen, kex->hostkey_alg, ssh->compat)) < 0) goto out; /* destroy_sensitive_data(); */ /* send server hostkey, DH pubkey 'f' and singed H */ if ((r = sshpkt_start(ssh, SSH2_MSG_KEXDH_REPLY)) != 0 || (r = sshpkt_put_string(ssh, server_host_key_blob, sbloblen)) != 0 || (r = sshpkt_put_bignum2(ssh, kex->dh->pub_key)) != 0 || /* f */ (r = sshpkt_put_string(ssh, signature, slen)) != 0 || (r = sshpkt_send(ssh)) != 0) goto out; if ((r = kex_derive_keys_bn(ssh, hash, hashlen, shared_secret)) == 0) r = kex_send_newkeys(ssh); out: explicit_bzero(hash, sizeof(hash)); DH_free(kex->dh); kex->dh = NULL; if (dh_client_pub) BN_clear_free(dh_client_pub); if (kbuf) { explicit_bzero(kbuf, klen); free(kbuf); } if (shared_secret) BN_clear_free(shared_secret); free(server_host_key_blob); free(signature); return r; }
int MAIN(int argc, char **argv) { DH *dh=NULL; int i,badops=0,text=0; #ifndef OPENSSL_NO_DSA int dsaparam=0; #endif BIO *in=NULL,*out=NULL; int informat,outformat,check=0,noout=0,C=0,ret=1; char *infile,*outfile,*prog; char *inrand=NULL; #ifndef OPENSSL_NO_ENGINE char *engine=NULL; #endif int num = 0, g = 0; apps_startup(); if (bio_err == NULL) if ((bio_err=BIO_new(BIO_s_file())) != NULL) BIO_set_fp(bio_err,stderr,BIO_NOCLOSE|BIO_FP_TEXT); if (!load_config(bio_err, NULL)) goto end; infile=NULL; outfile=NULL; informat=FORMAT_PEM; outformat=FORMAT_PEM; prog=argv[0]; argc--; argv++; while (argc >= 1) { if (strcmp(*argv,"-inform") == 0) { if (--argc < 1) goto bad; informat=str2fmt(*(++argv)); } else if (strcmp(*argv,"-outform") == 0) { if (--argc < 1) goto bad; outformat=str2fmt(*(++argv)); } else if (strcmp(*argv,"-in") == 0) { if (--argc < 1) goto bad; infile= *(++argv); } else if (strcmp(*argv,"-out") == 0) { if (--argc < 1) goto bad; outfile= *(++argv); } #ifndef OPENSSL_NO_ENGINE else if (strcmp(*argv,"-engine") == 0) { if (--argc < 1) goto bad; engine= *(++argv); } #endif else if (strcmp(*argv,"-check") == 0) check=1; else if (strcmp(*argv,"-text") == 0) text=1; #ifndef OPENSSL_NO_DSA else if (strcmp(*argv,"-dsaparam") == 0) dsaparam=1; #endif else if (strcmp(*argv,"-C") == 0) C=1; else if (strcmp(*argv,"-noout") == 0) noout=1; else if (strcmp(*argv,"-2") == 0) g=2; else if (strcmp(*argv,"-5") == 0) g=5; else if (strcmp(*argv,"-rand") == 0) { if (--argc < 1) goto bad; inrand= *(++argv); } else if (((sscanf(*argv,"%d",&num) == 0) || (num <= 0))) goto bad; argv++; argc--; } if (badops) { bad: BIO_printf(bio_err,"%s [options] [numbits]\n",prog); BIO_printf(bio_err,"where options are\n"); BIO_printf(bio_err," -inform arg input format - one of DER PEM\n"); BIO_printf(bio_err," -outform arg output format - one of DER PEM\n"); BIO_printf(bio_err," -in arg input file\n"); BIO_printf(bio_err," -out arg output file\n"); #ifndef OPENSSL_NO_DSA BIO_printf(bio_err," -dsaparam read or generate DSA parameters, convert to DH\n"); #endif BIO_printf(bio_err," -check check the DH parameters\n"); BIO_printf(bio_err," -text print a text form of the DH parameters\n"); BIO_printf(bio_err," -C Output C code\n"); BIO_printf(bio_err," -2 generate parameters using 2 as the generator value\n"); BIO_printf(bio_err," -5 generate parameters using 5 as the generator value\n"); BIO_printf(bio_err," numbits number of bits in to generate (default 512)\n"); #ifndef OPENSSL_NO_ENGINE BIO_printf(bio_err," -engine e use engine e, possibly a hardware device.\n"); #endif BIO_printf(bio_err," -rand file%cfile%c...\n", LIST_SEPARATOR_CHAR, LIST_SEPARATOR_CHAR); BIO_printf(bio_err," - load the file (or the files in the directory) into\n"); BIO_printf(bio_err," the random number generator\n"); BIO_printf(bio_err," -noout no output\n"); goto end; } ERR_load_crypto_strings(); #ifndef OPENSSL_NO_ENGINE setup_engine(bio_err, engine, 0); #endif if (g && !num) num = DEFBITS; #ifndef OPENSSL_NO_DSA if (dsaparam) { if (g) { BIO_printf(bio_err, "generator may not be chosen for DSA parameters\n"); goto end; } } else #endif { /* DH parameters */ if (num && !g) g = 2; } if(num) { BN_GENCB cb; BN_GENCB_set(&cb, dh_cb, bio_err); if (!app_RAND_load_file(NULL, bio_err, 1) && inrand == NULL) { BIO_printf(bio_err,"warning, not much extra random data, consider using the -rand option\n"); } if (inrand != NULL) BIO_printf(bio_err,"%ld semi-random bytes loaded\n", app_RAND_load_files(inrand)); #ifndef OPENSSL_NO_DSA if (dsaparam) { DSA *dsa = DSA_new(); BIO_printf(bio_err,"Generating DSA parameters, %d bit long prime\n",num); if(!dsa || !DSA_generate_parameters_ex(dsa, num, NULL, 0, NULL, NULL, &cb)) { if(dsa) DSA_free(dsa); ERR_print_errors(bio_err); goto end; } dh = DSA_dup_DH(dsa); DSA_free(dsa); if (dh == NULL) { ERR_print_errors(bio_err); goto end; } } else #endif { dh = DH_new(); BIO_printf(bio_err,"Generating DH parameters, %d bit long safe prime, generator %d\n",num,g); BIO_printf(bio_err,"This is going to take a long time\n"); if(!dh || !DH_generate_parameters_ex(dh, num, g, &cb)) { ERR_print_errors(bio_err); goto end; } } app_RAND_write_file(NULL, bio_err); } else { in=BIO_new(BIO_s_file()); if (in == NULL) { ERR_print_errors(bio_err); goto end; } if (infile == NULL) BIO_set_fp(in,stdin,BIO_NOCLOSE); else { if (BIO_read_filename(in,infile) <= 0) { perror(infile); goto end; } } if (informat != FORMAT_ASN1 && informat != FORMAT_PEM) { BIO_printf(bio_err,"bad input format specified\n"); goto end; } #ifndef OPENSSL_NO_DSA if (dsaparam) { DSA *dsa; if (informat == FORMAT_ASN1) dsa=d2i_DSAparams_bio(in,NULL); else /* informat == FORMAT_PEM */ dsa=PEM_read_bio_DSAparams(in,NULL,NULL,NULL); if (dsa == NULL) { BIO_printf(bio_err,"unable to load DSA parameters\n"); ERR_print_errors(bio_err); goto end; } dh = DSA_dup_DH(dsa); DSA_free(dsa); if (dh == NULL) { ERR_print_errors(bio_err); goto end; } } else #endif { if (informat == FORMAT_ASN1) dh=d2i_DHparams_bio(in,NULL); else /* informat == FORMAT_PEM */ dh=PEM_read_bio_DHparams(in,NULL,NULL,NULL); if (dh == NULL) { BIO_printf(bio_err,"unable to load DH parameters\n"); ERR_print_errors(bio_err); goto end; } } /* dh != NULL */ } out=BIO_new(BIO_s_file()); if (out == NULL) { ERR_print_errors(bio_err); goto end; } if (outfile == NULL) { BIO_set_fp(out,stdout,BIO_NOCLOSE); #ifdef OPENSSL_SYS_VMS { BIO *tmpbio = BIO_new(BIO_f_linebuffer()); out = BIO_push(tmpbio, out); } #endif } else { if (BIO_write_filename(out,outfile) <= 0) { perror(outfile); goto end; } } if (text) { DHparams_print(out,dh); } if (check) { if (!DH_check(dh,&i)) { ERR_print_errors(bio_err); goto end; } if (i & DH_CHECK_P_NOT_PRIME) printf("p value is not prime\n"); if (i & DH_CHECK_P_NOT_SAFE_PRIME) printf("p value is not a safe prime\n"); if (i & DH_UNABLE_TO_CHECK_GENERATOR) printf("unable to check the generator value\n"); if (i & DH_NOT_SUITABLE_GENERATOR) printf("the g value is not a generator\n"); if (i == 0) printf("DH parameters appear to be ok.\n"); } if (C) { unsigned char *data; int len,l,bits; len=BN_num_bytes(dh->p); bits=BN_num_bits(dh->p); data=(unsigned char *)OPENSSL_malloc(len); if (data == NULL) { perror("OPENSSL_malloc"); goto end; } printf("#ifndef HEADER_DH_H\n" "#include <openssl/dh.h>\n" "#endif\n"); printf("DH *get_dh%d()\n\t{\n",bits); l=BN_bn2bin(dh->p,data); printf("\tstatic unsigned char dh%d_p[]={",bits); for (i=0; i<l; i++) { if ((i%12) == 0) printf("\n\t\t"); printf("0x%02X,",data[i]); } printf("\n\t\t};\n"); l=BN_bn2bin(dh->g,data); printf("\tstatic unsigned char dh%d_g[]={",bits); for (i=0; i<l; i++) { if ((i%12) == 0) printf("\n\t\t"); printf("0x%02X,",data[i]); } printf("\n\t\t};\n"); printf("\tDH *dh;\n\n"); printf("\tif ((dh=DH_new()) == NULL) return(NULL);\n"); printf("\tdh->p=BN_bin2bn(dh%d_p,sizeof(dh%d_p),NULL);\n", bits,bits); printf("\tdh->g=BN_bin2bn(dh%d_g,sizeof(dh%d_g),NULL);\n", bits,bits); printf("\tif ((dh->p == NULL) || (dh->g == NULL))\n"); printf("\t\t{ DH_free(dh); return(NULL); }\n"); if (dh->length) printf("\tdh->length = %ld;\n", dh->length); printf("\treturn(dh);\n\t}\n"); OPENSSL_free(data); } if (!noout) { if (outformat == FORMAT_ASN1) i=i2d_DHparams_bio(out,dh); else if (outformat == FORMAT_PEM) i=PEM_write_bio_DHparams(out,dh); else { BIO_printf(bio_err,"bad output format specified for outfile\n"); goto end; } if (!i) { BIO_printf(bio_err,"unable to write DH parameters\n"); ERR_print_errors(bio_err); goto end; } } ret=0; end: if (in != NULL) BIO_free(in); if (out != NULL) BIO_free_all(out); if (dh != NULL) DH_free(dh); apps_shutdown(); OPENSSL_EXIT(ret); }
void kexdh_server(Kex *kex) { BIGNUM *shared_secret = NULL, *dh_client_pub = NULL; DH *dh; Key *server_host_public, *server_host_private; u_char *kbuf, *hash, *signature = NULL, *server_host_key_blob = NULL; u_int sbloblen, klen, hashlen, slen; int kout; /* generate server DH public key */ switch (kex->kex_type) { case KEX_DH_GRP1_SHA1: dh = dh_new_group1(); break; case KEX_DH_GRP14_SHA1: dh = dh_new_group14(); break; default: fatal("%s: Unexpected KEX type %d", __func__, kex->kex_type); } dh_gen_key(dh, kex->we_need * 8); debug("expecting SSH2_MSG_KEXDH_INIT"); packet_read_expect(SSH2_MSG_KEXDH_INIT); if (kex->load_host_public_key == NULL || kex->load_host_private_key == NULL) fatal("Cannot load hostkey"); server_host_public = kex->load_host_public_key(kex->hostkey_type); if (server_host_public == NULL) fatal("Unsupported hostkey type %d", kex->hostkey_type); server_host_private = kex->load_host_private_key(kex->hostkey_type); if (server_host_private == NULL) fatal("Missing private key for hostkey type %d", kex->hostkey_type); /* key, cert */ if ((dh_client_pub = BN_new()) == NULL) fatal("dh_client_pub == NULL"); packet_get_bignum2(dh_client_pub); packet_check_eom(); #ifdef DEBUG_KEXDH fprintf(stderr, "dh_client_pub= "); BN_print_fp(stderr, dh_client_pub); fprintf(stderr, "\n"); debug("bits %d", BN_num_bits(dh_client_pub)); #endif #ifdef DEBUG_KEXDH DHparams_print_fp(stderr, dh); fprintf(stderr, "pub= "); BN_print_fp(stderr, dh->pub_key); fprintf(stderr, "\n"); #endif if (!dh_pub_is_valid(dh, dh_client_pub)) packet_disconnect("bad client public DH value"); klen = DH_size(dh); kbuf = xmalloc(klen); if ((kout = DH_compute_key(kbuf, dh_client_pub, dh)) < 0) fatal("DH_compute_key: failed"); #ifdef DEBUG_KEXDH dump_digest("shared secret", kbuf, kout); #endif if ((shared_secret = BN_new()) == NULL) fatal("kexdh_server: BN_new failed"); if (BN_bin2bn(kbuf, kout, shared_secret) == NULL) fatal("kexdh_server: BN_bin2bn failed"); memset(kbuf, 0, klen); xfree(kbuf); key_to_blob(server_host_public, &server_host_key_blob, &sbloblen); /* calc H */ kex_dh_hash( kex->client_version_string, kex->server_version_string, buffer_ptr(&kex->peer), buffer_len(&kex->peer), buffer_ptr(&kex->my), buffer_len(&kex->my), server_host_key_blob, sbloblen, dh_client_pub, dh->pub_key, shared_secret, &hash, &hashlen ); BN_clear_free(dh_client_pub); /* save session id := H */ if (kex->session_id == NULL) { kex->session_id_len = hashlen; kex->session_id = xmalloc(kex->session_id_len); memcpy(kex->session_id, hash, kex->session_id_len); } /* sign H */ if (PRIVSEP(key_sign(server_host_private, &signature, &slen, hash, hashlen)) < 0) fatal("kexdh_server: key_sign failed"); /* destroy_sensitive_data(); */ /* send server hostkey, DH pubkey 'f' and singed H */ packet_start(SSH2_MSG_KEXDH_REPLY); packet_put_string(server_host_key_blob, sbloblen); packet_put_bignum2(dh->pub_key); /* f */ packet_put_string(signature, slen); packet_send(); xfree(signature); xfree(server_host_key_blob); /* have keys, free DH */ DH_free(dh); kex_derive_keys(kex, hash, hashlen, shared_secret); BN_clear_free(shared_secret); kex_finish(kex); }
int MAIN(int argc, char **argv) { #ifndef OPENSSL_NO_ENGINE ENGINE *e = NULL; #endif DH *dh=NULL; int i,badops=0,text=0; BIO *in=NULL,*out=NULL; int informat,outformat,check=0,noout=0,C=0,ret=1; char *infile,*outfile,*prog; #ifndef OPENSSL_NO_ENGINE char *engine; #endif apps_startup(); if (bio_err == NULL) if ((bio_err=BIO_new(BIO_s_file())) != NULL) BIO_set_fp(bio_err,stderr,BIO_NOCLOSE|BIO_FP_TEXT); if (!load_config(bio_err, NULL)) goto end; #ifndef OPENSSL_NO_ENGINE engine=NULL; #endif infile=NULL; outfile=NULL; informat=FORMAT_PEM; outformat=FORMAT_PEM; prog=argv[0]; argc--; argv++; while (argc >= 1) { if (strcmp(*argv,"-inform") == 0) { if (--argc < 1) goto bad; informat=str2fmt(*(++argv)); } else if (strcmp(*argv,"-outform") == 0) { if (--argc < 1) goto bad; outformat=str2fmt(*(++argv)); } else if (strcmp(*argv,"-in") == 0) { if (--argc < 1) goto bad; infile= *(++argv); } else if (strcmp(*argv,"-out") == 0) { if (--argc < 1) goto bad; outfile= *(++argv); } #ifndef OPENSSL_NO_ENGINE else if (strcmp(*argv,"-engine") == 0) { if (--argc < 1) goto bad; engine= *(++argv); } #endif else if (strcmp(*argv,"-check") == 0) check=1; else if (strcmp(*argv,"-text") == 0) text=1; else if (strcmp(*argv,"-C") == 0) C=1; else if (strcmp(*argv,"-noout") == 0) noout=1; else { BIO_printf(bio_err,"unknown option %s\n",*argv); badops=1; break; } argc--; argv++; } if (badops) { bad: BIO_printf(bio_err,"%s [options] <infile >outfile\n",prog); BIO_printf(bio_err,"where options are\n"); BIO_printf(bio_err," -inform arg input format - one of DER PEM\n"); BIO_printf(bio_err," -outform arg output format - one of DER PEM\n"); BIO_printf(bio_err," -in arg input file\n"); BIO_printf(bio_err," -out arg output file\n"); BIO_printf(bio_err," -check check the DH parameters\n"); BIO_printf(bio_err," -text print a text form of the DH parameters\n"); BIO_printf(bio_err," -C Output C code\n"); BIO_printf(bio_err," -noout no output\n"); #ifndef OPENSSL_NO_ENGINE BIO_printf(bio_err," -engine e use engine e, possibly a hardware device.\n"); #endif goto end; } ERR_load_crypto_strings(); #ifndef OPENSSL_NO_ENGINE e = setup_engine(bio_err, engine, 0); #endif in=BIO_new(BIO_s_file()); out=BIO_new(BIO_s_file()); if ((in == NULL) || (out == NULL)) { ERR_print_errors(bio_err); goto end; } if (infile == NULL) BIO_set_fp(in,stdin,BIO_NOCLOSE); else { if (BIO_read_filename(in,infile) <= 0) { perror(infile); goto end; } } if (outfile == NULL) { BIO_set_fp(out,stdout,BIO_NOCLOSE); #ifdef OPENSSL_SYS_VMS { BIO *tmpbio = BIO_new(BIO_f_linebuffer()); out = BIO_push(tmpbio, out); } #endif } else { if (BIO_write_filename(out,outfile) <= 0) { perror(outfile); goto end; } } if (informat == FORMAT_ASN1) dh=d2i_DHparams_bio(in,NULL); else if (informat == FORMAT_PEM) dh=PEM_read_bio_DHparams(in,NULL,NULL,NULL); else { BIO_printf(bio_err,"bad input format specified\n"); goto end; } if (dh == NULL) { BIO_printf(bio_err,"unable to load DH parameters\n"); ERR_print_errors(bio_err); goto end; } if (text) { DHparams_print(out,dh); #ifdef undef printf("p="); BN_print(stdout,dh->p); printf("\ng="); BN_print(stdout,dh->g); printf("\n"); if (dh->length != 0) printf("recommended private length=%ld\n",dh->length); #endif } if (check) { if (!DH_check(dh,&i)) { ERR_print_errors(bio_err); goto end; } if (i & DH_CHECK_P_NOT_PRIME) printf("p value is not prime\n"); if (i & DH_CHECK_P_NOT_SAFE_PRIME) printf("p value is not a safe prime\n"); if (i & DH_UNABLE_TO_CHECK_GENERATOR) printf("unable to check the generator value\n"); if (i & DH_NOT_SUITABLE_GENERATOR) printf("the g value is not a generator\n"); if (i == 0) printf("DH parameters appear to be ok.\n"); } if (C) { unsigned char *data; int len,l,bits; len=BN_num_bytes(dh->p); bits=BN_num_bits(dh->p); data=(unsigned char *)OPENSSL_malloc(len); if (data == NULL) { perror("OPENSSL_malloc"); goto end; } l=BN_bn2bin(dh->p,data); printf("static unsigned char dh%d_p[]={",bits); for (i=0; i<l; i++) { if ((i%12) == 0) printf("\n\t"); printf("0x%02X,",data[i]); } printf("\n\t};\n"); l=BN_bn2bin(dh->g,data); printf("static unsigned char dh%d_g[]={",bits); for (i=0; i<l; i++) { if ((i%12) == 0) printf("\n\t"); printf("0x%02X,",data[i]); } printf("\n\t};\n\n"); printf("DH *get_dh%d()\n\t{\n",bits); printf("\tDH *dh;\n\n"); printf("\tif ((dh=DH_new()) == NULL) return(NULL);\n"); printf("\tdh->p=BN_bin2bn(dh%d_p,sizeof(dh%d_p),NULL);\n", bits,bits); printf("\tdh->g=BN_bin2bn(dh%d_g,sizeof(dh%d_g),NULL);\n", bits,bits); printf("\tif ((dh->p == NULL) || (dh->g == NULL))\n"); printf("\t\treturn(NULL);\n"); printf("\treturn(dh);\n\t}\n"); OPENSSL_free(data); } if (!noout) { if (outformat == FORMAT_ASN1) i=i2d_DHparams_bio(out,dh); else if (outformat == FORMAT_PEM) i=PEM_write_bio_DHparams(out,dh); else { BIO_printf(bio_err,"bad output format specified for outfile\n"); goto end; } if (!i) { BIO_printf(bio_err,"unable to write DH parameters\n"); ERR_print_errors(bio_err); goto end; } } ret=0; end: if (in != NULL) BIO_free(in); if (out != NULL) BIO_free_all(out); if (dh != NULL) DH_free(dh); apps_shutdown(); OPENSSL_EXIT(ret); }
static int tls_load_dhparams_default(void) { # ifdef HAVE_DH_GET_2048_256 DH *dh; if ((dh = DH_get_2048_256()) == NULL) { die_mem(); } # else # if BN_BITS2 == 64 static const BN_ULONG dh2048_256_p[] = { 0xDB094AE91E1A1597ULL, 0x693877FAD7EF09CAULL, 0x6116D2276E11715FULL, 0xA4B54330C198AF12ULL, 0x75F26375D7014103ULL, 0xC3A3960A54E710C3ULL, 0xDED4010ABD0BE621ULL, 0xC0B857F689962856ULL, 0xB3CA3F7971506026ULL, 0x1CCACB83E6B486F6ULL, 0x67E144E514056425ULL, 0xF6A167B5A41825D9ULL, 0x3AD8347796524D8EULL, 0xF13C6D9A51BFA4ABULL, 0x2D52526735488A0EULL, 0xB63ACAE1CAA6B790ULL, 0x4FDB70C581B23F76ULL, 0xBC39A0BF12307F5CULL, 0xB941F54EB1E59BB8ULL, 0x6C5BFC11D45F9088ULL, 0x22E0B1EF4275BF7BULL, 0x91F9E6725B4758C0ULL, 0x5A8A9D306BCF67EDULL, 0x209E0C6497517ABDULL, 0x3BF4296D830E9A7CULL, 0x16C3D91134096FAAULL, 0xFAF7DF4561B2AA30ULL, 0xE00DF8F1D61957D4ULL, 0x5D2CEED4435E3B00ULL, 0x8CEEF608660DD0F2ULL, 0xFFBBD19C65195999ULL, 0x87A8E61DB4B6663CULL }; static const BN_ULONG dh2048_256_g[] = { 0x664B4C0F6CC41659ULL, 0x5E2327CFEF98C582ULL, 0xD647D148D4795451ULL, 0x2F63078490F00EF8ULL, 0x184B523D1DB246C3ULL, 0xC7891428CDC67EB6ULL, 0x7FD028370DF92B52ULL, 0xB3353BBB64E0EC37ULL, 0xECD06E1557CD0915ULL, 0xB7D2BBD2DF016199ULL, 0xC8484B1E052588B9ULL, 0xDB2A3B7313D3FE14ULL, 0xD052B985D182EA0AULL, 0xA4BD1BFFE83B9C80ULL, 0xDFC967C1FB3F2E55ULL, 0xB5045AF2767164E1ULL, 0x1D14348F6F2F9193ULL, 0x64E67982428EBC83ULL, 0x8AC376D282D6ED38ULL, 0x777DE62AAAB8A862ULL, 0xDDF463E5E9EC144BULL, 0x0196F931C77A57F2ULL, 0xA55AE31341000A65ULL, 0x901228F8C28CBB18ULL, 0xBC3773BF7E8C6F62ULL, 0xBE3A6C1B0C6B47B1ULL, 0xFF4FED4AAC0BB555ULL, 0x10DBC15077BE463FULL, 0x07F4793A1A0BA125ULL, 0x4CA7B18F21EF2054ULL, 0x2E77506660EDBD48ULL, 0x3FB32C9B73134D0BULL }; static const BN_ULONG dh2048_256_q[] = { 0xA308B0FE64F5FBD3ULL, 0x99B1A47D1EB3750BULL, 0xB447997640129DA2ULL, 0x8CF83642A709A097ULL }; # elif BN_BITS2 == 32 static const BN_ULONG dh2048_256_p[] = { 0x1E1A1597, 0xDB094AE9, 0xD7EF09CA, 0x693877FA, 0x6E11715F, 0x6116D227, 0xC198AF12, 0xA4B54330, 0xD7014103, 0x75F26375, 0x54E710C3, 0xC3A3960A, 0xBD0BE621, 0xDED4010A, 0x89962856, 0xC0B857F6, 0x71506026, 0xB3CA3F79, 0xE6B486F6, 0x1CCACB83, 0x14056425, 0x67E144E5, 0xA41825D9, 0xF6A167B5, 0x96524D8E, 0x3AD83477, 0x51BFA4AB, 0xF13C6D9A, 0x35488A0E, 0x2D525267, 0xCAA6B790, 0xB63ACAE1, 0x81B23F76, 0x4FDB70C5, 0x12307F5C, 0xBC39A0BF, 0xB1E59BB8, 0xB941F54E, 0xD45F9088, 0x6C5BFC11, 0x4275BF7B, 0x22E0B1EF, 0x5B4758C0, 0x91F9E672, 0x6BCF67ED, 0x5A8A9D30, 0x97517ABD, 0x209E0C64, 0x830E9A7C, 0x3BF4296D, 0x34096FAA, 0x16C3D911, 0x61B2AA30, 0xFAF7DF45, 0xD61957D4, 0xE00DF8F1, 0x435E3B00, 0x5D2CEED4, 0x660DD0F2, 0x8CEEF608, 0x65195999, 0xFFBBD19C, 0xB4B6663C, 0x87A8E61D }; static const BN_ULONG dh2048_256_g[] = { 0x6CC41659, 0x664B4C0F, 0xEF98C582, 0x5E2327CF, 0xD4795451, 0xD647D148, 0x90F00EF8, 0x2F630784, 0x1DB246C3, 0x184B523D, 0xCDC67EB6, 0xC7891428, 0x0DF92B52, 0x7FD02837, 0x64E0EC37, 0xB3353BBB, 0x57CD0915, 0xECD06E15, 0xDF016199, 0xB7D2BBD2, 0x052588B9, 0xC8484B1E, 0x13D3FE14, 0xDB2A3B73, 0xD182EA0A, 0xD052B985, 0xE83B9C80, 0xA4BD1BFF, 0xFB3F2E55, 0xDFC967C1, 0x767164E1, 0xB5045AF2, 0x6F2F9193, 0x1D14348F, 0x428EBC83, 0x64E67982, 0x82D6ED38, 0x8AC376D2, 0xAAB8A862, 0x777DE62A, 0xE9EC144B, 0xDDF463E5, 0xC77A57F2, 0x0196F931, 0x41000A65, 0xA55AE313, 0xC28CBB18, 0x901228F8, 0x7E8C6F62, 0xBC3773BF, 0x0C6B47B1, 0xBE3A6C1B, 0xAC0BB555, 0xFF4FED4A, 0x77BE463F, 0x10DBC150, 0x1A0BA125, 0x07F4793A, 0x21EF2054, 0x4CA7B18F, 0x60EDBD48, 0x2E775066, 0x73134D0B, 0x3FB32C9B }; static const BN_ULONG dh2048_256_q[] = { 0x64F5FBD3, 0xA308B0FE, 0x1EB3750B, 0x99B1A47D, 0x40129DA2, 0xB4479976, 0xA709A097, 0x8CF83642 }; # else # error "unsupported BN_BITS2" # endif static const BIGNUM p = { (BN_ULONG *) dh2048_256_p, sizeof(dh2048_256_p) / sizeof(BN_ULONG), sizeof(dh2048_256_p) / sizeof(BN_ULONG), 0, BN_FLG_STATIC_DATA }; static const BIGNUM g = { (BN_ULONG *) dh2048_256_g, sizeof(dh2048_256_g) / sizeof(BN_ULONG), sizeof(dh2048_256_g) / sizeof(BN_ULONG), 0, BN_FLG_STATIC_DATA }; static const BIGNUM q = { (BN_ULONG *) dh2048_256_q, sizeof(dh2048_256_q) / sizeof(BN_ULONG), sizeof(dh2048_256_q) / sizeof(BN_ULONG), 0, BN_FLG_STATIC_DATA }; DH *dh; if ((dh = DH_new()) == NULL) { die_mem(); } dh->p = BN_dup(&p); dh->g = BN_dup(&g); dh->q = BN_dup(&q); if (dh->p == NULL || dh->g == NULL || dh->q == NULL) { DH_free(dh); die_mem(); } # endif SSL_CTX_set_tmp_dh(tls_ctx, dh); DH_free(dh); # ifdef SSL_OP_SINGLE_DH_USE SSL_CTX_set_options(tls_ctx, SSL_OP_SINGLE_DH_USE); # endif return 0; }
CERT * ssl_cert_dup(CERT *cert) { CERT *ret; int i; ret = calloc(1, sizeof(CERT)); if (ret == NULL) { SSLerr(SSL_F_SSL_CERT_DUP, ERR_R_MALLOC_FAILURE); return (NULL); } /* * same as ret->key = ret->pkeys + (cert->key - cert->pkeys), * if you find that more readable */ ret->key = &ret->pkeys[cert->key - &cert->pkeys[0]]; ret->valid = cert->valid; ret->mask_k = cert->mask_k; ret->mask_a = cert->mask_a; if (cert->rsa_tmp != NULL) { RSA_up_ref(cert->rsa_tmp); ret->rsa_tmp = cert->rsa_tmp; } ret->rsa_tmp_cb = cert->rsa_tmp_cb; if (cert->dh_tmp != NULL) { ret->dh_tmp = DHparams_dup(cert->dh_tmp); if (ret->dh_tmp == NULL) { SSLerr(SSL_F_SSL_CERT_DUP, ERR_R_DH_LIB); goto err; } if (cert->dh_tmp->priv_key) { BIGNUM *b = BN_dup(cert->dh_tmp->priv_key); if (!b) { SSLerr(SSL_F_SSL_CERT_DUP, ERR_R_BN_LIB); goto err; } ret->dh_tmp->priv_key = b; } if (cert->dh_tmp->pub_key) { BIGNUM *b = BN_dup(cert->dh_tmp->pub_key); if (!b) { SSLerr(SSL_F_SSL_CERT_DUP, ERR_R_BN_LIB); goto err; } ret->dh_tmp->pub_key = b; } } ret->dh_tmp_cb = cert->dh_tmp_cb; if (cert->ecdh_tmp) { ret->ecdh_tmp = EC_KEY_dup(cert->ecdh_tmp); if (ret->ecdh_tmp == NULL) { SSLerr(SSL_F_SSL_CERT_DUP, ERR_R_EC_LIB); goto err; } } ret->ecdh_tmp_cb = cert->ecdh_tmp_cb; ret->ecdh_tmp_auto = cert->ecdh_tmp_auto; for (i = 0; i < SSL_PKEY_NUM; i++) { if (cert->pkeys[i].x509 != NULL) { ret->pkeys[i].x509 = cert->pkeys[i].x509; CRYPTO_add(&ret->pkeys[i].x509->references, 1, CRYPTO_LOCK_X509); } if (cert->pkeys[i].privatekey != NULL) { ret->pkeys[i].privatekey = cert->pkeys[i].privatekey; CRYPTO_add(&ret->pkeys[i].privatekey->references, 1, CRYPTO_LOCK_EVP_PKEY); switch (i) { /* * If there was anything special to do for * certain types of keys, we'd do it here. * (Nothing at the moment, I think.) */ case SSL_PKEY_RSA_ENC: case SSL_PKEY_RSA_SIGN: /* We have an RSA key. */ break; case SSL_PKEY_DSA_SIGN: /* We have a DSA key. */ break; case SSL_PKEY_DH_RSA: case SSL_PKEY_DH_DSA: /* We have a DH key. */ break; case SSL_PKEY_ECC: /* We have an ECC key */ break; default: /* Can't happen. */ SSLerr(SSL_F_SSL_CERT_DUP, SSL_R_LIBRARY_BUG); } } } /* * ret->extra_certs *should* exist, but currently the own certificate * chain is held inside SSL_CTX */ ret->references = 1; /* * Set digests to defaults. NB: we don't copy existing values * as they will be set during handshake. */ ssl_cert_set_default_md(ret); return (ret); err: RSA_free(ret->rsa_tmp); DH_free(ret->dh_tmp); EC_KEY_free(ret->ecdh_tmp); for (i = 0; i < SSL_PKEY_NUM; i++) { if (ret->pkeys[i].x509 != NULL) X509_free(ret->pkeys[i].x509); EVP_PKEY_free(ret->pkeys[i].privatekey); } free (ret); return NULL; }
int main(int argc, char **argv){ int result=OK; int x; char buffer[MAX_INPUT_BUFFER]; char *env_string=NULL; #ifdef HAVE_SSL DH *dh; char seedfile[FILENAME_MAX]; int i,c; #endif /* set some environment variables */ asprintf(&env_string,"NRPE_MULTILINESUPPORT=1"); putenv(env_string); asprintf(&env_string,"NRPE_PROGRAMVERSION=%s",PROGRAM_VERSION); putenv(env_string); /* process command-line args */ result=process_arguments(argc,argv); if(result!=OK || show_help==TRUE || show_license==TRUE || show_version==TRUE){ printf("\n"); printf("NRPE - Nagios Remote Plugin Executor\n"); printf("Copyright (c) 1999-2008 Ethan Galstad ([email protected])\n"); printf("Version: %s\n",PROGRAM_VERSION); printf("Last Modified: %s\n",MODIFICATION_DATE); printf("License: GPL v2 with exemptions (-l for more info)\n"); #ifdef HAVE_SSL printf("SSL/TLS Available: Anonymous DH Mode, OpenSSL 0.9.6 or higher required\n"); #endif #ifdef HAVE_LIBWRAP printf("TCP Wrappers Available\n"); #endif printf("\n"); #ifdef ENABLE_COMMAND_ARGUMENTS printf("***************************************************************\n"); printf("** POSSIBLE SECURITY RISK - COMMAND ARGUMENTS ARE SUPPORTED! **\n"); printf("** Read the NRPE SECURITY file for more information **\n"); printf("***************************************************************\n"); printf("\n"); #endif #ifndef HAVE_LIBWRAP printf("***************************************************************\n"); printf("** POSSIBLE SECURITY RISK - TCP WRAPPERS ARE NOT AVAILABLE! **\n"); printf("** Read the NRPE SECURITY file for more information **\n"); printf("***************************************************************\n"); printf("\n"); #endif } if(show_license==TRUE) display_license(); else if(result!=OK || show_help==TRUE){ printf("Usage: nrpe [-n] -c <config_file> <mode>\n"); printf("\n"); printf("Options:\n"); printf(" -n = Do not use SSL\n"); printf(" <config_file> = Name of config file to use\n"); printf(" <mode> = One of the following operating modes:\n"); printf(" -i = Run as a service under inetd or xinetd\n"); printf(" -d = Run as a standalone daemon\n"); /* Updates help section to indicate how to start under SRC on AIX */ printf(" -d -s = Run as a subsystem under AIX\n"); printf("\n"); printf("Notes:\n"); printf("This program is designed to process requests from the check_nrpe\n"); printf("plugin on the host(s) running Nagios. It can run as a service\n"); printf("under inetd or xinetd (read the docs for info on this), or as a\n"); printf("standalone daemon. Once a request is received from an authorized\n"); printf("host, NRPE will execute the command/plugin (as defined in the\n"); printf("config file) and return the plugin output and return code to the\n"); printf("check_nrpe plugin.\n"); printf("\n"); } if(result!=OK || show_help==TRUE || show_license==TRUE || show_version==TRUE) exit(STATE_UNKNOWN); /* open a connection to the syslog facility */ /* facility name may be overridden later */ get_log_facility(NRPE_LOG_FACILITY); openlog("nrpe",LOG_PID,log_facility); /* make sure the config file uses an absolute path */ if(config_file[0]!='/'){ /* save the name of the config file */ strncpy(buffer,config_file,sizeof(buffer)); buffer[sizeof(buffer)-1]='\x0'; /* get absolute path of current working directory */ strcpy(config_file,""); getcwd(config_file,sizeof(config_file)); /* append a forward slash */ strncat(config_file,"/",sizeof(config_file)-2); config_file[sizeof(config_file)-1]='\x0'; /* append the config file to the path */ strncat(config_file,buffer,sizeof(config_file)-strlen(config_file)-1); config_file[sizeof(config_file)-1]='\x0'; } /* read the config file */ result=read_config_file(config_file); /* exit if there are errors... */ if(result==ERROR){ syslog(LOG_ERR,"Config file '%s' contained errors, aborting...",config_file); return STATE_CRITICAL; } /* generate the CRC 32 table */ generate_crc32_table(); /* initialize macros */ for(x=0;x<MAX_COMMAND_ARGUMENTS;x++) macro_argv[x]=NULL; #ifdef HAVE_SSL /* initialize SSL */ if(use_ssl==TRUE){ SSL_library_init(); SSLeay_add_ssl_algorithms(); meth=SSLv23_server_method(); SSL_load_error_strings(); /* use week random seed if necessary */ if(allow_weak_random_seed && (RAND_status()==0)){ if(RAND_file_name(seedfile,sizeof(seedfile)-1)) if(RAND_load_file(seedfile,-1)) RAND_write_file(seedfile); if(RAND_status()==0){ syslog(LOG_ERR,"Warning: SSL/TLS uses a weak random seed which is highly discouraged"); srand(time(NULL)); for(i=0;i<500 && RAND_status()==0;i++){ for(c=0;c<sizeof(seedfile);c+=sizeof(int)){ *((int *)(seedfile+c))=rand(); } RAND_seed(seedfile,sizeof(seedfile)); } } } if((ctx=SSL_CTX_new(meth))==NULL){ syslog(LOG_ERR,"Error: could not create SSL context.\n"); exit(STATE_CRITICAL); } /* ADDED 01/19/2004 */ /* use only TLSv1 protocol */ SSL_CTX_set_options(ctx,SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3); /* use anonymous DH ciphers */ SSL_CTX_set_cipher_list(ctx,"ADH"); dh=get_dh512(); SSL_CTX_set_tmp_dh(ctx,dh); DH_free(dh); if(debug==TRUE) syslog(LOG_INFO,"INFO: SSL/TLS initialized. All network traffic will be encrypted."); } else{ if(debug==TRUE) syslog(LOG_INFO,"INFO: SSL/TLS NOT initialized. Network encryption DISABLED."); } #endif /* if we're running under inetd... */ if(use_inetd==TRUE){ /* make sure we're not root */ check_privileges(); /* redirect STDERR to /dev/null */ close(2); open("/dev/null",O_WRONLY); /* handle the connection */ handle_connection(0); } /* if we're running under SRC... we don't fork but does drop-privileges*/ else if (use_src==TRUE){ /* close standard file descriptors */ close(0); close(1); close(2); /* redirect standard descriptors to /dev/null */ open("/dev/null",O_RDONLY); open("/dev/null",O_WRONLY); open("/dev/null",O_WRONLY); chdir("/"); /*umask(0);*/ /* handle signals */ signal(SIGQUIT,sighandler); signal(SIGTERM,sighandler); signal(SIGHUP,sighandler); /* log info to syslog facility */ syslog(LOG_NOTICE,"Starting up daemon"); /* write pid file */ if(write_pid_file()==ERROR) return STATE_CRITICAL; /* drop privileges */ drop_privileges(nrpe_user,nrpe_group); /* make sure we're not root */ check_privileges(); do{ /* reset flags */ sigrestart=FALSE; sigshutdown=FALSE; /* wait for connections */ wait_for_connections(); /* free all memory we allocated */ free_memory(); if(sigrestart==TRUE){ /* read the config file */ result=read_config_file(config_file); /* exit if there are errors... */ if(result==ERROR){ syslog(LOG_ERR,"Config file '%s' contained errors, bailing out...",config_file); return STATE_CRITICAL; } } }while(sigrestart==TRUE && sigshutdown==FALSE); /* remove pid file */ remove_pid_file(); syslog(LOG_NOTICE,"Daemon shutdown\n"); } /* else daemonize and start listening for requests... */ else if(fork()==0){ /* we're a daemon - set up a new process group */ setsid(); /* close standard file descriptors */ close(0); close(1); close(2); /* redirect standard descriptors to /dev/null */ open("/dev/null",O_RDONLY); open("/dev/null",O_WRONLY); open("/dev/null",O_WRONLY); chdir("/"); /*umask(0);*/ /* handle signals */ signal(SIGQUIT,sighandler); signal(SIGTERM,sighandler); signal(SIGHUP,sighandler); /* log info to syslog facility */ syslog(LOG_NOTICE,"Starting up daemon"); /* write pid file */ if(write_pid_file()==ERROR) return STATE_CRITICAL; /* drop privileges */ drop_privileges(nrpe_user,nrpe_group); /* make sure we're not root */ check_privileges(); do{ /* reset flags */ sigrestart=FALSE; sigshutdown=FALSE; /* wait for connections */ wait_for_connections(); /* free all memory we allocated */ free_memory(); if(sigrestart==TRUE){ /* read the config file */ result=read_config_file(config_file); /* exit if there are errors... */ if(result==ERROR){ syslog(LOG_ERR,"Config file '%s' contained errors, bailing out...",config_file); return STATE_CRITICAL; } } }while(sigrestart==TRUE && sigshutdown==FALSE); /* remove pid file */ remove_pid_file(); syslog(LOG_NOTICE,"Daemon shutdown\n"); } #ifdef HAVE_SSL if(use_ssl==TRUE) SSL_CTX_free(ctx); #endif /* We are now running in daemon mode, or the connection handed over by inetd has been completed, so the parent process exits */ return STATE_OK; }
int dhparam_main(int argc, char **argv) { BIO *in = NULL, *out = NULL; DH *dh = NULL; char *infile = NULL, *outfile = NULL, *prog; ENGINE *e = NULL; #ifndef OPENSSL_NO_DSA int dsaparam = 0; #endif int i, text = 0, C = 0, ret = 1, num = 0, g = 0; int informat = FORMAT_PEM, outformat = FORMAT_PEM, check = 0, noout = 0; OPTION_CHOICE o; prog = opt_init(argc, argv, dhparam_options); while ((o = opt_next()) != OPT_EOF) { switch (o) { case OPT_EOF: case OPT_ERR: opthelp: BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); goto end; case OPT_HELP: opt_help(dhparam_options); ret = 0; goto end; case OPT_INFORM: if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &informat)) goto opthelp; break; case OPT_OUTFORM: if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &outformat)) goto opthelp; break; case OPT_IN: infile = opt_arg(); break; case OPT_OUT: outfile = opt_arg(); break; case OPT_ENGINE: e = setup_engine(opt_arg(), 0); break; case OPT_CHECK: check = 1; break; case OPT_TEXT: text = 1; break; case OPT_DSAPARAM: #ifndef OPENSSL_NO_DSA dsaparam = 1; #endif break; case OPT_C: C = 1; break; case OPT_2: g = 2; break; case OPT_5: g = 5; break; case OPT_NOOUT: noout = 1; break; case OPT_R_CASES: if (!opt_rand(o)) goto end; break; } } argc = opt_num_rest(); argv = opt_rest(); if (argv[0] != NULL && (!opt_int(argv[0], &num) || num <= 0)) goto end; if (g && !num) num = DEFBITS; # ifndef OPENSSL_NO_DSA if (dsaparam && g) { BIO_printf(bio_err, "generator may not be chosen for DSA parameters\n"); goto end; } # endif /* DH parameters */ if (num && !g) g = 2; if (num) { BN_GENCB *cb; cb = BN_GENCB_new(); if (cb == NULL) { ERR_print_errors(bio_err); goto end; } BN_GENCB_set(cb, dh_cb, bio_err); # ifndef OPENSSL_NO_DSA if (dsaparam) { DSA *dsa = DSA_new(); BIO_printf(bio_err, "Generating DSA parameters, %d bit long prime\n", num); if (dsa == NULL || !DSA_generate_parameters_ex(dsa, num, NULL, 0, NULL, NULL, cb)) { DSA_free(dsa); BN_GENCB_free(cb); ERR_print_errors(bio_err); goto end; } dh = DSA_dup_DH(dsa); DSA_free(dsa); if (dh == NULL) { BN_GENCB_free(cb); ERR_print_errors(bio_err); goto end; } } else # endif { dh = DH_new(); BIO_printf(bio_err, "Generating DH parameters, %d bit long safe prime, generator %d\n", num, g); BIO_printf(bio_err, "This is going to take a long time\n"); if (dh == NULL || !DH_generate_parameters_ex(dh, num, g, cb)) { BN_GENCB_free(cb); ERR_print_errors(bio_err); goto end; } } BN_GENCB_free(cb); } else { in = bio_open_default(infile, 'r', informat); if (in == NULL) goto end; # ifndef OPENSSL_NO_DSA if (dsaparam) { DSA *dsa; if (informat == FORMAT_ASN1) dsa = d2i_DSAparams_bio(in, NULL); else /* informat == FORMAT_PEM */ dsa = PEM_read_bio_DSAparams(in, NULL, NULL, NULL); if (dsa == NULL) { BIO_printf(bio_err, "unable to load DSA parameters\n"); ERR_print_errors(bio_err); goto end; } dh = DSA_dup_DH(dsa); DSA_free(dsa); if (dh == NULL) { ERR_print_errors(bio_err); goto end; } } else # endif { if (informat == FORMAT_ASN1) { /* * We have no PEM header to determine what type of DH params it * is. We'll just try both. */ dh = d2i_DHparams_bio(in, NULL); /* BIO_reset() returns 0 for success for file BIOs only!!! */ if (dh == NULL && BIO_reset(in) == 0) dh = d2i_DHxparams_bio(in, NULL); } else { /* informat == FORMAT_PEM */ dh = PEM_read_bio_DHparams(in, NULL, NULL, NULL); } if (dh == NULL) { BIO_printf(bio_err, "unable to load DH parameters\n"); ERR_print_errors(bio_err); goto end; } } /* dh != NULL */ } out = bio_open_default(outfile, 'w', outformat); if (out == NULL) goto end; if (text) { DHparams_print(out, dh); } if (check) { if (!DH_check(dh, &i)) { ERR_print_errors(bio_err); goto end; } if (i & DH_CHECK_P_NOT_PRIME) BIO_printf(bio_err, "WARNING: p value is not prime\n"); if (i & DH_CHECK_P_NOT_SAFE_PRIME) BIO_printf(bio_err, "WARNING: p value is not a safe prime\n"); if (i & DH_CHECK_Q_NOT_PRIME) BIO_printf(bio_err, "WARNING: q value is not a prime\n"); if (i & DH_CHECK_INVALID_Q_VALUE) BIO_printf(bio_err, "WARNING: q value is invalid\n"); if (i & DH_CHECK_INVALID_J_VALUE) BIO_printf(bio_err, "WARNING: j value is invalid\n"); if (i & DH_UNABLE_TO_CHECK_GENERATOR) BIO_printf(bio_err, "WARNING: unable to check the generator value\n"); if (i & DH_NOT_SUITABLE_GENERATOR) BIO_printf(bio_err, "WARNING: the g value is not a generator\n"); if (i == 0) BIO_printf(bio_err, "DH parameters appear to be ok.\n"); if (num != 0 && i != 0) { /* * We have generated parameters but DH_check() indicates they are * invalid! This should never happen! */ BIO_printf(bio_err, "ERROR: Invalid parameters generated\n"); goto end; } } if (C) { unsigned char *data; int len, bits; const BIGNUM *pbn, *gbn; len = DH_size(dh); bits = DH_bits(dh); DH_get0_pqg(dh, &pbn, NULL, &gbn); data = app_malloc(len, "print a BN"); BIO_printf(out, "#ifndef HEADER_DH_H\n" "# include <openssl/dh.h>\n" "#endif\n" "\n"); BIO_printf(out, "DH *get_dh%d()\n{\n", bits); print_bignum_var(out, pbn, "dhp", bits, data); print_bignum_var(out, gbn, "dhg", bits, data); BIO_printf(out, " DH *dh = DH_new();\n" " BIGNUM *dhp_bn, *dhg_bn;\n" "\n" " if (dh == NULL)\n" " return NULL;\n"); BIO_printf(out, " dhp_bn = BN_bin2bn(dhp_%d, sizeof(dhp_%d), NULL);\n", bits, bits); BIO_printf(out, " dhg_bn = BN_bin2bn(dhg_%d, sizeof(dhg_%d), NULL);\n", bits, bits); BIO_printf(out, " if (dhp_bn == NULL || dhg_bn == NULL\n" " || !DH_set0_pqg(dh, dhp_bn, NULL, dhg_bn)) {\n" " DH_free(dh);\n" " BN_free(dhp_bn);\n" " BN_free(dhg_bn);\n" " return NULL;\n" " }\n"); if (DH_get_length(dh) > 0) BIO_printf(out, " if (!DH_set_length(dh, %ld)) {\n" " DH_free(dh);\n" " }\n", DH_get_length(dh)); BIO_printf(out, " return dh;\n}\n"); OPENSSL_free(data); } if (!noout) { const BIGNUM *q; DH_get0_pqg(dh, NULL, &q, NULL); if (outformat == FORMAT_ASN1) { if (q != NULL) i = i2d_DHxparams_bio(out, dh); else i = i2d_DHparams_bio(out, dh); } else if (q != NULL) { i = PEM_write_bio_DHxparams(out, dh); } else { i = PEM_write_bio_DHparams(out, dh); } if (!i) { BIO_printf(bio_err, "unable to write DH parameters\n"); ERR_print_errors(bio_err); goto end; } } ret = 0; end: BIO_free(in); BIO_free_all(out); DH_free(dh); release_engine(e); return ret; }
void Server::initializeCert() { QByteArray crt, key, pass, dhparams; crt = getConf("certificate", QString()).toByteArray(); key = getConf("key", QString()).toByteArray(); pass = getConf("passphrase", QByteArray()).toByteArray(); dhparams = getConf("sslDHParams", Meta::mp.qbaDHParams).toByteArray(); QList<QSslCertificate> ql; // Attempt to load key as an RSA key or a DSA key if (! key.isEmpty()) { qskKey = QSslKey(key, QSsl::Rsa, QSsl::Pem, QSsl::PrivateKey, pass); if (qskKey.isNull()) qskKey = QSslKey(key, QSsl::Dsa, QSsl::Pem, QSsl::PrivateKey, pass); } // If we still can't load the key, try loading any keys from the certificate if (qskKey.isNull() && ! crt.isEmpty()) { qskKey = QSslKey(crt, QSsl::Rsa, QSsl::Pem, QSsl::PrivateKey, pass); if (qskKey.isNull()) qskKey = QSslKey(crt, QSsl::Dsa, QSsl::Pem, QSsl::PrivateKey, pass); } // If have a key, walk the list of certs, find the one for our key, // remove any certs for our key from the list, what's left is part of // the CA certificate chain. if (! qskKey.isNull()) { ql << QSslCertificate::fromData(crt); ql << QSslCertificate::fromData(key); for (int i=0;i<ql.size();++i) { const QSslCertificate &c = ql.at(i); if (isKeyForCert(qskKey, c)) { qscCert = c; ql.removeAt(i); } } qlCA = ql; } #if defined(USE_QSSLDIFFIEHELLMANPARAMETERS) if (! dhparams.isEmpty()) { QSslDiffieHellmanParameters qdhp = QSslDiffieHellmanParameters(dhparams); if (qdhp.isValid()) { qsdhpDHParams = qdhp; } else { log(QString::fromLatin1("Unable to use specified Diffie-Hellman parameters (sslDHParams): %1").arg(qdhp.errorString())); } } #else if (! dhparams.isEmpty()) { log("Diffie-Hellman parameters (sslDHParams) were specified, but will not be used. This version of Murmur does not support Diffie-Hellman parameters."); } #endif QString issuer; #if QT_VERSION >= 0x050000 QStringList issuerNames = qscCert.issuerInfo(QSslCertificate::CommonName); if (! issuerNames.isEmpty()) { issuer = issuerNames.first(); } #else issuer = qscCert.issuerInfo(QSslCertificate::CommonName); #endif // Really old certs/keys are no good, throw them away so we can // generate a new one below. if (issuer == QString::fromUtf8("Murmur Autogenerated Certificate")) { log("Old autogenerated certificate is unusable for registration, invalidating it"); qscCert = QSslCertificate(); qskKey = QSslKey(); } // If we have a cert, and it's a self-signed one, but we're binding to // all the same addresses as the Meta server is, use it's cert instead. // This allows a self-signed certificate generated by Murmur to be // replaced by a CA-signed certificate in the .ini file. if (!qscCert.isNull() && issuer == QString::fromUtf8("Murmur Autogenerated Certificate v2") && ! Meta::mp.qscCert.isNull() && ! Meta::mp.qskKey.isNull() && (Meta::mp.qlBind == qlBind)) { qscCert = Meta::mp.qscCert; qskKey = Meta::mp.qskKey; } // If we still don't have a certificate by now, try to load the one from Meta if (qscCert.isNull() || qskKey.isNull()) { if (! key.isEmpty() || ! crt.isEmpty()) { log("Certificate specified, but failed to load."); } qskKey = Meta::mp.qskKey; qscCert = Meta::mp.qscCert; // If loading from Meta doesn't work, build+sign a new one if (qscCert.isNull() || qskKey.isNull()) { log("Generating new server certificate."); CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON); X509 *x509 = X509_new(); EVP_PKEY *pkey = EVP_PKEY_new(); RSA *rsa = RSA_generate_key(2048,RSA_F4,NULL,NULL); EVP_PKEY_assign_RSA(pkey, rsa); X509_set_version(x509, 2); ASN1_INTEGER_set(X509_get_serialNumber(x509),1); X509_gmtime_adj(X509_get_notBefore(x509),0); X509_gmtime_adj(X509_get_notAfter(x509),60*60*24*365*20); X509_set_pubkey(x509, pkey); X509_NAME *name=X509_get_subject_name(x509); X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC, reinterpret_cast<unsigned char *>(const_cast<char *>("Murmur Autogenerated Certificate v2")), -1, -1, 0); X509_set_issuer_name(x509, name); add_ext(x509, NID_basic_constraints, SSL_STRING("critical,CA:FALSE")); add_ext(x509, NID_ext_key_usage, SSL_STRING("serverAuth,clientAuth")); add_ext(x509, NID_subject_key_identifier, SSL_STRING("hash")); add_ext(x509, NID_netscape_comment, SSL_STRING("Generated from murmur")); X509_sign(x509, pkey, EVP_sha1()); crt.resize(i2d_X509(x509, NULL)); unsigned char *dptr=reinterpret_cast<unsigned char *>(crt.data()); i2d_X509(x509, &dptr); qscCert = QSslCertificate(crt, QSsl::Der); if (qscCert.isNull()) log("Certificate generation failed"); key.resize(i2d_PrivateKey(pkey, NULL)); dptr=reinterpret_cast<unsigned char *>(key.data()); i2d_PrivateKey(pkey, &dptr); qskKey = QSslKey(key, QSsl::Rsa, QSsl::Der); if (qskKey.isNull()) log("Key generation failed"); setConf("certificate", qscCert.toPem()); setConf("key", qskKey.toPem()); } } #if defined(USE_QSSLDIFFIEHELLMANPARAMETERS) if (qsdhpDHParams.isEmpty()) { log("Generating new server 2048-bit Diffie-Hellman parameters. This could take a while..."); DH *dh = DH_new(); if (dh == NULL) { qFatal("DH_new failed: unable to generate Diffie-Hellman parameters for virtual server"); } // Generate DH params. // We register a status callback in order to update the UI // for Murmur on Windows. We don't show the actual status, // but we do it to keep Murmur on Windows responsive while // generating the parameters. BN_GENCB cb; memset(&cb, 0, sizeof(BN_GENCB)); BN_GENCB_set(&cb, dh_progress, NULL); if (DH_generate_parameters_ex(dh, 2048, 2, &cb) == 0) { qFatal("DH_generate_parameters_ex failed: unable to generate Diffie-Hellman parameters for virtual server"); } BIO *mem = BIO_new(BIO_s_mem()); if (PEM_write_bio_DHparams(mem, dh) == 0) { qFatal("PEM_write_bio_DHparams failed: unable to write generated Diffie-Hellman parameters to memory"); } char *pem = NULL; long len = BIO_get_mem_data(mem, &pem); if (len <= 0) { qFatal("BIO_get_mem_data returned an empty or invalid buffer"); } QByteArray pemdh(pem, len); QSslDiffieHellmanParameters qdhp(pemdh); if (!qdhp.isValid()) { qFatal("QSslDiffieHellmanParameters: unable to import generated Diffie-HellmanParameters: %s", qdhp.errorString().toStdString().c_str()); } qsdhpDHParams = qdhp; setConf("sslDHParams", pemdh); BIO_free(mem); DH_free(dh); } #endif // Drain OpenSSL's per-thread error queue // to ensure that errors from the operations // we've done in here do not leak out into // Qt's SSL module. // // If an error leaks, it can break all connections // to the server because each invocation of Qt's SSL // read callback checks OpenSSL's per-thread error // queue (albeit indirectly, via SSL_get_error()). // Qt expects any errors returned from SSL_get_error() // to be related to the QSslSocket it is currently // processing -- which is the obvious thing to expect: // SSL_get_error() takes a pointer to an SSL object // and the return code of the failed operation. // However, it is also documented as: // // "In addition to ssl and ret, SSL_get_error() // inspects the current thread's OpenSSL error // queue." // // So, if any OpenSSL operation on the main thread // forgets to clear the error queue, those errors // *will* leak into other things that *do* error // checking. In our case, into Qt's SSL read callback, // resulting in all clients being disconnected. ERR_clear_error(); }
int main(int argc, char *argv[]) { BN_GENCB *_cb = NULL; DH *a = NULL; DH *b = 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"); BIO_puts(out, "\np ="); BN_print(out, a->p); BIO_puts(out, "\ng ="); BN_print(out, a->g); BIO_puts(out, "\n"); b = DH_new(); if (b == NULL) goto err; b->p = BN_dup(a->p); b->g = BN_dup(a->g); if ((b->p == NULL) || (b->g == NULL)) goto err; /* Set a to run with normal modexp and b to use constant time */ a->flags &= ~DH_FLAG_NO_EXP_CONSTTIME; b->flags |= DH_FLAG_NO_EXP_CONSTTIME; if (!DH_generate_key(a)) goto err; BIO_puts(out, "pri 1="); BN_print(out, a->priv_key); BIO_puts(out, "\npub 1="); BN_print(out, a->pub_key); BIO_puts(out, "\n"); if (!DH_generate_key(b)) goto err; BIO_puts(out, "pri 2="); BN_print(out, b->priv_key); BIO_puts(out, "\npub 2="); BN_print(out, b->pub_key); BIO_puts(out, "\n"); alen = DH_size(a); abuf = OPENSSL_malloc(alen); if (abuf == NULL) goto err; aout = DH_compute_key(abuf, b->pub_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, a->pub_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: ERR_print_errors_fp(stderr); OPENSSL_free(abuf); OPENSSL_free(bbuf); DH_free(b); DH_free(a); BN_GENCB_free(_cb); BIO_free(out); # ifdef OPENSSL_SYS_NETWARE if (ret) printf("ERROR: %d\n", ret); # endif EXIT(ret); }
static int run_rfc5114_tests(void) { int i; DH *dhA = NULL; DH *dhB = NULL; unsigned char *Z1 = NULL; unsigned char *Z2 = NULL; const rfc5114_td *td = NULL; for (i = 0; i < (int)OSSL_NELEM(rfctd); i++) { dhA = NULL; dhB = NULL; Z1 = NULL; Z2 = NULL; td = rfctd + i; /* Set up DH structures setting key components */ dhA = td->get_param(); dhB = td->get_param(); if ((dhA == NULL) || (dhB == NULL)) goto bad_err; dhA->priv_key = BN_bin2bn(td->xA, td->xA_len, NULL); dhA->pub_key = BN_bin2bn(td->yA, td->yA_len, NULL); dhB->priv_key = BN_bin2bn(td->xB, td->xB_len, NULL); dhB->pub_key = BN_bin2bn(td->yB, td->yB_len, NULL); if ((dhA->priv_key == NULL) || (dhA->pub_key == NULL) || (dhB->priv_key == NULL) || (dhB->pub_key == NULL)) goto bad_err; if ((td->Z_len != (size_t)DH_size(dhA)) || (td->Z_len != (size_t)DH_size(dhB))) goto err; Z1 = OPENSSL_malloc(DH_size(dhA)); Z2 = OPENSSL_malloc(DH_size(dhB)); if ((Z1 == NULL) || (Z2 == NULL)) goto bad_err; /* * Work out shared secrets using both sides and compare with expected * values. */ if (DH_compute_key(Z1, dhB->pub_key, dhA) == -1) goto bad_err; if (DH_compute_key(Z2, dhA->pub_key, dhB) == -1) goto bad_err; if (memcmp(Z1, td->Z, td->Z_len)) goto err; if (memcmp(Z2, td->Z, td->Z_len)) goto err; printf("RFC5114 parameter test %d OK\n", i + 1); DH_free(dhA); DH_free(dhB); OPENSSL_free(Z1); OPENSSL_free(Z2); } return 1; bad_err: DH_free(dhA); DH_free(dhB); OPENSSL_free(Z1); OPENSSL_free(Z2); fprintf(stderr, "Initalisation error RFC5114 set %d\n", i + 1); ERR_print_errors_fp(stderr); return 0; err: DH_free(dhA); DH_free(dhB); OPENSSL_free(Z1); OPENSSL_free(Z2); fprintf(stderr, "Test failed RFC5114 set %d\n", i + 1); return 0; }
static void mech_finish(sasl_session_t *p) { DH_free((DH *) p->mechdata); p->mechdata = NULL; }
/* Actually there is no reason to insist that 'generator' be a generator. * It's just as OK (and in some sense better) to use a generator of the * order-q subgroup. */ DH *DH_generate_parameters(int prime_len, int generator, void (*callback)(int,int,void *), void *cb_arg) { BIGNUM *p=NULL,*t1,*t2; DH *ret=NULL; int g,ok= -1; BN_CTX *ctx=NULL; ret=DH_new(); if (ret == NULL) goto err; ctx=BN_CTX_new(); if (ctx == NULL) goto err; BN_CTX_start(ctx); t1 = BN_CTX_get(ctx); t2 = BN_CTX_get(ctx); if (t1 == NULL || t2 == NULL) goto err; if (generator <= 1) goto err; if (generator == DH_GENERATOR_2) { if (!BN_set_word(t1,24)) goto err; if (!BN_set_word(t2,11)) goto err; g=2; } else if (generator == DH_GENERATOR_5) { if (!BN_set_word(t1,10)) goto err; if (!BN_set_word(t2,3)) goto err; /* BN_set_word(t3,7); just have to miss * out on these ones :-( */ g=5; } else { /* in the general case, don't worry if 'generator' is a * generator or not: since we are using safe primes, * it will generate either an order-q or an order-2q group, * which both is OK */ if (!BN_set_word(t1,2)) goto err; if (!BN_set_word(t2,1)) goto err; g=generator; } p=BN_generate_prime(NULL,prime_len,1,t1,t2,callback,cb_arg); if (p == NULL) goto err; if (callback != NULL) callback(3,0,cb_arg); ret->p=p; ret->g=BN_new(); if (!BN_set_word(ret->g,g)) goto err; ok=1; err: if (ok == -1) ok=0; if (ctx != NULL) { BN_CTX_end(ctx); BN_CTX_free(ctx); } if (!ok && (ret != NULL)) { DH_free(ret); ret=NULL; } return(ret); }
int dhparam_main(int argc, char **argv) { BIO *in = NULL, *out = NULL; DH *dh = NULL; char *infile = NULL, *outfile = NULL, *prog, *inrand = NULL; #ifndef OPENSSL_NO_DSA int dsaparam = 0; #endif int i, text = 0, C = 0, ret = 1, num = 0, g = 0; int informat = FORMAT_PEM, outformat = FORMAT_PEM, check = 0, noout = 0; OPTION_CHOICE o; prog = opt_init(argc, argv, dhparam_options); while ((o = opt_next()) != OPT_EOF) { switch (o) { case OPT_EOF: case OPT_ERR: opthelp: BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); goto end; case OPT_HELP: opt_help(dhparam_options); ret = 0; goto end; case OPT_INFORM: if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &informat)) goto opthelp; break; case OPT_OUTFORM: if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &outformat)) goto opthelp; break; case OPT_IN: infile = opt_arg(); break; case OPT_OUT: outfile = opt_arg(); break; case OPT_ENGINE: (void)setup_engine(opt_arg(), 0); break; case OPT_CHECK: check = 1; break; case OPT_TEXT: text = 1; break; case OPT_DSAPARAM: #ifndef OPENSSL_NO_DSA dsaparam = 1; #endif break; case OPT_C: C = 1; break; case OPT_2: g = 2; break; case OPT_5: g = 5; break; case OPT_NOOUT: noout = 1; break; case OPT_RAND: inrand = opt_arg(); break; } } argc = opt_num_rest(); argv = opt_rest(); if (argv[0] && (!opt_int(argv[0], &num) || num <= 0)) goto end; if (g && !num) num = DEFBITS; # ifndef OPENSSL_NO_DSA if (dsaparam && g) { BIO_printf(bio_err, "generator may not be chosen for DSA parameters\n"); goto end; } # endif /* DH parameters */ if (num && !g) g = 2; if (num) { BN_GENCB *cb; cb = BN_GENCB_new(); if (cb == NULL) { ERR_print_errors(bio_err); goto end; } BN_GENCB_set(cb, dh_cb, bio_err); if (!app_RAND_load_file(NULL, 1) && inrand == NULL) { BIO_printf(bio_err, "warning, not much extra random data, consider using the -rand option\n"); } if (inrand != NULL) BIO_printf(bio_err, "%ld semi-random bytes loaded\n", app_RAND_load_files(inrand)); # ifndef OPENSSL_NO_DSA if (dsaparam) { DSA *dsa = DSA_new(); BIO_printf(bio_err, "Generating DSA parameters, %d bit long prime\n", num); if (dsa == NULL || !DSA_generate_parameters_ex(dsa, num, NULL, 0, NULL, NULL, cb)) { DSA_free(dsa); BN_GENCB_free(cb); ERR_print_errors(bio_err); goto end; } dh = DSA_dup_DH(dsa); DSA_free(dsa); if (dh == NULL) { BN_GENCB_free(cb); ERR_print_errors(bio_err); goto end; } } else # endif { dh = DH_new(); BIO_printf(bio_err, "Generating DH parameters, %d bit long safe prime, generator %d\n", num, g); BIO_printf(bio_err, "This is going to take a long time\n"); if (dh == NULL || !DH_generate_parameters_ex(dh, num, g, cb)) { BN_GENCB_free(cb); ERR_print_errors(bio_err); goto end; } } BN_GENCB_free(cb); app_RAND_write_file(NULL); } else { in = bio_open_default(infile, 'r', informat); if (in == NULL) goto end; # ifndef OPENSSL_NO_DSA if (dsaparam) { DSA *dsa; if (informat == FORMAT_ASN1) dsa = d2i_DSAparams_bio(in, NULL); else /* informat == FORMAT_PEM */ dsa = PEM_read_bio_DSAparams(in, NULL, NULL, NULL); if (dsa == NULL) { BIO_printf(bio_err, "unable to load DSA parameters\n"); ERR_print_errors(bio_err); goto end; } dh = DSA_dup_DH(dsa); DSA_free(dsa); if (dh == NULL) { ERR_print_errors(bio_err); goto end; } } else # endif { if (informat == FORMAT_ASN1) dh = d2i_DHparams_bio(in, NULL); else /* informat == FORMAT_PEM */ dh = PEM_read_bio_DHparams(in, NULL, NULL, NULL); if (dh == NULL) { BIO_printf(bio_err, "unable to load DH parameters\n"); ERR_print_errors(bio_err); goto end; } } /* dh != NULL */ } out = bio_open_default(outfile, 'w', outformat); if (out == NULL) goto end; if (text) { DHparams_print(out, dh); } if (check) { if (!DH_check(dh, &i)) { ERR_print_errors(bio_err); goto end; } if (i & DH_CHECK_P_NOT_PRIME) printf("p value is not prime\n"); if (i & DH_CHECK_P_NOT_SAFE_PRIME) printf("p value is not a safe prime\n"); if (i & DH_UNABLE_TO_CHECK_GENERATOR) printf("unable to check the generator value\n"); if (i & DH_NOT_SUITABLE_GENERATOR) printf("the g value is not a generator\n"); if (i == 0) printf("DH parameters appear to be ok.\n"); } if (C) { unsigned char *data; int len, bits; BIGNUM *pbn, *gbn; len = DH_size(dh); bits = DH_bits(dh); DH_get0_pqg(dh, &pbn, NULL, &gbn); data = app_malloc(len, "print a BN"); BIO_printf(out, "#ifndef HEADER_DH_H\n" "# include <openssl/dh.h>\n" "#endif\n" "\n"); BIO_printf(out, "DH *get_dh%d()\n{\n", bits); print_bignum_var(out, pbn, "dhp", bits, data); print_bignum_var(out, gbn, "dhg", bits, data); BIO_printf(out, " DH *dh = DH_new();\n" " BIGNUM *dhp_bn, *dhg_bn;\n" "\n" " if (dh == NULL)\n" " return NULL;\n"); BIO_printf(out, " dhp_bn = BN_bin2bn(dhp_%d, sizeof (dhp_%d), NULL);\n", bits, bits); BIO_printf(out, " dhg_bn = BN_bin2bn(dhg_%d, sizeof (dhg_%d), NULL);\n", bits, bits); BIO_printf(out, " if (dhp_bn == NULL || dhg_bn == NULL\n" " || !DH_set0_pqg(dh, dhp_bn, NULL, dhg_bn)) {\n" " DH_free(dh);\n" " BN_free(dhp_bn);\n" " BN_free(dhg_bn);\n" " return NULL;\n" " }\n"); if (DH_get_length(dh) > 0) BIO_printf(out, " if (!DH_set_length(dh, %ld)) {\n" " DH_free(dh);\n" " }\n", DH_get_length(dh)); BIO_printf(out, " return dh;\n}\n"); OPENSSL_free(data); } if (!noout) { BIGNUM *q; DH_get0_pqg(dh, NULL, &q, NULL); if (outformat == FORMAT_ASN1) i = i2d_DHparams_bio(out, dh); else if (q != NULL) i = PEM_write_bio_DHxparams(out, dh); else i = PEM_write_bio_DHparams(out, dh); if (!i) { BIO_printf(bio_err, "unable to write DH parameters\n"); ERR_print_errors(bio_err); goto end; } } ret = 0; end: BIO_free(in); BIO_free_all(out); DH_free(dh); return (ret); }
int dh_im_compute_key(PACE_CTX * ctx, const BUF_MEM * s, const BUF_MEM * in, BN_CTX *bn_ctx) { int ret = 0; BUF_MEM * x_mem = NULL; BIGNUM * x_bn = NULL, *a = NULL, *p_1 = NULL, *q = NULL; DH *static_key = NULL, *ephemeral_key = NULL; check((ctx && in && ctx->ka_ctx), "Invalid arguments"); if (in->length < (size_t) EVP_CIPHER_key_length(ctx->ka_ctx->cipher) || !ctx->static_key) goto err; BN_CTX_start(bn_ctx); static_key = EVP_PKEY_get1_DH(ctx->static_key); if (!static_key) goto err; /* Initialize ephemeral parameters with parameters from the static key */ ephemeral_key = DHparams_dup_with_q(static_key); if (!ephemeral_key) goto err; /* Perform the actual mapping */ x_mem = cipher_no_pad(ctx->ka_ctx, NULL, in, s, 1); if (!x_mem) goto err; x_bn = BN_bin2bn((unsigned char *) x_mem->data, x_mem->length, x_bn); a = BN_CTX_get(bn_ctx); q = DH_get_q(static_key, bn_ctx); p_1 = BN_dup(static_key->p); if (!x_bn || !a || !q || !p_1 || /* p_1 = p-1 */ !BN_sub_word(p_1, 1) || /* a = p-1 / q */ !BN_div(a, NULL, p_1, q, bn_ctx) || /* g~ = x^a mod p */ !BN_mod_exp(ephemeral_key->g, x_bn, a, static_key->p, bn_ctx)) goto err; /* check if g~ != 1 */ check((!BN_is_one(ephemeral_key->g)), "Bad DH generator"); /* Copy ephemeral key to context structure */ if (!EVP_PKEY_set1_DH(ctx->ka_ctx->key, ephemeral_key)) goto err; ret = 1; err: if (q) BN_clear_free(q); if (p_1) BN_clear_free(p_1); if (x_bn) BN_clear_free(x_bn); if (x_mem) BUF_MEM_free(x_mem); /* Decrement reference count, keys are still available via PACE_CTX */ if (static_key) DH_free(static_key); if (ephemeral_key) DH_free(ephemeral_key); BN_CTX_end(bn_ctx); return ret; }
DH *get_dh8192() { static unsigned char dh8192_p[]={ 0xB8,0xAE,0x14,0x2F,0x6F,0xD0,0x94,0xD4,0xA0,0x1C,0x6E,0x61, 0xF3,0xC2,0x79,0x84,0xA5,0x1E,0x09,0x65,0x9B,0x33,0xB1,0x96, 0x18,0x9D,0xBF,0xC9,0x0E,0xD3,0xA1,0xCF,0x4B,0xC7,0x88,0x78, 0x18,0xC7,0x59,0x78,0x2F,0x5F,0x46,0x7D,0xF2,0x44,0x6F,0xFB, 0x4A,0x46,0x38,0xFA,0xDC,0xCD,0x17,0x50,0x44,0x11,0x2F,0x5E, 0x66,0x46,0x02,0xF7,0xAA,0x3F,0x70,0x22,0x2B,0xD0,0xA1,0x0F, 0x9E,0x0E,0xFF,0x32,0x5B,0xBB,0x2E,0xB6,0x08,0xE3,0x0F,0x31, 0x21,0xE9,0x90,0x32,0x86,0x75,0x92,0xDE,0xE8,0x9B,0xA6,0x28, 0x1A,0xE5,0xFC,0x8D,0x2A,0x41,0xD7,0x9D,0x3A,0x4D,0x87,0x25, 0x54,0xC3,0x72,0x2D,0x07,0xD1,0x54,0xA0,0x48,0xC0,0x6E,0x81, 0x0C,0x20,0xD4,0xE8,0xD4,0x3E,0xB5,0x78,0xE1,0x2B,0x07,0x66, 0xBB,0x2F,0xC4,0xBE,0x10,0xCB,0xAB,0x34,0x2D,0xB0,0x4C,0xC6, 0x92,0x35,0x4F,0x37,0x88,0xD2,0xA1,0xA5,0x35,0x04,0xE6,0x4C, 0x09,0x15,0xB8,0x59,0x55,0xE6,0xC5,0x05,0x69,0x00,0xD4,0x09, 0xCE,0xE3,0x2F,0x63,0x8C,0xD1,0xCB,0xBD,0x98,0x7B,0xDF,0xA8, 0xAA,0xAD,0xAC,0xBC,0x94,0x4E,0x76,0xED,0x5F,0x4F,0x92,0x53, 0xFD,0x15,0x64,0xFA,0x58,0x97,0x63,0x5C,0x40,0xFB,0x46,0xF9, 0xCA,0x32,0x2F,0xA8,0xC3,0x1D,0x83,0xD3,0x7C,0xCB,0x48,0x7F, 0x88,0x4B,0x13,0x7D,0xF9,0xC1,0xAF,0x20,0x00,0xAA,0xAB,0x4E, 0x70,0x83,0xE3,0x04,0x74,0x95,0x33,0x02,0x0F,0xD3,0xAE,0x12, 0xA0,0x5E,0xF6,0x2A,0xBE,0xF2,0x3C,0x32,0x57,0x6C,0x13,0x9A, 0x84,0xD8,0x08,0x7E,0x2E,0x12,0x92,0x79,0x9B,0xB7,0xAC,0x4E, 0xDD,0x9A,0x05,0x44,0xC9,0xC7,0xD2,0x0E,0x57,0x00,0x4B,0xA0, 0x3B,0xA4,0x01,0x5A,0xF5,0x36,0x2D,0x97,0x43,0x10,0x50,0xB3, 0xDE,0xE9,0xAB,0xF7,0x90,0xC0,0x2F,0xB0,0x1A,0xBC,0x0A,0x20, 0x0A,0x13,0x14,0x3E,0x57,0xBC,0xD8,0xF5,0x5C,0xFE,0x1D,0x78, 0xF9,0x20,0xCE,0x1A,0xD5,0xAF,0xC1,0xAB,0xAD,0x58,0x44,0x5C, 0x18,0xF5,0x9E,0xB9,0x83,0xDD,0xEA,0xE9,0x4B,0x16,0xA3,0x79, 0xB4,0x26,0xAF,0xFF,0xFE,0x9F,0x18,0xAC,0x93,0x42,0x2B,0xEF, 0x52,0x2D,0xB3,0x4B,0xA7,0x55,0x0D,0xCC,0x95,0x49,0xD9,0x25, 0xD5,0xE0,0x4A,0x79,0xA9,0xEB,0x62,0xC7,0xD1,0x28,0xBF,0x4C, 0xD9,0x23,0xB7,0xC6,0x23,0x35,0x75,0xE1,0xCB,0xA0,0x7F,0x07, 0x69,0x00,0x46,0x8C,0x3D,0x4A,0x2D,0xF1,0x03,0xFB,0xDC,0x17, 0xFA,0xDD,0xB5,0x71,0xE1,0xB3,0x7B,0x44,0xD5,0x23,0x70,0x58, 0x49,0x1C,0xD8,0x39,0x42,0x63,0x7C,0x75,0x10,0x27,0xCC,0xAC, 0x2E,0x7C,0x59,0xE8,0x6D,0x36,0x24,0x1B,0xDF,0x6C,0xF7,0x7C, 0x1E,0x17,0x57,0x8C,0xB5,0xAA,0x12,0x63,0xC0,0x1B,0x15,0xC5, 0xF2,0xA3,0xBC,0x26,0xEB,0xA4,0xE7,0x8E,0xEA,0x64,0x39,0x18, 0xDC,0x6F,0xFC,0x78,0xB5,0x4B,0xC3,0xA4,0xF9,0x9D,0x0D,0x1F, 0x07,0x42,0x56,0x46,0xA2,0xB0,0x1C,0x3B,0xF9,0x5A,0xDE,0xD9, 0x40,0xDE,0xCB,0x7A,0x28,0x6E,0xEA,0x03,0x7D,0x10,0xAE,0x04, 0xD4,0x0E,0xD4,0x67,0x89,0x89,0x0D,0x42,0x93,0x0C,0xEA,0x13, 0x24,0x32,0x12,0x2F,0x20,0x77,0x3A,0xB4,0x99,0x97,0xB3,0x8E, 0x66,0x07,0xD6,0xCC,0xDB,0x6E,0xBA,0xB7,0xFC,0x93,0x55,0x40, 0x29,0x69,0x87,0x91,0x45,0xC6,0x36,0xB1,0x14,0x22,0x35,0x79, 0x12,0xD1,0x15,0x5E,0xB3,0xF7,0x75,0xCB,0x29,0xC6,0x22,0xE3, 0x35,0xCA,0x84,0xD2,0x7E,0x6B,0xD3,0xBE,0xE5,0x66,0x35,0x04, 0xDD,0x3C,0xD7,0x1E,0x0F,0xF0,0x82,0xDA,0xE8,0xF5,0x37,0xD7, 0x85,0x6A,0x26,0x0B,0x0C,0xE3,0xC5,0x3A,0xDF,0x2F,0x38,0x4C, 0xCA,0xC7,0xB2,0xCB,0xB3,0x35,0x5C,0xED,0x73,0xE9,0xA8,0x95, 0xD0,0x2E,0x38,0x05,0x1E,0x8B,0x54,0xBD,0x24,0xAA,0x3C,0x61, 0x87,0xE4,0x3E,0xAC,0xBE,0x6B,0xFB,0xC0,0xD9,0x07,0xC9,0x65, 0xC4,0x4D,0x7B,0xB0,0x05,0x9B,0x16,0xCF,0x0E,0x2D,0xA3,0x58, 0xC6,0xAC,0xBB,0x2C,0xEA,0x08,0xDA,0x90,0x7D,0x6C,0x72,0xBE, 0xDD,0x39,0x90,0x28,0xC9,0x5A,0xC3,0x90,0x91,0xE8,0xB7,0xD3, 0x55,0xE3,0x25,0x6A,0xFE,0x01,0x61,0x79,0xEF,0xEC,0x19,0x64, 0x39,0xED,0xDF,0x55,0xC2,0x05,0x42,0x16,0x40,0x7B,0x1D,0xB9, 0xF0,0xC0,0x7A,0x09,0xF1,0xEA,0x96,0xA3,0x6B,0xA2,0x72,0x53, 0x6E,0xA0,0xF8,0xB6,0xA0,0xC8,0x27,0xE7,0x96,0x34,0x33,0x01, 0xD7,0x4D,0x7B,0x9F,0x08,0x97,0xCB,0x4C,0x32,0xA6,0x65,0x80, 0xC8,0xB0,0x5A,0x49,0x79,0xC6,0x53,0x73,0x25,0x1B,0x7E,0x61, 0x20,0x2D,0x13,0x0D,0x70,0xD5,0x53,0x49,0x90,0x13,0x50,0x37, 0x27,0x80,0xDE,0x16,0xB1,0xAA,0x4A,0x87,0x00,0x86,0x85,0x29, 0xEF,0xCD,0x00,0x0B,0xAC,0x21,0x56,0x81,0xAE,0xCC,0x12,0xE1, 0xAD,0xEA,0xE2,0x0C,0x59,0xC7,0x2C,0xCA,0xBB,0x47,0x9B,0x99, 0xC6,0xA5,0x4C,0x4E,0x0D,0xF0,0x05,0x03,0xB0,0x15,0x86,0xE8, 0x0E,0xAE,0xA8,0x46,0x20,0xCC,0x6D,0x09,0x9E,0x64,0x60,0xCB, 0xBE,0x96,0x08,0xB3,0x44,0x7D,0x6C,0x69,0x4B,0xD5,0xEE,0xE6, 0xD6,0xDE,0xF3,0x6F,0xC9,0x1D,0xB8,0x93,0x20,0x70,0xBD,0x66, 0x5C,0x1C,0x97,0x2D,0x61,0x88,0xB1,0x45,0x76,0xA9,0x69,0xD3, 0x7D,0x20,0xEE,0xD1,0xF8,0x78,0xED,0x57,0x98,0x2F,0x44,0x7B, 0x68,0x37,0xE7,0x6F,0xCB,0x25,0xCF,0x30,0xEF,0x18,0xD2,0xF6, 0xBC,0x08,0x98,0x2C,0xAA,0x82,0xB1,0xF2,0x7C,0x99,0x08,0xA0, 0x86,0x9A,0x8B,0x01,0xB7,0x39,0xBC,0x93,0x3B,0xAC,0xC4,0x8B, 0x7B,0x62,0xF2,0xCC,0x79,0xA3,0x6F,0xDC,0x08,0x65,0x7E,0xFE, 0x75,0xEF,0xED,0xAE,0x8E,0x5D,0xA3,0x47,0x44,0x67,0x8B,0x19, 0x27,0xC8,0xD6,0x4C,0x9F,0xF4,0xE0,0x1B,0x45,0x4D,0x8F,0x05, 0xD7,0xD8,0x02,0x15,0x58,0x37,0xD8,0x22,0xA0,0x59,0xD3,0x5A, 0xB3,0x0E,0xFD,0xA0,0xD2,0x05,0x2B,0xD3,0xDF,0xAF,0x68,0x39, 0x6D,0x66,0x3E,0x50,0x08,0xB4,0xB2,0x0A,0x70,0x51,0x9B,0xC1, 0x7D,0xC4,0x49,0xB6,0x47,0x75,0x5F,0xEC,0x33,0x8C,0xCE,0xDB, 0xE8,0xFF,0x24,0x29,0x61,0x28,0xFE,0x9D,0xC2,0x23,0xC4,0xB5, 0x3A,0xF1,0x76,0x30,0xB2,0xF6,0x59,0xBD,0xC4,0xDF,0xAA,0xC8, 0x92,0x2F,0xF8,0x5C,0x04,0xE0,0xA8,0xB9,0xDB,0x0A,0xBB,0x87, 0x49,0x95,0xDD,0x63,0xAF,0x17,0xED,0x62,0xE6,0x25,0xE8,0xC5, 0xD5,0x9E,0x82,0x4B, }; static unsigned char dh8192_g[]={ 0x02, }; DH *dh; if ((dh=DH_new()) == NULL) return(NULL); dh->p=BN_bin2bn(dh8192_p,sizeof(dh8192_p),NULL); dh->g=BN_bin2bn(dh8192_g,sizeof(dh8192_g),NULL); if ((dh->p == NULL) || (dh->g == NULL)) { DH_free(dh); return(NULL); } return(dh); }
int dh_gm_compute_key(PACE_CTX * ctx, const BUF_MEM * s, const BUF_MEM * in, BN_CTX *bn_ctx) { int ret = 0; BUF_MEM * mem_h = NULL; BIGNUM * bn_s = NULL, *bn_h = NULL, *bn_g = NULL; DH *static_key = NULL, *ephemeral_key = NULL; check(ctx && ctx->static_key && s && ctx->ka_ctx, "Invalid arguments"); BN_CTX_start(bn_ctx); static_key = EVP_PKEY_get1_DH(ctx->static_key); if (!static_key) goto err; /* Convert nonce to BIGNUM */ bn_s = BN_bin2bn((unsigned char *) s->data, s->length, bn_s); if (!bn_s) goto err; /* complete the DH and convert the result to a BIGNUM */ mem_h = dh_compute_key(ctx->static_key, in, bn_ctx); if (!mem_h) goto err; bn_h = BN_bin2bn((unsigned char *) mem_h->data, mem_h->length, bn_h); if (!bn_h) goto err; /* Initialize ephemeral parameters with parameters from the static key */ ephemeral_key = DHparams_dup_with_q(static_key); if (!ephemeral_key) goto err; /* map to new generator */ bn_g = BN_CTX_get(bn_ctx); if (!bn_g || /* bn_g = g^s mod p */ !BN_mod_exp(bn_g, static_key->g, bn_s, static_key->p, bn_ctx) || /* ephemeral_key->g = bn_g * h mod p = g^s * h mod p */ !BN_mod_mul(ephemeral_key->g, bn_g, bn_h, static_key->p, bn_ctx)) goto err; /* Copy ephemeral key to context structure */ if (!EVP_PKEY_set1_DH(ctx->ka_ctx->key, ephemeral_key)) goto err; ret = 1; err: if (mem_h) { OPENSSL_cleanse(mem_h->data, mem_h->max); BUF_MEM_free(mem_h); } if (bn_h) BN_clear_free(bn_h); if (bn_s) BN_clear_free(bn_s); /* Decrement reference count, keys are still available via PACE_CTX */ if (static_key) DH_free(static_key); if (ephemeral_key) DH_free(ephemeral_key); BN_CTX_end(bn_ctx); return ret; }
int ssl_test_dh(int argc, char *argv[]) { BN_GENCB _cb; DH *a; DH *b=NULL; char buf[12]; unsigned char *abuf=NULL,*bbuf=NULL; int i,alen,blen,aout,bout,ret=1; BIO *out; CRYPTO_malloc_debug_init(); CRYPTO_dbg_set_options(V_CRYPTO_MDEBUG_ALL); CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON); #ifdef OPENSSL_SYS_WIN32 CRYPTO_malloc_init(); #endif RAND_seed(rnd_seed, sizeof rnd_seed); #ifndef OPENSSL_SYS_WINDOWS out = BIO_new(BIO_s_mem()); if (out == NULL) return(1); #else out=BIO_new(BIO_s_file()); if (out == NULL) EXIT(1); BIO_set_fp(out,OPENSSL_TYPE__FILE_STDOUT,BIO_NOCLOSE); #endif 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) TINYCLR_SSL_PRINTF( "p value is not prime\n"); if (i & DH_CHECK_P_NOT_SAFE_PRIME) TINYCLR_SSL_PRINTF( "p value is not a safe prime\n"); if (i & DH_UNABLE_TO_CHECK_GENERATOR) TINYCLR_SSL_PRINTF( "unable to check the generator value\n"); if (i & DH_NOT_SUITABLE_GENERATOR) TINYCLR_SSL_PRINTF( "the g value is not a generator\n"); TINYCLR_SSL_PRINTF("\np ="); BN_print(out,a->p); TINYCLR_SSL_PRINTF("\ng ="); BN_print(out,a->g); TINYCLR_SSL_PRINTF("\n"); b=DH_new(); if (b == NULL) goto err; b->p=BN_dup(a->p); b->g=BN_dup(a->g); if ((b->p == NULL) || (b->g == NULL)) goto err; /* Set a to run with normal modexp and b to use constant time */ a->flags &= ~DH_FLAG_NO_EXP_CONSTTIME; b->flags |= DH_FLAG_NO_EXP_CONSTTIME; if (!DH_generate_key(a)) goto err; TINYCLR_SSL_PRINTF("pri 1="); BN_print(out,a->priv_key); TINYCLR_SSL_PRINTF("\npub 1="); BN_print(out,a->pub_key); TINYCLR_SSL_PRINTF("\n"); if (!DH_generate_key(b)) goto err; TINYCLR_SSL_PRINTF("pri 2="); BN_print(out,b->priv_key); TINYCLR_SSL_PRINTF("\npub 2="); BN_print(out,b->pub_key); TINYCLR_SSL_PRINTF("\n"); alen=DH_size(a); abuf=(unsigned char *)OPENSSL_malloc(alen); aout=DH_compute_key(abuf,b->pub_key,a); TINYCLR_SSL_PRINTF("key1 ="); for (i=0; i<aout; i++) { TINYCLR_SSL_SNPRINTF(buf,sizeof(buf),"%02X",abuf[i]); TINYCLR_SSL_PRINTF(buf); } TINYCLR_SSL_PRINTF("\n"); blen=DH_size(b); bbuf=(unsigned char *)OPENSSL_malloc(blen); bout=DH_compute_key(bbuf,a->pub_key,b); TINYCLR_SSL_PRINTF("key2 ="); for (i=0; i<bout; i++) { TINYCLR_SSL_SNPRINTF(buf,sizeof(buf),"%02X",bbuf[i]); TINYCLR_SSL_PRINTF(buf); } TINYCLR_SSL_PRINTF("\n"); if ((aout < 4) || (bout != aout) || (TINYCLR_SSL_MEMCMP(abuf,bbuf,aout) != 0)) { TINYCLR_SSL_PRINTF("Error in DH routines\n"); ret=1; } else ret=0; err: ERR_print_errors_fp(OPENSSL_TYPE__FILE_STDERR); if (abuf != NULL) OPENSSL_free(abuf); if (bbuf != NULL) OPENSSL_free(bbuf); if(b != NULL) DH_free(b); if(a != NULL) DH_free(a); BIO_free(out); #ifdef OPENSSL_SYS_NETWARE if (ret) TINYCLR_SSL_PRINTF("ERROR: %d\n", ret); #endif return(ret); }
static int check_prime(ENGINE *engine, struct prime *pr) { DH *dh1, *dh2; BIGNUM *p, *g; unsigned char *sec1, *sec2; size_t size; int ret; if (verbose) printf("Testing %s\n", pr->name); p = BN_new(); g = BN_new(); dh1 = DH_new_method(engine); dh2 = DH_new_method(engine); /* 1. set shared parameter */ set_prime(p, pr->value); set_generator(g); dh1->p = BN_dup(p); dh1->g = BN_dup(g); dh2->p = BN_dup(p); dh2->g = BN_dup(g); /* 2. set keys */ ret = DH_generate_key(dh1); if (ret == 0) { fprintf(stderr, "DH_generate_key\n"); exit(EXIT_FAILURE); } ret = DH_generate_key(dh2); if (ret == 0) { fprintf(stderr, "DH_generate_key\n"); exit(EXIT_FAILURE); } /* 3. compute shared secret */ size = DH_size(dh1); if (size != DH_size(dh2)) { fprintf(stderr, "size does not match!\n"); exit(EXIT_FAILURE); } sec1 = malloc(size); sec2 = malloc(size); if (!sec1 || !sec2) { perror("malloc"); exit(EXIT_FAILURE); } ret = DH_compute_key(sec1, dh2->pub_key, dh1); if (ret == -1) { fprintf(stderr, "DH_compute_key"); exit(EXIT_FAILURE); } ret = DH_compute_key(sec2, dh1->pub_key, dh2); if (ret == -1) { fprintf(stderr, "DH_compute_key"); exit(EXIT_FAILURE); } /* 4. compare shared secret */ if (verbose) { printf("shared secret 1\n"); print_secret(sec1, size); printf("shared secret 2\n"); print_secret(sec2, size); } if (memcmp(sec1, sec2, size) == 0) ret = 1; else ret = 0; free(sec2); free(sec1); DH_free(dh2); DH_free(dh1); BN_free(g); BN_free(p); return ret; }
void kexgex_server(Kex *kex) { BIGNUM *shared_secret = NULL, *dh_client_pub = NULL; Key *server_host_public, *server_host_private; DH *dh; u_char *kbuf, *hash, *signature = NULL, *server_host_key_blob = NULL; u_int sbloblen, klen, slen, hashlen; int omin = -1, min = -1, omax = -1, max = -1, onbits = -1, nbits = -1; int type, kout; if (kex->load_host_public_key == NULL || kex->load_host_private_key == NULL) fatal("Cannot load hostkey"); server_host_public = kex->load_host_public_key(kex->hostkey_type); if (server_host_public == NULL) fatal("Unsupported hostkey type %d", kex->hostkey_type); server_host_private = kex->load_host_private_key(kex->hostkey_type); type = packet_read(); switch (type) { case SSH2_MSG_KEX_DH_GEX_REQUEST: debug("SSH2_MSG_KEX_DH_GEX_REQUEST received"); omin = min = packet_get_int(); onbits = nbits = packet_get_int(); omax = max = packet_get_int(); min = MAX(DH_GRP_MIN, min); max = MIN(DH_GRP_MAX, max); nbits = MAX(DH_GRP_MIN, nbits); nbits = MIN(DH_GRP_MAX, nbits); break; case SSH2_MSG_KEX_DH_GEX_REQUEST_OLD: debug("SSH2_MSG_KEX_DH_GEX_REQUEST_OLD received"); onbits = nbits = packet_get_int(); /* unused for old GEX */ omin = min = DH_GRP_MIN; omax = max = DH_GRP_MAX; break; default: fatal("protocol error during kex, no DH_GEX_REQUEST: %d", type); } packet_check_eom(); if (omax < omin || onbits < omin || omax < onbits) fatal("DH_GEX_REQUEST, bad parameters: %d !< %d !< %d", omin, onbits, omax); /* Contact privileged parent */ dh = PRIVSEP(choose_dh(min, nbits, max)); if (dh == NULL) packet_disconnect("Protocol error: no matching DH grp found"); debug("SSH2_MSG_KEX_DH_GEX_GROUP sent"); packet_start(SSH2_MSG_KEX_DH_GEX_GROUP); packet_put_bignum2(dh->p); packet_put_bignum2(dh->g); packet_send(); /* flush */ packet_write_wait(); /* Compute our exchange value in parallel with the client */ dh_gen_key(dh, kex->we_need * 8); debug("expecting SSH2_MSG_KEX_DH_GEX_INIT"); packet_read_expect(SSH2_MSG_KEX_DH_GEX_INIT); /* key, cert */ if ((dh_client_pub = BN_new()) == NULL) fatal("dh_client_pub == NULL"); packet_get_bignum2(dh_client_pub); packet_check_eom(); #ifdef DEBUG_KEXDH fprintf(stderr, "dh_client_pub= "); BN_print_fp(stderr, dh_client_pub); fprintf(stderr, "\n"); debug("bits %d", BN_num_bits(dh_client_pub)); #endif #ifdef DEBUG_KEXDH DHparams_print_fp(stderr, dh); fprintf(stderr, "pub= "); BN_print_fp(stderr, dh->pub_key); fprintf(stderr, "\n"); #endif if (!dh_pub_is_valid(dh, dh_client_pub)) packet_disconnect("bad client public DH value"); klen = DH_size(dh); kbuf = xmalloc(klen); if ((kout = DH_compute_key(kbuf, dh_client_pub, dh)) < 0) fatal("DH_compute_key: failed"); #ifdef DEBUG_KEXDH dump_digest("shared secret", kbuf, kout); #endif if ((shared_secret = BN_new()) == NULL) fatal("kexgex_server: BN_new failed"); if (BN_bin2bn(kbuf, kout, shared_secret) == NULL) fatal("kexgex_server: BN_bin2bn failed"); memset(kbuf, 0, klen); free(kbuf); key_to_blob(server_host_public, &server_host_key_blob, &sbloblen); if (type == SSH2_MSG_KEX_DH_GEX_REQUEST_OLD) omin = min = omax = max = -1; /* calc H */ kexgex_hash( kex->evp_md, kex->client_version_string, kex->server_version_string, buffer_ptr(&kex->peer), buffer_len(&kex->peer), buffer_ptr(&kex->my), buffer_len(&kex->my), server_host_key_blob, sbloblen, omin, onbits, omax, dh->p, dh->g, dh_client_pub, dh->pub_key, shared_secret, &hash, &hashlen ); BN_clear_free(dh_client_pub); /* save session id := H */ if (kex->session_id == NULL) { kex->session_id_len = hashlen; kex->session_id = xmalloc(kex->session_id_len); memcpy(kex->session_id, hash, kex->session_id_len); } /* sign H */ kex->sign(server_host_private, server_host_public, &signature, &slen, hash, hashlen); /* destroy_sensitive_data(); */ /* send server hostkey, DH pubkey 'f' and singed H */ debug("SSH2_MSG_KEX_DH_GEX_REPLY sent"); packet_start(SSH2_MSG_KEX_DH_GEX_REPLY); packet_put_string(server_host_key_blob, sbloblen); packet_put_bignum2(dh->pub_key); /* f */ packet_put_string(signature, slen); packet_send(); free(signature); free(server_host_key_blob); /* have keys, free DH */ DH_free(dh); kex_derive_keys(kex, hash, hashlen, shared_secret); BN_clear_free(shared_secret); kex_finish(kex); }
static void ssl_dhe_cleanup(SSL_ECDH_CTX *ctx) { DH_free((DH *)ctx->data); }
static void int_dh_free(EVP_PKEY *pkey) { DH_free(pkey->pkey.dh); }
/* * initialize a new TLS context */ static int tlso_ctx_init( struct ldapoptions *lo, struct ldaptls *lt, int is_server ) { tlso_ctx *ctx = (tlso_ctx *)lo->ldo_tls_ctx; int i; if ( is_server ) { SSL_CTX_set_session_id_context( ctx, (const unsigned char *) "OpenLDAP", sizeof("OpenLDAP")-1 ); } #ifdef SSL_OP_NO_TLSv1 #ifdef SSL_OP_NO_TLSv1_1 #ifdef SSL_OP_NO_TLSv1_2 if ( lo->ldo_tls_protocol_min > LDAP_OPT_X_TLS_PROTOCOL_TLS1_2) SSL_CTX_set_options( ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1 | SSL_OP_NO_TLSv1_2 ); else #endif if ( lo->ldo_tls_protocol_min > LDAP_OPT_X_TLS_PROTOCOL_TLS1_1) SSL_CTX_set_options( ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1 ); else #endif if ( lo->ldo_tls_protocol_min > LDAP_OPT_X_TLS_PROTOCOL_TLS1_0) SSL_CTX_set_options( ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1); else #endif if ( lo->ldo_tls_protocol_min > LDAP_OPT_X_TLS_PROTOCOL_SSL3 ) SSL_CTX_set_options( ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 ); else if ( lo->ldo_tls_protocol_min > LDAP_OPT_X_TLS_PROTOCOL_SSL2 ) SSL_CTX_set_options( ctx, SSL_OP_NO_SSLv2 ); if ( lo->ldo_tls_ciphersuite && !SSL_CTX_set_cipher_list( ctx, lt->lt_ciphersuite ) ) { Debug( LDAP_DEBUG_ANY, "TLS: could not set cipher list %s.\n", lo->ldo_tls_ciphersuite, 0, 0 ); tlso_report_error(); return -1; } if ( lo->ldo_tls_cacertfile == NULL && lo->ldo_tls_cacertdir == NULL && lo->ldo_tls_cacert.bv_val == NULL ) { if ( !SSL_CTX_set_default_verify_paths( ctx ) ) { Debug( LDAP_DEBUG_ANY, "TLS: " "could not use default certificate paths", 0, 0, 0 ); tlso_report_error(); return -1; } } else { X509 *cert = NULL; if ( lo->ldo_tls_cacert.bv_val ) { const unsigned char *pp = lo->ldo_tls_cacert.bv_val; cert = d2i_X509( NULL, &pp, lo->ldo_tls_cacert.bv_len ); X509_STORE *store = SSL_CTX_get_cert_store( ctx ); if ( !X509_STORE_add_cert( store, cert )) { Debug( LDAP_DEBUG_ANY, "TLS: " "could not use CA certificate", 0, 0, 0 ); tlso_report_error(); return -1; } } if (( lt->lt_cacertfile || lt->lt_cacertdir ) && !SSL_CTX_load_verify_locations( ctx, lt->lt_cacertfile, lt->lt_cacertdir ) ) { Debug( LDAP_DEBUG_ANY, "TLS: " "could not load verify locations (file:`%s',dir:`%s').\n", lo->ldo_tls_cacertfile ? lo->ldo_tls_cacertfile : "", lo->ldo_tls_cacertdir ? lo->ldo_tls_cacertdir : "", 0 ); tlso_report_error(); return -1; } if ( is_server ) { STACK_OF(X509_NAME) *calist; /* List of CA names to send to a client */ calist = tlso_ca_list( lt->lt_cacertfile, lt->lt_cacertdir, cert ); if ( !calist ) { Debug( LDAP_DEBUG_ANY, "TLS: " "could not load client CA list (file:`%s',dir:`%s').\n", lo->ldo_tls_cacertfile ? lo->ldo_tls_cacertfile : "", lo->ldo_tls_cacertdir ? lo->ldo_tls_cacertdir : "", 0 ); tlso_report_error(); return -1; } SSL_CTX_set_client_CA_list( ctx, calist ); } if ( cert ) X509_free( cert ); } if ( lo->ldo_tls_cert.bv_val ) { const unsigned char *pp = lo->ldo_tls_cert.bv_val; X509 *cert = d2i_X509( NULL, &pp, lo->ldo_tls_cert.bv_len ); if ( !SSL_CTX_use_certificate( ctx, cert )) { Debug( LDAP_DEBUG_ANY, "TLS: could not use certificate.\n", 0,0,0); tlso_report_error(); return -1; } X509_free( cert ); } else if ( lo->ldo_tls_certfile && !SSL_CTX_use_certificate_file( ctx, lt->lt_certfile, SSL_FILETYPE_PEM ) ) { Debug( LDAP_DEBUG_ANY, "TLS: could not use certificate file `%s'.\n", lo->ldo_tls_certfile,0,0); tlso_report_error(); return -1; } /* Key validity is checked automatically if cert has already been set */ if ( lo->ldo_tls_key.bv_val ) { const unsigned char *pp = lo->ldo_tls_key.bv_val; EVP_PKEY *pkey = d2i_AutoPrivateKey( NULL, &pp, lo->ldo_tls_key.bv_len ); if ( !SSL_CTX_use_PrivateKey( ctx, pkey )) { Debug( LDAP_DEBUG_ANY, "TLS: could not use private key.\n", 0,0,0); tlso_report_error(); return -1; } EVP_PKEY_free( pkey ); } else if ( lo->ldo_tls_keyfile && !SSL_CTX_use_PrivateKey_file( ctx, lt->lt_keyfile, SSL_FILETYPE_PEM ) ) { Debug( LDAP_DEBUG_ANY, "TLS: could not use key file `%s'.\n", lo->ldo_tls_keyfile,0,0); tlso_report_error(); return -1; } if ( is_server && lo->ldo_tls_dhfile ) { DH *dh; BIO *bio; if (( bio=BIO_new_file( lt->lt_dhfile,"r" )) == NULL ) { Debug( LDAP_DEBUG_ANY, "TLS: could not use DH parameters file `%s'.\n", lo->ldo_tls_dhfile,0,0); tlso_report_error(); return -1; } if (!( dh=PEM_read_bio_DHparams( bio, NULL, NULL, NULL ))) { Debug( LDAP_DEBUG_ANY, "TLS: could not read DH parameters file `%s'.\n", lo->ldo_tls_dhfile,0,0); tlso_report_error(); BIO_free( bio ); return -1; } BIO_free( bio ); SSL_CTX_set_tmp_dh( ctx, dh ); SSL_CTX_set_options( ctx, SSL_OP_SINGLE_DH_USE ); DH_free( dh ); } if ( is_server && lo->ldo_tls_ecname ) { #ifdef OPENSSL_NO_EC Debug( LDAP_DEBUG_ANY, "TLS: Elliptic Curves not supported.\n", 0,0,0 ); return -1; #else EC_KEY *ecdh; int nid = OBJ_sn2nid( lt->lt_ecname ); if ( nid == NID_undef ) { Debug( LDAP_DEBUG_ANY, "TLS: could not use EC name `%s'.\n", lo->ldo_tls_ecname,0,0); tlso_report_error(); return -1; } ecdh = EC_KEY_new_by_curve_name( nid ); if ( ecdh == NULL ) { Debug( LDAP_DEBUG_ANY, "TLS: could not generate key for EC name `%s'.\n", lo->ldo_tls_ecname,0,0); tlso_report_error(); return -1; } SSL_CTX_set_tmp_ecdh( ctx, ecdh ); SSL_CTX_set_options( ctx, SSL_OP_SINGLE_ECDH_USE ); EC_KEY_free( ecdh ); #endif } if ( tlso_opt_trace ) { SSL_CTX_set_info_callback( ctx, tlso_info_cb ); } i = SSL_VERIFY_NONE; if ( lo->ldo_tls_require_cert ) { i = SSL_VERIFY_PEER; if ( lo->ldo_tls_require_cert == LDAP_OPT_X_TLS_DEMAND || lo->ldo_tls_require_cert == LDAP_OPT_X_TLS_HARD ) { i |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT; } } SSL_CTX_set_verify( ctx, i, lo->ldo_tls_require_cert == LDAP_OPT_X_TLS_ALLOW ? tlso_verify_ok : tlso_verify_cb ); #if OPENSSL_VERSION_NUMBER < 0x10100000 SSL_CTX_set_tmp_rsa_callback( ctx, tlso_tmp_rsa_cb ); #endif #ifdef HAVE_OPENSSL_CRL if ( lo->ldo_tls_crlcheck ) { X509_STORE *x509_s = SSL_CTX_get_cert_store( ctx ); if ( lo->ldo_tls_crlcheck == LDAP_OPT_X_TLS_CRL_PEER ) { X509_STORE_set_flags( x509_s, X509_V_FLAG_CRL_CHECK ); } else if ( lo->ldo_tls_crlcheck == LDAP_OPT_X_TLS_CRL_ALL ) { X509_STORE_set_flags( x509_s, X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL ); } } #endif return 0; }
void kexdh_client(Kex *kex) { BIGNUM *dh_server_pub = NULL, *shared_secret = NULL; DH *dh; Key *server_host_key; u_char *server_host_key_blob = NULL, *signature = NULL; u_char *kbuf, *hash; u_int klen, slen, sbloblen, hashlen; int kout; /* generate and send 'e', client DH public key */ switch (kex->kex_type) { case KEX_DH_GRP1_SHA1: dh = dh_new_group1(); break; case KEX_DH_GRP14_SHA1: dh = dh_new_group14(); break; default: fatal("%s: Unexpected KEX type %d", __func__, kex->kex_type); } dh_gen_key(dh, kex->we_need * 8); packet_start(SSH2_MSG_KEXDH_INIT); packet_put_bignum2(dh->pub_key); packet_send(); debug("sending SSH2_MSG_KEXDH_INIT"); #ifdef DEBUG_KEXDH DHparams_print_fp(stderr, dh); fprintf(stderr, "pub= "); BN_print_fp(stderr, dh->pub_key); fprintf(stderr, "\n"); #endif debug("expecting SSH2_MSG_KEXDH_REPLY"); packet_read_expect(SSH2_MSG_KEXDH_REPLY); /* key, cert */ server_host_key_blob = packet_get_string(&sbloblen); server_host_key = key_from_blob(server_host_key_blob, sbloblen); if (server_host_key == NULL) fatal("cannot decode server_host_key_blob"); if (server_host_key->type != kex->hostkey_type) fatal("type mismatch for decoded server_host_key_blob"); if (kex->verify_host_key == NULL) fatal("cannot verify server_host_key"); if (kex->verify_host_key(server_host_key) == -1) fatal("server_host_key verification failed"); /* DH parameter f, server public DH key */ if ((dh_server_pub = BN_new()) == NULL) fatal("dh_server_pub == NULL"); packet_get_bignum2(dh_server_pub); #ifdef DEBUG_KEXDH fprintf(stderr, "dh_server_pub= "); BN_print_fp(stderr, dh_server_pub); fprintf(stderr, "\n"); debug("bits %d", BN_num_bits(dh_server_pub)); #endif /* signed H */ signature = packet_get_string(&slen); packet_check_eom(); if (!dh_pub_is_valid(dh, dh_server_pub)) packet_disconnect("bad server public DH value"); klen = DH_size(dh); kbuf = xmalloc(klen); if ((kout = DH_compute_key(kbuf, dh_server_pub, dh)) < 0) fatal("DH_compute_key: failed"); #ifdef DEBUG_KEXDH dump_digest("shared secret", kbuf, kout); #endif if ((shared_secret = BN_new()) == NULL) fatal("kexdh_client: BN_new failed"); if (BN_bin2bn(kbuf, kout, shared_secret) == NULL) fatal("kexdh_client: BN_bin2bn failed"); memset(kbuf, 0, klen); free(kbuf); /* calc and verify H */ kex_dh_hash( kex->client_version_string, kex->server_version_string, buffer_ptr(&kex->my), buffer_len(&kex->my), buffer_ptr(&kex->peer), buffer_len(&kex->peer), server_host_key_blob, sbloblen, dh->pub_key, dh_server_pub, shared_secret, &hash, &hashlen ); free(server_host_key_blob); BN_clear_free(dh_server_pub); DH_free(dh); if (key_verify(server_host_key, signature, slen, hash, hashlen) != 1) fatal("key_verify failed for server_host_key"); key_free(server_host_key); free(signature); /* save session id */ if (kex->session_id == NULL) { kex->session_id_len = hashlen; kex->session_id = xmalloc(kex->session_id_len); memcpy(kex->session_id, hash, kex->session_id_len); } kex_derive_keys_bn(kex, hash, hashlen, shared_secret); BN_clear_free(shared_secret); kex_finish(kex); }
int MAIN(int argc, char **argv) { BN_GENCB cb; DH *dh=NULL; int ret=1,num=DEFBITS; int g=2; char *outfile=NULL; char *inrand=NULL; #ifndef OPENSSL_NO_ENGINE char *engine=NULL; #endif BIO *out=NULL; apps_startup(); BN_GENCB_set(&cb, dh_cb, bio_err); if (bio_err == NULL) if ((bio_err=BIO_new(BIO_s_file())) != NULL) BIO_set_fp(bio_err,stderr,BIO_NOCLOSE|BIO_FP_TEXT); if (!load_config(bio_err, NULL)) goto end; argv++; argc--; for (;;) { if (argc <= 0) break; if (strcmp(*argv,"-out") == 0) { if (--argc < 1) goto bad; outfile= *(++argv); } else if (strcmp(*argv,"-2") == 0) g=2; /* else if (strcmp(*argv,"-3") == 0) g=3; */ else if (strcmp(*argv,"-5") == 0) g=5; #ifndef OPENSSL_NO_ENGINE else if (strcmp(*argv,"-engine") == 0) { if (--argc < 1) goto bad; engine= *(++argv); } #endif else if (strcmp(*argv,"-rand") == 0) { if (--argc < 1) goto bad; inrand= *(++argv); } else break; argv++; argc--; } if ((argc >= 1) && ((sscanf(*argv,"%d",&num) == 0) || (num < 0))) { bad: BIO_printf(bio_err,"usage: gendh [args] [numbits]\n"); BIO_printf(bio_err," -out file - output the key to 'file\n"); BIO_printf(bio_err," -2 - use 2 as the generator value\n"); /* BIO_printf(bio_err," -3 - use 3 as the generator value\n"); */ BIO_printf(bio_err," -5 - use 5 as the generator value\n"); #ifndef OPENSSL_NO_ENGINE BIO_printf(bio_err," -engine e - use engine e, possibly a hardware device.\n"); #endif BIO_printf(bio_err," -rand file%cfile%c...\n", LIST_SEPARATOR_CHAR, LIST_SEPARATOR_CHAR); BIO_printf(bio_err," - load the file (or the files in the directory) into\n"); BIO_printf(bio_err," the random number generator\n"); goto end; } #ifndef OPENSSL_NO_ENGINE setup_engine(bio_err, engine, 0); #endif out=BIO_new(BIO_s_file()); if (out == NULL) { ERR_print_errors(bio_err); goto end; } if (outfile == NULL) { BIO_set_fp(out,stdout,BIO_NOCLOSE); #ifdef OPENSSL_SYS_VMS { BIO *tmpbio = BIO_new(BIO_f_linebuffer()); out = BIO_push(tmpbio, out); } #endif } else { if (BIO_write_filename(out,outfile) <= 0) { perror(outfile); goto end; } } if (!app_RAND_load_file(NULL, bio_err, 1) && inrand == NULL) { BIO_printf(bio_err,"warning, not much extra random data, consider using the -rand option\n"); } if (inrand != NULL) BIO_printf(bio_err,"%ld semi-random bytes loaded\n", app_RAND_load_files(inrand)); BIO_printf(bio_err,"Generating DH parameters, %d bit long safe prime, generator %d\n",num,g); BIO_printf(bio_err,"This is going to take a long time\n"); if(((dh = DH_new()) == NULL) || !DH_generate_parameters_ex(dh, num, g, &cb)) goto end; app_RAND_write_file(NULL, bio_err); if (!PEM_write_bio_DHparams(out,dh)) goto end; ret=0; end: if (ret != 0) ERR_print_errors(bio_err); if (out != NULL) BIO_free_all(out); if (dh != NULL) DH_free(dh); apps_shutdown(); OPENSSL_EXIT(ret); }
static krb5_error_code get_dh_param(krb5_context context, krb5_kdc_configuration *config, SubjectPublicKeyInfo *dh_key_info, pk_client_params *client_params) { DomainParameters dhparam; DH *dh = NULL; krb5_error_code ret; memset(&dhparam, 0, sizeof(dhparam)); if ((dh_key_info->subjectPublicKey.length % 8) != 0) { ret = KRB5_BADMSGTYPE; krb5_set_error_message(context, ret, "PKINIT: subjectPublicKey not aligned " "to 8 bit boundary"); goto out; } if (dh_key_info->algorithm.parameters == NULL) { krb5_set_error_message(context, KRB5_BADMSGTYPE, "PKINIT missing algorithm parameter " "in clientPublicValue"); return KRB5_BADMSGTYPE; } ret = decode_DomainParameters(dh_key_info->algorithm.parameters->data, dh_key_info->algorithm.parameters->length, &dhparam, NULL); if (ret) { krb5_set_error_message(context, ret, "Can't decode algorithm " "parameters in clientPublicValue"); goto out; } ret = _krb5_dh_group_ok(context, config->pkinit_dh_min_bits, &dhparam.p, &dhparam.g, &dhparam.q, moduli, &client_params->dh_group_name); if (ret) { /* XXX send back proposal of better group */ goto out; } dh = DH_new(); if (dh == NULL) { ret = ENOMEM; krb5_set_error_message(context, ret, "Cannot create DH structure"); goto out; } ret = KRB5_BADMSGTYPE; dh->p = integer_to_BN(context, "DH prime", &dhparam.p); if (dh->p == NULL) goto out; dh->g = integer_to_BN(context, "DH base", &dhparam.g); if (dh->g == NULL) goto out; dh->q = integer_to_BN(context, "DH p-1 factor", &dhparam.q); if (dh->g == NULL) goto out; { heim_integer glue; size_t size; ret = decode_DHPublicKey(dh_key_info->subjectPublicKey.data, dh_key_info->subjectPublicKey.length / 8, &glue, &size); if (ret) { krb5_clear_error_message(context); return ret; } client_params->u.dh.public_key = integer_to_BN(context, "subjectPublicKey", &glue); der_free_heim_integer(&glue); if (client_params->u.dh.public_key == NULL) { ret = KRB5_BADMSGTYPE; goto out; } } client_params->u.dh.key = dh; dh = NULL; ret = 0; out: if (dh) DH_free(dh); free_DomainParameters(&dhparam); return ret; }
static int run_rfc5114_tests(void) { int i; DH *dhA = NULL; DH *dhB = NULL; unsigned char *Z1 = NULL; unsigned char *Z2 = NULL; const rfc5114_td *td = NULL; BIGNUM *bady = NULL, *priv_key = NULL, *pub_key = NULL; for (i = 0; i < (int)OSSL_NELEM(rfctd); i++) { td = rfctd + i; /* Set up DH structures setting key components */ dhA = td->get_param(); dhB = td->get_param(); if ((dhA == NULL) || (dhB == NULL)) goto bad_err; priv_key = BN_bin2bn(td->xA, td->xA_len, NULL); pub_key = BN_bin2bn(td->yA, td->yA_len, NULL); if (priv_key == NULL || pub_key == NULL || !DH_set0_key(dhA, pub_key, priv_key)) goto bad_err; priv_key = BN_bin2bn(td->xB, td->xB_len, NULL); pub_key = BN_bin2bn(td->yB, td->yB_len, NULL); if (priv_key == NULL || pub_key == NULL || !DH_set0_key(dhB, pub_key, priv_key)) goto bad_err; priv_key = pub_key = NULL; if ((td->Z_len != (size_t)DH_size(dhA)) || (td->Z_len != (size_t)DH_size(dhB))) goto err; Z1 = OPENSSL_malloc(DH_size(dhA)); Z2 = OPENSSL_malloc(DH_size(dhB)); if ((Z1 == NULL) || (Z2 == NULL)) goto bad_err; /* * Work out shared secrets using both sides and compare with expected * values. */ DH_get0_key(dhB, &pub_key, NULL); if (DH_compute_key(Z1, pub_key, dhA) == -1) { pub_key = NULL; goto bad_err; } DH_get0_key(dhA, &pub_key, NULL); if (DH_compute_key(Z2, pub_key, dhB) == -1) { pub_key = NULL; goto bad_err; } pub_key = NULL; if (memcmp(Z1, td->Z, td->Z_len)) goto err; if (memcmp(Z2, td->Z, td->Z_len)) goto err; printf("RFC5114 parameter test %d OK\n", i + 1); DH_free(dhA); DH_free(dhB); OPENSSL_free(Z1); OPENSSL_free(Z2); dhA = NULL; dhB = NULL; Z1 = NULL; Z2 = NULL; } /* Now i == OSSL_NELEM(rfctd) */ /* RFC5114 uses unsafe primes, so now test an invalid y value */ dhA = DH_get_2048_224(); if (dhA == NULL) goto bad_err; Z1 = OPENSSL_malloc(DH_size(dhA)); if (Z1 == NULL) goto bad_err; bady = BN_bin2bn(dhtest_rfc5114_2048_224_bad_y, sizeof(dhtest_rfc5114_2048_224_bad_y), NULL); if (bady == NULL) goto bad_err; if (!DH_generate_key(dhA)) goto bad_err; if (DH_compute_key(Z1, bady, dhA) != -1) { /* * DH_compute_key should fail with -1. If we get here we unexpectedly * allowed an invalid y value */ goto err; } /* We'll have a stale error on the queue from the above test so clear it */ ERR_clear_error(); printf("RFC5114 parameter test %d OK\n", i + 1); BN_free(bady); DH_free(dhA); OPENSSL_free(Z1); return 1; bad_err: BN_free(bady); DH_free(dhA); DH_free(dhB); BN_free(pub_key); BN_free(priv_key); OPENSSL_free(Z1); OPENSSL_free(Z2); fprintf(stderr, "Initalisation error RFC5114 set %d\n", i + 1); ERR_print_errors_fp(stderr); return 0; err: BN_free(bady); DH_free(dhA); DH_free(dhB); OPENSSL_free(Z1); OPENSSL_free(Z2); fprintf(stderr, "Test failed RFC5114 set %d\n", i + 1); return 0; }