Exemple #1
0
/**
 * @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;
}
Exemple #2
0
/**
 * @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;
}
Exemple #4
0
const char *TLSErrorString(intmax_t errcode)
{
    const char *errmsg = ERR_reason_error_string((unsigned long) errcode);
    return (errmsg != NULL) ? errmsg : "no error message";
}
Exemple #5
0
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;
}
Exemple #6
0
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);
}
Exemple #7
0
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;
}
Exemple #8
0
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;
}
Exemple #9
0
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;
}
Exemple #10
0
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;
}
Exemple #12
0
//
// 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;
}
Exemple #13
0
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()));
}
Exemple #14
0
const char* rocksock_ssl_strerror(rocksock *sock, int error) {
	return ERR_reason_error_string(error);
}
Exemple #15
0
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
Exemple #16
0
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;
}
Exemple #17
0
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));
}
Exemple #18
0
/**
 * 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);
}
Exemple #19
0
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);
}
Exemple #20
0
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;
    }
  }
}
Exemple #22
0
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;
}
Exemple #25
0
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;
}
Exemple #26
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;
}
Exemple #28
0
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);
}
Exemple #29
0
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;
}
Exemple #30
0
/**
 * 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()));
    }
}