/** * @return returns X.509 certificate serial number. * @throws IOException exception is thrown if the serial is incorrect. */ std::string digidoc::X509Cert::getSerial() const throw(IOException) { std::string serial; BIGNUM *bn = ASN1_INTEGER_to_BN(X509_get_serialNumber(cert), 0); if(bn) { char *str = BN_bn2dec(bn); if(str) serial = str; OPENSSL_free(str); BN_free(bn); } if(serial.empty()) { THROW_IOEXCEPTION("Failed to read certificate serial number from X.509 certificate: %s", ERR_reason_error_string(ERR_get_error())); } return serial; }
/** * @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; }
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; }
const char *TLSErrorString(intmax_t errcode) { const char *errmsg = ERR_reason_error_string((unsigned long) errcode); return (errmsg != NULL) ? errmsg : "no error message"; }
int AXIS2_CALL openssl_rsa_prv_encrypt( const axutil_env_t *env, const openssl_pkey_t *pkey, const axis2_char_t *padding, oxs_buffer_t *in, oxs_buffer_t *out) { unsigned char *encrypted = NULL; int ret; EVP_PKEY *key = NULL; int pad = RSA_PKCS1_PADDING; AXIS2_ENV_CHECK(env, AXIS2_FAILURE); /*Get the private key*/ key = (EVP_PKEY *)openssl_pkey_get_key(pkey, env); /*Set padding. This is the only diff btwn RSA-v1.5 and RSA-OAEP*/ if(0 == axutil_strcmp(padding, OPENSSL_RSA_PKCS1_OAEP_PADDING ) ){ pad = RSA_PKCS1_OAEP_PADDING; }else if(0 == axutil_strcmp(padding, OPENSSL_RSA_PKCS1_PADDING ) ){ pad = RSA_PKCS1_PADDING; } encrypted = AXIS2_MALLOC(env->allocator, RSA_size(key->pkey.rsa)); ret = RSA_private_encrypt(RSA_size(key->pkey.rsa), oxs_buffer_get_data(in, env), encrypted, key->pkey.rsa, pad); if (ret < 0) { oxs_error(env, OXS_ERROR_LOCATION, OXS_ERROR_OPENSSL_FUNC_FAILED, "RSA private encryption(Signing) failed. Error code %d: %s",ERR_get_error(), ERR_reason_error_string(ERR_get_error())); return (-1); } oxs_buffer_populate(out, env, encrypted, ret); return ret; }
int main(int argc, char **argv) { FILE *fp = NULL; EVP_PKEY *pkey = NULL; X509 *cert = NULL; STACK_OF(X509) *ca = NULL; PKCS12 *p12 = NULL; char *pass = strdup(""); int i; if (argc != 2) { fprintf(stderr, "[!] Usage: %s certificate.p12\n", argv[0]); exit(1); } printf("[+] Initializing OpenSSL\n"); SSLeay_add_all_algorithms(); ERR_load_crypto_strings(); printf("[+] Opening PKCS#12 certificate\n"); if (!(fp = fopen(argv[1], "r"))) { fprintf(stderr, "[!] Unable to open certificate `%s'\n", argv[1]); goto endpkcs12; } if (chdir(dirname(argv[1])) == -1) { fprintf(stderr, "[!] Unable to change directory to `%s'\n", dirname(argv[1])); goto endpkcs12; } p12 = d2i_PKCS12_fp(fp, NULL); fclose(fp); fp = NULL; if (!p12) { fprintf(stderr, "[!] Unable to parse PKCS#12 certificate: %s\n", ERR_reason_error_string(ERR_get_error())); goto endpkcs12; } while (!PKCS12_parse(p12, pass, &pkey, &cert, &ca)) { ca = NULL; free(pass); if (getpassword("[?] Password: "******"[!] PKCS#12 certificate is incomplete\n"); goto endpkcs12; } #define PEM_w(path, call) \ do { \ if (!(fp = fopen(path, "w"))) { \ fprintf(stderr, "[!] Unable to open `%s'\n", path); \ goto endpkcs12; \ } \ printf("[+] Write certificate to `%s'\n", path); \ call; \ fclose(fp); fp = NULL; \ } while(0) PEM_w("user.pem", PEM_write_X509(fp, cert)); PEM_w("user.key", PEM_write_PrivateKey(fp, pkey, NULL, NULL, 0, NULL, NULL)); PEM_w("cacert.pem", for (i = 0; i < sk_X509_num(ca); i++) PEM_write_X509(fp, sk_X509_value(ca, i))); sk_free(ca); X509_free(cert); EVP_PKEY_free(pkey); exit(0); endpkcs12: if (pass) free(pass); if (ca) sk_free(ca); if (cert) X509_free(cert); if (pkey) EVP_PKEY_free(pkey); if (p12) PKCS12_free(p12); if (fp) fclose(fp); exit(1); }
void *netConnectHttpsThread(void *threadParam) /* use a thread to run socket back to user */ { /* child */ struct netConnectHttpsParams *params = threadParam; pthread_detach(params->thread); // this thread will never join back with it's progenitor int fd=0; char hostnameProto[256]; BIO *sbio; SSL_CTX *ctx; SSL *ssl; openSslInit(); ctx = SSL_CTX_new(SSLv23_client_method()); fd_set readfds; fd_set writefds; int err; struct timeval tv; /* TODO checking certificates char *certFile = NULL; char *certPath = NULL; if (certFile || certPath) { SSL_CTX_load_verify_locations(ctx,certFile,certPath); #if (OPENSSL_VERSION_NUMBER < 0x0090600fL) SSL_CTX_set_verify_depth(ctx,1); #endif } // verify paths and mode. */ sbio = BIO_new_ssl_connect(ctx); BIO_get_ssl(sbio, &ssl); if(!ssl) { xerr("Can't locate SSL pointer"); goto cleanup; } /* Don't want any retries since we are non-blocking bio now */ //SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY); safef(hostnameProto,sizeof(hostnameProto),"%s:%d",params->hostName,params->port); BIO_set_conn_hostname(sbio, hostnameProto); BIO_set_nbio(sbio, 1); /* non-blocking mode */ while (1) { if (BIO_do_connect(sbio) == 1) { break; /* Connected */ } if (! BIO_should_retry(sbio)) { xerr("BIO_do_connect() failed"); char s[256]; safef(s, sizeof s, "SSL error: %s", ERR_reason_error_string(ERR_get_error())); xerr(s); goto cleanup; } fd = BIO_get_fd(sbio, NULL); if (fd == -1) { xerr("unable to get BIO descriptor"); goto cleanup; } FD_ZERO(&readfds); FD_ZERO(&writefds); if (BIO_should_read(sbio)) { FD_SET(fd, &readfds); } else if (BIO_should_write(sbio)) { FD_SET(fd, &writefds); } else { /* BIO_should_io_special() */ FD_SET(fd, &readfds); FD_SET(fd, &writefds); } tv.tv_sec = (long) (DEFAULTCONNECTTIMEOUTMSEC/1000); // timeout default 10 seconds tv.tv_usec = (long) (((DEFAULTCONNECTTIMEOUTMSEC/1000)-tv.tv_sec)*1000000); err = select(fd + 1, &readfds, &writefds, NULL, &tv); if (err < 0) { xerr("select() error"); goto cleanup; } if (err == 0) { char s[256]; safef(s, sizeof s, "connection timeout to %s", params->hostName); xerr(s); goto cleanup; } } /* TODO checking certificates if (certFile || certPath) if (!check_cert(ssl, host)) return -1; */ /* we need to wait on both the user's socket and the BIO SSL socket * to see if we need to ferry data from one to the other */ char sbuf[32768]; // socket buffer sv[1] to user char bbuf[32768]; // bio buffer int srd = 0; int swt = 0; int brd = 0; int bwt = 0; while (1) { // Do NOT move this outside the while loop. /* Get underlying file descriptor, needed for select call */ fd = BIO_get_fd(sbio, NULL); if (fd == -1) { xerr("BIO doesn't seem to be initialized in https, unable to get descriptor."); goto cleanup; } FD_ZERO(&readfds); FD_ZERO(&writefds); if (brd == 0) FD_SET(fd, &readfds); if (swt < srd) FD_SET(fd, &writefds); if (srd == 0) FD_SET(params->sv[1], &readfds); tv.tv_sec = (long) (DEFAULTCONNECTTIMEOUTMSEC/1000); // timeout default 10 seconds tv.tv_usec = (long) (((DEFAULTCONNECTTIMEOUTMSEC/1000)-tv.tv_sec)*1000000); err = select(max(fd,params->sv[1]) + 1, &readfds, &writefds, NULL, &tv); /* Evaluate select() return code */ if (err < 0) { xerr("error during select()"); goto cleanup; } else if (err == 0) { /* Timed out - just quit */ xerr("https timeout expired"); goto cleanup; } else { if (FD_ISSET(params->sv[1], &readfds)) { swt = 0; srd = read(params->sv[1], sbuf, 32768); if (srd == -1) { if (errno != 104) // udcCache often closes causing "Connection reset by peer" xerrno("error reading https socket"); goto cleanup; } if (srd == 0) break; // user closed socket, we are done } if (FD_ISSET(fd, &writefds)) { int swtx = BIO_write(sbio, sbuf+swt, srd-swt); if (swtx <= 0) { if (!BIO_should_write(sbio)) { ERR_print_errors_fp(stderr); xerr("Error writing SSL connection"); goto cleanup; } } else { swt += swtx; if (swt >= srd) { swt = 0; srd = 0; } } } if (FD_ISSET(fd, &readfds)) { bwt = 0; brd = BIO_read(sbio, bbuf, 32768); if (brd <= 0) { if (BIO_should_read(sbio)) { brd = 0; continue; } else { if (brd == 0) break; ERR_print_errors_fp(stderr); xerr("Error reading SSL connection"); goto cleanup; } } // write the https data received immediately back on socket to user, and it's ok if it blocks. while(bwt < brd) { int bwtx = write(params->sv[1], bbuf+bwt, brd-bwt); if (bwtx == -1) { if ((errno != 104) // udcCache often closes causing "Connection reset by peer" && (errno != 32)) // udcCache often closes causing "Broken pipe" xerrno("error writing https data back to user socket"); goto cleanup; } bwt += bwtx; } brd = 0; bwt = 0; } } } cleanup: BIO_free_all(sbio); close(params->sv[1]); /* we are done with it */ return NULL; }
int create_public_key_digest(RSA *private_key_rsa, PyObject **py_public_key_digest, int *public_key_digest_len) { unsigned int err; unsigned char *public_key_der = NULL; size_t der_len; unsigned char *key_digest; size_t key_digest_size; PyObject *py_digest = NULL; int r; EVP_PKEY *public_key = NULL; RSA *public_key_rsa = NULL; assert(private_key_rsa); assert(py_public_key_digest); public_key = EVP_PKEY_new(); JUMP_IF_NULL(public_key, openssl_error); public_key_rsa = RSAPublicKey_dup(private_key_rsa); JUMP_IF_NULL(public_key_rsa, openssl_error); r = EVP_PKEY_set1_RSA(public_key, public_key_rsa); RSA_free(public_key_rsa); public_key_rsa = NULL; JUMP_IF_NEG(r, openssl_error); r = i2d_PUBKEY(public_key, &public_key_der); EVP_PKEY_free(public_key); public_key = NULL; if (r < 0) { free(public_key_der); goto openssl_error; } der_len = r; r = create_key_digest(public_key_der, der_len, &key_digest, &key_digest_size); free(public_key_der); public_key_der = NULL; JUMP_IF_NEG(r, error); py_digest = PyBytes_FromStringAndSize((char *) key_digest, key_digest_size); JUMP_IF_NULL(py_digest, error); *py_public_key_digest = py_digest; if (public_key_digest_len) *public_key_digest_len = key_digest_size; return 0; openssl_error: err = ERR_get_error(); PyErr_Format(g_PyExc_CCNKeyError, "Unable to generate digest from the key:" " %s", ERR_reason_error_string(err)); error: if (public_key_rsa) RSA_free(public_key_rsa); if (public_key) EVP_PKEY_free(public_key); if (public_key_der) free(public_key_der); return -1; }
int main(int argc, char *argv[]) { PKCS11_CTX *ctx; PKCS11_SLOT *slots, *slot; unsigned char random[10]; int rc = 0, i, len; unsigned int nslots; if (argc != 2) { fprintf(stderr, "usage: getrandom /usr/lib/opensc-pkcs11.so\n"); return 1; } /* new context */ ctx = PKCS11_CTX_new(); /* load pkcs #11 module */ rc = PKCS11_CTX_load(ctx, argv[1]); if (rc) { fprintf(stderr, "loading pkcs11 engine failed: %s\n", ERR_reason_error_string(ERR_get_error())); rc = 1; goto nolib; } /* get information on all slots */ rc = PKCS11_enumerate_slots(ctx, &slots, &nslots); if (rc < 0) { fprintf(stderr, "no slots available\n"); rc = 2; goto noslots; } printf("%d slots available\n", nslots); /* get first slot with a token */ slot = PKCS11_find_token(ctx, slots, nslots); if (!slot || !slot->token) { fprintf(stderr, "no token available\n"); rc = 3; goto notoken; } printf("Slot manufacturer......: %s\n", slot->manufacturer); printf("Slot description.......: %s\n", slot->description); printf("Slot token label.......: %s\n", slot->token->label); printf("Slot token manufacturer: %s\n", slot->token->manufacturer); printf("Slot token model.......: %s\n", slot->token->model); printf("Slot token serialnr....: %s\n", slot->token->serialnr); /* get 10 random bytes */ len = sizeof(random); rc = PKCS11_generate_random(slot, random, len); if (rc < 0) { fprintf(stderr, "generate_random failed: %s\n", ERR_reason_error_string(ERR_get_error())); rc = 4; goto norandom; } printf("\nRandom numbers generated by the token: "); for (i = 0; i < len; i++) printf("%02X ", random[i]); printf("\n"); rc = 0; norandom: notoken: PKCS11_release_all_slots(ctx, slots, nslots); noslots: PKCS11_CTX_unload(ctx); nolib: PKCS11_CTX_free(ctx); return rc; }
const char *CryptoLastErrorString() { const char *errmsg = ERR_reason_error_string(ERR_get_error()); return (errmsg != NULL) ? errmsg : "no error message"; }
static gssize log_transport_tls_write_method(LogTransport *s, const gpointer buf, gsize buflen) { LogTransportTLS *self = (LogTransportTLS *) s; gint ssl_error; gint rc; /* assume that we need to poll our output for writing unless * SSL_ERROR_WANT_READ is specified by libssl */ self->super.cond = G_IO_OUT; rc = SSL_write(self->tls_session->ssl, buf, buflen); if (rc < 0) { ssl_error = SSL_get_error(self->tls_session->ssl, rc); switch (ssl_error) { case SSL_ERROR_WANT_READ: /* although we are writing this fd, libssl wants to read. This * happens during renegotiation for example */ self->super.cond = G_IO_IN; errno = EAGAIN; break; case SSL_ERROR_WANT_WRITE: errno = EAGAIN; break; case SSL_ERROR_SYSCALL: /* errno is set accordingly */ break; default: goto tls_error; } } return rc; tls_error: ssl_error = ERR_get_error(); msg_error("SSL error while writing stream", evt_tag_printf("tls_error", "%s:%s:%s", ERR_lib_error_string(ssl_error), ERR_func_error_string(ssl_error), ERR_reason_error_string(ssl_error)), NULL); ERR_clear_error(); errno = EPIPE; return -1; }
// // write() // ssize_t SSLOutputStream::write(const unsigned char* b, size_t size, size_t off, size_t len) throw(IOException, IllegalBlockingModeException, IndexOutOfBoundsException) { // Comprueba los limites del array if (off + len > size) { throw IndexOutOfBoundsException("Index out of bounds"); } // Delega la operacion en el canal, si este existe if (_channel) { SocketChannel* ch = dynamic_cast<SocketChannel*>(_channel); return ch->write(b+off, len); } //SSL_set_connect_state(_ssl); //SSL_set_mode(_ssl,SSL_MODE_ENABLE_PARTIAL_WRITE); //ssize_t n = ::SSL_write(_ssl, (void*) (b + off), len); // Temporal workaround: 2 SSL_write per operation in order to force flush ssize_t n = ::SSL_write(_ssl, (void*) (b + off), len-1); n += ::SSL_write(_ssl, (void*) (b + off + len - 1), 1); if (n <= 0) { int ssl_error = SSL_get_error(_ssl, n); int error = ERR_get_error(); OSTRINGSTREAM reason; reason << "SSLOutputStream::write error: "; switch(ssl_error) { case SSL_ERROR_NONE: reason << "SSL_ERROR_NONE reason: " << ERR_reason_error_string(error) << ends; throw IOException(reason.str().c_str()); break; case SSL_ERROR_WANT_READ: reason << "SSL_ERROR_WANT_READ reason: " << ERR_reason_error_string(error) << ends; throw IOException(reason.str().c_str()); break; case SSL_ERROR_WANT_WRITE: reason << "SSL_ERROR_WANT_WRITE reason: " << ERR_reason_error_string(error) << ends; throw IOException(reason.str().c_str()); break; case SSL_ERROR_ZERO_RETURN: reason << "SSL_ERROR_ZERO_RETURN reason: " << ERR_reason_error_string(error) << ends; throw IOException(reason.str().c_str()); break; case SSL_ERROR_WANT_CONNECT: reason << "SSL_ERROR_WANT_CONNECT reason: " << ERR_reason_error_string(error) << ends; throw IOException(reason.str().c_str()); break; case SSL_ERROR_WANT_X509_LOOKUP: reason << "SSL_ERROR_WANT_X509_LOOKUP reason: " << ERR_reason_error_string(error) << ends; throw IOException(reason.str().c_str()); break; case SSL_ERROR_SYSCALL: reason << "SSL_ERROR_SYSCALL reason: " << ERR_reason_error_string(error) << ends; throw IOException(reason.str().c_str()); break; case SSL_ERROR_SSL: reason << "SSL_ERROR_SSL reason: " << ERR_reason_error_string(error) << ends; throw IOException(reason.str().c_str()); break; default: reason << "unknown: " << ends; throw IOException(reason.str().c_str()); } } //BIO_flush(_sbio); return n; }
void digidoc::Digest::reset() { int result = 1; switch(d->method) { case NID_sha1: result = SHA1_Init(&d->sha1); break; case NID_sha224: result = SHA224_Init(&d->sha256); break; case NID_sha256: result = SHA256_Init(&d->sha256); break; case NID_sha384: result = SHA384_Init(&d->sha512); break; case NID_sha512: result = SHA512_Init(&d->sha512); break; default: break; } d->digest.clear(); if(result != 1) THROW_IOEXCEPTION("Failed to initialize %s digest calculator: %s", getName().c_str(), ERR_reason_error_string(ERR_get_error())); }
const char* rocksock_ssl_strerror(rocksock *sock, int error) { return ERR_reason_error_string(error); }
bool SSLSocket::waitWant(int ret, uint64_t millis) { #ifdef HEADER_OPENSSLV_H int err = SSL_get_error(ssl, ret); switch(err) { case SSL_ERROR_WANT_READ: return wait(millis, Socket::WAIT_READ) == WAIT_READ; case SSL_ERROR_WANT_WRITE: return wait(millis, Socket::WAIT_WRITE) == WAIT_WRITE; #else int err = ssl->last_error; switch(err) { case GNUTLS_E_INTERRUPTED: case GNUTLS_E_AGAIN: { int waitFor = wait(millis, Socket::WAIT_READ | Socket::WAIT_WRITE); return (waitFor & Socket::WAIT_READ) || (waitFor & Socket::WAIT_WRITE); } #endif // Check if this is a fatal error... default: checkSSL(ret); } dcdebug("SSL: Unexpected fallthrough"); // There was no error? return true; } int SSLSocket::read(void* aBuffer, int aBufLen) throw(SocketException) { if(!ssl) { return -1; } int len = checkSSL(SSL_read(ssl, aBuffer, aBufLen)); if(len > 0) { stats.totalDown += len; //dcdebug("In(s): %.*s\n", len, (char*)aBuffer); } return len; } int SSLSocket::write(const void* aBuffer, int aLen) throw(SocketException) { if(!ssl) { return -1; } int ret = checkSSL(SSL_write(ssl, aBuffer, aLen)); if(ret > 0) { stats.totalUp += ret; //dcdebug("Out(s): %.*s\n", ret, (char*)aBuffer); } return ret; } int SSLSocket::checkSSL(int ret) throw(SocketException) { if(!ssl) { return -1; } if(ret <= 0) { int err = SSL_get_error(ssl, ret); switch(err) { case SSL_ERROR_NONE: // Fallthrough - YaSSL doesn't for example return an openssl compatible error on recv fail case SSL_ERROR_WANT_READ: // Fallthrough case SSL_ERROR_WANT_WRITE: return -1; case SSL_ERROR_ZERO_RETURN: #ifndef HEADER_OPENSSLV_H if(ssl->last_error == GNUTLS_E_INTERRUPTED || ssl->last_error == GNUTLS_E_AGAIN) return -1; #endif throw SocketException(STRING(CONNECTION_CLOSED)); default: { ssl.reset(); // @todo replace 80 with MAX_ERROR_SZ or whatever's appropriate for yaSSL in some nice way... char errbuf[80]; /* TODO: better message for SSL_ERROR_SYSCALL * If the error queue is empty (i.e. ERR_get_error() returns 0), ret can be used to find out more about the error: * If ret == 0, an EOF was observed that violates the protocol. If ret == -1, the underlying BIO reported an I/O error * (for socket I/O on Unix systems, consult errno for details). */ int error = ERR_get_error(); sprintf(errbuf, "%s %d: %s", CSTRING(SSL_ERROR), err, (error == 0) ? CSTRING(CONNECTION_CLOSED) : ERR_reason_error_string(error)); throw SSLSocketException(errbuf); } } } return ret; } int SSLSocket::wait(uint64_t millis, int waitFor) throw(SocketException) { #ifdef HEADER_OPENSSLV_H if(ssl && (waitFor & Socket::WAIT_READ)) { /** @todo Take writing into account as well if reading is possible? */ char c; if(SSL_peek(ssl, &c, 1) > 0) return WAIT_READ; } #endif return Socket::wait(millis, waitFor); } bool SSLSocket::isTrusted() throw() { if(!ssl) { return false; } #ifdef HEADER_OPENSSLV_H if(SSL_get_verify_result(ssl) != X509_V_OK) { return false; } #else if(gnutls_certificate_verify_peers(((SSL*)ssl)->gnutls_state) != 0) { return false; } #endif X509* cert = SSL_get_peer_certificate(ssl); if(!cert) { return false; } X509_free(cert); return true; } std::string SSLSocket::getCipherName() throw() { if(!ssl) return Util::emptyString; return SSL_get_cipher_name(ssl); } std::string SSLSocket::getDigest() const throw() { #ifdef HEADER_OPENSSLV_H if(!ssl) return Util::emptyString; X509* x509 = SSL_get_peer_certificate(ssl); if(!x509) return Util::emptyString; return ssl::X509_digest(x509, EVP_sha1()); #else return Util::emptyString; #endif } void SSLSocket::shutdown() throw() { if(ssl) SSL_shutdown(ssl); } void SSLSocket::close() throw() { if(ssl) { ssl.reset(); } Socket::shutdown(); Socket::close(); } } // namespace dcpp
TLSSession * tls_context_setup_session(TLSContext *self) { SSL *ssl; TLSSession *session; gint ssl_error; long ssl_options; if (!self->ssl_ctx) { gint verify_mode = 0; gint verify_flags = X509_V_FLAG_POLICY_CHECK; if (self->mode == TM_CLIENT) self->ssl_ctx = SSL_CTX_new(SSLv23_client_method()); else self->ssl_ctx = SSL_CTX_new(SSLv23_server_method()); if (!self->ssl_ctx) goto error; if (file_exists(self->key_file) && !SSL_CTX_use_PrivateKey_file(self->ssl_ctx, self->key_file, SSL_FILETYPE_PEM)) goto error; if (file_exists(self->cert_file) && !SSL_CTX_use_certificate_chain_file(self->ssl_ctx, self->cert_file)) goto error; if (self->key_file && self->cert_file && !SSL_CTX_check_private_key(self->ssl_ctx)) goto error; if (file_exists(self->ca_dir) && !SSL_CTX_load_verify_locations(self->ssl_ctx, NULL, self->ca_dir)) goto error; if (file_exists(self->crl_dir) && !SSL_CTX_load_verify_locations(self->ssl_ctx, NULL, self->crl_dir)) goto error; if (self->crl_dir) verify_flags |= X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL; X509_VERIFY_PARAM_set_flags(self->ssl_ctx->param, verify_flags); switch (self->verify_mode) { case TVM_NONE: verify_mode = SSL_VERIFY_NONE; break; case TVM_OPTIONAL | TVM_UNTRUSTED: verify_mode = SSL_VERIFY_NONE; break; case TVM_OPTIONAL | TVM_TRUSTED: verify_mode = SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE; break; case TVM_REQUIRED | TVM_UNTRUSTED: verify_mode = SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE | SSL_VERIFY_FAIL_IF_NO_PEER_CERT; break; case TVM_REQUIRED | TVM_TRUSTED: verify_mode = SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE | SSL_VERIFY_FAIL_IF_NO_PEER_CERT; break; default: g_assert_not_reached(); } SSL_CTX_set_verify(self->ssl_ctx, verify_mode, tls_session_verify_callback); if (self->ssl_options != TSO_NONE) { ssl_options=0; if(self->ssl_options & TSO_NOSSLv2) ssl_options |= SSL_OP_NO_SSLv2; if(self->ssl_options & TSO_NOSSLv3) ssl_options |= SSL_OP_NO_SSLv3; if(self->ssl_options & TSO_NOTLSv1) ssl_options |= SSL_OP_NO_TLSv1; #ifdef SSL_OP_NO_TLSv1_2 if(self->ssl_options & TSO_NOTLSv11) ssl_options |= SSL_OP_NO_TLSv1_1; if(self->ssl_options & TSO_NOTLSv12) ssl_options |= SSL_OP_NO_TLSv1_2; #endif SSL_CTX_set_options(self->ssl_ctx, ssl_options); } else msg_debug("empty ssl options",NULL); if (self->cipher_suite) { if (!SSL_CTX_set_cipher_list(self->ssl_ctx, self->cipher_suite)) goto error; } } ssl = SSL_new(self->ssl_ctx); if (self->mode == TM_CLIENT) SSL_set_connect_state(ssl); else SSL_set_accept_state(ssl); session = tls_session_new(ssl, self); SSL_set_app_data(ssl, session); return session; error: ssl_error = ERR_get_error(); msg_error("Error setting up TLS session context", evt_tag_printf("tls_error", "%s:%s:%s", ERR_lib_error_string(ssl_error), ERR_func_error_string(ssl_error), ERR_reason_error_string(ssl_error)), NULL); ERR_clear_error(); if (self->ssl_ctx) { SSL_CTX_free(self->ssl_ctx); self->ssl_ctx = NULL; } return NULL; }
void ssl_error(char *message) { int err_code = ERR_get_error(); printf("%s: Function: %s : %s\n",message,ERR_func_error_string(err_code),ERR_reason_error_string(err_code)); }
/** * oh_ssl_connect * @hostname: Name of target host. Format: * "hostname:port" or "IPaddress:port" * @ctx: pointer to SSL_CTX as returned by oh_ssl_ctx_init() * @timeout: maximum number of seconds to wait for a connection to * hostname, or zero to wait forever * * Create and open a new ssl conection to the specified host. * * Return value: pointer to BIO, or NULL for failure **/ BIO *oh_ssl_connect(char *hostname, SSL_CTX *ctx, long timeout) { BIO *bio; SSL *ssl; fd_set readfds; fd_set writefds; struct timeval tv; int fd; int err; if (hostname == NULL) { err("NULL hostname in oh_ssl_connect()"); return(NULL); } if (ctx == NULL) { err("NULL ctx in oh_ssl_connect()"); return(NULL); } if (timeout < 0) { err("inappropriate timeout in oh_ssl_connect()"); return(NULL); } /* Start with a new SSL BIO */ bio = BIO_new_ssl_connect(ctx); if (bio == NULL) { err("BIO_new_ssl_connect() failed"); return(NULL); } /* Set up connection parameters for this BIO */ BIO_set_conn_hostname(bio, hostname); BIO_set_nbio(bio, 1); /* Set underlying socket to * non-blocking mode */ /* Set up SSL session parameters */ BIO_get_ssl(bio, &ssl); if (ssl == NULL) { err("BIO_get_ssl() failed"); BIO_free_all(bio); return(NULL); } SSL_set_mode(ssl, SSL_MODE_ENABLE_PARTIAL_WRITE); /* Ready to open the connection. Note that this call will probably * take a while, so we need to retry it, watching for a timeout. */ while (1) { if (BIO_do_connect(bio) == 1) { break; /* Connection established */ } if (! BIO_should_retry(bio)) { /* Hard error? */ err("BIO_do_connect() failed"); err("SSL error: %s", ERR_reason_error_string(ERR_get_error())); BIO_free_all(bio); return(NULL); } /* Wait until there's a change in the socket's status or until * the timeout period. * * Get underlying file descriptor, needed for the select call. */ fd = BIO_get_fd(bio, NULL); if (fd == -1) { err("BIO isn't initialized in oh_ssl_connect()"); BIO_free_all(bio); return(NULL); } FD_ZERO(&readfds); FD_ZERO(&writefds); if (BIO_should_read(bio)) { FD_SET(fd, &readfds); } else if (BIO_should_write(bio)) { FD_SET(fd, &writefds); } else { /* This is BIO_should_io_special(). * Not sure what "special" needs to * wait for, but both read and write * seems to work without unnecessary * retries. */ FD_SET(fd, &readfds); FD_SET(fd, &writefds); } if (timeout) { tv.tv_sec = timeout; tv.tv_usec = 0; err = select(fd + 1, &readfds, &writefds, NULL, &tv); } else { /* No timeout */ err = select(fd + 1, &readfds, &writefds, NULL, NULL); } /* Evaluate select() return code */ if (err < 0) { err("error during select()"); BIO_free_all(bio); return(NULL); } if (err == 0) { err("connection timeout to %s", hostname); BIO_free_all(bio); return(NULL); /* Timeout */ } } /* TODO: Do I need to set the client or server mode here? I don't * think so. */ return(bio); }
void KeepKeyPromises(const char *public_key_file, const char *private_key_file) { unsigned long err; #ifdef OPENSSL_NO_DEPRECATED RSA *pair = RSA_new(); BIGNUM *rsa_bignum = BN_new(); #else RSA *pair; #endif FILE *fp; struct stat statbuf; int fd; static char *passphrase = "Cfengine passphrase"; const EVP_CIPHER *cipher; char vbuff[CF_BUFSIZE]; cipher = EVP_des_ede3_cbc(); if (stat(public_key_file, &statbuf) != -1) { printf("A key file already exists at %s\n", public_key_file); return; } if (stat(private_key_file, &statbuf) != -1) { printf("A key file already exists at %s\n", private_key_file); return; } printf("Making a key pair for cfengine, please wait, this could take a minute...\n"); #ifdef OPENSSL_NO_DEPRECATED BN_set_word(rsa_bignum, 35); if (!RSA_generate_key_ex(pair, 2048, rsa_bignum, NULL)) #else pair = RSA_generate_key(2048, 35, NULL, NULL); if (pair == NULL) #endif { err = ERR_get_error(); Log(LOG_LEVEL_ERR, "Unable to generate key '%s'", ERR_reason_error_string(err)); return; } fd = open(private_key_file, O_WRONLY | O_CREAT | O_TRUNC, 0600); if (fd < 0) { Log(LOG_LEVEL_ERR, "Open '%s' failed. (open: %s)", private_key_file, GetErrorStr()); return; } if ((fp = fdopen(fd, "w")) == NULL) { Log(LOG_LEVEL_ERR, "Couldn't open private key '%s'. (fdopen: %s)", private_key_file, GetErrorStr()); close(fd); return; } Log(LOG_LEVEL_VERBOSE, "Writing private key to '%s'", private_key_file); if (!PEM_write_RSAPrivateKey(fp, pair, cipher, passphrase, strlen(passphrase), NULL, NULL)) { err = ERR_get_error(); Log(LOG_LEVEL_ERR, "Couldn't write private key. (PEM_write_RSAPrivateKey: %s)", ERR_reason_error_string(err)); return; } fclose(fp); fd = open(public_key_file, O_WRONLY | O_CREAT | O_TRUNC, 0600); if (fd < 0) { Log(LOG_LEVEL_ERR, "Unable to open public key '%s'. (open: %s)", public_key_file, GetErrorStr()); return; } if ((fp = fdopen(fd, "w")) == NULL) { Log(LOG_LEVEL_ERR, "Open '%s' failed. (fdopen: %s)", public_key_file, GetErrorStr()); close(fd); return; } Log(LOG_LEVEL_VERBOSE, "Writing public key to file '%s'", public_key_file); if (!PEM_write_RSAPublicKey(fp, pair)) { err = ERR_get_error(); Log(LOG_LEVEL_ERR, "Unable to write public key. (PEM_write_RSAPublicKey: %s)", ERR_reason_error_string(err)); return; } fclose(fp); snprintf(vbuff, CF_BUFSIZE, "%s/randseed", CFWORKDIR); RAND_write_file(vbuff); chmod(vbuff, 0644); }
bool MCCrypt_rsa_op(bool p_encrypt, RSA_KEYTYPE p_key_type, const char *p_message_in, uint32_t p_message_in_length, const char *p_key, uint32_t p_key_length, const char *p_passphrase, char *&r_message_out, uint32_t &r_message_out_length, char *&r_result, uint32_t &r_error) { bool t_success = true; EVP_PKEY *t_key = NULL; RSA *t_rsa = NULL; int32_t t_rsa_size; uint8_t *t_output_buffer = NULL; int32_t t_output_length; if (!InitSSLCrypt()) { t_success = false; MCCStringClone("error: ssl library initialization failed", r_result); } if (t_success) { if (!load_pem_key(p_key, p_key_length, p_key_type, p_passphrase, t_key)) { t_success = false; MCCStringClone("error: invalid key", r_result); } } if (t_success) { t_rsa = EVP_PKEY_get1_RSA(t_key); if (t_rsa == NULL) { t_success = false; MCCStringClone("error: not an RSA key", r_result); } } if (t_success) { t_rsa_size = RSA_size(t_rsa); if (!MCMemoryAllocate(t_rsa_size, t_output_buffer)) { t_success = false; r_error = EE_NO_MEMORY; } } int (*t_rsa_func)(int, const unsigned char*, unsigned char*, RSA*, int) = NULL; if (t_success) { if (p_encrypt) { if (p_key_type == RSAKEY_PRIVKEY) t_rsa_func = RSA_private_encrypt; else t_rsa_func = RSA_public_encrypt; if (p_message_in_length >= unsigned(t_rsa_size - 11)) { t_success = false; MCCStringClone("error: message too large", r_result); } } else { if (p_key_type == RSAKEY_PRIVKEY) t_rsa_func = RSA_private_decrypt; else t_rsa_func = RSA_public_decrypt; if (p_message_in_length != t_rsa_size) { t_success = false; MCCStringClone("error: invalid message size", r_result); } } } if (t_success) { t_output_length = t_rsa_func(p_message_in_length, (const uint8_t*)p_message_in, t_output_buffer, t_rsa, RSA_PKCS1_PADDING); if (t_output_length < 0) { t_success = false; MCCStringClone("error: SSL operation failed", r_result); } } if (t_rsa != NULL) RSA_free(t_rsa); if (t_key != NULL) EVP_PKEY_free(t_key); if (t_success) { r_message_out = (char*)t_output_buffer; r_message_out_length = t_output_length; } else { uint32_t t_err; t_err = ERR_get_error(); if (t_err) { const char *t_ssl_error = ERR_reason_error_string(t_err); MCCStringAppendFormat(r_result, " (SSL error: %s)", t_ssl_error); } MCMemoryDeallocate(t_output_buffer); } return t_success; }
void ERR_error_string_n(uint32_t packed_error, char *buf, size_t len) { char lib_buf[64], func_buf[64], reason_buf[64]; const char *lib_str, *func_str, *reason_str; unsigned lib, func, reason; if (len == 0) { return; } lib = ERR_GET_LIB(packed_error); func = ERR_GET_FUNC(packed_error); reason = ERR_GET_REASON(packed_error); lib_str = ERR_lib_error_string(packed_error); func_str = ERR_func_error_string(packed_error); reason_str = ERR_reason_error_string(packed_error); if (lib_str == NULL) { BIO_snprintf(lib_buf, sizeof(lib_buf), "lib(%u)", lib); lib_str = lib_buf; } if (func_str == NULL) { BIO_snprintf(func_buf, sizeof(func_buf), "func(%u)", func); func_str = func_buf; } if (reason_str == NULL) { BIO_snprintf(reason_buf, sizeof(reason_buf), "reason(%u)", reason); reason_str = reason_buf; } BIO_snprintf(buf, len, "error:%08" PRIx32 ":%s:%s:%s", packed_error, lib_str, func_str, reason_str); if (strlen(buf) == len - 1) { /* output may be truncated; make sure we always have 5 colon-separated * fields, i.e. 4 colons. */ static const unsigned num_colons = 4; unsigned i; char *s = buf; if (len <= num_colons) { /* In this situation it's not possible to ensure that the correct number * of colons are included in the output. */ return; } for (i = 0; i < num_colons; i++) { char *colon = strchr(s, ':'); char *last_pos = &buf[len - 1] - num_colons + i; if (colon == NULL || colon > last_pos) { /* set colon |i| at last possible position (buf[len-1] is the * terminating 0). If we're setting this colon, then all whole of the * rest of the string must be colons in order to have the correct * number. */ memset(last_pos, ':', num_colons - i); break; } s = colon + 1; } } }
static int importKeychainToX509_STORE(X509_STORE* verifyStore, char* err, size_t err_len) { int status = 1; CFArrayRef result = NULL; OSStatus osStatus; // This copies all the certificates trusted by the system (regardless of what // keychain they're // attached to) into a CFArray. if ((osStatus = SecTrustCopyAnchorCertificates(&result)) != 0) { CFStringRef statusString = SecCopyErrorMessageString(osStatus, NULL); snprintf(err, err_len, "Error enumerating certificates: %s", CFStringGetCStringPtr(statusString, kCFStringEncodingASCII)); CFRelease(statusString); status = 0; goto CLEANUP; } CFDataRef rawData = NULL; X509* x509Cert = NULL; for (CFIndex i = 0; i < CFArrayGetCount(result); i++) { SecCertificateRef cert = (SecCertificateRef)CFArrayGetValueAtIndex(result, i); rawData = SecCertificateCopyData(cert); if (!rawData) { snprintf(err, err_len, "Error enumerating certificates"); status = 0; goto CLEANUP; } const uint8_t* rawDataPtr = CFDataGetBytePtr(rawData); // Parse an openssl X509 object from each returned certificate x509Cert = d2i_X509(NULL, &rawDataPtr, CFDataGetLength(rawData)); if (!x509Cert) { snprintf(err, err_len, "Error parsing X509 certificate from system keychain: %s", ERR_reason_error_string(ERR_peek_last_error())); status = 0; goto CLEANUP; } // Add the parsed X509 object to the X509_STORE verification store if (X509_STORE_add_cert(verifyStore, x509Cert) != 1) { int check_error_status = checkX509_STORE_error(err, err_len); if (!check_error_status) { status = check_error_status; goto CLEANUP; } } CFRelease(rawData); rawData = NULL; X509_free(x509Cert); x509Cert = NULL; } CLEANUP: if (result != NULL) { CFRelease(result); } if (rawData != NULL) { CFRelease(rawData); } if (x509Cert != NULL) { X509_free(x509Cert); } return status; }
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"); }
int SSLSocket::checkSSL(int ret) { if(!ssl) { return -1; } if(ret <= 0) { int err = SSL_get_error(ssl, ret); switch(err) { case SSL_ERROR_NONE: // Fallthrough - YaSSL doesn't for example return an openssl compatible error on recv fail case SSL_ERROR_WANT_READ: // Fallthrough case SSL_ERROR_WANT_WRITE: return -1; case SSL_ERROR_ZERO_RETURN: throw SocketException("Connection closed"); default: { ssl.reset(); // @todo replace 80 with MAX_ERROR_SZ or whatever's appropriate for yaSSL in some nice way... int error = ERR_get_error(); throw SSLSocketException(str(boost::format("SSL Error %1%: %2%") % err % (error == 0 ? CSTRING(CONNECTION_CLOSED) : ERR_reason_error_string(error)))); } } } 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; }
char * wd_ssl_strerror(void) { return ERR_peek_error() != 0 ? (char *) ERR_reason_error_string(ERR_get_error()) : strerror(errno); }
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; }
static void KeepKeyPromises(void) { unsigned long err; RSA *pair; FILE *fp; struct stat statbuf; int fd; static char *passphrase = "Cfengine passphrase"; const EVP_CIPHER *cipher; char vbuff[CF_BUFSIZE]; NewScope("common"); cipher = EVP_des_ede3_cbc(); if (cfstat(CFPUBKEYFILE, &statbuf) != -1) { CfOut(cf_cmdout, "", "A key file already exists at %s\n", CFPUBKEYFILE); return; } if (cfstat(CFPRIVKEYFILE, &statbuf) != -1) { CfOut(cf_cmdout, "", "A key file already exists at %s\n", CFPRIVKEYFILE); return; } printf("Making a key pair for cfengine, please wait, this could take a minute...\n"); pair = RSA_generate_key(2048, 35, NULL, NULL); if (pair == NULL) { err = ERR_get_error(); CfOut(cf_error, "", "Unable to generate key: %s\n", ERR_reason_error_string(err)); return; } if (DEBUG) { RSA_print_fp(stdout, pair, 0); } fd = open(CFPRIVKEYFILE, O_WRONLY | O_CREAT | O_TRUNC, 0600); if (fd < 0) { CfOut(cf_error, "open", "Open %s failed: %s.", CFPRIVKEYFILE, strerror(errno)); return; } if ((fp = fdopen(fd, "w")) == NULL) { CfOut(cf_error, "fdopen", "Couldn't open private key %s.", CFPRIVKEYFILE); close(fd); return; } CfOut(cf_verbose, "", "Writing private key to %s\n", CFPRIVKEYFILE); if (!PEM_write_RSAPrivateKey(fp, pair, cipher, passphrase, strlen(passphrase), NULL, NULL)) { err = ERR_get_error(); CfOut(cf_error, "", "Couldn't write private key: %s\n", ERR_reason_error_string(err)); return; } fclose(fp); fd = open(CFPUBKEYFILE, O_WRONLY | O_CREAT | O_TRUNC, 0600); if (fd < 0) { CfOut(cf_error, "open", "Unable to open public key %s.", CFPUBKEYFILE); return; } if ((fp = fdopen(fd, "w")) == NULL) { CfOut(cf_error, "fdopen", "Open %s failed.", CFPUBKEYFILE); close(fd); return; } CfOut(cf_verbose, "", "Writing public key to %s\n", CFPUBKEYFILE); if (!PEM_write_RSAPublicKey(fp, pair)) { err = ERR_get_error(); CfOut(cf_error, "", "Unable to write public key: %s\n", ERR_reason_error_string(err)); return; } fclose(fp); snprintf(vbuff, CF_BUFSIZE, "%s/randseed", CFWORKDIR); RAND_write_file(vbuff); cf_chmod(vbuff, 0644); }
int main(int argc, char *argv[]) { PKCS11_CTX *ctx; PKCS11_SLOT *slots, *slot; PKCS11_CERT *certs; pid_t pid; int status = 0; PKCS11_KEY *authkey; PKCS11_CERT *authcert; EVP_PKEY *pubkey = NULL; unsigned char *random = NULL, *signature = NULL; char password[20]; int rc = 0, fd; unsigned int nslots, ncerts, siglen; if (argc < 2) { fprintf(stderr, "usage: auth /usr/lib/opensc-pkcs11.so [PIN]\n"); return 1; } ctx = PKCS11_CTX_new(); /* load pkcs #11 module */ rc = PKCS11_CTX_load(ctx, argv[1]); if (rc) { fprintf(stderr, "loading pkcs11 engine failed: %s\n", ERR_reason_error_string(ERR_get_error())); rc = 1; goto nolib; } /* get information on all slots */ rc = PKCS11_enumerate_slots(ctx, &slots, &nslots); if (rc < 0) { fprintf(stderr, "no slots available\n"); rc = 2; goto noslots; } /* get first slot with a token */ slot = PKCS11_find_token(ctx, slots, nslots); if (!slot || !slot->token) { fprintf(stderr, "no token available\n"); rc = 3; goto notoken; } printf("Slot manufacturer......: %s\n", slot->manufacturer); printf("Slot description.......: %s\n", slot->description); printf("Slot token label.......: %s\n", slot->token->label); printf("Slot token manufacturer: %s\n", slot->token->manufacturer); printf("Slot token model.......: %s\n", slot->token->model); printf("Slot token serialnr....: %s\n", slot->token->serialnr); if (!slot->token->loginRequired) goto loggedin; /* get password */ if (argc > 2) { strcpy(password, argv[2]); } else { exit(1); } loggedin: /* perform pkcs #11 login */ rc = PKCS11_login(slot, 0, password); memset(password, 0, strlen(password)); if (rc != 0) { fprintf(stderr, "PKCS11_login failed\n"); goto failed; } /* get all certs */ rc = PKCS11_enumerate_certs(slot->token, &certs, &ncerts); if (rc) { fprintf(stderr, "PKCS11_enumerate_certs failed\n"); goto failed; } if (ncerts <= 0) { fprintf(stderr, "no certificates found\n"); goto failed; } /* use the first cert */ authcert=&certs[0]; /* get random bytes */ random = malloc(RANDOM_SIZE); if (!random) goto failed; fd = open(RANDOM_SOURCE, O_RDONLY); if (fd < 0) { fprintf(stderr, "fatal: cannot open RANDOM_SOURCE: %s\n", strerror(errno)); goto failed; } rc = read(fd, random, RANDOM_SIZE); if (rc < 0) { fprintf(stderr, "fatal: read from random source failed: %s\n", strerror(errno)); close(fd); goto failed; } if (rc < RANDOM_SIZE) { fprintf(stderr, "fatal: read returned less than %d<%d bytes\n", rc, RANDOM_SIZE); close(fd); goto failed; } close(fd); authkey = PKCS11_find_key(authcert); if (!authkey) { fprintf(stderr, "no key matching certificate available\n"); goto failed; } /* ask for a sha1 hash of the random data, signed by the key */ siglen = MAX_SIGSIZE; signature = malloc(MAX_SIGSIZE); if (!signature) goto failed; /* Do the operation after a fork */ pid = fork(); if (pid == -1) exit(5); if (pid) { waitpid(pid, &status, 0); if (WIFEXITED(status)) return WEXITSTATUS(status); return 2; } /* do the operations in child */ rc = PKCS11_sign(NID_sha1, random, RANDOM_SIZE, signature, &siglen, authkey); if (rc != 1) { fprintf(stderr, "fatal: pkcs11_sign failed\n"); goto failed; } /* verify the signature */ pubkey = X509_get_pubkey(authcert->x509); if (pubkey == NULL) { fprintf(stderr, "could not extract public key\n"); goto failed; } /* now verify the result */ rc = RSA_verify(NID_sha1, random, RANDOM_SIZE, signature, siglen, pubkey->pkey.rsa); if (rc != 1) { fprintf(stderr, "fatal: RSA_verify failed\n"); goto failed; } if (pubkey != NULL) EVP_PKEY_free(pubkey); if (random != NULL) free(random); if (signature != NULL) free(signature); PKCS11_release_all_slots(ctx, slots, nslots); PKCS11_CTX_unload(ctx); PKCS11_CTX_free(ctx); CRYPTO_cleanup_all_ex_data(); ERR_free_strings(); printf("authentication successfull.\n"); return 0; failed: ERR_print_errors_fp(stderr); notoken: PKCS11_release_all_slots(ctx, slots, nslots); noslots: PKCS11_CTX_unload(ctx); nolib: PKCS11_CTX_free(ctx); printf("authentication failed.\n"); return 1; }
/** * Signs the digest provided using the selected certificate. If the certificate needs PIN, * the PIN is acquired by calling the callback function <code>getPin</code>. * * @param digest digest, which is being signed. * @param signature memory for the signature that is created. Struct parameter <code>length</code> * is set to the actual signature length. * @throws SignException throws exception if the signing operation failed. */ void digidoc::PKCS11Signer::sign(const Digest& digest, Signature& signature) throw(SignException) { DEBUG("sign(digest = {type=%s,digest=%p,length=%d}, signature={signature=%p,length=%d})", OBJ_nid2sn(digest.type), digest.digest, digest.length, signature.signature, signature.length); // Check that sign slot and certificate are selected. if(d->sign.certificate == NULL || d->sign.slot == NULL) { THROW_SIGNEXCEPTION("Signing slot or certificate are not selected."); } // Login if required. if(d->sign.slot->token->loginRequired) { int rv = 0; if(d->sign.slot->token->secureLogin) { showPinpad(); rv = PKCS11_login(d->sign.slot, 0, NULL); hidePinpad(); } else rv = PKCS11_login(d->sign.slot, 0, getPin(d->createPKCS11Cert(d->sign.slot, d->sign.certificate)).c_str()); switch(ERR_GET_REASON(ERR_get_error())) { case CKR_OK: break; case CKR_CANCEL: case CKR_FUNCTION_CANCELED: { SignException e( __FILE__, __LINE__, "PIN acquisition canceled."); e.setCode( Exception::PINCanceled ); throw e; break; } case CKR_PIN_INCORRECT: { SignException e( __FILE__, __LINE__, "PIN Incorrect" ); e.setCode( Exception::PINIncorrect ); throw e; break; } case CKR_PIN_LOCKED: { SignException e( __FILE__, __LINE__, "PIN Locked" ); e.setCode( Exception::PINLocked ); throw e; break; } default: std::ostringstream s; s << "Failed to login to token '" << d->sign.slot->token->label << "': " << ERR_reason_error_string(ERR_get_error()); SignException e( __FILE__, __LINE__, s.str() ); e.setCode( Exception::PINFailed ); throw e; break; } } PKCS11_KEY* signKey = PKCS11_find_key(d->sign.certificate); if(signKey == NULL) { THROW_SIGNEXCEPTION("Could not get key that matches selected certificate."); } // Sign the digest. int result = PKCS11_sign(digest.type, digest.digest, digest.length, signature.signature, &(signature.length), signKey); if(result != 1) { THROW_SIGNEXCEPTION("Failed to sign digest: %s", ERR_reason_error_string(ERR_get_error())); } }