int network_write_chunkqueue_openssl(server *srv, connection *con, SSL *ssl, chunkqueue *cq) { int ssl_r; chunk *c; size_t chunks_written = 0; /* this is a 64k sendbuffer * * it has to stay at the same location all the time to satisfy the needs * of SSL_write to pass the SAME parameter in case of a _WANT_WRITE * * the buffer is allocated once, is NOT realloced and is NOT freed at shutdown * -> we expect a 64k block to 'leak' in valgrind * * * In reality we would like to use mmap() but we don't have a guarantee that * we get the same mmap() address for each call. On openbsd the mmap() address * even randomized. * That means either we keep the mmap() open or we do a read() into a * constant buffer * */ #define LOCAL_SEND_BUFSIZE (64 * 1024) static char *local_send_buffer = NULL; /* the remote side closed the connection before without shutdown request * - IE * - wget * if keep-alive is disabled */ if (con->keep_alive == 0) { SSL_set_shutdown(ssl, SSL_RECEIVED_SHUTDOWN); } for(c = cq->first; c; c = c->next) { int chunk_finished = 0; switch(c->type) { case MEM_CHUNK: { char * offset; size_t toSend; ssize_t r; if (c->mem->used == 0 || c->mem->used == 1) { chunk_finished = 1; break; } offset = c->mem->ptr + c->offset; toSend = c->mem->used - 1 - c->offset; /** * SSL_write man-page * * WARNING * When an SSL_write() operation has to be repeated because of * SSL_ERROR_WANT_READ or SSL_ERROR_WANT_WRITE, it must be * repeated with the same arguments. * */ ERR_clear_error(); if ((r = SSL_write(ssl, offset, toSend)) <= 0) { unsigned long err; switch ((ssl_r = SSL_get_error(ssl, r))) { case SSL_ERROR_WANT_WRITE: break; case SSL_ERROR_SYSCALL: /* perhaps we have error waiting in our error-queue */ if (0 != (err = ERR_get_error())) { do { log_error_write(srv, __FILE__, __LINE__, "sdds", "SSL:", ssl_r, r, ERR_error_string(err, NULL)); } while((err = ERR_get_error())); } else if (r == -1) { /* no, but we have errno */ switch(errno) { case EPIPE: case ECONNRESET: return -2; default: log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL:", ssl_r, r, errno, strerror(errno)); break; } } else { /* neither error-queue nor errno ? */ log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL (error):", ssl_r, r, errno, strerror(errno)); } return -1; case SSL_ERROR_ZERO_RETURN: /* clean shutdown on the remote side */ if (r == 0) return -2; /* fall through */ default: while((err = ERR_get_error())) { log_error_write(srv, __FILE__, __LINE__, "sdds", "SSL:", ssl_r, r, ERR_error_string(err, NULL)); } return -1; } } else { c->offset += r; cq->bytes_out += r; } if (c->offset == (off_t)c->mem->used - 1) { chunk_finished = 1; } break; } case FILE_CHUNK: { char *s; ssize_t r; stat_cache_entry *sce = NULL; int ifd; int write_wait = 0; if (HANDLER_ERROR == stat_cache_get_entry(srv, con, c->file.name, &sce)) { log_error_write(srv, __FILE__, __LINE__, "sb", strerror(errno), c->file.name); return -1; } if (NULL == local_send_buffer) { local_send_buffer = malloc(LOCAL_SEND_BUFSIZE); assert(local_send_buffer); } do { off_t offset = c->file.start + c->offset; off_t toSend = c->file.length - c->offset; if (toSend > LOCAL_SEND_BUFSIZE) toSend = LOCAL_SEND_BUFSIZE; if (-1 == (ifd = open(c->file.name->ptr, O_RDONLY))) { log_error_write(srv, __FILE__, __LINE__, "ss", "open failed:", strerror(errno)); return -1; } lseek(ifd, offset, SEEK_SET); if (-1 == (toSend = read(ifd, local_send_buffer, toSend))) { close(ifd); log_error_write(srv, __FILE__, __LINE__, "ss", "read failed:", strerror(errno)); return -1; } s = local_send_buffer; close(ifd); ERR_clear_error(); if ((r = SSL_write(ssl, s, toSend)) <= 0) { unsigned long err; switch ((ssl_r = SSL_get_error(ssl, r))) { case SSL_ERROR_WANT_WRITE: write_wait = 1; break; case SSL_ERROR_SYSCALL: /* perhaps we have error waiting in our error-queue */ if (0 != (err = ERR_get_error())) { do { log_error_write(srv, __FILE__, __LINE__, "sdds", "SSL:", ssl_r, r, ERR_error_string(err, NULL)); } while((err = ERR_get_error())); } else if (r == -1) { /* no, but we have errno */ switch(errno) { case EPIPE: case ECONNRESET: return -2; default: log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL:", ssl_r, r, errno, strerror(errno)); break; } } else { /* neither error-queue nor errno ? */ log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL (error):", ssl_r, r, errno, strerror(errno)); } return -1; case SSL_ERROR_ZERO_RETURN: /* clean shutdown on the remote side */ if (r == 0) return -2; /* fall thourgh */ default: while((err = ERR_get_error())) { log_error_write(srv, __FILE__, __LINE__, "sdds", "SSL:", ssl_r, r, ERR_error_string(err, NULL)); } return -1; } } else { c->offset += r; cq->bytes_out += r; } if (c->offset == c->file.length) { chunk_finished = 1; } } while(!chunk_finished && !write_wait); break; } default: log_error_write(srv, __FILE__, __LINE__, "s", "type not known"); return -1; } if (!chunk_finished) { /* not finished yet */ break; } chunks_written++; } return chunks_written; }
bytes public_key::decrypt( const bytes& in )const { FC_ASSERT( my && my->rsa ); bytes out( RSA_size(my->rsa) );//, char(0) ); int rtn = RSA_public_decrypt( in.size(), (unsigned char*)in.data(), (unsigned char*)out.data(), my->rsa, RSA_PKCS1_OAEP_PADDING ); if( rtn >= 0 ) { out.resize(rtn); return out; } FC_THROW_EXCEPTION( exception, "openssl: ${message}", ("message",fc::string(ERR_error_string( ERR_get_error(),NULL))) ); }
void private_key::sign( const sha1& digest, array<char,2048/8>& sig )const { FC_ASSERT( (size_t(RSA_size(my->rsa)) <= sizeof(sig)), "Invalid RSA size" ); uint32_t slen = 0; if( 1 != RSA_sign( NID_sha1, (uint8_t*)&digest, 20, (unsigned char*)&sig, &slen, my->rsa ) ) { FC_THROW_EXCEPTION( exception, "rsa sign failed with ${message}", ("message",fc::string(ERR_error_string( ERR_get_error(),NULL))) ); } }
static int tap11_change_pin( const char *p11lib, int is_so, const char *pin, const char *newpin) { int rc = 0; unsigned int nslots; PKCS11_CTX *p11ctx; PKCS11_SLOT *slots, *slot; p11ctx = PKCS11_CTX_new(); /* load pkcs #11 module */ rc = PKCS11_CTX_load(p11ctx,p11lib); if (rc) { fprintf(stderr,"PKCS11_CTX_load\n"); return -1; } /* get information on all slots */ rc = PKCS11_enumerate_slots(p11ctx, &slots, &nslots); if (rc < 0) { fprintf(stderr,"PKCS11_enumerate_slots\n"); return -1; } /* get first slot with a token */ slot = PKCS11_find_token(p11ctx, slots, nslots); if (!slot || !slot->token) { fprintf(stderr,"PKCS11_find_token\n"); return -1; } fprintf(stderr,"Slot manufacturer......: %s\n", slot->manufacturer); fprintf(stderr,"Slot description.......: %s\n", slot->description); fprintf(stderr,"Slot token label.......: %s\n", slot->token->label); fprintf(stderr,"Slot token manufacturer: %s\n", slot->token->manufacturer); fprintf(stderr,"Slot token model.......: %s\n", slot->token->model); fprintf(stderr,"Slot token serialnr....: %s\n", slot->token->serialnr); /* rw mode */ rc = PKCS11_open_session(slot, 1); if (rc != 0) { ERR_load_PKCS11_strings(); fprintf(stderr,"PKCS11_open_session %s\n", ERR_reason_error_string(ERR_get_error())); return -1; } rc = PKCS11_login(slot, is_so, pin); if (rc != 0) { ERR_load_PKCS11_strings(); fprintf(stderr,"PKCS11_init_login %s\n", ERR_reason_error_string(ERR_get_error())); return -1; } rc = PKCS11_change_pin(slot,pin,newpin); if (rc != 0) { ERR_load_PKCS11_strings(); fprintf(stderr,"PKCS11_change_pin %s\n", ERR_reason_error_string(ERR_get_error())); return -1; } PKCS11_logout(slot); PKCS11_release_all_slots(p11ctx, slots, nslots); PKCS11_CTX_unload(p11ctx); PKCS11_CTX_free(p11ctx); fprintf(stderr,"\n\npin change succeed\n"); return 0; }
int proxy_tls_recv(rad_listen_t *listener) { int rcode; size_t length; listen_socket_t *sock = listener->data; char buffer[256]; RADIUS_PACKET *packet; uint8_t *data; /* * Get the maximum size of data to receive. */ if (!sock->data) sock->data = talloc_array(sock, uint8_t, sock->ssn->offset); data = sock->data; DEBUG3("Proxy SSL socket has data to read"); PTHREAD_MUTEX_LOCK(&sock->mutex); redo: rcode = SSL_read(sock->ssn->ssl, data, 4); if (rcode <= 0) { int err = SSL_get_error(sock->ssn->ssl, rcode); switch (err) { case SSL_ERROR_WANT_READ: case SSL_ERROR_WANT_WRITE: goto redo; case SSL_ERROR_ZERO_RETURN: /* remote end sent close_notify, send one back */ SSL_shutdown(sock->ssn->ssl); case SSL_ERROR_SYSCALL: do_close: PTHREAD_MUTEX_UNLOCK(&sock->mutex); tls_socket_close(listener); return 0; default: while ((err = ERR_get_error())) { DEBUG("proxy recv says %s", ERR_error_string(err, NULL)); } goto do_close; } } length = (data[2] << 8) | data[3]; DEBUG3("Proxy received header saying we have a packet of %u bytes", (unsigned int) length); if (length > sock->ssn->offset) { INFO("Received packet will be too large! Set \"fragment_size=%u\"", (data[2] << 8) | data[3]); goto do_close; } rcode = SSL_read(sock->ssn->ssl, data + 4, length); if (rcode <= 0) { switch (SSL_get_error(sock->ssn->ssl, rcode)) { case SSL_ERROR_WANT_READ: case SSL_ERROR_WANT_WRITE: break; case SSL_ERROR_ZERO_RETURN: /* remote end sent close_notify, send one back */ SSL_shutdown(sock->ssn->ssl); goto do_close; default: goto do_close; } } PTHREAD_MUTEX_UNLOCK(&sock->mutex); packet = rad_alloc(NULL, 0); packet->sockfd = listener->fd; packet->src_ipaddr = sock->other_ipaddr; packet->src_port = sock->other_port; packet->dst_ipaddr = sock->my_ipaddr; packet->dst_port = sock->my_port; packet->code = data[0]; packet->id = data[1]; packet->data_len = length; packet->data = talloc_array(packet, uint8_t, packet->data_len); memcpy(packet->data, data, packet->data_len); memcpy(packet->vector, packet->data + 4, 16); /* * FIXME: Client MIB updates? */ switch(packet->code) { case PW_AUTHENTICATION_ACK: case PW_ACCESS_CHALLENGE: case PW_AUTHENTICATION_REJECT: break; #ifdef WITH_ACCOUNTING case PW_ACCOUNTING_RESPONSE: break; #endif default: /* * FIXME: Update MIB for packet types? */ ERROR("Invalid packet code %d sent to a proxy port " "from home server %s port %d - ID %d : IGNORED", packet->code, ip_ntoh(&packet->src_ipaddr, buffer, sizeof(buffer)), packet->src_port, packet->id); rad_free(&packet); return 0; } if (!request_proxy_reply(packet)) { rad_free(&packet); return 0; } return 1; }
static int new_ssl_stream(const char *name, int fd, enum session_type type, enum ssl_state state, struct stream **streamp) { struct ssl_stream *sslv; SSL *ssl = NULL; int retval; /* Check for all the needful configuration. */ retval = 0; if (!private_key.read) { VLOG_ERR("Private key must be configured to use SSL"); retval = ENOPROTOOPT; } if (!certificate.read) { VLOG_ERR("Certificate must be configured to use SSL"); retval = ENOPROTOOPT; } if (!ca_cert.read && verify_peer_cert && !bootstrap_ca_cert) { VLOG_ERR("CA certificate must be configured to use SSL"); retval = ENOPROTOOPT; } if (!retval && !SSL_CTX_check_private_key(ctx)) { VLOG_ERR("Private key does not match certificate public key: %s", ERR_error_string(ERR_get_error(), NULL)); retval = ENOPROTOOPT; } if (retval) { goto error; } /* Disable Nagle. * On windows platforms, this can only be called upon TCP connected. */ if (state == STATE_SSL_CONNECTING) { setsockopt_tcp_nodelay(fd); } /* Create and configure OpenSSL stream. */ ssl = SSL_new(ctx); if (ssl == NULL) { VLOG_ERR("SSL_new: %s", ERR_error_string(ERR_get_error(), NULL)); retval = ENOPROTOOPT; goto error; } if (SSL_set_fd(ssl, fd) == 0) { VLOG_ERR("SSL_set_fd: %s", ERR_error_string(ERR_get_error(), NULL)); retval = ENOPROTOOPT; goto error; } if (!verify_peer_cert || (bootstrap_ca_cert && type == CLIENT)) { SSL_set_verify(ssl, SSL_VERIFY_NONE, NULL); } /* Create and return the ssl_stream. */ sslv = xmalloc(sizeof *sslv); stream_init(&sslv->stream, &ssl_stream_class, EAGAIN, name); sslv->state = state; sslv->type = type; sslv->fd = fd; sslv->ssl = ssl; sslv->txbuf = NULL; sslv->rx_want = sslv->tx_want = SSL_NOTHING; sslv->session_nr = next_session_nr++; sslv->n_head = 0; if (VLOG_IS_DBG_ENABLED()) { SSL_set_msg_callback(ssl, ssl_protocol_cb); SSL_set_msg_callback_arg(ssl, sslv); } *streamp = &sslv->stream; return 0; error: if (ssl) { SSL_free(ssl); } closesocket(fd); return retval; }
static int interpret_ssl_error(const char *function, int ret, int error, int *want) { *want = SSL_NOTHING; switch (error) { case SSL_ERROR_NONE: VLOG_ERR_RL(&rl, "%s: unexpected SSL_ERROR_NONE", function); break; case SSL_ERROR_ZERO_RETURN: VLOG_ERR_RL(&rl, "%s: unexpected SSL_ERROR_ZERO_RETURN", function); break; case SSL_ERROR_WANT_READ: *want = SSL_READING; return EAGAIN; case SSL_ERROR_WANT_WRITE: *want = SSL_WRITING; return EAGAIN; case SSL_ERROR_WANT_CONNECT: VLOG_ERR_RL(&rl, "%s: unexpected SSL_ERROR_WANT_CONNECT", function); break; case SSL_ERROR_WANT_ACCEPT: VLOG_ERR_RL(&rl, "%s: unexpected SSL_ERROR_WANT_ACCEPT", function); break; case SSL_ERROR_WANT_X509_LOOKUP: VLOG_ERR_RL(&rl, "%s: unexpected SSL_ERROR_WANT_X509_LOOKUP", function); break; case SSL_ERROR_SYSCALL: { int queued_error = ERR_get_error(); if (queued_error == 0) { if (ret < 0) { int status = errno; VLOG_WARN_RL(&rl, "%s: system error (%s)", function, ovs_strerror(status)); return status; } else { VLOG_WARN_RL(&rl, "%s: unexpected SSL connection close", function); return EPROTO; } } else { VLOG_WARN_RL(&rl, "%s: %s", function, ERR_error_string(queued_error, NULL)); break; } } case SSL_ERROR_SSL: interpret_queued_ssl_error(function); break; default: VLOG_ERR_RL(&rl, "%s: bad SSL error code %d", function, error); break; } return EIO; }
/** * @return returns X.509 certificate serial number. * @throws IOException exception is thrown if the serial is incorrect. */ long digidoc::X509Cert::getSerial() const throw(IOException) { long serial = ASN1_INTEGER_get(X509_get_serialNumber(cert)); if(serial <= 0) { THROW_IOEXCEPTION("Failed to read certificate serial number from X.509 certificate: %s", ERR_reason_error_string(ERR_get_error())); } return serial; }
/** * Converts X.509 issuer name to string. * * @return issuer name converted to string. * @throws IOException exception is throws if the conversion failed. */ std::string digidoc::X509Cert::getIssuerName() const throw(IOException) { X509_NAME* issuerName = X509_get_issuer_name(cert); if(issuerName == NULL) { THROW_IOEXCEPTION("Failed to convert X.509 certificate issuer name: %s", ERR_reason_error_string(ERR_get_error())); } return toString(issuerName); }
int rb_setup_ssl_server(const char *cert, const char *keyfile, const char *dhfile, const char *cipher_list) { DH *dh; unsigned long err; if(cert == NULL) { rb_lib_log("rb_setup_ssl_server: No certificate file"); return 0; } if(!SSL_CTX_use_certificate_chain_file(ssl_server_ctx, cert) || !SSL_CTX_use_certificate_chain_file(ssl_client_ctx, cert)) { err = ERR_get_error(); rb_lib_log("rb_setup_ssl_server: Error loading certificate file [%s]: %s", cert, get_ssl_error(err)); return 0; } if(keyfile == NULL) { rb_lib_log("rb_setup_ssl_server: No key file"); return 0; } if(!SSL_CTX_use_PrivateKey_file(ssl_server_ctx, keyfile, SSL_FILETYPE_PEM) || !SSL_CTX_use_PrivateKey_file(ssl_client_ctx, keyfile, SSL_FILETYPE_PEM)) { err = ERR_get_error(); rb_lib_log("rb_setup_ssl_server: Error loading keyfile [%s]: %s", keyfile, get_ssl_error(err)); return 0; } if(dhfile != NULL) { /* DH parameters aren't necessary, but they are nice..if they didn't pass one..that is their problem */ BIO *bio = BIO_new_file(dhfile, "r"); if(bio != NULL) { dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL); if(dh == NULL) { err = ERR_get_error(); rb_lib_log ("rb_setup_ssl_server: Error loading DH params file [%s]: %s", dhfile, get_ssl_error(err)); BIO_free(bio); return 0; } BIO_free(bio); SSL_CTX_set_tmp_dh(ssl_server_ctx, dh); } else { err = ERR_get_error(); rb_lib_log("rb_setup_ssl_server: Error loading DH params file [%s]: %s", dhfile, get_ssl_error(err)); } } if (cipher_list != NULL) { SSL_CTX_set_cipher_list(ssl_server_ctx, cipher_list); } return 1; }
/** * Creates a copy of the X509 certificate. * * @param cert X509 certificate to be copied. * @return returns copy of X509. * @throws IOException throws exception if the X509 cert structure copy fails. */ X509* digidoc::X509Cert::copyX509(X509* cert) throw(IOException) { X509* copy = X509_dup(cert); if(copy == NULL) { THROW_IOEXCEPTION("Failed to copy X509 certificate: %s", ERR_reason_error_string(ERR_get_error())); } return copy; }
int rb_init_ssl(void) { int ret = 1; char librb_data[] = "librb data"; const char librb_ciphers[] = "kEECDH+HIGH:kEDH+HIGH:HIGH:!RC4:!aNULL"; SSL_load_error_strings(); SSL_library_init(); librb_index = SSL_get_ex_new_index(0, librb_data, NULL, NULL, NULL); #ifndef LRB_HAVE_TLS_METHOD_API ssl_server_ctx = SSL_CTX_new(SSLv23_server_method()); #else ssl_server_ctx = SSL_CTX_new(TLS_server_method()); #endif if(ssl_server_ctx == NULL) { rb_lib_log("rb_init_openssl: Unable to initialize OpenSSL server context: %s", get_ssl_error(ERR_get_error())); ret = 0; } long server_options = SSL_CTX_get_options(ssl_server_ctx); #ifndef LRB_HAVE_TLS_METHOD_API server_options |= SSL_OP_NO_SSLv2; server_options |= SSL_OP_NO_SSLv3; #endif #ifdef SSL_OP_SINGLE_DH_USE server_options |= SSL_OP_SINGLE_DH_USE; #endif #ifdef SSL_OP_SINGLE_ECDH_USE server_options |= SSL_OP_SINGLE_ECDH_USE; #endif #ifdef SSL_OP_NO_TICKET server_options |= SSL_OP_NO_TICKET; #endif server_options |= SSL_OP_CIPHER_SERVER_PREFERENCE; SSL_CTX_set_options(ssl_server_ctx, server_options); SSL_CTX_set_verify(ssl_server_ctx, SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE, verify_accept_all_cb); SSL_CTX_set_session_cache_mode(ssl_server_ctx, SSL_SESS_CACHE_OFF); SSL_CTX_set_cipher_list(ssl_server_ctx, librb_ciphers); /* Set ECDHE on OpenSSL 1.00+, but make sure it's actually available * (it's not by default on Solaris or Red Hat... f**k Red Hat and Oracle) */ #if (OPENSSL_VERSION_NUMBER >= 0x10000000L) && !defined(OPENSSL_NO_ECDH) EC_KEY *key = EC_KEY_new_by_curve_name(NID_secp384r1); if (key) { SSL_CTX_set_tmp_ecdh(ssl_server_ctx, key); EC_KEY_free(key); } #endif #ifndef LRB_HAVE_TLS_METHOD_API ssl_client_ctx = SSL_CTX_new(SSLv23_client_method()); #else ssl_client_ctx = SSL_CTX_new(TLS_client_method()); #endif if(ssl_client_ctx == NULL) { rb_lib_log("rb_init_openssl: Unable to initialize OpenSSL client context: %s", get_ssl_error(ERR_get_error())); ret = 0; } #ifndef LRB_HAVE_TLS_METHOD_API SSL_CTX_set_options(ssl_client_ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3); #endif #ifdef SSL_OP_NO_TICKET SSL_CTX_set_options(ssl_client_ctx, SSL_OP_NO_TICKET); #endif SSL_CTX_set_cipher_list(ssl_client_ctx, librb_ciphers); return ret; }
int main(){ int len = 1024; //buffer length char buf[len]; //read buffer /* Initializing OpenSSL */ SSL_load_error_strings(); ERR_load_BIO_strings(); OpenSSL_add_all_algorithms(); SSL_library_init(); BIO *bio, *abio, *out; //the sockets SSL_CTX *ctx = SSL_CTX_new(SSLv23_server_method()); SSL *ssl; if( ctx == NULL ){ fprintf(stderr, "DEBUG ctx is null\n"); fprintf(stderr, "ERROR::OpenSLL: %s\n", ERR_reason_error_string(ERR_get_error())); exit(1); } //get password for private key // SSL_CTX_set_default_passwd_cb( ctx, &pem_passwd_cb ); //load certificate (with public key) SSL_CTX_use_certificate_file( ctx, "/home/mml/Develop/ca/certs/01.pem", SSL_FILETYPE_PEM); //load private key SSL_CTX_use_PrivateKey_file( ctx, "/home/mml/Develop/ca/testkey.pem", SSL_FILETYPE_PEM); bio = BIO_new_ssl(ctx, 0); if( bio == NULL ){ fprintf(stderr, "ERROR cannot bind\n"); exit(1); } BIO_get_ssl(bio, &ssl); SSL_set_mode( ssl, SSL_MODE_AUTO_RETRY ); abio = BIO_new_accept("localhost:15001"); BIO_set_accept_bios(abio, bio); BIO_do_accept(abio); fprintf(stdout, "DEBUG: waiting for connection\n"); BIO_do_accept(abio); out = BIO_pop(abio); fprintf(stdout, "DEBUG: doing handshake\n"); BIO_do_handshake(out); if(BIO_write(out, "Hello", 5) <= 0){ if(! BIO_should_retry(bio)) { fprintf(stderr, "ERROR connection is already closed. (write)\n"); exit(1); } else { //retry routine } } bzero(buf, len); if( BIO_read(out, buf, len) <= 0 ){ if( !(BIO_should_retry(bio)) ){ fprintf(stderr, "ERROR connection is already closed (read)\n"); exit(0); } else { //retry routine } } fprintf(stdout, "Hello%s\n", buf); //close connection BIO_free_all(abio); BIO_free_all(out); BIO_free_all(bio); SSL_CTX_free(ctx); return 0; }
void _openssl_log_error(int rc, SSL *con, const char *location) { const char *reason, *file, *data; unsigned long numerical_reason; int flags, line; snmp_log(LOG_ERR, "---- OpenSSL Related Errors: ----\n"); /* SSL specific errors */ if (con) { int sslnum = SSL_get_error(con, rc); switch(sslnum) { case SSL_ERROR_NONE: reason = "SSL_ERROR_NONE"; break; case SSL_ERROR_SSL: reason = "SSL_ERROR_SSL"; break; case SSL_ERROR_WANT_READ: reason = "SSL_ERROR_WANT_READ"; break; case SSL_ERROR_WANT_WRITE: reason = "SSL_ERROR_WANT_WRITE"; break; case SSL_ERROR_WANT_X509_LOOKUP: reason = "SSL_ERROR_WANT_X509_LOOKUP"; break; case SSL_ERROR_SYSCALL: reason = "SSL_ERROR_SYSCALL"; snmp_log(LOG_ERR, "TLS error: %s: rc=%d, sslerror = %d (%s): system_error=%d (%s)\n", location, rc, sslnum, reason, errno, strerror(errno)); snmp_log(LOG_ERR, "TLS Error: %s\n", ERR_reason_error_string(ERR_get_error())); return; case SSL_ERROR_ZERO_RETURN: reason = "SSL_ERROR_ZERO_RETURN"; break; case SSL_ERROR_WANT_CONNECT: reason = "SSL_ERROR_WANT_CONNECT"; break; case SSL_ERROR_WANT_ACCEPT: reason = "SSL_ERROR_WANT_ACCEPT"; break; default: reason = "unknown"; } snmp_log(LOG_ERR, " TLS error: %s: rc=%d, sslerror = %d (%s)\n", location, rc, sslnum, reason); snmp_log(LOG_ERR, " TLS Error: %s\n", ERR_reason_error_string(ERR_get_error())); } /* other errors */ while ((numerical_reason = ERR_get_error_line_data(&file, &line, &data, &flags)) != 0) { snmp_log(LOG_ERR, " error: #%lu (file %s, line %d)\n", numerical_reason, file, line); /* if we have a text translation: */ if (data && (flags & ERR_TXT_STRING)) { snmp_log(LOG_ERR, " Textual Error: %s\n", data); /* * per openssl man page: If it has been allocated by * OPENSSL_malloc(), *flags&ERR_TXT_MALLOCED is true. * * arggh... stupid openssl prototype for ERR_get_error_line_data * wants a const char **, but returns something that we might * need to free?? */ if (flags & ERR_TXT_MALLOCED) OPENSSL_free(NETSNMP_REMOVE_CONST(void *, data)); } } snmp_log(LOG_ERR, "---- End of OpenSSL Errors ----\n"); }
tcp_stream_t * tcp_stream_create_ssl_from_fd(int fd, const char *hostname, const tcp_ssl_info_t *tsi, char *errbuf, size_t errlen) { char errmsg[120]; tcp_stream_t *ts = calloc(1, sizeof(tcp_stream_t)); ts->ts_fd = fd; if((ts->ts_ssl = SSL_new(ssl_ctx)) == NULL) goto bad_ssl; if(SSL_set_fd(ts->ts_ssl, fd) == 0) goto bad_ssl; if(tsi->key != NULL) { BIO *cbio = BIO_new_mem_buf((char *)tsi->key, -1); EVP_PKEY *key = PEM_read_bio_PrivateKey(cbio, NULL, NULL, NULL); BIO_free(cbio); if(key == NULL) { snprintf(errbuf, errlen, "Unable to load private key"); goto bad; } SSL_use_PrivateKey(ts->ts_ssl, key); EVP_PKEY_free(key); } if(tsi->cert != NULL) { BIO *cbio = BIO_new_mem_buf((char *)tsi->cert, -1); X509 *cert = PEM_read_bio_X509(cbio, NULL, 0, NULL); BIO_free(cbio); if(cert == NULL) { snprintf(errbuf, errlen, "Unable to load certificate"); goto bad; } SSL_use_certificate(ts->ts_ssl, cert); X509_free(cert); } if(SSL_connect(ts->ts_ssl) <= 0) { goto bad_ssl; } SSL_set_mode(ts->ts_ssl, SSL_MODE_AUTO_RETRY); X509 *peer = SSL_get_peer_certificate(ts->ts_ssl); if(peer == NULL) { goto bad_ssl; } int err = SSL_get_verify_result(ts->ts_ssl); if(err != X509_V_OK) { snprintf(errbuf, errlen, "Certificate error: %s", X509_verify_cert_error_string(err)); X509_free(peer); goto bad; } if(verify_hostname(hostname, peer, errbuf, errlen)) { X509_free(peer); goto bad; } X509_free(peer); ts->ts_fd = fd; htsbuf_queue_init(&ts->ts_spill, INT32_MAX); htsbuf_queue_init(&ts->ts_sendq, INT32_MAX); ts->ts_write = ssl_write; ts->ts_read = ssl_read; return ts; bad_ssl: ERR_error_string(ERR_get_error(), errmsg); snprintf(errbuf, errlen, "SSL: %s", errmsg); bad: tcp_close(ts); return NULL; }
/** * Converts X.509 subject to string. * * @return issuer name converted to string. * @throws IOException exception is throws if the conversion failed. */ std::string digidoc::X509Cert::getSubject() const throw(IOException) { X509_NAME* subject = X509_get_subject_name(cert); if(subject == NULL) { THROW_IOEXCEPTION("Failed to convert X.509 certificate subject: %s", ERR_reason_error_string(ERR_get_error())); } return toString(subject); }
/* RSASSA-PKCS1-v1_5 (PKCS #1 v2.0 signature) with SHA1 */ int ssh_rsa_sign(const Key *key, u_char **sigp, u_int *lenp, const u_char *data, u_int datalen) { const EVP_MD *evp_md; EVP_MD_CTX md; u_char *sig = NULL; u_int slen = 0, len; #ifdef USE_LEGACY_RSA_SIGN u_char digest[EVP_MAX_MD_SIZE]; u_int dlen; #endif int ok, nid; Buffer b; if (key == NULL || key->rsa == NULL || (key->type != KEY_RSA && key->type != KEY_RSA_CERT && key->type != KEY_RSA_CERT_V00)) { error("ssh_rsa_sign: no RSA key"); return -1; } nid = (datafellows & SSH_BUG_RSASIGMD5) ? NID_md5 : NID_sha1; if ((evp_md = EVP_get_digestbynid(nid)) == NULL) { error("ssh_rsa_sign: EVP_get_digestbynid %d failed", nid); return -1; } #ifdef USE_LEGACY_RSA_SIGN EVP_DigestInit(&md, evp_md); EVP_DigestUpdate(&md, data, datalen); EVP_DigestFinal(&md, digest, &dlen); slen = RSA_size(key->rsa); sig = xmalloc(slen); ok = RSA_sign(nid, digest, dlen, sig, &len, key->rsa); memset(digest, 'd', sizeof(digest)); #else /*ndef USE_LEGACY_RSA_SIGN*/ { EVP_PKEY *pkey = NULL; ok = -1; pkey = EVP_PKEY_new(); if (pkey == NULL) { error("%s: out of memory", __func__); goto done; } EVP_PKEY_set1_RSA(pkey, key->rsa); slen = EVP_PKEY_size(pkey); sig = xmalloc(slen); /*fatal on error*/ ssh_EVP_MD_CTX_init(&md); ok = ssh_EVP_SignInit_ex(&md, evp_md, NULL); if (ok <= 0) { char ebuf[256]; error("%s: EVP_SignInit_ex fail with errormsg='%.*s'" , __func__ , (int)sizeof(ebuf), openssl_errormsg(ebuf, sizeof(ebuf))); goto clean; } ok = ssh_EVP_SignUpdate(&md, data, datalen); if (ok <= 0) { char ebuf[256]; error("%s: EVP_SignUpdate fail with errormsg='%.*s'" , __func__ , (int)sizeof(ebuf), openssl_errormsg(ebuf, sizeof(ebuf))); goto clean; } ok = EVP_SignFinal(&md, sig, &len, pkey); if (ok <= 0) { char ebuf[256]; error("%s: SignFinal fail with errormsg='%.*s'" , __func__ , (int)sizeof(ebuf), openssl_errormsg(ebuf, sizeof(ebuf))); goto clean; } clean: ssh_EVP_MD_CTX_cleanup(&md); done: if (pkey != NULL) EVP_PKEY_free(pkey); } #endif /*ndef USE_LEGACY_RSA_SIGN*/ if (ok <= 0) { #ifdef USE_LEGACY_RSA_SIGN int ecode = ERR_get_error(); error("ssh_rsa_sign: RSA_sign failed: %s", ERR_error_string(ecode, NULL)); #endif /*def USE_LEGACY_RSA_SIGN*/ xfree(sig); return -1; } if (len < slen) { u_int diff = slen - len; debug("slen %u > len %u", slen, len); memmove(sig + diff, sig, len); memset(sig, 0, diff); } else if (len > slen) { error("ssh_rsa_sign: slen %u slen2 %u", slen, len); xfree(sig); return -1; } /* encode signature */ buffer_init(&b); buffer_put_cstring(&b, "ssh-rsa"); buffer_put_string(&b, sig, slen); len = buffer_len(&b); if (lenp != NULL) *lenp = len; if (sigp != NULL) { *sigp = xmalloc(len); memcpy(*sigp, buffer_ptr(&b), len); } buffer_free(&b); memset(sig, 's', slen); xfree(sig); return 0; }
/** * Converts X509_NAME struct to string. * * @param name X509_NAME struct that is converted to string. * @return converted value of X509_NAME. * @throws IOException throws exception if conversion failed. */ std::string digidoc::X509Cert::toString(X509_NAME* name) throw(IOException) { BIO* mem = BIO_new(BIO_s_mem()); BIO_scope memScope(&mem); if(mem == NULL) { THROW_IOEXCEPTION("Failed to allocate memory for X509_NAME conversion: %s", ERR_reason_error_string(ERR_get_error())); } // Convert the X509_NAME struct to string. if(X509_NAME_print_ex(mem, name, 0, XN_FLAG_RFC2253) < 0) { THROW_IOEXCEPTION("Failed to convert X509_NAME struct to string: %s", ERR_reason_error_string(ERR_get_error())); } // Read the converted string from buffer. char buf[128]; int bytesRead; std::string str; while((bytesRead = BIO_gets(mem, &buf[0], sizeof(buf))) > 0) { str.append(buf); } return str; }
static int do_ca_cert_bootstrap(struct stream *stream) { struct ssl_stream *sslv = ssl_stream_cast(stream); STACK_OF(X509) *chain; X509 *cert; FILE *file; int error; int fd; chain = SSL_get_peer_cert_chain(sslv->ssl); if (!chain || !sk_X509_num(chain)) { VLOG_ERR("could not bootstrap CA cert: no certificate presented by " "peer"); return EPROTO; } cert = sk_X509_value(chain, sk_X509_num(chain) - 1); /* Check that 'cert' is self-signed. Otherwise it is not a CA * certificate and we should not attempt to use it as one. */ error = X509_check_issued(cert, cert); if (error) { VLOG_ERR("could not bootstrap CA cert: obtained certificate is " "not self-signed (%s)", X509_verify_cert_error_string(error)); if (sk_X509_num(chain) < 2) { VLOG_ERR("only one certificate was received, so probably the peer " "is not configured to send its CA certificate"); } return EPROTO; } fd = open(ca_cert.file_name, O_CREAT | O_EXCL | O_WRONLY, 0444); if (fd < 0) { if (errno == EEXIST) { VLOG_INFO_RL(&rl, "reading CA cert %s created by another process", ca_cert.file_name); stream_ssl_set_ca_cert_file__(ca_cert.file_name, true, true); return EPROTO; } else { VLOG_ERR("could not bootstrap CA cert: creating %s failed: %s", ca_cert.file_name, ovs_strerror(errno)); return errno; } } file = fdopen(fd, "w"); if (!file) { error = errno; VLOG_ERR("could not bootstrap CA cert: fdopen failed: %s", ovs_strerror(error)); unlink(ca_cert.file_name); return error; } if (!PEM_write_X509(file, cert)) { VLOG_ERR("could not bootstrap CA cert: PEM_write_X509 to %s failed: " "%s", ca_cert.file_name, ERR_error_string(ERR_get_error(), NULL)); fclose(file); unlink(ca_cert.file_name); return EIO; } if (fclose(file)) { error = errno; VLOG_ERR("could not bootstrap CA cert: writing %s failed: %s", ca_cert.file_name, ovs_strerror(error)); unlink(ca_cert.file_name); return error; } VLOG_INFO("successfully bootstrapped CA cert to %s", ca_cert.file_name); log_ca_cert(ca_cert.file_name, cert); bootstrap_ca_cert = false; ca_cert.read = true; /* SSL_CTX_add_client_CA makes a copy of cert's relevant data. */ SSL_CTX_add_client_CA(ctx, cert); SSL_CTX_set_cert_store(ctx, X509_STORE_new()); if (SSL_CTX_load_verify_locations(ctx, ca_cert.file_name, NULL) != 1) { VLOG_ERR("SSL_CTX_load_verify_locations: %s", ERR_error_string(ERR_get_error(), NULL)); return EPROTO; } VLOG_INFO("killing successful connection to retry using CA cert"); return EPROTO; }
/** * @return returns X.509 certificates public key. * @throws IOException throws exception if public key is missing. */ EVP_PKEY* digidoc::X509Cert::getPublicKey() const throw(IOException) { EVP_PKEY* pubKey = X509_get_pubkey(cert); if((pubKey == NULL) || (pubKey->type != EVP_PKEY_RSA)) { EVP_PKEY_free(pubKey); THROW_IOEXCEPTION("Unable to load RSA public Key: %s", ERR_reason_error_string(ERR_get_error())); } return pubKey; }
int AuthenticateAgent(AgentConnection *conn, Attributes attr, Promise *pp) { char sendbuffer[CF_EXPANDSIZE], in[CF_BUFSIZE], *out, *decrypted_cchall; BIGNUM *nonce_challenge, *bn = NULL; unsigned long err; unsigned char digest[EVP_MAX_MD_SIZE]; int encrypted_len, nonce_len = 0, len, session_size; bool implicitly_trust_server; char enterprise_field = 'c'; RSA *server_pubkey = NULL; if ((PUBKEY == NULL) || (PRIVKEY == NULL)) { CfOut(cf_error, "", "No public/private key pair found at %s\n", CFPUBKEYFILE); return false; } enterprise_field = CfEnterpriseOptions(); session_size = CfSessionKeySize(enterprise_field); /* Generate a random challenge to authenticate the server */ nonce_challenge = BN_new(); if (nonce_challenge == NULL) { CfOut(cf_error, "", "Cannot allocate BIGNUM structure for server challenge\n"); return false; } BN_rand(nonce_challenge, CF_NONCELEN, 0, 0); nonce_len = BN_bn2mpi(nonce_challenge, in); if (FIPS_MODE) { HashString(in, nonce_len, digest, CF_DEFAULT_DIGEST); } else { HashString(in, nonce_len, digest, cf_md5); } /* We assume that the server bound to the remote socket is the official one i.e. = root's */ if ((server_pubkey = HavePublicKeyByIP(conn->username, conn->remoteip))) { implicitly_trust_server = false; encrypted_len = RSA_size(server_pubkey); } else { implicitly_trust_server = true; encrypted_len = nonce_len; } // Server pubkey is what we want to has as a unique ID snprintf(sendbuffer, sizeof(sendbuffer), "SAUTH %c %d %d %c", implicitly_trust_server ? 'n': 'y', encrypted_len, nonce_len, enterprise_field); out = xmalloc(encrypted_len); if (server_pubkey != NULL) { if (RSA_public_encrypt(nonce_len, in, out, server_pubkey, RSA_PKCS1_PADDING) <= 0) { err = ERR_get_error(); cfPS(cf_error, CF_FAIL, "", pp, attr, "Public encryption failed = %s\n", ERR_reason_error_string(err)); free(out); RSA_free(server_pubkey); return false; } memcpy(sendbuffer + CF_RSA_PROTO_OFFSET, out, encrypted_len); } else { memcpy(sendbuffer + CF_RSA_PROTO_OFFSET, in, nonce_len); } /* proposition C1 - Send challenge / nonce */ SendTransaction(conn->sd, sendbuffer, CF_RSA_PROTO_OFFSET + encrypted_len, CF_DONE); BN_free(bn); BN_free(nonce_challenge); free(out); if (DEBUG) { RSA_print_fp(stdout, PUBKEY, 0); } /*Send the public key - we don't know if server has it */ /* proposition C2 */ memset(sendbuffer, 0, CF_EXPANDSIZE); len = BN_bn2mpi(PUBKEY->n, sendbuffer); SendTransaction(conn->sd, sendbuffer, len, CF_DONE); /* No need to encrypt the public key ... */ /* proposition C3 */ memset(sendbuffer, 0, CF_EXPANDSIZE); len = BN_bn2mpi(PUBKEY->e, sendbuffer); SendTransaction(conn->sd, sendbuffer, len, CF_DONE); /* check reply about public key - server can break connection here */ /* proposition S1 */ memset(in, 0, CF_BUFSIZE); if (ReceiveTransaction(conn->sd, in, NULL) == -1) { cfPS(cf_error, CF_INTERPT, "recv", pp, attr, "Protocol transaction broken off (1)"); RSA_free(server_pubkey); return false; } if (BadProtoReply(in)) { CfOut(cf_error, "", "%s", in); RSA_free(server_pubkey); return false; } /* Get challenge response - should be CF_DEFAULT_DIGEST of challenge */ /* proposition S2 */ memset(in, 0, CF_BUFSIZE); if (ReceiveTransaction(conn->sd, in, NULL) == -1) { cfPS(cf_error, CF_INTERPT, "recv", pp, attr, "Protocol transaction broken off (2)"); RSA_free(server_pubkey); return false; } if ((HashesMatch(digest, in, CF_DEFAULT_DIGEST)) || (HashesMatch(digest, in, cf_md5))) // Legacy { if (implicitly_trust_server == false) /* challenge reply was correct */ { CfOut(cf_verbose, "", ".....................[.h.a.i.l.].................................\n"); CfOut(cf_verbose, "", "Strong authentication of server=%s connection confirmed\n", pp->this_server); } else { if (attr.copy.trustkey) { CfOut(cf_verbose, "", " -> Trusting server identity, promise to accept key from %s=%s", pp->this_server, conn->remoteip); } else { CfOut(cf_error, "", " !! Not authorized to trust the server=%s's public key (trustkey=false)\n", pp->this_server); PromiseRef(cf_verbose, pp); RSA_free(server_pubkey); return false; } } } else { cfPS(cf_error, CF_INTERPT, "", pp, attr, "Challenge response from server %s/%s was incorrect!", pp->this_server, conn->remoteip); RSA_free(server_pubkey); return false; } /* Receive counter challenge from server */ CfDebug("Receive counter challenge from server\n"); /* proposition S3 */ memset(in, 0, CF_BUFSIZE); encrypted_len = ReceiveTransaction(conn->sd, in, NULL); if (encrypted_len <= 0) { CfOut(cf_error, "", "Protocol transaction sent illegal cipher length"); RSA_free(server_pubkey); return false; } decrypted_cchall = xmalloc(encrypted_len); if (RSA_private_decrypt(encrypted_len, in, decrypted_cchall, PRIVKEY, RSA_PKCS1_PADDING) <= 0) { err = ERR_get_error(); cfPS(cf_error, CF_INTERPT, "", pp, attr, "Private decrypt failed = %s, abandoning\n", ERR_reason_error_string(err)); RSA_free(server_pubkey); return false; } /* proposition C4 */ if (FIPS_MODE) { HashString(decrypted_cchall, nonce_len, digest, CF_DEFAULT_DIGEST); } else { HashString(decrypted_cchall, nonce_len, digest, cf_md5); } CfDebug("Replying to counter challenge with hash\n"); if (FIPS_MODE) { SendTransaction(conn->sd, digest, CF_DEFAULT_DIGEST_LEN, CF_DONE); } else { SendTransaction(conn->sd, digest, CF_MD5_LEN, CF_DONE); } free(decrypted_cchall); /* If we don't have the server's public key, it will be sent */ if (server_pubkey == NULL) { RSA *newkey = RSA_new(); CfOut(cf_verbose, "", " -> Collecting public key from server!\n"); /* proposition S4 - conditional */ if ((len = ReceiveTransaction(conn->sd, in, NULL)) <= 0) { CfOut(cf_error, "", "Protocol error in RSA authentation from IP %s\n", pp->this_server); return false; } if ((newkey->n = BN_mpi2bn(in, len, NULL)) == NULL) { err = ERR_get_error(); cfPS(cf_error, CF_INTERPT, "", pp, attr, "Private key decrypt failed = %s\n", ERR_reason_error_string(err)); RSA_free(newkey); return false; } /* proposition S5 - conditional */ if ((len = ReceiveTransaction(conn->sd, in, NULL)) <= 0) { cfPS(cf_inform, CF_INTERPT, "", pp, attr, "Protocol error in RSA authentation from IP %s\n", pp->this_server); RSA_free(newkey); return false; } if ((newkey->e = BN_mpi2bn(in, len, NULL)) == NULL) { err = ERR_get_error(); cfPS(cf_error, CF_INTERPT, "", pp, attr, "Public key decrypt failed = %s\n", ERR_reason_error_string(err)); RSA_free(newkey); return false; } server_pubkey = RSAPublicKey_dup(newkey); RSA_free(newkey); } /* proposition C5 */ SetSessionKey(conn); if (conn->session_key == NULL) { CfOut(cf_error, "", "A random session key could not be established"); RSA_free(server_pubkey); return false; } encrypted_len = RSA_size(server_pubkey); CfDebug("Encrypt %d bytes of session key into %d RSA bytes\n", session_size, encrypted_len); out = xmalloc(encrypted_len); if (RSA_public_encrypt(session_size, conn->session_key, out, server_pubkey, RSA_PKCS1_PADDING) <= 0) { err = ERR_get_error(); cfPS(cf_error, CF_INTERPT, "", pp, attr, "Public encryption failed = %s\n", ERR_reason_error_string(err)); free(out); RSA_free(server_pubkey); return false; } SendTransaction(conn->sd, out, encrypted_len, CF_DONE); if (server_pubkey != NULL) { HashPubKey(server_pubkey, conn->digest, CF_DEFAULT_DIGEST); CfOut(cf_verbose, "", " -> Public key identity of host \"%s\" is \"%s\"", conn->remoteip, HashPrint(CF_DEFAULT_DIGEST, conn->digest)); SavePublicKey(conn->username, conn->remoteip, HashPrint(CF_DEFAULT_DIGEST, conn->digest), server_pubkey); // FIXME: username is local LastSaw(conn->remoteip, conn->digest, cf_connect); } free(out); RSA_free(server_pubkey); return true; }
/** * Creates X509 certificate from the provider DER encoded bytes. * * @param bytes X509 certificate in DER encoding. * @throws IOException throws exception if X509 certificate parsing failed. */ digidoc::X509Cert::X509Cert(std::vector<unsigned char> bytes) throw(IOException) : cert(NULL) { if(bytes.empty()) { THROW_IOEXCEPTION("No bytes given to parse X509."); } // Parse certificate from DER formatted buffer. const unsigned char* pBytes = reinterpret_cast<const unsigned char*>(&bytes[0]); d2i_X509(&cert, &pBytes, bytes.size()); if(cert == NULL) { THROW_IOEXCEPTION("Failed to parse X509 certificate from bytes given: %s", ERR_reason_error_string(ERR_get_error())); } }
/** * Check a canonical sig+rrset and signature against a dnskey * @param buf: buffer with data to verify, the first rrsig part and the * canonicalized rrset. * @param algo: DNSKEY algorithm. * @param sigblock: signature rdata field from RRSIG * @param sigblock_len: length of sigblock data. * @param key: public key data from DNSKEY RR. * @param keylen: length of keydata. * @param reason: bogus reason in more detail. * @return secure if verification succeeded, bogus on crypto failure, * unchecked on format errors and alloc failures. */ int _getdns_verify_canonrrset(gldns_buffer* buf, int algo, unsigned char* sigblock, unsigned int sigblock_len, unsigned char* key, unsigned int keylen, char** reason) { const EVP_MD *digest_type; EVP_MD_CTX* ctx; int res, dofree = 0; EVP_PKEY *evp_key = NULL; if(!setup_key_digest(algo, &evp_key, &digest_type, key, keylen)) { verbose(VERB_QUERY, "verify: failed to setup key"); *reason = "use of key for crypto failed"; EVP_PKEY_free(evp_key); return 0; } #ifdef USE_DSA /* if it is a DSA signature in bind format, convert to DER format */ if((algo == GLDNS_DSA || algo == GLDNS_DSA_NSEC3) && sigblock_len == 1+2*SHA_DIGEST_LENGTH) { if(!setup_dsa_sig(&sigblock, &sigblock_len)) { verbose(VERB_QUERY, "verify: failed to setup DSA sig"); *reason = "use of key for DSA crypto failed"; EVP_PKEY_free(evp_key); return 0; } dofree = 1; } #endif #if defined(USE_ECDSA) && defined(USE_DSA) else #endif #ifdef USE_ECDSA if(algo == GLDNS_ECDSAP256SHA256 || algo == GLDNS_ECDSAP384SHA384) { /* EVP uses ASN prefix on sig, which is not in the wire data */ if(!setup_ecdsa_sig(&sigblock, &sigblock_len)) { verbose(VERB_QUERY, "verify: failed to setup ECDSA sig"); *reason = "use of signature for ECDSA crypto failed"; EVP_PKEY_free(evp_key); return 0; } dofree = 1; } #endif /* USE_ECDSA */ /* do the signature cryptography work */ #ifdef HAVE_EVP_MD_CTX_NEW ctx = EVP_MD_CTX_new(); #else ctx = (EVP_MD_CTX*)malloc(sizeof(*ctx)); if(ctx) EVP_MD_CTX_init(ctx); #endif if(!ctx) { log_err("EVP_MD_CTX_new: malloc failure"); EVP_PKEY_free(evp_key); if(dofree) free(sigblock); return 0; } if(EVP_VerifyInit(ctx, digest_type) == 0) { verbose(VERB_QUERY, "verify: EVP_VerifyInit failed"); EVP_MD_CTX_destroy(ctx); EVP_PKEY_free(evp_key); if(dofree) free(sigblock); return 0; } if(EVP_VerifyUpdate(ctx, (unsigned char*)gldns_buffer_begin(buf), (unsigned int)gldns_buffer_limit(buf)) == 0) { verbose(VERB_QUERY, "verify: EVP_VerifyUpdate failed"); EVP_MD_CTX_destroy(ctx); EVP_PKEY_free(evp_key); if(dofree) free(sigblock); return 0; } res = EVP_VerifyFinal(ctx, sigblock, sigblock_len, evp_key); EVP_MD_CTX_destroy(ctx); EVP_PKEY_free(evp_key); if(dofree) free(sigblock); if(res == 1) { return 1; } else if(res == 0) { verbose(VERB_QUERY, "verify: signature mismatch"); *reason = "signature crypto failed"; return 0; } log_crypto_error("verify:", ERR_get_error()); return 0; }
void pki_evp::fload(const QString fname) { pass_info p(XCA_TITLE, qApp->translate("MainWindow", "Please enter the password to decrypt the private key: '%1'"). arg(fname)); pem_password_cb *cb = MainWindow::passRead; FILE *fp = fopen(QString2filename(fname), "r"); EVP_PKEY *pkey; pki_ign_openssl_error(); if (!fp) { fopen_error(fname); return; } pkey = PEM_read_PrivateKey(fp, NULL, cb, &p); if (!pkey) { if (ERR_get_error() == 0x06065064) { fclose(fp); pki_ign_openssl_error(); throw errorEx(tr("Failed to decrypt the key (bad password) ") + fname, class_name); } } if (!pkey) { pki_ign_openssl_error(); rewind(fp); pkey = d2i_PrivateKey_fp(fp, NULL); } if (!pkey) { pki_ign_openssl_error(); rewind(fp); pkey = d2i_PKCS8PrivateKey_fp(fp, NULL, cb, &p); } if (!pkey) { PKCS8_PRIV_KEY_INFO *p8inf; pki_ign_openssl_error(); rewind(fp); p8inf = d2i_PKCS8_PRIV_KEY_INFO_fp(fp, NULL); if (p8inf) { pkey = EVP_PKCS82PKEY(p8inf); PKCS8_PRIV_KEY_INFO_free(p8inf); } } if (!pkey) { pki_ign_openssl_error(); rewind(fp); pkey = PEM_read_PUBKEY(fp, NULL, cb, &p); } if (!pkey) { pki_ign_openssl_error(); rewind(fp); pkey = d2i_PUBKEY_fp(fp, NULL); } fclose(fp); if (pki_ign_openssl_error()) { if (pkey) EVP_PKEY_free(pkey); throw errorEx(tr("Unable to load the private key in file %1. Tried PEM and DER private, public and PKCS#8 key types.").arg(fname)); } if (pkey){ if (pkey->type == EVP_PKEY_EC) search_ec_oid(pkey->pkey.ec); if (key) EVP_PKEY_free(key); key = pkey; if (EVP_PKEY_isPrivKey(key)) bogusEncryptKey(); setIntName(rmslashdot(fname)); } }
/** * @brief Sign a TFTF * * @param filename The pathname to the TFTF file to sign. * @param signature_format The pathname to the TFTF file to sign. * @param signature_algorithm The pathname to the TFTF file to sign. * @param key_filename The pathname to the TFTF file to sign. * @param write_if_good If true and we were able to sign it, write the signed * TFTF file. If false only verify we can sign the TFTF. * @param verbose If true, display the signed TFTF. * * @returns True on success, false on failure */ bool sign_tftf(const char * filename, const uint32_t signature_algorithm, const char * key_name, const char * key_filename, const bool write_if_good, const bool verbose) { bool success = false; int status; ssize_t tftf_size; tftf_header * tftf_hdr = NULL; char * loc_key_filename = NULL; /* Sanity check */ if (!filename || !key_filename) { fprintf (stderr, "ERROR (sign_tftf): invalid parameters\n"); return false; } /* Create a local copy of the key_filename */ loc_key_filename = malloc(strlen(key_filename) + 1); if (!loc_key_filename) { fprintf(stderr, "ERROR (sign_tftf): can't alloc. local key_filename\n"); return false; } strcpy(loc_key_filename, key_filename); /* Read in the TFTF file as a blob */ tftf_hdr = (tftf_header *)alloc_load_file(filename, &tftf_size); if (tftf_hdr) { EVP_MD_CTX * mdctx; uint8_t * hdr_signable_start = NULL; size_t hdr_signable_length = 0; uint8_t * scn_signable_start = NULL; size_t scn_signable_length = 0; tftf_signature signature_block; uint8_t md_value[EVP_MAX_MD_SIZE]; unsigned int md_len; unsigned int sig_len = sizeof(signature_block.signature); /* Initialize the signature block */ signature_block.length = sizeof(signature_block); signature_block.type = signature_algorithm; safer_strcpy(signature_block.key_name, sizeof(signature_block.key_name), key_name); /* Extract the signable blob from the TFTF and sign it */ success = tftf_get_signable_region(tftf_hdr, &hdr_signable_start, &hdr_signable_length, &scn_signable_start, &scn_signable_length); mdctx = EVP_MD_CTX_create(); if (mdctx) { status = EVP_DigestInit_ex(mdctx, EVP_sha256(), NULL); if (status < 1) { fprintf(stderr, "ERROR: EVP_DigestInit_ex failed: %s\n", ERR_error_string(ERR_get_error(), NULL)); goto signing_err; } status = EVP_DigestUpdate(mdctx, hdr_signable_start, hdr_signable_length); if (status < 1) { fprintf(stderr, "ERROR: EVP_DigestUpdate (hdr) failed: %s\n", ERR_error_string(ERR_get_error(), NULL)); goto signing_err; } status = EVP_DigestUpdate(mdctx, scn_signable_start, scn_signable_length); if (status < 1) { fprintf(stderr, "ERROR: EVP_DigestUpdate (scn) failed: %s\n", ERR_error_string(ERR_get_error(), NULL)); goto signing_err; } status = EVP_DigestFinal_ex(mdctx, md_value, &md_len); if (status < 1) { fprintf(stderr, "ERROR: EVP_DigestFinal_ex failed: %s\n", ERR_error_string(ERR_get_error(), NULL)); goto signing_err; } status = RSA_sign(NID_sha256, md_value, md_len, signature_block.signature, &sig_len, rsa); if (status < 1) { fprintf(stderr, "ERROR: RSA_sign failed: %s\n", ERR_error_string(ERR_get_error(), NULL)); } success = true; signing_err: EVP_MD_CTX_destroy(mdctx); } else { fprintf(stderr, "ERROR: EVP_MD_CTX_create failed\n"); } /* Append the signature block to the TFTF */ if (success) { success = tftf_add_section(&tftf_hdr, TFTF_SECTION_SIGNATURE, 0, 0, DATA_ADDRESS_TO_BE_IGNORED, (uint8_t*)&signature_block, sizeof(signature_block)); if (!success) { fprintf(stderr, "ERROR: File is signable but no room for signature\n"); } } if (success) { /* Rewrite the file with the amended TFTF */ if (write_if_good) { success = write_tftf_file(tftf_hdr, filename); } /* Show the user what they've produced? */ if (verbose) { print_tftf_file(tftf_hdr, filename); } } } /* Dispose of any local allocations */ if (tftf_hdr) { free(tftf_hdr); } if (loc_key_filename) { free(loc_key_filename); } return success; }
void SslContext::setCerti(const std::string &file, TYPE_FILE) { this->_certi = file; if (!SSL_CTX_use_certificate_file(this->_ctx, this->_certi.c_str(),SSL_FILETYPE_PEM)) throw SslException(SslException::CONTEXT , ERR_error_string(ERR_get_error(), NULL)); }
bytes public_key::serialize()const { bytes ba; if( !my ) { return ba; } BIO *mem = BIO_new(BIO_s_mem()); int e = PEM_write_bio_RSAPublicKey( mem, my->rsa ); if( e != 1 ) { BIO_free(mem); FC_THROW_EXCEPTION( exception, "openssl: ${message}", ("message",fc::string(ERR_error_string( ERR_get_error(),NULL))) ); } char* dat; uint32_t l = BIO_get_mem_data( mem, &dat ); fc::stringstream ss( string( dat, l ) ); fc::stringstream key; fc::string tmp; fc::getline( ss, tmp ); fc::getline( ss, tmp ); while( tmp.size() && tmp[0] != '-' ) { key << tmp; fc::getline( ss, tmp ); } auto str = key.str(); str = fc::base64_decode( str ); ba = bytes( str.begin(), str.end() ); BIO_free(mem); return ba; }
int run_receiver(UDR_Options * udr_options) { int orig_ppid = getppid(); UDT::startup(); addrinfo hints; addrinfo* res; set_verbosity(udr_options->verbose); memset(&hints, 0, sizeof(struct addrinfo)); hints.ai_flags = AI_PASSIVE; hints.ai_family = AF_INET; hints.ai_socktype = SOCK_STREAM; char receiver_port[NI_MAXSERV]; UDTSOCKET serv; bool bad_port = false; for(int port_num = udr_options->start_port; port_num < udr_options->end_port; port_num++) { bad_port = false; snprintf(receiver_port, sizeof(receiver_port), "%d", port_num); if (0 != getaddrinfo(NULL, receiver_port, &hints, &res)) { bad_port = true; } else { serv = UDT::socket(res->ai_family, res->ai_socktype, res->ai_protocol); if (UDT::ERROR == UDT::bind(serv, res->ai_addr, res->ai_addrlen)) { bad_port = true; } } freeaddrinfo(res); if(!bad_port) break; } if(bad_port){ fprintf(stderr, "[udr receiver] ERROR: could not bind to any port in range %d - %d\n", udr_options->start_port, udr_options->end_port); return 0; } unsigned char rand_pp[PASSPHRASE_SIZE]; if (!RAND_bytes((unsigned char *) rand_pp, PASSPHRASE_SIZE)) { fprintf(stderr, "Couldn't generate random key: %ld\n", ERR_get_error()); exit(EXIT_FAILURE); } //stdout port number and password -- to send back to the client printf("%s ", receiver_port); for(int i = 0; i < PASSPHRASE_SIZE; i++) { printf("%02x", rand_pp[i]); } printf(" \n"); fflush(stdout); verbose_print("[udr receiver] server is ready at port %s\n", receiver_port); if (UDT::ERROR == UDT::listen(serv, 10)) { cerr << "[udr receiver] listen: " << UDT::getlasterror().getErrorMessage() << endl; return 0; } sockaddr_storage clientaddr; int addrlen = sizeof(clientaddr); UDTSOCKET recver; if (UDT::INVALID_SOCK == (recver = UDT::accept(serv, (sockaddr*)&clientaddr, &addrlen))) { fprintf(stderr, "[udr receiver] accept: %s\n", UDT::getlasterror().getErrorMessage()); return 0; } char clienthost[NI_MAXHOST]; char clientservice[NI_MAXSERV]; getnameinfo((sockaddr *)&clientaddr, addrlen, clienthost, sizeof(clienthost), clientservice, sizeof(clientservice), NI_NUMERICHOST|NI_NUMERICSERV); string cmd_str = udt_recv_string(recver); const char * cmd = cmd_str.c_str(); //perhaps want to at least check that starts with rsync? if(strncmp(cmd, "rsync ", 5) != 0){ exit(1); } char * rsync_cmd; if(udr_options->server_connect){ verbose_print("[udr receiver] server connect mode\n"); rsync_cmd = (char *)malloc(100); if(strlen(udr_options->server_config) > 0){ sprintf(rsync_cmd, "%s%s %s", "rsync --config=", udr_options->server_config, " --server --daemon ."); } else{ strcpy(rsync_cmd, "rsync --server --daemon ."); } } else{ rsync_cmd = (char *)malloc(strlen(cmd) + 1); strcpy(rsync_cmd, cmd); } verbose_print("[udr receiver] rsync cmd: %s\n", rsync_cmd); char ** sh_cmd = (char **)malloc(sizeof(char *) * 4); sh_cmd[0] = udr_options->shell_program; sh_cmd[1] = "-c"; sh_cmd[2] = rsync_cmd; sh_cmd[3] = NULL; //now fork and exec the rsync on the remote side using sh (so that wildcards will be expanded properly) int child_to_parent, parent_to_child; int rsync_pid = fork_execvp(udr_options->shell_program, sh_cmd, &parent_to_child, &child_to_parent); //now if we're in server mode need to drop privileges if specified if(udr_options->rsync_gid > 0){ setgid(udr_options->rsync_gid); } if(udr_options->rsync_uid > 0){ setuid(udr_options->rsync_uid); } verbose_print("[udr receiver] rsync pid: %d\n", rsync_pid); struct thread_data recv_to_udt; recv_to_udt.udt_socket = &recver; recv_to_udt.fd = child_to_parent; //stdout of rsync server process recv_to_udt.id = 2; recv_to_udt.is_complete = false; struct thread_data udt_to_recv; udt_to_recv.udt_socket = &recver; udt_to_recv.fd = parent_to_child; //stdin of rsync server process udt_to_recv.id = 3; udt_to_recv.is_complete = false; if(udr_options->encryption){ crypto encrypt(EVP_ENCRYPT, PASSPHRASE_SIZE, rand_pp, udr_options->encryption_type); crypto decrypt(EVP_DECRYPT, PASSPHRASE_SIZE, rand_pp, udr_options->encryption_type); recv_to_udt.crypt = &encrypt; udt_to_recv.crypt = &decrypt; } else{ recv_to_udt.crypt = NULL; udt_to_recv.crypt = NULL; } pthread_t recv_to_udt_thread; pthread_create(&recv_to_udt_thread, NULL, handle_to_udt, (void *)&recv_to_udt); pthread_t udt_to_recv_thread; pthread_create(&udt_to_recv_thread, NULL, udt_to_handle, (void*)&udt_to_recv); verbose_print("[udr receiver] waiting to join on recv_to_udt_thread\n"); verbose_print("[udr receiver] ppid %d pid %d\n", getppid(), getpid()); //going to poll if the ppid changes then we know it's exited and then we exit all of our threads and exit as well //also going to check if either thread is complete, if one is then the other should also be killed //bit of a hack to deal with the pthreads while(true){ if(getppid() != orig_ppid){ pthread_kill(recv_to_udt_thread, SIGUSR1); pthread_kill(udt_to_recv_thread, SIGUSR1); break; } if(recv_to_udt.is_complete && udt_to_recv.is_complete){ verbose_print("[udr receiver] both threads are complete: recv_to_udt.is_complete %d udt_to_recv.is_complete %d\n", recv_to_udt.is_complete, udt_to_recv.is_complete); break; } else if(recv_to_udt.is_complete){ verbose_print("[udr receiver] recv_to_udt is complete: recv_to_udt.is_complete %d udt_to_recv.is_complete %d\n", recv_to_udt.is_complete, udt_to_recv.is_complete); break; } else if(udt_to_recv.is_complete){ verbose_print("[udr receiver] udt_to_recv is complete: recv_to_udt.is_complete %d udt_to_recv.is_complete %d\n", recv_to_udt.is_complete, udt_to_recv.is_complete); break; } sleep(ppid_poll); } verbose_print("[udr receiver] Trying to close recver\n"); UDT::close(recver); verbose_print("[udr receiver] Closed recver\n"); UDT::close(serv); verbose_print("[udr receiver] Closed serv\n"); UDT::cleanup(); verbose_print("[udr receiver] UDT cleaned up\n"); return 0; }
signature private_key::sign( const sha256& digest )const { if( !my ) FC_THROW_EXCEPTION( assert_exception, "!null" ); signature sig; sig.resize( RSA_size(my->rsa) ); uint32_t slen = 0; if( 1 != RSA_sign( NID_sha256, (uint8_t*)digest.data(), 32, (unsigned char*)sig.data(), &slen, my->rsa ) ) { FC_THROW_EXCEPTION( exception, "rsa sign failed with ${message}", ("message",fc::string(ERR_error_string( ERR_get_error(),NULL))) ); } return sig; }
/** * @retval 1 equal * @retval 0 not equal * @retval -1 error */ static int CompareCertToRSA(X509 *cert, RSA *rsa_key) { int ret; int retval = -1; /* ERROR */ EVP_PKEY *cert_pkey = X509_get_pubkey(cert); if (cert_pkey == NULL) { Log(LOG_LEVEL_ERR, "X509_get_pubkey: %s", TLSErrorString(ERR_get_error())); goto ret1; } if (EVP_PKEY_base_id(cert_pkey) != EVP_PKEY_RSA) { Log(LOG_LEVEL_ERR, "Received key of unknown type, only RSA currently supported!"); goto ret2; } RSA *cert_rsa_key = EVP_PKEY_get1_RSA(cert_pkey); if (cert_rsa_key == NULL) { Log(LOG_LEVEL_ERR, "TLSVerifyPeer: EVP_PKEY_get1_RSA failed!"); goto ret2; } EVP_PKEY *rsa_pkey = EVP_PKEY_new(); if (rsa_pkey == NULL) { Log(LOG_LEVEL_ERR, "TLSVerifyPeer: EVP_PKEY_new allocation failed!"); goto ret3; } ret = EVP_PKEY_set1_RSA(rsa_pkey, rsa_key); if (ret == 0) { Log(LOG_LEVEL_ERR, "TLSVerifyPeer: EVP_PKEY_set1_RSA failed!"); goto ret4; } ret = EVP_PKEY_cmp(cert_pkey, rsa_pkey); if (ret == 1) { Log(LOG_LEVEL_DEBUG, "Public key to certificate compare equal"); retval = 1; /* EQUAL */ } else if (ret == 0 || ret == -1) { Log(LOG_LEVEL_DEBUG, "Public key to certificate compare different"); retval = 0; /* NOT EQUAL */ } else { Log(LOG_LEVEL_ERR, "OpenSSL EVP_PKEY_cmp: %d %s", ret, TLSErrorString(ERR_get_error())); } ret4: EVP_PKEY_free(rsa_pkey); ret3: RSA_free(cert_rsa_key); ret2: EVP_PKEY_free(cert_pkey); ret1: return retval; }