int __openssl_generate_key( u_int8_t *&_private_key, u_int8_t *&_public_key, int32_t &size, DH *&pdh, int32_t &bits_count, u_int8_t *&shared_key, int32_t &shared_key_length, BIGNUM *&peer_public_key ) { int ret = ERROR_SUCCESS; //1. Create the DH if ((pdh = DH_new()) == NULL) { ret = ERROR_OpenSslCreateDH; return ret; } //2. Create his internal p and g if ((pdh->p = BN_new()) == NULL) { ret = ERROR_OpenSslCreateP; return ret; } if ((pdh->g = BN_new()) == NULL) { ret = ERROR_OpenSslCreateG; return ret; } //3. initialize p, g and key length if (BN_hex2bn(&pdh->p, RFC2409_PRIME_1024) == 0) { ret = ERROR_OpenSslParseP1024; return ret; } if (BN_set_word(pdh->g, 2) != 1) { ret = ERROR_OpenSslSetG; return ret; } //4. Set the key length pdh->length = bits_count; //5. Generate private and public key if (DH_generate_key(pdh) != 1) { ret = ERROR_OpenSslGenerateDHKeys; return ret; } // CreateSharedKey if (pdh == NULL) { ret = ERROR_OpenSslGenerateDHKeys; return ret; } if (shared_key_length != 0 || shared_key != NULL) { ret = ERROR_OpenSslShareKeyComputed; return ret; } shared_key_length = DH_size(pdh); if (shared_key_length <= 0 || shared_key_length > 1024) { ret = ERROR_OpenSslGetSharedKeySize; return ret; } shared_key = new u_int8_t[shared_key_length]; memset(shared_key, 0, shared_key_length); peer_public_key = BN_bin2bn(_private_key, size, 0); if (peer_public_key == NULL) { ret = ERROR_OpenSslGetPeerPublicKey; return ret; } if (DH_compute_key(shared_key, peer_public_key, pdh) == -1) { ret = ERROR_OpenSslComputeSharedKey; return ret; } // CopyPublicKey if (pdh == NULL) { ret = ERROR_OpenSslComputeSharedKey; return ret; } int32_t keySize = BN_num_bytes(pdh->pub_key); if ((keySize <= 0) || (size <= 0) || (keySize > size)) { //("CopyPublicKey failed due to either invalid DH state or invalid call"); return ret; ret = ERROR_OpenSslInvalidDHState; return ret; } if (BN_bn2bin(pdh->pub_key, _public_key) != keySize) { //("Unable to copy key"); return ret; ret = ERROR_OpenSslCopyKey; return ret; } return ret; }
int network_init(server *srv) { buffer *b; size_t i; network_backend_t backend; #if OPENSSL_VERSION_NUMBER >= 0x0090800fL EC_KEY *ecdh; int nid; #endif #ifdef USE_OPENSSL DH *dh; BIO *bio; /* 1024-bit MODP Group with 160-bit prime order subgroup (RFC5114) * -----BEGIN DH PARAMETERS----- * MIIBDAKBgQCxC4+WoIDgHd6S3l6uXVTsUsmfvPsGo8aaap3KUtI7YWBz4oZ1oj0Y * mDjvHi7mUsAT7LSuqQYRIySXXDzUm4O/rMvdfZDEvXCYSI6cIZpzck7/1vrlZEc4 * +qMaT/VbzMChUa9fDci0vUW/N982XBpl5oz9p21NpwjfH7K8LkpDcQKBgQCk0cvV * w/00EmdlpELvuZkF+BBN0lisUH/WQGz/FCZtMSZv6h5cQVZLd35pD1UE8hMWAhe0 * sBuIal6RVH+eJ0n01/vX07mpLuGQnQ0iY/gKdqaiTAh6CR9THb8KAWm2oorWYqTR * jnOvoy13nVkY0IvIhY9Nzvl8KiSFXm7rIrOy5QICAKA= * -----END DH PARAMETERS----- */ static const unsigned char dh1024_p[]={ 0xB1,0x0B,0x8F,0x96,0xA0,0x80,0xE0,0x1D,0xDE,0x92,0xDE,0x5E, 0xAE,0x5D,0x54,0xEC,0x52,0xC9,0x9F,0xBC,0xFB,0x06,0xA3,0xC6, 0x9A,0x6A,0x9D,0xCA,0x52,0xD2,0x3B,0x61,0x60,0x73,0xE2,0x86, 0x75,0xA2,0x3D,0x18,0x98,0x38,0xEF,0x1E,0x2E,0xE6,0x52,0xC0, 0x13,0xEC,0xB4,0xAE,0xA9,0x06,0x11,0x23,0x24,0x97,0x5C,0x3C, 0xD4,0x9B,0x83,0xBF,0xAC,0xCB,0xDD,0x7D,0x90,0xC4,0xBD,0x70, 0x98,0x48,0x8E,0x9C,0x21,0x9A,0x73,0x72,0x4E,0xFF,0xD6,0xFA, 0xE5,0x64,0x47,0x38,0xFA,0xA3,0x1A,0x4F,0xF5,0x5B,0xCC,0xC0, 0xA1,0x51,0xAF,0x5F,0x0D,0xC8,0xB4,0xBD,0x45,0xBF,0x37,0xDF, 0x36,0x5C,0x1A,0x65,0xE6,0x8C,0xFD,0xA7,0x6D,0x4D,0xA7,0x08, 0xDF,0x1F,0xB2,0xBC,0x2E,0x4A,0x43,0x71, }; static const unsigned char dh1024_g[]={ 0xA4,0xD1,0xCB,0xD5,0xC3,0xFD,0x34,0x12,0x67,0x65,0xA4,0x42, 0xEF,0xB9,0x99,0x05,0xF8,0x10,0x4D,0xD2,0x58,0xAC,0x50,0x7F, 0xD6,0x40,0x6C,0xFF,0x14,0x26,0x6D,0x31,0x26,0x6F,0xEA,0x1E, 0x5C,0x41,0x56,0x4B,0x77,0x7E,0x69,0x0F,0x55,0x04,0xF2,0x13, 0x16,0x02,0x17,0xB4,0xB0,0x1B,0x88,0x6A,0x5E,0x91,0x54,0x7F, 0x9E,0x27,0x49,0xF4,0xD7,0xFB,0xD7,0xD3,0xB9,0xA9,0x2E,0xE1, 0x90,0x9D,0x0D,0x22,0x63,0xF8,0x0A,0x76,0xA6,0xA2,0x4C,0x08, 0x7A,0x09,0x1F,0x53,0x1D,0xBF,0x0A,0x01,0x69,0xB6,0xA2,0x8A, 0xD6,0x62,0xA4,0xD1,0x8E,0x73,0xAF,0xA3,0x2D,0x77,0x9D,0x59, 0x18,0xD0,0x8B,0xC8,0x85,0x8F,0x4D,0xCE,0xF9,0x7C,0x2A,0x24, 0x85,0x5E,0x6E,0xEB,0x22,0xB3,0xB2,0xE5, }; #endif struct nb_map { network_backend_t nb; const char *name; } network_backends[] = { /* lowest id wins */ #if defined USE_LINUX_SENDFILE { NETWORK_BACKEND_LINUX_SENDFILE, "linux-sendfile" }, #endif #if defined USE_FREEBSD_SENDFILE { NETWORK_BACKEND_FREEBSD_SENDFILE, "freebsd-sendfile" }, #endif #if defined USE_SOLARIS_SENDFILEV { NETWORK_BACKEND_SOLARIS_SENDFILEV, "solaris-sendfilev" }, #endif #if defined USE_WRITEV { NETWORK_BACKEND_WRITEV, "writev" }, #endif { NETWORK_BACKEND_WRITE, "write" }, { NETWORK_BACKEND_UNSET, NULL } }; #ifdef USE_OPENSSL /* load SSL certificates */ for (i = 0; i < srv->config_context->used; i++) { specific_config *s = srv->config_storage[i]; if (buffer_is_empty(s->ssl_pemfile)) continue; #ifdef OPENSSL_NO_TLSEXT { data_config *dc = (data_config *)srv->config_context->data[i]; if (COMP_HTTP_HOST == dc->comp) { log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:", "can't use ssl.pemfile with $HTTP[\"host\"], openssl version does not support TLS extensions"); return -1; } } #endif if (srv->ssl_is_init == 0) { SSL_load_error_strings(); SSL_library_init(); OpenSSL_add_all_algorithms(); srv->ssl_is_init = 1; if (0 == RAND_status()) { log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:", "not enough entropy in the pool"); return -1; } } if (NULL == (s->ssl_ctx = SSL_CTX_new(SSLv23_server_method()))) { log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:", ERR_error_string(ERR_get_error(), NULL)); return -1; } if (!s->ssl_use_sslv2) { /* disable SSLv2 */ if (!(SSL_OP_NO_SSLv2 & SSL_CTX_set_options(s->ssl_ctx, SSL_OP_NO_SSLv2))) { log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:", ERR_error_string(ERR_get_error(), NULL)); return -1; } } if (!s->ssl_use_sslv3) { /* disable SSLv3 */ if (!(SSL_OP_NO_SSLv3 & SSL_CTX_set_options(s->ssl_ctx, SSL_OP_NO_SSLv3))) { log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:", ERR_error_string(ERR_get_error(), NULL)); return -1; } } if (!buffer_is_empty(s->ssl_cipher_list)) { /* Disable support for low encryption ciphers */ if (SSL_CTX_set_cipher_list(s->ssl_ctx, s->ssl_cipher_list->ptr) != 1) { log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:", ERR_error_string(ERR_get_error(), NULL)); return -1; } } /* Support for Diffie-Hellman key exchange */ if (!buffer_is_empty(s->ssl_dh_file)) { /* DH parameters from file */ bio = BIO_new_file((char *) s->ssl_dh_file->ptr, "r"); if (bio == NULL) { log_error_write(srv, __FILE__, __LINE__, "ss", "SSL: Unable to open file", s->ssl_dh_file->ptr); return -1; } dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL); BIO_free(bio); if (dh == NULL) { log_error_write(srv, __FILE__, __LINE__, "ss", "SSL: PEM_read_bio_DHparams failed", s->ssl_dh_file->ptr); return -1; } } else { /* Default DH parameters from RFC5114 */ dh = DH_new(); if (dh == NULL) { log_error_write(srv, __FILE__, __LINE__, "s", "SSL: DH_new () failed"); return -1; } dh->p = BN_bin2bn(dh1024_p,sizeof(dh1024_p), NULL); dh->g = BN_bin2bn(dh1024_g,sizeof(dh1024_g), NULL); dh->length = 160; if ((dh->p == NULL) || (dh->g == NULL)) { DH_free(dh); log_error_write(srv, __FILE__, __LINE__, "s", "SSL: BN_bin2bn () failed"); return -1; } } SSL_CTX_set_tmp_dh(s->ssl_ctx,dh); SSL_CTX_set_options(s->ssl_ctx,SSL_OP_SINGLE_DH_USE); DH_free(dh); #if OPENSSL_VERSION_NUMBER >= 0x0090800fL #ifndef OPENSSL_NO_ECDH /* Support for Elliptic-Curve Diffie-Hellman key exchange */ if (!buffer_is_empty(s->ssl_ec_curve)) { /* OpenSSL only supports the "named curves" from RFC 4492, section 5.1.1. */ nid = OBJ_sn2nid((char *) s->ssl_ec_curve->ptr); if (nid == 0) { log_error_write(srv, __FILE__, __LINE__, "ss", "SSL: Unknown curve name", s->ssl_ec_curve->ptr); return -1; } } else { /* Default curve */ nid = OBJ_sn2nid("prime256v1"); } ecdh = EC_KEY_new_by_curve_name(nid); if (ecdh == NULL) { log_error_write(srv, __FILE__, __LINE__, "ss", "SSL: Unable to create curve", s->ssl_ec_curve->ptr); return -1; } SSL_CTX_set_tmp_ecdh(s->ssl_ctx,ecdh); SSL_CTX_set_options(s->ssl_ctx,SSL_OP_SINGLE_ECDH_USE); EC_KEY_free(ecdh); #endif #endif if (!buffer_is_empty(s->ssl_ca_file)) { if (1 != SSL_CTX_load_verify_locations(s->ssl_ctx, s->ssl_ca_file->ptr, NULL)) { log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:", ERR_error_string(ERR_get_error(), NULL), s->ssl_ca_file); return -1; } if (s->ssl_verifyclient) { STACK_OF(X509_NAME) *certs = SSL_load_client_CA_file(s->ssl_ca_file->ptr); if (!certs) { log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:", ERR_error_string(ERR_get_error(), NULL), s->ssl_ca_file); } if (SSL_CTX_set_session_id_context(s->ssl_ctx, (void*) &srv, sizeof(srv)) != 1) { log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:", ERR_error_string(ERR_get_error(), NULL)); return -1; } SSL_CTX_set_client_CA_list(s->ssl_ctx, certs); SSL_CTX_set_verify( s->ssl_ctx, SSL_VERIFY_PEER | (s->ssl_verifyclient_enforce ? SSL_VERIFY_FAIL_IF_NO_PEER_CERT : 0), NULL ); SSL_CTX_set_verify_depth(s->ssl_ctx, s->ssl_verifyclient_depth); } } else if (s->ssl_verifyclient) { log_error_write( srv, __FILE__, __LINE__, "s", "SSL: You specified ssl.verifyclient.activate but no ca_file" ); } if (SSL_CTX_use_certificate_file(s->ssl_ctx, s->ssl_pemfile->ptr, SSL_FILETYPE_PEM) < 0) { log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:", ERR_error_string(ERR_get_error(), NULL), s->ssl_pemfile); return -1; } if (SSL_CTX_use_PrivateKey_file (s->ssl_ctx, s->ssl_pemfile->ptr, SSL_FILETYPE_PEM) < 0) { log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:", ERR_error_string(ERR_get_error(), NULL), s->ssl_pemfile); return -1; } if (SSL_CTX_check_private_key(s->ssl_ctx) != 1) { log_error_write(srv, __FILE__, __LINE__, "sssb", "SSL:", "Private key does not match the certificate public key, reason:", ERR_error_string(ERR_get_error(), NULL), s->ssl_pemfile); return -1; } SSL_CTX_set_default_read_ahead(s->ssl_ctx, 1); SSL_CTX_set_mode(s->ssl_ctx, SSL_CTX_get_mode(s->ssl_ctx) | SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER); # ifndef OPENSSL_NO_TLSEXT if (!SSL_CTX_set_tlsext_servername_callback(s->ssl_ctx, network_ssl_servername_callback) || !SSL_CTX_set_tlsext_servername_arg(s->ssl_ctx, srv)) { log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:", "failed to initialize TLS servername callback, openssl library does not support TLS servername extension"); return -1; } # endif } #endif b = buffer_init(); buffer_copy_string_buffer(b, srv->srvconf.bindhost); buffer_append_string_len(b, CONST_STR_LEN(":")); buffer_append_long(b, srv->srvconf.port); if (0 != network_server_init(srv, b, srv->config_storage[0])) { return -1; } buffer_free(b); #ifdef USE_OPENSSL srv->network_ssl_backend_write = network_write_chunkqueue_openssl; #endif /* get a usefull default */ backend = network_backends[0].nb; /* match name against known types */ if (!buffer_is_empty(srv->srvconf.network_backend)) { for (i = 0; network_backends[i].name; i++) { /**/ if (buffer_is_equal_string(srv->srvconf.network_backend, network_backends[i].name, strlen(network_backends[i].name))) { backend = network_backends[i].nb; break; } } if (NULL == network_backends[i].name) { /* we don't know it */ log_error_write(srv, __FILE__, __LINE__, "sb", "server.network-backend has a unknown value:", srv->srvconf.network_backend); return -1; } } switch(backend) { case NETWORK_BACKEND_WRITE: srv->network_backend_write = network_write_chunkqueue_write; break; #ifdef USE_WRITEV case NETWORK_BACKEND_WRITEV: srv->network_backend_write = network_write_chunkqueue_writev; break; #endif #ifdef USE_LINUX_SENDFILE case NETWORK_BACKEND_LINUX_SENDFILE: srv->network_backend_write = network_write_chunkqueue_linuxsendfile; break; #endif #ifdef USE_FREEBSD_SENDFILE case NETWORK_BACKEND_FREEBSD_SENDFILE: srv->network_backend_write = network_write_chunkqueue_freebsdsendfile; break; #endif #ifdef USE_SOLARIS_SENDFILEV case NETWORK_BACKEND_SOLARIS_SENDFILEV: srv->network_backend_write = network_write_chunkqueue_solarissendfilev; break; #endif default: return -1; } /* check for $SERVER["socket"] */ for (i = 1; i < srv->config_context->used; i++) { data_config *dc = (data_config *)srv->config_context->data[i]; specific_config *s = srv->config_storage[i]; size_t j; /* not our stage */ if (COMP_SERVER_SOCKET != dc->comp) continue; if (dc->cond != CONFIG_COND_EQ) continue; /* check if we already know this socket, * if yes, don't init it */ for (j = 0; j < srv->srv_sockets.used; j++) { if (buffer_is_equal(srv->srv_sockets.ptr[j]->srv_token, dc->string)) { break; } } if (j == srv->srv_sockets.used) { if (0 != network_server_init(srv, dc->string, s)) return -1; } } return 0; }
int main(int argc, char *argv[]) { BN_GENCB *_cb = NULL; DH *a = NULL; DH *b = NULL; BIGNUM *ap = NULL, *ag = NULL, *bp = NULL, *bg = NULL, *apub_key = NULL; BIGNUM *bpub_key = NULL, *priv_key = NULL; char buf[12] = {0}; unsigned char *abuf = NULL; unsigned char *bbuf = NULL; int i, alen, blen, aout, bout; int ret = 1; BIO *out = NULL; CRYPTO_set_mem_debug(1); CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON); RAND_seed(rnd_seed, sizeof rnd_seed); out = BIO_new(BIO_s_file()); if (out == NULL) EXIT(1); BIO_set_fp(out, stdout, BIO_NOCLOSE | BIO_FP_TEXT); _cb = BN_GENCB_new(); if (_cb == NULL) goto err; BN_GENCB_set(_cb, &cb, out); if (((a = DH_new()) == NULL) || (!DH_generate_parameters_ex(a, 64, DH_GENERATOR_5, _cb))) goto err; if (!DH_check(a, &i)) goto err; if (i & DH_CHECK_P_NOT_PRIME) BIO_puts(out, "p value is not prime\n"); if (i & DH_CHECK_P_NOT_SAFE_PRIME) BIO_puts(out, "p value is not a safe prime\n"); if (i & DH_UNABLE_TO_CHECK_GENERATOR) BIO_puts(out, "unable to check the generator value\n"); if (i & DH_NOT_SUITABLE_GENERATOR) BIO_puts(out, "the g value is not a generator\n"); DH_get0_pqg(a, &ap, NULL, &ag); BIO_puts(out, "\np ="); BN_print(out, ap); BIO_puts(out, "\ng ="); BN_print(out, ag); BIO_puts(out, "\n"); b = DH_new(); if (b == NULL) goto err; bp = BN_dup(ap); bg = BN_dup(ag); if ((bp == NULL) || (bg == NULL) || !DH_set0_pqg(b, bp, NULL, bg)) goto err; bp = bg = NULL; if (!DH_generate_key(a)) goto err; DH_get0_key(a, &apub_key, &priv_key); BIO_puts(out, "pri 1="); BN_print(out, priv_key); BIO_puts(out, "\npub 1="); BN_print(out, apub_key); BIO_puts(out, "\n"); if (!DH_generate_key(b)) goto err; DH_get0_key(b, &bpub_key, &priv_key); BIO_puts(out, "pri 2="); BN_print(out, priv_key); BIO_puts(out, "\npub 2="); BN_print(out, bpub_key); BIO_puts(out, "\n"); alen = DH_size(a); abuf = OPENSSL_malloc(alen); if (abuf == NULL) goto err; aout = DH_compute_key(abuf, bpub_key, a); BIO_puts(out, "key1 ="); for (i = 0; i < aout; i++) { sprintf(buf, "%02X", abuf[i]); BIO_puts(out, buf); } BIO_puts(out, "\n"); blen = DH_size(b); bbuf = OPENSSL_malloc(blen); if (bbuf == NULL) goto err; bout = DH_compute_key(bbuf, apub_key, b); BIO_puts(out, "key2 ="); for (i = 0; i < bout; i++) { sprintf(buf, "%02X", bbuf[i]); BIO_puts(out, buf); } BIO_puts(out, "\n"); if ((aout < 4) || (bout != aout) || (memcmp(abuf, bbuf, aout) != 0)) { fprintf(stderr, "Error in DH routines\n"); ret = 1; } else ret = 0; if (!run_rfc5114_tests()) ret = 1; err: (void)BIO_flush(out); ERR_print_errors_fp(stderr); OPENSSL_free(abuf); OPENSSL_free(bbuf); DH_free(b); DH_free(a); BN_free(bp); BN_free(bg); BN_GENCB_free(_cb); BIO_free(out); #ifndef OPENSSL_NO_CRYPTO_MDEBUG if (CRYPTO_mem_leaks_fp(stderr) <= 0) ret = 1; #endif EXIT(ret); }
DH *get_dh4096(void) { static unsigned char dh4096_p[]= { 0xFA,0x14,0x72,0x52,0xC1,0x4D,0xE1,0x5A,0x49,0xD4,0xEF,0x09, 0x2D,0xC0,0xA8,0xFD,0x55,0xAB,0xD7,0xD9,0x37,0x04,0x28,0x09, 0xE2,0xE9,0x3E,0x77,0xE2,0xA1,0x7A,0x18,0xDD,0x46,0xA3,0x43, 0x37,0x23,0x90,0x97,0xF3,0x0E,0xC9,0x03,0x50,0x7D,0x65,0xCF, 0x78,0x62,0xA6,0x3A,0x62,0x22,0x83,0xA1,0x2F,0xFE,0x79,0xBA, 0x35,0xFF,0x59,0xD8,0x1D,0x61,0xDD,0x1E,0x21,0x13,0x17,0xFE, 0xCD,0x38,0x87,0x9E,0xF5,0x4F,0x79,0x10,0x61,0x8D,0xD4,0x22, 0xF3,0x5A,0xED,0x5D,0xEA,0x21,0xE9,0x33,0x6B,0x48,0x12,0x0A, 0x20,0x77,0xD4,0x25,0x60,0x61,0xDE,0xF6,0xB4,0x4F,0x1C,0x63, 0x40,0x8B,0x3A,0x21,0x93,0x8B,0x79,0x53,0x51,0x2C,0xCA,0xB3, 0x7B,0x29,0x56,0xA8,0xC7,0xF8,0xF4,0x7B,0x08,0x5E,0xA6,0xDC, 0xA2,0x45,0x12,0x56,0xDD,0x41,0x92,0xF2,0xDD,0x5B,0x8F,0x23, 0xF0,0xF3,0xEF,0xE4,0x3B,0x0A,0x44,0xDD,0xED,0x96,0x84,0xF1, 0xA8,0x32,0x46,0xA3,0xDB,0x4A,0xBE,0x3D,0x45,0xBA,0x4E,0xF8, 0x03,0xE5,0xDD,0x6B,0x59,0x0D,0x84,0x1E,0xCA,0x16,0x5A,0x8C, 0xC8,0xDF,0x7C,0x54,0x44,0xC4,0x27,0xA7,0x3B,0x2A,0x97,0xCE, 0xA3,0x7D,0x26,0x9C,0xAD,0xF4,0xC2,0xAC,0x37,0x4B,0xC3,0xAD, 0x68,0x84,0x7F,0x99,0xA6,0x17,0xEF,0x6B,0x46,0x3A,0x7A,0x36, 0x7A,0x11,0x43,0x92,0xAD,0xE9,0x9C,0xFB,0x44,0x6C,0x3D,0x82, 0x49,0xCC,0x5C,0x6A,0x52,0x42,0xF8,0x42,0xFB,0x44,0xF9,0x39, 0x73,0xFB,0x60,0x79,0x3B,0xC2,0x9E,0x0B,0xDC,0xD4,0xA6,0x67, 0xF7,0x66,0x3F,0xFC,0x42,0x3B,0x1B,0xDB,0x4F,0x66,0xDC,0xA5, 0x8F,0x66,0xF9,0xEA,0xC1,0xED,0x31,0xFB,0x48,0xA1,0x82,0x7D, 0xF8,0xE0,0xCC,0xB1,0xC7,0x03,0xE4,0xF8,0xB3,0xFE,0xB7,0xA3, 0x13,0x73,0xA6,0x7B,0xC1,0x0E,0x39,0xC7,0x94,0x48,0x26,0x00, 0x85,0x79,0xFC,0x6F,0x7A,0xAF,0xC5,0x52,0x35,0x75,0xD7,0x75, 0xA4,0x40,0xFA,0x14,0x74,0x61,0x16,0xF2,0xEB,0x67,0x11,0x6F, 0x04,0x43,0x3D,0x11,0x14,0x4C,0xA7,0x94,0x2A,0x39,0xA1,0xC9, 0x90,0xCF,0x83,0xC6,0xFF,0x02,0x8F,0xA3,0x2A,0xAC,0x26,0xDF, 0x0B,0x8B,0xBE,0x64,0x4A,0xF1,0xA1,0xDC,0xEE,0xBA,0xC8,0x03, 0x82,0xF6,0x62,0x2C,0x5D,0xB6,0xBB,0x13,0x19,0x6E,0x86,0xC5, 0x5B,0x2B,0x5E,0x3A,0xF3,0xB3,0x28,0x6B,0x70,0x71,0x3A,0x8E, 0xFF,0x5C,0x15,0xE6,0x02,0xA4,0xCE,0xED,0x59,0x56,0xCC,0x15, 0x51,0x07,0x79,0x1A,0x0F,0x25,0x26,0x27,0x30,0xA9,0x15,0xB2, 0xC8,0xD4,0x5C,0xCC,0x30,0xE8,0x1B,0xD8,0xD5,0x0F,0x19,0xA8, 0x80,0xA4,0xC7,0x01,0xAA,0x8B,0xBA,0x53,0xBB,0x47,0xC2,0x1F, 0x6B,0x54,0xB0,0x17,0x60,0xED,0x79,0x21,0x95,0xB6,0x05,0x84, 0x37,0xC8,0x03,0xA4,0xDD,0xD1,0x06,0x69,0x8F,0x4C,0x39,0xE0, 0xC8,0x5D,0x83,0x1D,0xBE,0x6A,0x9A,0x99,0xF3,0x9F,0x0B,0x45, 0x29,0xD4,0xCB,0x29,0x66,0xEE,0x1E,0x7E,0x3D,0xD7,0x13,0x4E, 0xDB,0x90,0x90,0x58,0xCB,0x5E,0x9B,0xCD,0x2E,0x2B,0x0F,0xA9, 0x4E,0x78,0xAC,0x05,0x11,0x7F,0xE3,0x9E,0x27,0xD4,0x99,0xE1, 0xB9,0xBD,0x78,0xE1,0x84,0x41,0xA0,0xDF, }; static unsigned char dh4096_g[]= { 0x02, }; DH *dh; if ((dh=DH_new()) == NULL) return(NULL); dh->p=BN_bin2bn(dh4096_p,sizeof(dh4096_p),NULL); dh->g=BN_bin2bn(dh4096_g,sizeof(dh4096_g),NULL); if ((dh->p == NULL) || (dh->g == NULL)) { DH_free(dh); return(NULL); } return(dh); }
int gendh_main(int argc, char **argv) { BN_GENCB cb; DH *dh = NULL; int ret = 1, num = DEFBITS; int g = 2; char *outfile = NULL; #ifndef OPENSSL_NO_ENGINE char *engine = NULL; #endif BIO *out = NULL; BN_GENCB_set(&cb, dh_cb, bio_err); 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 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 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); } else { if (BIO_write_filename(out, outfile) <= 0) { perror(outfile); goto end; } } 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; 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); 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) 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; 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); }
void Context::initDH(const std::string& dhParamsFile) { #ifndef OPENSSL_NO_DH // 1024-bit MODP Group with 160-bit prime order subgroup (RFC5114) // -----BEGIN DH PARAMETERS----- // MIIBDAKBgQCxC4+WoIDgHd6S3l6uXVTsUsmfvPsGo8aaap3KUtI7YWBz4oZ1oj0Y // mDjvHi7mUsAT7LSuqQYRIySXXDzUm4O/rMvdfZDEvXCYSI6cIZpzck7/1vrlZEc4 // +qMaT/VbzMChUa9fDci0vUW/N982XBpl5oz9p21NpwjfH7K8LkpDcQKBgQCk0cvV // w/00EmdlpELvuZkF+BBN0lisUH/WQGz/FCZtMSZv6h5cQVZLd35pD1UE8hMWAhe0 // sBuIal6RVH+eJ0n01/vX07mpLuGQnQ0iY/gKdqaiTAh6CR9THb8KAWm2oorWYqTR // jnOvoy13nVkY0IvIhY9Nzvl8KiSFXm7rIrOy5QICAKA= // -----END DH PARAMETERS----- // static const unsigned char dh1024_p[] = { 0xB1,0x0B,0x8F,0x96,0xA0,0x80,0xE0,0x1D,0xDE,0x92,0xDE,0x5E, 0xAE,0x5D,0x54,0xEC,0x52,0xC9,0x9F,0xBC,0xFB,0x06,0xA3,0xC6, 0x9A,0x6A,0x9D,0xCA,0x52,0xD2,0x3B,0x61,0x60,0x73,0xE2,0x86, 0x75,0xA2,0x3D,0x18,0x98,0x38,0xEF,0x1E,0x2E,0xE6,0x52,0xC0, 0x13,0xEC,0xB4,0xAE,0xA9,0x06,0x11,0x23,0x24,0x97,0x5C,0x3C, 0xD4,0x9B,0x83,0xBF,0xAC,0xCB,0xDD,0x7D,0x90,0xC4,0xBD,0x70, 0x98,0x48,0x8E,0x9C,0x21,0x9A,0x73,0x72,0x4E,0xFF,0xD6,0xFA, 0xE5,0x64,0x47,0x38,0xFA,0xA3,0x1A,0x4F,0xF5,0x5B,0xCC,0xC0, 0xA1,0x51,0xAF,0x5F,0x0D,0xC8,0xB4,0xBD,0x45,0xBF,0x37,0xDF, 0x36,0x5C,0x1A,0x65,0xE6,0x8C,0xFD,0xA7,0x6D,0x4D,0xA7,0x08, 0xDF,0x1F,0xB2,0xBC,0x2E,0x4A,0x43,0x71, }; static const unsigned char dh1024_g[] = { 0xA4,0xD1,0xCB,0xD5,0xC3,0xFD,0x34,0x12,0x67,0x65,0xA4,0x42, 0xEF,0xB9,0x99,0x05,0xF8,0x10,0x4D,0xD2,0x58,0xAC,0x50,0x7F, 0xD6,0x40,0x6C,0xFF,0x14,0x26,0x6D,0x31,0x26,0x6F,0xEA,0x1E, 0x5C,0x41,0x56,0x4B,0x77,0x7E,0x69,0x0F,0x55,0x04,0xF2,0x13, 0x16,0x02,0x17,0xB4,0xB0,0x1B,0x88,0x6A,0x5E,0x91,0x54,0x7F, 0x9E,0x27,0x49,0xF4,0xD7,0xFB,0xD7,0xD3,0xB9,0xA9,0x2E,0xE1, 0x90,0x9D,0x0D,0x22,0x63,0xF8,0x0A,0x76,0xA6,0xA2,0x4C,0x08, 0x7A,0x09,0x1F,0x53,0x1D,0xBF,0x0A,0x01,0x69,0xB6,0xA2,0x8A, 0xD6,0x62,0xA4,0xD1,0x8E,0x73,0xAF,0xA3,0x2D,0x77,0x9D,0x59, 0x18,0xD0,0x8B,0xC8,0x85,0x8F,0x4D,0xCE,0xF9,0x7C,0x2A,0x24, 0x85,0x5E,0x6E,0xEB,0x22,0xB3,0xB2,0xE5, }; DH* dh = 0; if (!dhParamsFile.empty()) { BIO* bio = BIO_new_file(dhParamsFile.c_str(), "r"); if (!bio) { std::string msg = Utility::getLastError(); throw SSLContextException(std::string("Error opening Diffie-Hellman parameters file ") + dhParamsFile, msg); } dh = PEM_read_bio_DHparams(bio, 0, 0, 0); BIO_free(bio); if (!dh) { std::string msg = Utility::getLastError(); throw SSLContextException(std::string("Error reading Diffie-Hellman parameters from file ") + dhParamsFile, msg); } } else { dh = DH_new(); if (!dh) { std::string msg = Utility::getLastError(); throw SSLContextException("Error creating Diffie-Hellman parameters", msg); } #if OPENSSL_VERSION_NUMBER >= 0x10100000L BIGNUM* p = BN_bin2bn(dh1024_p, sizeof(dh1024_p), 0); BIGNUM* g = BN_bin2bn(dh1024_g, sizeof(dh1024_g), 0); DH_set0_pqg(dh, p, 0, g); DH_set_length(dh, 160); if (!p || !g) { DH_free(dh); throw SSLContextException("Error creating Diffie-Hellman parameters"); } #else dh->p = BN_bin2bn(dh1024_p, sizeof(dh1024_p), 0); dh->g = BN_bin2bn(dh1024_g, sizeof(dh1024_g), 0); dh->length = 160; if ((!dh->p) || (!dh->g)) { DH_free(dh); throw SSLContextException("Error creating Diffie-Hellman parameters"); } #endif } SSL_CTX_set_tmp_dh(_pSSLContext, dh); SSL_CTX_set_options(_pSSLContext, SSL_OP_SINGLE_DH_USE); DH_free(dh); #else if (!dhParamsFile.empty()) throw SSLContextException("OpenSSL does not support DH"); #endif }
int main(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; CRYPTO_library_init(); BN_GENCB_set(&_cb, &cb, stdout); 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) { puts("p value is not prime\n"); } if (i & DH_CHECK_P_NOT_SAFE_PRIME) { puts("p value is not a safe prime\n"); } if (i & DH_CHECK_UNABLE_TO_CHECK_GENERATOR) { puts("unable to check the generator value\n"); } if (i & DH_CHECK_NOT_SUITABLE_GENERATOR) { puts("the g value is not a generator\n"); } puts("\np ="); BN_print_fp(stdout, a->p); puts("\ng ="); BN_print_fp(stdout, a->g); puts("\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; } if (!DH_generate_key(a)) { goto err; } puts("pri 1="); BN_print_fp(stdout, a->priv_key); puts("\npub 1="); BN_print_fp(stdout, a->pub_key); puts("\n"); if (!DH_generate_key(b)) { goto err; } puts("pri 2="); BN_print_fp(stdout, b->priv_key); puts("\npub 2="); BN_print_fp(stdout, b->pub_key); puts("\n"); alen = DH_size(a); abuf = (unsigned char *)OPENSSL_malloc(alen); aout = DH_compute_key(abuf, b->pub_key, a); puts("key1 ="); for (i = 0; i < aout; i++) { sprintf(buf, "%02X", abuf[i]); puts(buf); } puts("\n"); blen = DH_size(b); bbuf = (unsigned char *)OPENSSL_malloc(blen); bout = DH_compute_key(bbuf, a->pub_key, b); puts("key2 ="); for (i = 0; i < bout; i++) { sprintf(buf, "%02X", bbuf[i]); puts(buf); } puts("\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); if (abuf != NULL) { OPENSSL_free(abuf); } if (bbuf != NULL) { OPENSSL_free(bbuf); } if (b != NULL) { DH_free(b); } if (a != NULL) { DH_free(a); } return ret; }
/* 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) { DHerr(DH_F_DH_GENERATE_PARAMETERS, DH_R_BAD_GENERATOR); 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; } #if 0 /* does not work for safe primes */ else if (generator == DH_GENERATOR_3) { if (!BN_set_word(t1,12)) goto err; if (!BN_set_word(t2,5)) goto err; g=3; } #endif 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) { DHerr(DH_F_DH_GENERATE_PARAMETERS,ERR_R_BN_LIB); ok=0; } if (ctx != NULL) { BN_CTX_end(ctx); BN_CTX_free(ctx); } if (!ok && (ret != NULL)) { DH_free(ret); ret=NULL; } return(ret); }
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); } }
DhParamRAII() { dh = DH_new(); }
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 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; }
SESSION *session_init_client (void) { SESSION *session; if ((session = (SESSION *) calloc (1, sizeof (SESSION))) == NULL) return NULL; session->client_OS = 0x00; /* 0x00 == Windows, 0x01 == Mac OS X */ memcpy(session->client_id, "\x01\x04\x01\x01", 4); session->client_revision = 99999; /* * Client and server generate 16 random bytes each. */ RAND_bytes (session->client_random_16, 16); if ((session->rsa = RSA_generate_key (1024, 65537, NULL, NULL)) == NULL) { DSFYDEBUG ("RSA key generation failed with error %lu\n", ERR_get_error ()); } assert (session->rsa != NULL); /* * Create a private and public key. * This, along with key signing, is used to securely * agree on a session key for the Shannon stream cipher. * */ session->dh = DH_new (); session->dh->p = BN_bin2bn (DH_prime, 96, NULL); session->dh->g = BN_bin2bn (DH_generator, 1, NULL); assert (DH_generate_key (session->dh) == 1); BN_bn2bin (session->dh->priv_key, session->my_priv_key); BN_bn2bin (session->dh->pub_key, session->my_pub_key); /* * Found in Storage.dat (cache) at offset 16. * Automatically generated, but we're lazy. * */ memcpy (session->cache_hash, "\xf4\xc2\xaa\x05\xe8\x25\xa7\xb5\xe4\xe6\x59\x0f\x3d\xd0\xbe\x0a\xef\x20\x51\x95", 20); session->cache_hash[0] = (unsigned char) getpid (); session->ap_sock = -1; session->username[0] = 0; session->server_host[0] = 0; session->server_port = 0; session->key_recv_IV = 0; session->key_send_IV = 0; session->user_info.username[0] = 0; session->user_info.country[0] = 0; session->user_info.server_host[0] = 0; session->user_info.server_port = 0; pthread_mutex_init(&session->login_mutex, NULL); pthread_cond_init(&session->login_cond, NULL); return session; }
int main( int argc, char *argv[] ) { int nRetVal = EXIT_SUCCESS; DH *pMine = NULL, *pTheirs = NULL; int nSharedKey = 0; char* pSharedKey = NULL; char pFoldedKey[ SHA256_DIGEST_LENGTH ] = { 0 }; ARGS sArgs = { 0 }; int fdSock = 0; if( !parseArgs( &sArgs, argc, argv ) ) { printf( "usage:\n%s\n" "\t-client <ip>:<port>\n" "\t-server <port>\n", argv[0] ); nRetVal = EXIT_FAILURE; } // bind/connect if( EXIT_SUCCESS == nRetVal ) { fdSock = getNetworkConnection( &sArgs ); if( -1 == fdSock ) { nRetVal = EXIT_FAILURE; } else { #ifdef DEBUG_OUTPUT printf( "[i]\tgot a connection\n" ); #endif } } // create diffie structures if( EXIT_SUCCESS == nRetVal ) { pMine = DH_new(); pTheirs = DH_new(); if( pMine && pTheirs ) { BN_hex2bn( &(pMine->p), "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" "83655D23DCA3AD961C62F356208552BB9ED529077096966D" "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9" "DE2BCBF6955817183995497CEA956AE515D2261898FA0510" "15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64" "ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7" "ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B" "F12FFA06D98A0864D87602733EC86A64521F2B18177B200C" "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31" "43DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D7" "88719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA" "2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6" "287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED" "1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA9" "93B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934028492" "36C3FAB4D27C7026C1D4DCB2602646DEC9751E763DBA37BD" "F8FF9406AD9E530EE5DB382F413001AEB06A53ED9027D831" "179727B0865A8918DA3EDBEBCF9B14ED44CE6CBACED4BB1B" "DB7F1447E6CC254B332051512BD7AF426FB8F401378CD2BF" "5983CA01C64B92ECF032EA15D1721D03F482D7CE6E74FEF6" "D55E702F46980C82B5A84031900B1C9E59E7C97FBEC7E8F3" "23A97A7E36CC88BE0F1D45B7FF585AC54BD407B22B4154AA" "CC8F6D7EBF48E1D814CC5ED20F8037E0A79715EEF29BE328" "06A1D58BB7C5DA76F550AA3D8A1FBFF0EB19CCB1A313D55C" "DA56C9EC2EF29632387FE8D76E3C0468043E8F663F4860EE" "12BF2D5B0B7474D6E694F91E6DBE115974A3926F12FEE5E4" "38777CB6A932DF8CD8BEC4D073B931BA3BC832B68D9DD300" "741FA7BF8AFC47ED2576F6936BA424663AAB639C5AE4F568" "3423B4742BF1C978238F16CBE39D652DE3FDB8BEFC848AD9" "22222E04A4037C0713EB57A81A23F0C73473FC646CEA306B" "4BCBC8862F8385DDFA9D4B7FA2C087E879683303ED5BDD3A" "062B3CF5B3A278A66D2A13F83F44F82DDF310EE074AB6A36" "4597E899A0255DC164F31CC50846851DF9AB48195DED7EA1" "B1D510BD7EE74D73FAF36BC31ECFA268359046F4EB879F92" "4009438B481C6CD7889A002ED5EE382BC9190DA6FC026E47" "9558E4475677E9AA9E3050E2765694DFC81F56E880B96E71" "60C980DD98EDD3DFFFFFFFFFFFFFFFFF" ); BN_hex2bn( &(pMine->g), "2" ); // "they're" going to use the same pTheirs->p = BN_dup( pMine->p ); pTheirs->g = BN_dup( pMine->g ); } // check we have everything we should if( NULL == pMine || NULL == pMine->p || NULL == pMine->g || NULL == pTheirs || NULL == pTheirs->p || NULL == pTheirs->g ) { nRetVal = EXIT_FAILURE; } } // pMine has p & g if( EXIT_SUCCESS == nRetVal && pMine ) { #ifdef DEBUG_OUTPUT fprintf( stdout, "[i]\tgenerating key....." ); fflush( stdout ); #endif if( DH_generate_key( pMine ) ) { #ifdef DEBUG_OUTPUT fprintf( stdout, "done.\n" ); #endif } else { #ifdef DEBUG_OUTPUT fprintf( stdout, "failed.\n" ); #endif nRetVal = EXIT_FAILURE; } } // // we now have public and private keys // // // now push our public key // if( EXIT_SUCCESS == nRetVal ) { pSharedKey = BN_bn2hex( pMine->pub_key ); // ( just reusing the var ) if( pSharedKey ) { nSharedKey = strlen( pSharedKey ); #ifdef DEBUG_OUTPUT printf( "[i]\tsending public key (%d)\n", nSharedKey ); #endif write( fdSock, pSharedKey, nSharedKey ); } else { nRetVal = EXIT_FAILURE; } } // // read in pTheirs public key // (reusing pShareKey's buffer - its the same size after all) // if( EXIT_SUCCESS == nRetVal && pSharedKey ) { bzero( pSharedKey, nSharedKey ); if( nSharedKey == read( fdSock, pSharedKey, nSharedKey ) ) { // looks good } else { // incompleate read - should really re-try nRetVal = EXIT_FAILURE; } } // // parse in the public key // if( EXIT_SUCCESS == nRetVal && pSharedKey ) { BN_hex2bn( &(pTheirs->pub_key), pSharedKey ); } // // free that temp buffer // if( pSharedKey ) { OPENSSL_free( pSharedKey ); pSharedKey = NULL; nSharedKey = 0; } // // calculate shared key // if( EXIT_SUCCESS == nRetVal ) { nSharedKey = DH_size( pMine ); pSharedKey = OPENSSL_malloc( nSharedKey ); if( pSharedKey ) { DH_compute_key( pSharedKey, pTheirs->pub_key, pMine ); } else { // malloc failed nRetVal = EXIT_FAILURE; } } if( EXIT_SUCCESS == nRetVal && nSharedKey && pSharedKey ) { // key is too big - needs folding SHA256_CTX ctx = { 0 }; SHA256_Init( &ctx ); SHA256_Update( &ctx, pSharedKey, nSharedKey ); SHA256_Final( pFoldedKey, &ctx ); #ifdef DEBUG_OUTPUT fprintf( stdout, "[i]\tsuccesfully key-exchanged.\n" ); { BIGNUM *pOutput = BN_bin2bn( pFoldedKey, sizeof( pFoldedKey ), NULL ); char *pTextOut= BN_bn2hex( pOutput ); fprintf( stdout, "[i]\tshared key:\n%s\n", pTextOut ); OPENSSL_free( pTextOut ); BN_free( pOutput ); } #endif nRetVal = copyLoop( fdSock, pFoldedKey, sizeof( pFoldedKey ) ); // // close the socket connection // close( fdSock ); } if( pSharedKey ) { OPENSSL_free( pSharedKey ); pSharedKey = NULL; nSharedKey = 0; } if( pMine ) { DH_free( pMine ); pMine = NULL; } if( pTheirs ) { DH_free( pTheirs ); pTheirs = NULL; } return nRetVal; }
static LUA_FUNCTION(openssl_pkey_new) { EVP_PKEY *pkey = NULL; const char* alg = "rsa"; if (lua_isnoneornil(L, 1) || lua_isstring(L, 1)) { alg = luaL_optstring(L, 1, alg); if (strcasecmp(alg, "rsa") == 0) { int bits = luaL_optint(L, 2, 1024); int e = luaL_optint(L, 3, 65537); RSA* rsa = RSA_new(); BIGNUM *E = BN_new(); BN_set_word(E, e); if (RSA_generate_key_ex(rsa, bits, E, NULL)) { pkey = EVP_PKEY_new(); EVP_PKEY_assign_RSA(pkey, rsa); } else RSA_free(rsa); BN_free(E); } else if (strcasecmp(alg, "dsa") == 0) { int bits = luaL_optint(L, 2, 1024); size_t seed_len = 0; const char* seed = luaL_optlstring(L, 3, NULL, &seed_len); DSA *dsa = DSA_new(); if (DSA_generate_parameters_ex(dsa, bits, (byte*)seed, seed_len, NULL, NULL, NULL) && DSA_generate_key(dsa)) { pkey = EVP_PKEY_new(); EVP_PKEY_assign_DSA(pkey, dsa); } else DSA_free(dsa); } else if (strcasecmp(alg, "dh") == 0) { int bits = luaL_optint(L, 2, 512); int generator = luaL_optint(L, 3, 2); DH* dh = DH_new(); if (DH_generate_parameters_ex(dh, bits, generator, NULL)) { if (DH_generate_key(dh)) { pkey = EVP_PKEY_new(); EVP_PKEY_assign_DH(pkey, dh); } else DH_free(dh); } else DH_free(dh); } #ifndef OPENSSL_NO_EC else if (strcasecmp(alg, "ec") == 0) { int ec_name = NID_undef; EC_KEY *ec = NULL; EC_GROUP *group = openssl_get_ec_group(L, 2, 3, 4); if (!group) luaL_error(L, "failed to get ec_group object"); ec = EC_KEY_new(); if (ec) { EC_KEY_set_group(ec, group); EC_GROUP_free(group); if (EC_KEY_generate_key(ec)) { pkey = EVP_PKEY_new(); EVP_PKEY_assign_EC_KEY(pkey, ec); } else EC_KEY_free(ec); } else EC_GROUP_free(group); } #endif else { luaL_error(L, "not support %s!!!!", alg); } } else if (lua_istable(L, 1)) { lua_getfield(L, 1, "alg"); alg = luaL_optstring(L, -1, alg); lua_pop(L, 1); if (strcasecmp(alg, "rsa") == 0) { pkey = EVP_PKEY_new(); if (pkey) { RSA *rsa = RSA_new(); if (rsa) { OPENSSL_PKEY_SET_BN(1, rsa, n); OPENSSL_PKEY_SET_BN(1, rsa, e); OPENSSL_PKEY_SET_BN(1, rsa, d); OPENSSL_PKEY_SET_BN(1, rsa, p); OPENSSL_PKEY_SET_BN(1, rsa, q); OPENSSL_PKEY_SET_BN(1, rsa, dmp1); OPENSSL_PKEY_SET_BN(1, rsa, dmq1); OPENSSL_PKEY_SET_BN(1, rsa, iqmp); if (rsa->n) { if (!EVP_PKEY_assign_RSA(pkey, rsa)) { EVP_PKEY_free(pkey); pkey = NULL; } } } } } else if (strcasecmp(alg, "dsa") == 0) { pkey = EVP_PKEY_new(); if (pkey) { DSA *dsa = DSA_new(); if (dsa) { OPENSSL_PKEY_SET_BN(-1, dsa, p); OPENSSL_PKEY_SET_BN(-1, dsa, q); OPENSSL_PKEY_SET_BN(-1, dsa, g); OPENSSL_PKEY_SET_BN(-1, dsa, priv_key); OPENSSL_PKEY_SET_BN(-1, dsa, pub_key); if (dsa->p && dsa->q && dsa->g) { if (!dsa->priv_key && !dsa->pub_key) { DSA_generate_key(dsa); } if (!EVP_PKEY_assign_DSA(pkey, dsa)) { EVP_PKEY_free(pkey); pkey = NULL; } } } } } else if (strcasecmp(alg, "dh") == 0) { pkey = EVP_PKEY_new(); if (pkey) { DH *dh = DH_new(); if (dh) { OPENSSL_PKEY_SET_BN(-1, dh, p); OPENSSL_PKEY_SET_BN(-1, dh, g); OPENSSL_PKEY_SET_BN(-1, dh, priv_key); OPENSSL_PKEY_SET_BN(-1, dh, pub_key); if (dh->p && dh->g) { if (!dh->pub_key) { DH_generate_key(dh); } if (!EVP_PKEY_assign_DH(pkey, dh)) { EVP_PKEY_free(pkey); pkey = NULL; } } } } } else if (strcasecmp(alg, "ec") == 0) { BIGNUM *d = NULL; BIGNUM *x = NULL; BIGNUM *y = NULL; BIGNUM *z = NULL; EC_GROUP *group = NULL; lua_getfield(L, -1, "ec_name"); lua_getfield(L, -2, "param_enc"); lua_getfield(L, -3, "conv_form"); group = openssl_get_ec_group(L, -3, -2, -1); lua_pop(L, 3); if (!group) { luaL_error(L, "get openssl.ec_group fail"); } EC_GET_FIELD(d); EC_GET_FIELD(x); EC_GET_FIELD(y); EC_GET_FIELD(z); pkey = EVP_PKEY_new(); if (pkey) { EC_KEY *ec = EC_KEY_new(); if (ec) { EC_KEY_set_group(ec, group); if (d) EC_KEY_set_private_key(ec, d); if (x != NULL && y != NULL) { EC_POINT *pnt = EC_POINT_new(group); if (z == NULL) EC_POINT_set_affine_coordinates_GFp(group, pnt, x, y, NULL); else EC_POINT_set_Jprojective_coordinates_GFp(group, pnt, x, y, z, NULL); EC_KEY_set_public_key(ec, pnt); } if (!EVP_PKEY_assign_EC_KEY(pkey, ec)) { EC_KEY_free(ec); EVP_PKEY_free(pkey); pkey = NULL; } if (d && !EC_KEY_check_key(ec)) { EC_KEY_generate_key_part(ec); } } } } } if (pkey) { PUSH_OBJECT(pkey, "openssl.evp_pkey"); return 1; } return 0; }
int MAIN(int argc, char **argv) { #ifndef OPENSSL_NO_ENGINE ENGINE *e = NULL; #endif 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 e = 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)) { if(dh) DH_free(dh); 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); }
uint32 CRegProtocol::GenerateDHKeyPair(DH **DHKeyPair, BufferObj &pubKey) { uint8 temp[SIZE_PUB_KEY]; try { //1. Initialize the DH structure *DHKeyPair = DH_new(); if(*DHKeyPair == NULL) { TUTRACE((TUTRACE_ERR, "RPROTO: DH_new failed\n")); throw RPROT_ERR_CRYPTO; } (*DHKeyPair)->p = BN_new(); (*DHKeyPair)->g = BN_new(); //2. load the value of P if(BN_bin2bn(DH_P_VALUE, BUF_SIZE_1536_BITS, (*DHKeyPair)->p)==NULL) { TUTRACE((TUTRACE_ERR, "RPROTO: BN_bin2bn P: %s", ERR_error_string(ERR_get_error(), NULL))); throw RPROT_ERR_CRYPTO; } //3. load the value of G uint32 g = WscHtonl(DH_G_VALUE); if(BN_bin2bn((uint8 *)&g, 4, (*DHKeyPair)->g)==NULL) { TUTRACE((TUTRACE_ERR, "RPROTO: BN_bin2bn G: %s", ERR_error_string(ERR_get_error(), NULL))); throw RPROT_ERR_CRYPTO; } //4. generate the DH key if(DH_generate_key(*DHKeyPair) == 0) { TUTRACE((TUTRACE_ERR, "RPROTO: DH_generate_key: %s", ERR_error_string(ERR_get_error(), NULL))); throw RPROT_ERR_CRYPTO; } //5. extract the DH public key int len = BN_bn2bin((*DHKeyPair)->pub_key, temp); if(0 == len) { TUTRACE((TUTRACE_ERR, "RPROTO: BN_bn2bin: %s", ERR_error_string(ERR_get_error(), NULL))); throw RPROT_ERR_CRYPTO; } pubKey.Append(SIZE_PUB_KEY, temp); return WSC_SUCCESS; } catch(uint32 err) { return err; } catch(...) { return WSC_ERR_SYSTEM; } }//GenerateDHKeyPair
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 == DH_GENERATOR_2) { BN_set_word(t1,24); BN_set_word(t2,11); g=2; } #ifdef undef /* does not work for safe primes */ else if (generator == DH_GENERATOR_3) { BN_set_word(t1,12); BN_set_word(t2,5); g=3; } #endif else if (generator == DH_GENERATOR_5) { BN_set_word(t1,10); BN_set_word(t2,3); /* BN_set_word(t3,7); just have to miss * out on these ones :-( */ g=5; } else 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) { DHerr(DH_F_DH_GENERATE_PARAMETERS,ERR_R_BN_LIB); ok=0; } if (ctx != NULL) { BN_CTX_end(ctx); BN_CTX_free(ctx); } if (!ok && (ret != NULL)) { DH_free(ret); ret=NULL; } return(ret); }
uint32 reg_proto_generate_prebuild_dhkeypair(DH **DHKeyPair, BufferObj *pubKey, uint8 *prebuild_privkey) { BIGNUM *pub_key = NULL, *priv_key = NULL; BN_CTX *ctx = NULL; BN_MONT_CTX *mont; uint8 temp[SIZE_PUB_KEY]; uint32 g = 0; uint32 ret = RPROT_ERR_CRYPTO; *DHKeyPair = DH_new(); if (*DHKeyPair == NULL) { TUTRACE((TUTRACE_ERR, "RPROTO: DH_new failed\n")); return RPROT_ERR_CRYPTO; } (*DHKeyPair)->p = BN_new(); if ((*DHKeyPair)->p == NULL) { TUTRACE((TUTRACE_ERR, "RPROTO: BN_new p failed\n")); return RPROT_ERR_CRYPTO; } (*DHKeyPair)->g = BN_new(); if ((*DHKeyPair)->g == NULL) { TUTRACE((TUTRACE_ERR, "RPROTO: BN_new g failed\n")); return RPROT_ERR_CRYPTO; } /* 2. load the value of P */ if (BN_bin2bn(DH_P_VALUE, BUF_SIZE_1536_BITS, (*DHKeyPair)->p) == NULL) { TUTRACE((TUTRACE_ERR, "RPROTO: load value p failed\n")); return RPROT_ERR_CRYPTO; } /* 3. load the value of G */ g = WpsHtonl(DH_G_VALUE); if (BN_bin2bn((uint8 *)&g, 4, (*DHKeyPair)->g) == NULL) { TUTRACE((TUTRACE_ERR, "RPROTO: load value g failed\n")); return RPROT_ERR_CRYPTO; } /* 4. generate the DH key */ ctx = BN_CTX_new(); if (ctx == NULL) goto err; priv_key = BN_new(); if (priv_key == NULL) goto err; pub_key = BN_new(); if (pub_key == NULL) goto err; if (!BN_bin2bn(prebuild_privkey, SIZE_PUB_KEY, priv_key)) goto err; if ((*DHKeyPair)->flags & DH_FLAG_CACHE_MONT_P) { if (((*DHKeyPair)->method_mont_p = BN_MONT_CTX_new()) != NULL) if (!BN_MONT_CTX_set((BN_MONT_CTX *)(*DHKeyPair)->method_mont_p, (*DHKeyPair)->p, ctx)) goto err; } mont = (BN_MONT_CTX *)(*DHKeyPair)->method_mont_p; if ((*DHKeyPair)->g->top == 1) { BN_ULONG A = (*DHKeyPair)->g->d[0]; if (!BN_mod_exp_mont_word(pub_key, A, priv_key, (*DHKeyPair)->p, ctx, mont)) goto err; } else if (!BN_mod_exp_mont(pub_key, (*DHKeyPair)->g, priv_key, (*DHKeyPair)->p, ctx, mont)) goto err; (*DHKeyPair)->pub_key = pub_key; (*DHKeyPair)->priv_key = priv_key; if (BN_num_bytes((*DHKeyPair)->pub_key) == 0) goto err; /* 5. extract the DH public key */ if (reg_proto_BN_bn2bin((*DHKeyPair)->pub_key, temp) != SIZE_PUB_KEY) { TUTRACE((TUTRACE_ERR, "RPROTO: invalid public key length\n")); goto err; } buffobj_Append(pubKey, SIZE_PUB_KEY, temp); ret = WPS_SUCCESS; err: if ((pub_key != NULL) && ((*DHKeyPair)->pub_key == NULL)) BN_free(pub_key); if ((priv_key != NULL) && ((*DHKeyPair)->priv_key == NULL)) BN_free(priv_key); if (ctx) BN_CTX_free(ctx); 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; 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 (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 (! 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 if (issuer == QString::fromUtf8("Murmur Autogenerated Certificate")) { log("Old autogenerated certificate is unusable for registration, invalidating it"); qscCert = QSslCertificate(); qskKey = QSslKey(); } 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 (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 (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 }
static int dh_test(void) { BN_GENCB *_cb = NULL; DH *a = NULL; DH *b = NULL; const BIGNUM *ap = NULL, *ag = NULL, *apub_key = NULL; const BIGNUM *bpub_key = NULL; BIGNUM *bp = NULL, *bg = NULL; unsigned char *abuf = NULL; unsigned char *bbuf = NULL; int i, alen, blen, aout, bout; int ret = 0; RAND_seed(rnd_seed, sizeof rnd_seed); if (!TEST_ptr(_cb = BN_GENCB_new())) goto err; BN_GENCB_set(_cb, &cb, NULL); if (!TEST_ptr(a = DH_new()) || !TEST_true(DH_generate_parameters_ex(a, 64, DH_GENERATOR_5, _cb))) goto err; if (!DH_check(a, &i)) goto err; if (!TEST_false(i & DH_CHECK_P_NOT_PRIME) || !TEST_false(i & DH_CHECK_P_NOT_SAFE_PRIME) || !TEST_false(i & DH_UNABLE_TO_CHECK_GENERATOR) || !TEST_false(i & DH_NOT_SUITABLE_GENERATOR)) goto err; DH_get0_pqg(a, &ap, NULL, &ag); if (!TEST_ptr(b = DH_new())) goto err; if (!TEST_ptr(bp = BN_dup(ap)) || !TEST_ptr(bg = BN_dup(ag)) || !TEST_true(DH_set0_pqg(b, bp, NULL, bg))) goto err; bp = bg = NULL; if (!DH_generate_key(a)) goto err; DH_get0_key(a, &apub_key, NULL); if (!DH_generate_key(b)) goto err; DH_get0_key(b, &bpub_key, NULL); alen = DH_size(a); if (!TEST_ptr(abuf = OPENSSL_malloc(alen)) || !TEST_true((aout = DH_compute_key(abuf, bpub_key, a)) != -1)) goto err; blen = DH_size(b); if (!TEST_ptr(bbuf = OPENSSL_malloc(blen)) || !TEST_true((bout = DH_compute_key(bbuf, apub_key, b)) != -1)) goto err; if (!TEST_true(aout >= 4) || !TEST_mem_eq(abuf, aout, bbuf, bout)) goto err; ret = 1; err: OPENSSL_free(abuf); OPENSSL_free(bbuf); DH_free(b); DH_free(a); BN_free(bp); BN_free(bg); BN_GENCB_free(_cb); return ret; }
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; if (dhparam.q) { 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 isc_result_t openssldh_generate(dst_key_t *key, int generator, void (*callback)(int)) { DH *dh = NULL; #if OPENSSL_VERSION_NUMBER > 0x00908000L BN_GENCB cb; union { void *dptr; void (*fptr)(int); } u; #else UNUSED(callback); #endif if (generator == 0) { if (key->key_size == 768 || key->key_size == 1024 || key->key_size == 1536) { dh = DH_new(); if (dh == NULL) return (dst__openssl_toresult(ISC_R_NOMEMORY)); if (key->key_size == 768) dh->p = &bn768; else if (key->key_size == 1024) dh->p = &bn1024; else dh->p = &bn1536; dh->g = &bn2; } else generator = 2; } if (generator != 0) { #if OPENSSL_VERSION_NUMBER > 0x00908000L dh = DH_new(); if (dh == NULL) return (dst__openssl_toresult(ISC_R_NOMEMORY)); if (callback == NULL) { BN_GENCB_set_old(&cb, NULL, NULL); } else { u.fptr = callback; BN_GENCB_set(&cb, &progress_cb, u.dptr); } if (!DH_generate_parameters_ex(dh, key->key_size, generator, &cb)) { DH_free(dh); return (dst__openssl_toresult2( "DH_generate_parameters_ex", DST_R_OPENSSLFAILURE)); } #else dh = DH_generate_parameters(key->key_size, generator, NULL, NULL); #endif } if (dh == NULL) return (dst__openssl_toresult2("DH_generate_parameters", DST_R_OPENSSLFAILURE)); if (DH_generate_key(dh) == 0) { DH_free(dh); return (dst__openssl_toresult2("DH_generate_key", DST_R_OPENSSLFAILURE)); } dh->flags &= ~DH_FLAG_CACHE_MONT_P; key->keydata.dh = dh; return (ISC_R_SUCCESS); }
LQ_EXTERN_C void* LQ_CALL LqConnSslCreate ( const void* MethodSSL, /* Example SSLv23_method()*/ const char* CertFile, /* Example: "server.pem"*/ const char* KeyFile, /*Example: "server.key"*/ const char* CipherList, int TypeCertFile, /*SSL_FILETYPE_ASN1 (The file is in abstract syntax notation 1 (ASN.1) format.) or SSL_FILETYPE_PEM (The file is in base64 privacy enhanced mail (PEM) format.)*/ const char* CAFile, const char* DhpFile ) { #ifdef HAVE_OPENSSL static const unsigned char dh1024_p[] = { 0xB1,0x0B,0x8F,0x96,0xA0,0x80,0xE0,0x1D,0xDE,0x92,0xDE,0x5E, 0xAE,0x5D,0x54,0xEC,0x52,0xC9,0x9F,0xBC,0xFB,0x06,0xA3,0xC6, 0x9A,0x6A,0x9D,0xCA,0x52,0xD2,0x3B,0x61,0x60,0x73,0xE2,0x86, 0x75,0xA2,0x3D,0x18,0x98,0x38,0xEF,0x1E,0x2E,0xE6,0x52,0xC0, 0x13,0xEC,0xB4,0xAE,0xA9,0x06,0x11,0x23,0x24,0x97,0x5C,0x3C, 0xD4,0x9B,0x83,0xBF,0xAC,0xCB,0xDD,0x7D,0x90,0xC4,0xBD,0x70, 0x98,0x48,0x8E,0x9C,0x21,0x9A,0x73,0x72,0x4E,0xFF,0xD6,0xFA, 0xE5,0x64,0x47,0x38,0xFA,0xA3,0x1A,0x4F,0xF5,0x5B,0xCC,0xC0, 0xA1,0x51,0xAF,0x5F,0x0D,0xC8,0xB4,0xBD,0x45,0xBF,0x37,0xDF, 0x36,0x5C,0x1A,0x65,0xE6,0x8C,0xFD,0xA7,0x6D,0x4D,0xA7,0x08, 0xDF,0x1F,0xB2,0xBC,0x2E,0x4A,0x43,0x71, }; static const unsigned char dh1024_g[] = { 0xA4,0xD1,0xCB,0xD5,0xC3,0xFD,0x34,0x12,0x67,0x65,0xA4,0x42, 0xEF,0xB9,0x99,0x05,0xF8,0x10,0x4D,0xD2,0x58,0xAC,0x50,0x7F, 0xD6,0x40,0x6C,0xFF,0x14,0x26,0x6D,0x31,0x26,0x6F,0xEA,0x1E, 0x5C,0x41,0x56,0x4B,0x77,0x7E,0x69,0x0F,0x55,0x04,0xF2,0x13, 0x16,0x02,0x17,0xB4,0xB0,0x1B,0x88,0x6A,0x5E,0x91,0x54,0x7F, 0x9E,0x27,0x49,0xF4,0xD7,0xFB,0xD7,0xD3,0xB9,0xA9,0x2E,0xE1, 0x90,0x9D,0x0D,0x22,0x63,0xF8,0x0A,0x76,0xA6,0xA2,0x4C,0x08, 0x7A,0x09,0x1F,0x53,0x1D,0xBF,0x0A,0x01,0x69,0xB6,0xA2,0x8A, 0xD6,0x62,0xA4,0xD1,0x8E,0x73,0xAF,0xA3,0x2D,0x77,0x9D,0x59, 0x18,0xD0,0x8B,0xC8,0x85,0x8F,0x4D,0xCE,0xF9,0x7C,0x2A,0x24, 0x85,0x5E,0x6E,0xEB,0x22,0xB3,0xB2,0xE5, }; SSL_CTX* NewCtx = NULL; bool r = false; static bool IsLoaded = false; if(MethodSSL == NULL) MethodSSL = SSLv23_server_method(); do { if(!IsLoaded) { IsLoaded = true; SSL_library_init(); OpenSSL_add_all_algorithms(); SSL_load_error_strings(); } if((NewCtx = SSL_CTX_new((const SSL_METHOD*)MethodSSL)) == NULL) break; SSL_CTX_set_read_ahead(NewCtx, 1); SSL_CTX_set_verify(NewCtx, SSL_VERIFY_NONE, NULL); if(CipherList != NULL) { if(SSL_CTX_set_cipher_list(NewCtx, CipherList) == 1) SSL_CTX_set_options(NewCtx, SSL_OP_CIPHER_SERVER_PREFERENCE); } if(CAFile != NULL) { if(!SSL_CTX_load_verify_locations(NewCtx, CAFile, NULL)) { SSL_CTX_free(NewCtx); NewCtx = NULL; break; } } if((SSL_CTX_use_certificate_file(NewCtx, CertFile, TypeCertFile) <= 0) || (SSL_CTX_use_PrivateKey_file(NewCtx, KeyFile, TypeCertFile) <= 0)) { SSL_CTX_free(NewCtx); NewCtx = NULL; break; } if(SSL_CTX_check_private_key(NewCtx) != 1) { SSL_CTX_free(NewCtx); NewCtx = NULL; break; } if(DhpFile != NULL) { BIO *bio = BIO_new_file(DhpFile, "r"); if(bio) { DH *dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL); BIO_free(bio); if(dh) { SSL_CTX_set_tmp_dh(NewCtx, dh); SSL_CTX_set_options(NewCtx, SSL_OP_SINGLE_DH_USE); DH_free(dh); } } } else { DH *dh = DH_new(); if(dh) { dh->p = BN_bin2bn(dh1024_p, sizeof(dh1024_p), NULL); dh->g = BN_bin2bn(dh1024_g, sizeof(dh1024_g), NULL); dh->length = 160; if(dh->p && dh->g) { SSL_CTX_set_tmp_dh(NewCtx, dh); SSL_CTX_set_options(NewCtx, SSL_OP_SINGLE_DH_USE); } DH_free(dh); } } } while(false); return NewCtx; #else lq_errno_set(ENOSYS); return NULL; #endif }
static int pkey_dh_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) { DH *dh = NULL; DH_PKEY_CTX *dctx = ctx->data; BN_GENCB *pcb, cb; int ret; if (dctx->rfc5114_param) { switch (dctx->rfc5114_param) { case 1: dh = DH_get_1024_160(); break; case 2: dh = DH_get_2048_224(); break; case 3: dh = DH_get_2048_256(); break; default: return -2; } EVP_PKEY_assign(pkey, EVP_PKEY_DHX, dh); return 1; } if (ctx->pkey_gencb) { pcb = &cb; evp_pkey_set_cb_translate(pcb, ctx); } else pcb = NULL; #ifndef OPENSSL_NO_DSA if (dctx->use_dsa) { DSA *dsa_dh; dsa_dh = dsa_dh_generate(dctx, pcb); if (!dsa_dh) return 0; dh = DSA_dup_DH(dsa_dh); DSA_free(dsa_dh); if (!dh) return 0; EVP_PKEY_assign(pkey, EVP_PKEY_DHX, dh); return 1; } #endif dh = DH_new(); if (!dh) return 0; ret = DH_generate_parameters_ex(dh, dctx->prime_len, dctx->generator, pcb); if (ret) EVP_PKEY_assign_DH(pkey, dh); else DH_free(dh); return ret; }
/** Add a DSA key to the tspc key file * * @param dsa the DSA param pointer filled with our key info * @param host the hostname of the corresponding broker * @param filename the keyfile to use * * @return 0 if error * 1 if ok * */ int add_dsakey_to_keyfile(DSA *dsa, char *host, char *filename, tBoolean autoaccept) { FILE *fp = NULL; Buffer buf; char *str = NULL; int ret = 0; switch (is_dsakey_in_keyfile(dsa, host, filename)) { case 0: Display(LOG_LEVEL_3, ELInfo, TSP_AUTH_PASSDSS_STRING, GOGO_STR_ERR_IN_KEY_VERIF); Display(LOG_LEVEL_3, ELWarning, TSP_AUTH_PASSDSS_STRING, GOGO_STR_SERVER_KEY_REJECTED); break; case 1: /* not in, we add and continue */ #if defined(WIN32) && !defined(WINCE) // When running as a service we can't ask user // permission. Compromise and accept the key auto // if (!IsService && !autoaccept) { #else if (!autoaccept) { #endif if (!ask(GOGO_STR_UNKNOWN_HOST_ADD_KEY, host)) { Display(LOG_LEVEL_3, ELWarning, TSP_AUTH_PASSDSS_STRING, GOGO_STR_SERVER_KEY_REJECTED_USER); break; } } else Display(LOG_LEVEL_1, ELWarning, TSP_AUTH_PASSDSS_STRING, GOGO_STR_WARN_SERVER_KEY_AUTO_ADDED); Display(LOG_LEVEL_2, ELInfo, TSP_AUTH_PASSDSS_STRING, GOGO_STR_SERVER_KEY_ACCEPTED_ADDED); buffer_init(&buf); if (buf.buf == NULL) break; buffer_put_cstring(&buf, "ssh-dss"); buffer_put_bignum(&buf, dsa->p); buffer_put_bignum(&buf, dsa->q); buffer_put_bignum(&buf, dsa->g); buffer_put_bignum(&buf, dsa->pub_key); if ( (str = pal_malloc(2 * buffer_len(&buf))) == NULL) break; if ( (base64encode(str, buffer_ptr(&buf), (int) buffer_len(&buf))) < 1) break; fp = fopen(filename, "a"); if (fp) { fprintf(fp, "%s ssh-dss %s\n", host, str); fclose(fp); ret = 1; } buffer_free(&buf); pal_free(str); break; case 2: /* in and matching correctly, hurray */ Display(LOG_LEVEL_2, ELInfo, TSP_AUTH_PASSDSS_STRING, GOGO_STR_MATCHING_KEY_FOUND_USED); ret = 1; break; case 3: /* in and NOT matching correctly */ Display(LOG_LEVEL_1, ELError, TSP_AUTH_PASSDSS_STRING, GOGO_STR_WARN_STORED_LOCAL_KEY_NO_MATCH, filename, host); Display(LOG_LEVEL_3, ELWarning, TSP_AUTH_PASSDSS_STRING, GOGO_STR_SERVER_KEY_REJECTED); ret = 0; break; } return ret; } /** * Authenticate to the Migration Broker using PASSDSS-3DES-1 * * Buf_H will contain the data used to validate the server * signature. The data is a concatenation of the following parameters, * in that order: * azname,authname,DH_public_key,pklength,"ssh-dss",p,q,g,z,Y,ssecmask,sbuflen,dh_K * * @param socket * @param user * @param passwd * @param host * @param nt * * @return * * @todo DH public key validation (RFC2631, 2.1.5) * @todo Local storage for server public keys * */ gogoc_status AuthPASSDSS_3DES_1(pal_socket_t socket, net_tools_t *nt, tConf *conf, tBrokerList **broker_list) { DH *dh = NULL; /**< client DH key used to exchange key with server */ DSA *dsa = NULL; /**< Remote server DSA key public information */ DSA_SIG *sig = NULL; /**< DSA signature */ char authenticate[] = "AUTHENTICATE PASSDSS-3DES-1\r\n"; char *BufferIn = NULL; char *BufferOut = NULL; char *BufferPtr = NULL; Buffer BufH; /**< Buffer to hold data used for signature. */ Buffer BufSpace; /**< Space to hold data before/after base64 conversion */ Buffer *Buf_H = &BufH; Buffer *Buf_Space = &BufSpace; BIO *bio_rw = NULL; /**< Memory buffer bio */ BIO *b64= NULL; /**< Base64 bio */ BIO *cipher = NULL; /**< Symmetric crypto bio */ BIGNUM *server_pubkey = NULL; /**< received server public DH key */ BIGNUM *dh_K = NULL; /**< DH computed shared secret */ u_char hash[20]; /**< SHA1 hash */ u_char enc_key[24]; /**< encryption key (3des) */ u_char enc_iv[8]; /**< initialization vector (3des) */ u_char int_key[20]; /**< cs integrity key */ u_char tmphash[40]; /**< temporary hash storage */ u_char hmac[EVP_MAX_MD_SIZE]; /**< HMAC for integrity of sent data (step L) */ int pklength = 0; /**< length of SSH-style DSA server public key */ int ssecmask = 0; /**< SASL security layers offered */ int sbuflen = 0; /**< maximum server security layer block size */ char *s = NULL; u_char num[3]; /**< Array to manupulate 3 octet number (sbuflen) */ /* Temporary variables */ int buflen, readlen, keysize, siglength; gogoc_status status = STATUS_SUCCESS_INIT; sint32_t tsp_status; /* From draft-newman-sasl-passdss-01. "This group was taken from the * ISAKMP/Oakley specification, and was originally generated by * Richard Schroeppel at the University of Arizona. Properties of * this prime are described in [Orm96]" */ /* RFC2409, DH group 2 (second Oakley group) */ static char *dh_group2= "FFFFFFFF" "FFFFFFFF" "C90FDAA2" "2168C234" "C4C6628B" "80DC1CD1" "29024E08" "8A67CC74" "020BBEA6" "3B139B22" "514A0879" "8E3404DD" "EF9519B3" "CD3A431B" "302B0A6D" "F25F1437" "4FE1356D" "6D51C245" "E485B576" "625E7EC6" "F44C42E9" "A637ED6B" "0BFF5CB6" "F406B7ED" "EE386BFB" "5A899FA5" "AE9F2411" "7C4B1FE6" "49286651" "ECE65381" "FFFFFFFF" "FFFFFFFF"; static unsigned char dh_g[]={ 0x02, }; /* Initialize Diffie Hellman variables */ if ((dh = DH_new()) == NULL || (server_pubkey = BN_new()) == NULL) { Display(LOG_LEVEL_1, ELError, TSP_AUTH_PASSDSS_STRING, STR_GEN_MALLOC_ERROR); status = make_status(CTX_TSPAUTHENTICATION, ERR_MEMORY_STARVATION); goto error; } /* Convert dh_group2 and dh_g to BIGNUM type */ BN_hex2bn(&dh->p, dh_group2); dh->g = BN_bin2bn(dh_g,sizeof(dh_g),NULL); if ((dh->p == NULL) || (dh->g == NULL)) { Display(LOG_LEVEL_1, ELError, TSP_AUTH_PASSDSS_STRING, GOGO_STR_INITIALIZATION_ERROR); status = make_status(CTX_TSPAUTHENTICATION, ERR_AUTHENTICATION_FAILURE); goto error; } if ((dh_K = BN_new()) == NULL) { Display(LOG_LEVEL_1, ELError, TSP_AUTH_PASSDSS_STRING, STR_GEN_MALLOC_ERROR); status = make_status(CTX_TSPAUTHENTICATION, ERR_MEMORY_STARVATION); goto error; } /* Reserve storage for DSA key */ if ((dsa = DSA_new()) == NULL || (dsa->p = BN_new()) == NULL || (dsa->q = BN_new()) == NULL || (dsa->g = BN_new()) == NULL || (dsa->pub_key = BN_new()) == NULL || (dsa->priv_key = BN_new()) == NULL) { Display(LOG_LEVEL_1, ELError, TSP_AUTH_PASSDSS_STRING, STR_GEN_MALLOC_ERROR); status = make_status(CTX_TSPAUTHENTICATION, ERR_MEMORY_STARVATION); goto error; } /* Allocate memory for DSA signature */ if ((sig = DSA_SIG_new()) == NULL) { Display(LOG_LEVEL_1, ELError, TSP_AUTH_PASSDSS_STRING, STR_GEN_MALLOC_ERROR); status = make_status(CTX_TSPAUTHENTICATION, ERR_MEMORY_STARVATION); goto error; } /* Initialize data buffers */ BufferIn = calloc(1, TSP_AUTH_PASSDSS_BUFFERSIZE); BufferOut = calloc(1, TSP_AUTH_PASSDSS_BUFFERSIZE); if ((BufferIn == NULL) || (BufferOut == NULL)) { Display(LOG_LEVEL_1, ELError, TSP_AUTH_PASSDSS_STRING, STR_GEN_MALLOC_ERROR); status = make_status(CTX_TSPAUTHENTICATION, ERR_MEMORY_STARVATION); goto error; } buffer_init(Buf_Space); buffer_init(Buf_H); if (Buf_Space->buf == NULL || Buf_H->buf == NULL) { Display(LOG_LEVEL_1, ELError, TSP_AUTH_PASSDSS_STRING, STR_GEN_MALLOC_ERROR); status = make_status(CTX_TSPAUTHENTICATION, ERR_MEMORY_STARVATION); goto error; } /* Create a read/write memory BIO. Memory is segment is * created and resized as needed. When BIO is destroyed, the * memory is freed. */ bio_rw = BIO_new(BIO_s_mem()); /* Create a base64 BIO filter */ b64 = BIO_new(BIO_f_base64()); if ((bio_rw == NULL) || (b64 == NULL)) { Display(LOG_LEVEL_1, ELError, TSP_AUTH_PASSDSS_STRING, STR_GEN_MALLOC_ERROR); status = make_status(CTX_TSPAUTHENTICATION, ERR_MEMORY_STARVATION); goto error; } /* Compute the Diffie-Hellman public value "X" as follows. If X has a value of 0, repeat. x X = g mod n where g = dh_g = 2 n = dh_group2 x = DH secret key X = DH public key */ if (DH_generate_key(dh) == 0) { Display(LOG_LEVEL_1, ELError, TSP_AUTH_PASSDSS_STRING, GOGO_STR_DH_GEN_ERROR); status = make_status(CTX_TSPAUTHENTICATION, ERR_AUTHENTICATION_FAILURE); goto error; } /* Validate DH public key (RFC2631, 2.1.5) */ /* Send message with SASL mechanism identifier */ if ( nt->netsend(socket, authenticate, sizeof(authenticate)) == -1 ) { Display(LOG_LEVEL_1, ELError, TSP_AUTH_PASSDSS_STRING, STR_NET_FAIL_W_SOCKET); status = make_status(CTX_TSPAUTHENTICATION, ERR_SOCKET_IO); goto error; } /* First PASSDSS message from client to server: string azname ; the user name to login as, may be empty if same as authentication name string authname ; the authentication name mpint X ; Diffie-Hellman parameter X */ /* azname is empty. Just insert a string length zero */ buffer_put_int(Buf_Space, 0); /* authname */ buffer_put_cstring(Buf_Space, conf->userid); /* DH public key */ buffer_put_bignum(Buf_Space, dh->pub_key); /* At this point, save the buffer into Buf_H. Used later for * signature verification. */ buffer_append(Buf_H, buffer_ptr(Buf_Space), buffer_len(Buf_Space)); /* Push base64 filter */ BIO_push(b64, bio_rw); /* no newline */ BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL); /* Write Buffer content into bio_rw. Buffer will be base64 * encoded. */ BIO_write(b64, buffer_ptr(Buf_Space), (int) buffer_len(Buf_Space)); BIO_flush(b64); /* Get pointer to the result */ buflen = BIO_get_mem_data(bio_rw, &BufferPtr); // Send data to server, save response in BufferIn. if((readlen = nt->netsendrecv(socket, BufferPtr, buflen, BufferIn, TSP_AUTH_PASSDSS_BUFFERSIZE)) == -1) { Display(LOG_LEVEL_1, ELError, TSP_AUTH_PASSDSS_STRING, STR_NET_FAIL_RW_SOCKET); status = make_status(CTX_TSPAUTHENTICATION, ERR_SOCKET_IO); goto error; } /* remove base64 filter */ BIO_pop(bio_rw); buffer_clear(Buf_Space); buflen = 0; /* Decode response (base64) and extract server response * * The response format is as follows: uint32 pklength ; length of SSH-style DSA server public key (number of bytes up to y, inclusively) string "ssh-dss" ; constant string "ssh-dss" (lower case) mpint p ; DSA public key parameters mpint q mpint g mpint z (y in draft) mpint Y ; Diffie-Hellman parameter Y OCTET ssecmask ; SASL security layers offered 3 OCTET sbuflen ; maximum server security layer block size uint32 siglength ; length of SSH-style dss signature (number of bytes up to s inclusively) string "ssh-dss" ; constant string "ssh-dss" (lower case) mpint r ; DSA signature parameters mpint s */ buflen = base64decode(BufferOut, BufferIn); buffer_append(Buf_Space, BufferOut, buflen); /* Get pklength */ pklength = buffer_get_int(Buf_Space); /* Assuming that * p, g, and y are 512 bits, * q is 160 bits, * "ssh-dss" is 7 bytes * pklength should be at least 240 bytes. */ if (pklength < 240) { Display(LOG_LEVEL_1, ELError, TSP_AUTH_PASSDSS_STRING, GOGO_STR_RCVD_DATA_INVALID); status = make_status(CTX_TSPAUTHENTICATION, ERR_AUTHENTICATION_FAILURE); goto error; } /* Make a copy of (pklength|"ssh-dss"|p|q|g|z) in Buf_H */ /* Add pklength */ buffer_put_int(Buf_H, pklength); /* Add "ssh-dss"|p|q|g|z */ buffer_append(Buf_H, buffer_ptr(Buf_Space), pklength); /* Get "ssh-dss" string */ s = buffer_get_string(Buf_Space, (unsigned int*)&buflen); pal_free(s); s = NULL; /* Get p */ buffer_get_bignum(Buf_Space, dsa->p); /* Get q */ buffer_get_bignum(Buf_Space, dsa->q); /* Get g */ buffer_get_bignum(Buf_Space, dsa->g); /* Get z (pub_key) */ buffer_get_bignum(Buf_Space, dsa->pub_key); /* Get DH public key */ buffer_get_bignum(Buf_Space, server_pubkey); /* Copy in Buf_H for signature verification later */ buffer_put_bignum(Buf_H, server_pubkey); /* Buffer now points at ssecmask (1 octet), followed by * sbuflen (3 octets). Make a copy of these 4 octets in Buf_H * now, then extract these values. */ buffer_append(Buf_H, buffer_ptr(Buf_Space), 4); /* Get ssecmask */ ssecmask = buffer_get_octet(Buf_Space); /* Get sbuflen * Big endian binary unsigned integer */ buffer_get(Buf_Space, (char *)num, 3); sbuflen = (((u_long)(u_char)(num)[0] << 16) | ((u_long)(u_char)(num)[1] << 8) | ((u_long)(u_char)(num)[2])); /* DSS signature */ /* Get siglength */ siglength = buffer_get_int(Buf_Space); /* r and s are 20 bytes each, encoded as mpint (2*24) * "ssh-dss" is 7 bytes + int32 siglength should be >= 59 * octets (mpint may have leading zero byte) */ if (siglength < 59) { Display(LOG_LEVEL_1, ELError, TSP_AUTH_PASSDSS_STRING, GOGO_STR_RCVD_DATA_INVALID); status = make_status(CTX_TSPAUTHENTICATION, ERR_AUTHENTICATION_FAILURE); goto error; } /* Get "ssh-dss" string */ s = buffer_get_string(Buf_Space, (unsigned int*)&buflen); pal_free(s); s = NULL; /* Get DSA signature r and s*/ if ((sig->r= BN_new()) == NULL || (sig->s = BN_new()) == NULL) { Display(LOG_LEVEL_1, ELError, TSP_AUTH_PASSDSS_STRING, STR_GEN_MALLOC_ERROR); status = make_status(CTX_TSPAUTHENTICATION, ERR_MEMORY_STARVATION); goto error; } /* Get r */ buffer_get_bignum(Buf_Space, sig->r); /* Get s */ buffer_get_bignum(Buf_Space, sig->s); /* Validate server DH public key (RFC2631, 2.1.5) */ { if( !add_dsakey_to_keyfile(dsa, conf->server, TSPC_DSA_KEYFILE, conf->no_questions) ) { Display(LOG_LEVEL_1, ELError, TSP_AUTH_PASSDSS_STRING, GOGO_STR_KEY_VERIF_ERROR); status = make_status(CTX_TSPAUTHENTICATION, ERR_AUTHENTICATION_FAILURE); goto error; } } /* Verify that DSA public key belongs to server */ /* Compute DH shared secret */ if ((s = calloc(1, DH_size(dh))) == NULL) { Display(LOG_LEVEL_1, ELError, TSP_AUTH_PASSDSS_STRING, STR_GEN_MALLOC_ERROR); status = make_status(CTX_TSPAUTHENTICATION, ERR_MEMORY_STARVATION); goto error; } if( (keysize = DH_compute_key((unsigned char*)s, server_pubkey, dh)) < 0 ) { Display(LOG_LEVEL_1, ELError, TSP_AUTH_PASSDSS_STRING, GOGO_STR_DH_SHARED_COMPUTE_ERROR); status = make_status(CTX_TSPAUTHENTICATION, ERR_AUTHENTICATION_FAILURE); goto error; } BN_bin2bn((const unsigned char*)s, keysize, dh_K); memset(s, 0, keysize); pal_free(s); s = NULL; Display(LOG_LEVEL_3, ELDebug, TSP_AUTH_PASSDSS_STRING, GOGO_STR_DH_SHARED_KEY, BN_bn2hex(dh_K)); /* Append dh_K in to complete the buffer. Use Buffer to hold * result to keep Bf_H intact, since to will be used (without * dh_K) to compute HMAC for packet integrity. */ buffer_clear(Buf_Space); buffer_append(Buf_Space, buffer_ptr(Buf_H), buffer_len(Buf_H)); buffer_put_bignum(Buf_Space, dh_K); /* Compute SHA1 hash of Buffer */ SHA1(buffer_ptr(Buf_Space), buffer_len(Buf_Space), hash); /* Debug information available at level 4 */ { BIGNUM *h; h = BN_bin2bn(hash, 20, NULL); Display(LOG_LEVEL_3, ELDebug, TSP_AUTH_PASSDSS_STRING, GOGO_STR_SIGNED_HASH, BN_bn2hex(h)); BN_free(h); } Display(LOG_LEVEL_3, ELDebug, TSP_AUTH_PASSDSS_STRING, GOGO_STR_DSA_SIGN_R, BN_bn2hex(sig->r)); Display(LOG_LEVEL_3, ELDebug, TSP_AUTH_PASSDSS_STRING, GOGO_STR_DSA_SIGN_S, BN_bn2hex(sig->s)); // Verify that the DSS signature is a signature of hash. switch( DSA_do_verify(hash, sizeof(hash), sig, dsa) ) { case 0: Display(LOG_LEVEL_1, ELError, TSP_AUTH_PASSDSS_STRING, GOGO_STR_BAD_SIG_FROM_SERVER); status = make_status(CTX_TSPAUTHENTICATION, ERR_AUTHENTICATION_FAILURE); goto error; break; /* NOTREACHED */ case 1: /* correct signature */ break; default: /* -1 on error */ Display(LOG_LEVEL_1, ELError, TSP_AUTH_PASSDSS_STRING, GOGO_STR_SIG_VERIF_ERROR); status = make_status(CTX_TSPAUTHENTICATION, ERR_AUTHENTICATION_FAILURE); goto error; break; /* NOTREACHED */ } /* Step I: Compute 3DES key and iv */ /* cs-encryption-iv = SHA1( K || "A" || H ) sc-encryption-iv = SHA1( K || "B" || H ) cs-encryption-key-1 = SHA1( K || "C" || H ) cs-encryption-key-2 = SHA1( K || cs-encryption-key-1 ) cs-encryption-key = cs-encryption-key-1 || cs-encryption-key-2 sc-encryption-key-1 = SHA1( K || "D" || H ) sc-encryption-key-2 = SHA1( K || sc-encryption-key-1 ) sc-encryption-key = sc-encryption-key-1 || sc-encryption-key-2 cs-integrity-key = SHA1( K || "E" || H ) sc-integrity-key = SHA1( K || "F" || H ) K is dh_k in mpint format (string) H is hash */ /* Since we won't support SASL security layers, we need to * compute the following only: * cs-encryption-iv * cs-encryption-key * cs-integrity-key */ buffer_clear(Buf_Space); buffer_put_bignum(Buf_Space, dh_K); buffer_put_octet(Buf_Space,'A'); buffer_append(Buf_Space, hash, 20); SHA1(buffer_ptr(Buf_Space), buffer_len(Buf_Space), tmphash); /* Use first 8 octets as iv */ memcpy(enc_iv, tmphash, 8); buffer_clear(Buf_Space); buffer_put_bignum(Buf_Space, dh_K); buffer_put_octet(Buf_Space,'E'); buffer_append(Buf_Space, hash, 20); SHA1(buffer_ptr(Buf_Space), buffer_len(Buf_Space), int_key); buffer_clear(Buf_Space); buffer_put_bignum(Buf_Space, dh_K); buffer_put_octet(Buf_Space,'C'); buffer_append(Buf_Space, hash, 20); SHA1(buffer_ptr(Buf_Space), buffer_len(Buf_Space), tmphash); buffer_clear(Buf_Space); buffer_put_bignum(Buf_Space, dh_K); buffer_append(Buf_Space, tmphash, 20); SHA1(buffer_ptr(Buf_Space), buffer_len(Buf_Space), tmphash+20); /* Use first 24 octets as key */ memcpy(enc_key, tmphash, 24); { BIGNUM *enc, *i, *iv; enc = BN_bin2bn(enc_key, 24, NULL); iv = BN_bin2bn(enc_iv, 8, NULL); i = BN_bin2bn(int_key, 20, NULL); Display(LOG_LEVEL_3, ELDebug, TSP_AUTH_PASSDSS_STRING, GOGO_STR_PASSDS_ENC_KEY, BN_bn2hex(enc)); Display(LOG_LEVEL_3, ELDebug, TSP_AUTH_PASSDSS_STRING, GOGO_STR_PASSDS_IV, BN_bn2hex(iv)); Display(LOG_LEVEL_3, ELDebug, TSP_AUTH_PASSDSS_STRING, GOGO_STR_PASSDS_INTEG_KEY, BN_bn2hex(i)); BN_free(enc); BN_free(i); BN_free(iv); } /* (J) Create a buffer beginning with a bit mask for the selected security layer (it MUST be one offered from server) followed by three octets representing the maximum cipher-text buffer size (at least 32) the client can accept in network byte order. This is followed by a string containing the passphrase. */ buffer_clear(Buf_Space); buffer_put_octet(Buf_Space, ssecmask); buffer_put_octet(Buf_Space, 0); buffer_put_octet(Buf_Space, 0); buffer_put_octet(Buf_Space, 0); /**< @bug must be at least 32 */ buffer_put_cstring(Buf_Space, conf->passwd); /* (K) Create a buffer containing items (1) through (7) immediately followed by the first four octets of (J). */ buffer_append(Buf_H, buffer_ptr(Buf_Space), 4); /* (L) Compute HMAC-SHA-1 with (K) as the data and the cs-integrity- key from step (I) as the key. This produces a 20 octet result. */ HMAC(EVP_sha1(), int_key, sizeof(int_key), buffer_ptr(Buf_H), buffer_len(Buf_H), hmac, (unsigned int*)&keysize); /* (M) Create a buffer containing (J) followed by (L) followed by an arbitrary number of zero octets as necessary to reach the block size of DES and conceal the passphrase length from an eavesdropper. */ buffer_append(Buf_Space, hmac, keysize); /* (N) Apply the triple-DES algorithm to (M) with the first 8 octets of cs-encryption-iv from step (I) as the initialization vector and the first 24 octets of cs-encryption-key as the key. */ /* Padding is automatically done. From OpenSSL EVP_EncryptInit(3): EVP_CIPHER_CTX_set_padding() enables or disables padding. By default encryption operations are padded using standard block padding and the padding is checked and removed when decrypting. */ /* Create BIO filter to encrypt using 3des + convert to base64. Result is written in memory BIO. */ /* Erase BIO and buffer memory */ BIO_reset(bio_rw); memset(BufferOut, 0, TSP_AUTH_PASSDSS_BUFFERSIZE); memset(BufferIn, 0, TSP_AUTH_PASSDSS_BUFFERSIZE); buflen = 0; /* Create cipher BIO */ cipher = BIO_new(BIO_f_cipher()); BIO_set_cipher(cipher, EVP_des_ede3_cbc(), enc_key, enc_iv, 1); /* Assemble filters as cipher->b64->bio_rw */ BIO_push(cipher, b64); BIO_push(b64, bio_rw); /* Write Buffer content into bio_rw */ BIO_write(cipher, buffer_ptr(Buf_Space), (int) buffer_len(Buf_Space)); BIO_flush(cipher); /* Get pointer to the result. */ buflen = BIO_get_mem_data(bio_rw, &BufferPtr); /* wipe encryption material */ memset(enc_key, 0, sizeof(enc_key)); memset(enc_iv, 0, sizeof(enc_iv)); /* Send data to server, save response in BufferIn */ if( (readlen = nt->netsendrecv(socket, BufferPtr, buflen, BufferIn, TSP_AUTH_PASSDSS_BUFFERSIZE)) == -1) { Display(LOG_LEVEL_1, ELError, TSP_AUTH_PASSDSS_STRING, STR_NET_FAIL_RW_SOCKET); status = make_status(CTX_TSPAUTHENTICATION, ERR_SOCKET_IO); goto error; } tsp_status = tspGetStatusCode(BufferIn); // Check if the reply status indicated a broker redirection. if( tspIsRedirectStatus(tsp_status) ) { if( tspHandleRedirect(BufferIn, conf, broker_list) == TSP_REDIRECT_OK ) { status = make_status(CTX_TSPAUTHENTICATION, EVNT_BROKER_REDIRECTION); } else { // Redirect error. status = make_status(CTX_TSPAUTHENTICATION, ERR_BROKER_REDIRECTION); } goto error; } // Check if authentication was successful. switch( tsp_status ) { case TSP_PROTOCOL_SUCCESS: break; case TSP_PROTOCOL_AUTH_FAILED: Display(LOG_LEVEL_1, ELError, "AuthPASSDSS_3DES_1", STR_TSP_AUTH_FAILED_USER, conf->userid); status = make_status(CTX_TSPAUTHENTICATION, ERR_AUTHENTICATION_FAILURE); goto error; default: Display(LOG_LEVEL_1, ELError, "AuthPASSDSS_3DES_1", STR_TSP_UNKNOWN_ERR_AUTH_FAILED, tspGetTspStatusStr(tsp_status)); status = make_status(CTX_TSPAUTHENTICATION, ERR_TSP_GENERIC_ERROR); goto error; } status = STATUS_SUCCESS_INIT; error: /* Free storage for DSA key */ if (dsa != NULL) DSA_free(dsa); /* Also frees BIGNUMs inside struct */ /* DSA signature */ if (sig != NULL) DSA_SIG_free(sig); /* Free Diffie Hellman variables */ if (dh != NULL) DH_free(dh); /* Also frees BIGNUMs inside struct */ if (server_pubkey != NULL) BN_free(server_pubkey); if (dh_K != NULL) BN_free(dh_K); /* Buffers */ if (Buf_Space->buf != NULL) buffer_free(Buf_Space); if (Buf_H->buf != NULL) buffer_free(Buf_H); /* malloc'ed space*/ if (BufferIn != NULL) pal_free(BufferIn); if (BufferOut != NULL) pal_free(BufferOut); /* BIOs */ if (cipher != NULL) BIO_vfree(cipher); if (b64 != NULL) BIO_vfree(b64); if (bio_rw != NULL) BIO_vfree(bio_rw); /* strings buffers */ if (s != NULL) pal_free(s); return status; }
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); }
int main(int argc, char *argv[]) { BN_GENCB *_cb; DH *a = NULL; 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); out = BIO_new(BIO_s_file()); if (out == NULL) EXIT(1); BIO_set_fp(out, stdout, BIO_NOCLOSE); _cb = BN_GENCB_new(); if (!_cb) 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 = (unsigned char *)OPENSSL_malloc(alen); 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 = (unsigned char *)OPENSSL_malloc(blen); 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); if (abuf != NULL) OPENSSL_free(abuf); if (bbuf != NULL) OPENSSL_free(bbuf); DH_free(b); DH_free(a); if (_cb) BN_GENCB_free(_cb); BIO_free(out); # ifdef OPENSSL_SYS_NETWARE if (ret) printf("ERROR: %d\n", ret); # endif EXIT(ret); }
inline dh_key dh_key::create() { return take_ownership(DH_new()); }