Exemple #1
0
janus_dtls_srtp *janus_dtls_srtp_create(void *ice_component, janus_dtls_role role) {
	janus_ice_component *component = (janus_ice_component *)ice_component;
	if(component == NULL) {
		JANUS_LOG(LOG_ERR, "No component, no DTLS...\n");
		return NULL;
	}
	janus_ice_stream *stream = component->stream;
	if(!stream) {
		JANUS_LOG(LOG_ERR, "No stream, no DTLS...\n");
		return NULL;
	}
	janus_ice_handle *handle = stream->handle;
	if(!handle || !handle->agent) {
		JANUS_LOG(LOG_ERR, "No handle/agent, no DTLS...\n");
		return NULL;
	}
	janus_dtls_srtp *dtls = calloc(1, sizeof(janus_dtls_srtp));
	if(dtls == NULL) {
		JANUS_LOG(LOG_FATAL, "Memory error!\n");
		return NULL;
	}
	/* Create SSL context, at last */
	dtls->srtp_valid = 0;
	dtls->dtls_last_msg = NULL;
	dtls->dtls_last_len = 0;
	dtls->ssl = SSL_new(janus_dtls_get_ssl_ctx());
	if(!dtls->ssl) {
		JANUS_LOG(LOG_ERR, "[%"SCNu64"]     No component DTLS SSL session??\n", handle->handle_id);
		janus_dtls_srtp_destroy(dtls);
		return NULL;
	}
	SSL_set_ex_data(dtls->ssl, 0, dtls);
	SSL_set_info_callback(dtls->ssl, janus_dtls_callback);
	dtls->read_bio = BIO_new(BIO_s_mem());
	if(!dtls->read_bio) {
		JANUS_LOG(LOG_ERR, "[%"SCNu64"]   Error creating read BIO!\n", handle->handle_id);
		janus_dtls_srtp_destroy(dtls);
		return NULL;
	}
	BIO_set_mem_eof_return(dtls->read_bio, -1);
	dtls->write_bio = BIO_new(BIO_s_mem());
	if(!dtls->write_bio) {
		JANUS_LOG(LOG_ERR, "[%"SCNu64"]   Error creating write BIO!\n", handle->handle_id);
		janus_dtls_srtp_destroy(dtls);
		return NULL;
	}
	BIO_set_mem_eof_return(dtls->write_bio, -1);
	SSL_set_bio(dtls->ssl, dtls->read_bio, dtls->write_bio);
	dtls->dtls_role = role;
	if(dtls->dtls_role == JANUS_DTLS_ROLE_CLIENT) {
		JANUS_LOG(LOG_VERB, "[%"SCNu64"]   Setting connect state (DTLS client)\n", handle->handle_id);
		SSL_set_connect_state(dtls->ssl);
	} else {
		JANUS_LOG(LOG_VERB, "[%"SCNu64"]   Setting accept state (DTLS server)\n", handle->handle_id);
		SSL_set_accept_state(dtls->ssl);
	}
	/* Done */
	dtls->component = component;
	return dtls;
}
Exemple #2
0
tnet_dtls_socket_handle_t* tnet_dtls_socket_create(struct tnet_socket_s* wrapped_sock, struct ssl_ctx_st* ssl_ctx)
{
#if !HAVE_OPENSSL || !HAVE_OPENSSL_DTLS
	TSK_DEBUG_ERROR("OpenSSL or DTLS not enabled");
	return tsk_null;
#else
	tnet_dtls_socket_t* socket;

	if (!wrapped_sock || !ssl_ctx){
		TSK_DEBUG_ERROR("Invalid parameter");
		return tsk_null;
	}
	if ((socket = tsk_object_new(tnet_dtls_socket_def_t))) {
		const tsk_bool_t set_mtu = TNET_SOCKET_TYPE_IS_DGRAM(wrapped_sock->type) || 1; //!\ This is required even if the local transport is TCP/TLS because the relayed (TURN) transport could be UDP
		socket->wrapped_sock = tsk_object_ref(wrapped_sock);
		if (!(socket->ssl = SSL_new(ssl_ctx))) {
			TSK_DEBUG_ERROR("SSL_new(CTX) failed [%s]", ERR_error_string(ERR_get_error(), tsk_null));
			TSK_OBJECT_SAFE_FREE(socket);
			return tsk_null;
		}
		if (set_mtu) {
			SSL_set_options(socket->ssl, SSL_OP_NO_QUERY_MTU);
			SSL_set_mtu(socket->ssl, TNET_DTLS_MTU - 28);
			socket->ssl->d1->mtu = TNET_DTLS_MTU - 28;
		}
		if (!(socket->rbio = BIO_new(BIO_s_mem())) || !(socket->wbio = BIO_new(BIO_s_mem()))){
			TSK_DEBUG_ERROR("BIO_new_socket(%d) failed [%s]", socket->wrapped_sock->fd, ERR_error_string(ERR_get_error(), tsk_null));
			if (socket->rbio){
				BIO_free(socket->rbio);
			}
			if (socket->wbio){
				BIO_free(socket->wbio);
			}
			TSK_OBJECT_SAFE_FREE(socket);
			return tsk_null;
		}
		BIO_set_mem_eof_return(socket->rbio, -1);
		BIO_set_mem_eof_return(socket->wbio, -1);
		SSL_set_bio(socket->ssl, socket->rbio, socket->wbio);
		SSL_set_mode(socket->ssl, SSL_MODE_AUTO_RETRY);
		SSL_set_read_ahead(socket->ssl, 1);
		if (set_mtu) {
			BIO_ctrl(SSL_get_wbio(socket->ssl), BIO_CTRL_DGRAM_SET_MTU, TNET_DTLS_MTU - 28, NULL);
		}

		if ((socket->verify_peer = (SSL_CTX_get_verify_mode(ssl_ctx) != SSL_VERIFY_NONE))){
			TSK_DEBUG_INFO("SSL cert verify: ON");
			socket->verify_peer = tsk_true;
			SSL_set_verify(socket->ssl, (SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT), _tnet_dtls_verify_cert);
		}
		else {
			TSK_DEBUG_ERROR("Verity not enabled");
		}

		SSL_set_app_data(socket->ssl, socket);
	}
	return socket;
#endif
}
/*
 * NOTE: Transfers control of the BIOs - this function will free them on error
 */
int create_ssl_objects(SSL_CTX *serverctx, SSL_CTX *clientctx, SSL **sssl,
                          SSL **cssl, BIO *s_to_c_fbio, BIO *c_to_s_fbio)
{
    SSL *serverssl = NULL, *clientssl = NULL;
    BIO *s_to_c_bio = NULL, *c_to_s_bio = NULL;

    if (*sssl != NULL)
        serverssl = *sssl;
    else if (!TEST_ptr(serverssl = SSL_new(serverctx)))
        goto error;
    if (*cssl != NULL)
        clientssl = *cssl;
    else if (!TEST_ptr(clientssl = SSL_new(clientctx)))
        goto error;

    if (SSL_is_dtls(clientssl)) {
        if (!TEST_ptr(s_to_c_bio = BIO_new(bio_s_mempacket_test()))
                || !TEST_ptr(c_to_s_bio = BIO_new(bio_s_mempacket_test())))
            goto error;
    } else {
        if (!TEST_ptr(s_to_c_bio = BIO_new(BIO_s_mem()))
                || !TEST_ptr(c_to_s_bio = BIO_new(BIO_s_mem())))
            goto error;
    }

    if (s_to_c_fbio != NULL
            && !TEST_ptr(s_to_c_bio = BIO_push(s_to_c_fbio, s_to_c_bio)))
        goto error;
    if (c_to_s_fbio != NULL
            && !TEST_ptr(c_to_s_bio = BIO_push(c_to_s_fbio, c_to_s_bio)))
        goto error;

    /* Set Non-blocking IO behaviour */
    BIO_set_mem_eof_return(s_to_c_bio, -1);
    BIO_set_mem_eof_return(c_to_s_bio, -1);

    /* Up ref these as we are passing them to two SSL objects */
    SSL_set_bio(serverssl, c_to_s_bio, s_to_c_bio);
    BIO_up_ref(s_to_c_bio);
    BIO_up_ref(c_to_s_bio);
    SSL_set_bio(clientssl, s_to_c_bio, c_to_s_bio);
    *sssl = serverssl;
    *cssl = clientssl;
    return 1;

 error:
    SSL_free(serverssl);
    SSL_free(clientssl);
    BIO_free(s_to_c_bio);
    BIO_free(c_to_s_bio);
    BIO_free(s_to_c_fbio);
    BIO_free(c_to_s_fbio);

    return 0;
}
Exemple #4
0
DTLSBio::DTLSBio() :
  _pInBIO(0),                                                                        /* we use memory read bios */
  _pOutBIO(0), 
  _pSSL(0),
  _pSocket(0)
{
  //
  // Create the bios
  //
  _pInBIO = BIO_new(BIO_s_mem());
  _pOutBIO = BIO_new(BIO_s_mem());
  
  BIO_set_mem_eof_return(_pInBIO, -1);
  BIO_set_mem_eof_return(_pOutBIO, -1);
}
Exemple #5
0
static int cms_copy_content(BIO *out, BIO *in, unsigned int flags)
	{
	struct sockaddr_in sa;
	unsigned char buf[4096];
	int r = 0, i;
	BIO *tmpout = NULL;

	if (out == NULL)
		tmpout = BIO_new(BIO_s_null());
	else if (flags & CMS_TEXT)
		{
		tmpout = BIO_new(BIO_s_mem());
		BIO_set_mem_eof_return(tmpout, 0);
		}
	else
		tmpout = out;

	if(!tmpout)
		{
		CMSerr(CMS_F_CMS_COPY_CONTENT,ERR_R_MALLOC_FAILURE);
		goto err;
		}

	/* Read all content through chain to process digest, decrypt etc */
	for (;;)
	{
		i=BIO_read(in,buf,sizeof(buf));
		if (i <= 0)
			{
			if (BIO_method_type(in) == BIO_TYPE_CIPHER)
				{
				if (!BIO_get_cipher_status(in))
					goto err;
				}
			if (i < 0)
				goto err;
			break;
			}
				
		if (tmpout && (BIO_write(tmpout, buf, i, 0, sa) != i))
			goto err;
	}

	if(flags & CMS_TEXT)
		{
		if(!SMIME_text(tmpout, out))
			{
			CMSerr(CMS_F_CMS_COPY_CONTENT,CMS_R_SMIME_TEXT_ERROR);
			goto err;
			}
		}

	r = 1;

	err:
	if (tmpout && (tmpout != out))
		BIO_free(tmpout);
	return r;

	}
Exemple #6
0
static PyObject *
memory_bio_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
    BIO *bio = NULL;
    PySSLMemoryBIO *self = NULL;

    if (!PyArg_ParseTuple(args, ":MemoryBIO"))
        RETURN_ERROR(NULL);

    bio = BIO_new(BIO_s_mem());
    if (bio == NULL)
        RETURN_ERROR("failed to allocate BIO");

    /* Since our BIO is non-blocking an empty read() does not indicate EOF,
     * just that no data is currently available. The SSL routines should retry
     * the read, which we can achieve by calling BIO_set_retry_read(). */
    BIO_set_retry_read(bio);
    BIO_set_mem_eof_return(bio, -1);

    self = (PySSLMemoryBIO *) type->tp_alloc(type, 0);
    if (self == NULL)
        RETURN_ERROR(NULL);

    self->bio = bio; bio = NULL;
    self->eof_written = 0;

error:
    if (bio != NULL) BIO_free(bio);
    return (PyObject *) self;
}
Exemple #7
0
  bool Parser::init() {

    if (!ssl) {
      printf("Error: dtls::Parser::init() failed because the `ssl` member hasn't been set yet.\n");
      return false;
    }

    /* in bio */
    {
      in_bio = BIO_new(BIO_s_mem());
      if (!in_bio) {
        printf("Error: dtls::Parser::init() failed because we can't create our in_bio.\n");
        return false;
      }

      BIO_set_mem_eof_return(in_bio, -1); /* see: https://www.openssl.org/docs/crypto/BIO_s_mem.html */
    }

    /* out bio */
    {
      out_bio = BIO_new(BIO_s_mem());
      if (!out_bio) {
        printf("Error: dtls::Parser::init() failed because can't create out out_bio.\n");
        /* @todo cleanup. */
        return false;
      }

      BIO_set_mem_eof_return(out_bio, -1); /* see: https://www.openssl.org/docs/crypto/BIO_s_mem.html */
    }

    /* set info callback */
    SSL_set_info_callback(ssl, dtls_parse_ssl_info_callback);

    /* set in and output bios. */
    SSL_set_bio(ssl, in_bio, out_bio);

    if (mode == DTLS_MODE_SERVER) { 
      SSL_set_accept_state(ssl); /* in case we're a server */
    }
    else if(mode == DTLS_MODE_CLIENT) {
      //SSL_set_connect_state(ssl); /* in case we're a client */
      printf("dtls::Parser - error: not yet handling client state for dtls::Parser().\n");
      exit(1);
    }
    
    return true;
  }
Exemple #8
0
struct dtls_transport *
create_dtls_transport(struct rtcdc_peer_connection *peer,
                      const struct dtls_context *context)
{
  if (peer == NULL || peer->transport == NULL || context == NULL || context->ctx == NULL)
    return NULL;

  struct dtls_transport *dtls = (struct dtls_transport *)calloc(1, sizeof *dtls);
  if (dtls == NULL)
    return NULL;
  peer->transport->dtls = dtls;

  SSL *ssl = SSL_new(context->ctx);
  if (ssl == NULL)
    goto trans_err;
  dtls->ssl = ssl;

  BIO *bio = BIO_new(BIO_s_mem());
  if (bio == NULL)
    goto trans_err;
  BIO_set_mem_eof_return(bio, -1);
  dtls->incoming_bio = bio;

  bio = BIO_new(BIO_s_mem());
  if (bio == NULL)
    goto trans_err;
  BIO_set_mem_eof_return(bio, -1);
  dtls->outgoing_bio = bio;

  SSL_set_bio(dtls->ssl, dtls->incoming_bio, dtls->outgoing_bio);

  EC_KEY *ecdh = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
  SSL_set_options(dtls->ssl, SSL_OP_SINGLE_ECDH_USE);
  SSL_set_tmp_ecdh(dtls->ssl, ecdh);
  EC_KEY_free(ecdh);

  if (0) {
trans_err:
    peer->transport->dtls = NULL;
    SSL_free(ssl);
    free(dtls);
    dtls = NULL;
  }

  return dtls;
}
Exemple #9
0
BIO *BIO_mem_dummy()
{
	static BIO *dummyBIO = NULL;
	if(!dummyBIO)
	{
		dummyBIO = BIO_new(BIO_s_mem());
		BIO_set_mem_eof_return(dummyBIO, -1);
	}
	return dummyBIO;
}
Exemple #10
0
static PyObject *
memory_bio_write_eof(PySSLMemoryBIO *self, PyObject *args)
{
    self->eof_written = 1;
    /* After an EOF is written, a zero return from read() should be a real EOF
     * i.e. it should not be retried. Clear the SHOULD_RETRY flag. */
    BIO_clear_retry_flags(self->bio);
    BIO_set_mem_eof_return(self->bio, 0);

    Py_RETURN_NONE;
}
Exemple #11
0
/* this sets up the SSL* */
int krx_ssl_init(krx* k, int isserver, info_callback cb) {

  /* create SSL* */
  k->ssl = SSL_new(k->ctx);
  if(!k->ssl) {
    printf("Error: cannot create new SSL*.\n");
    return -1;
  }

  /* info callback */
  SSL_set_info_callback(k->ssl, cb);
  
  /* bios */
  k->in_bio = BIO_new(BIO_s_mem());
  if(k->in_bio == NULL) {
    printf("Error: cannot allocate read bio.\n");
    return -2;
  }

  BIO_set_mem_eof_return(k->in_bio, -1); /* see: https://www.openssl.org/docs/crypto/BIO_s_mem.html */

  k->out_bio = BIO_new(BIO_s_mem());
  if(k->out_bio == NULL) {
    printf("Error: cannot allocate write bio.\n");
    return -3;
  }

  BIO_set_mem_eof_return(k->out_bio, -1); /* see: https://www.openssl.org/docs/crypto/BIO_s_mem.html */

  SSL_set_bio(k->ssl, k->in_bio, k->out_bio);

  /* either use the server or client part of the protocol */
  if(isserver == 1) {
    SSL_set_accept_state(k->ssl);
  }
  else {
    SSL_set_connect_state(k->ssl);
  }

  return 0;
}
Exemple #12
0
static BIO *cms_get_text_bio(BIO *out, unsigned int flags)
{
    BIO *rbio;
    if (out == NULL)
        rbio = BIO_new(BIO_s_null());
    else if (flags & CMS_TEXT) {
        rbio = BIO_new(BIO_s_mem());
        BIO_set_mem_eof_return(rbio, 0);
    } else
        rbio = out;
    return rbio;
}
Exemple #13
0
@return: None\n\
";

static PyObject *
ssl_Connection_bio_shutdown(ssl_ConnectionObj *self, PyObject *args)
{
    if (self->from_ssl == NULL) 
    {
            PyErr_SetString(PyExc_TypeError, "Connection sock was not None");
            return NULL;
    }

    BIO_set_mem_eof_return(self->into_ssl, 0);
    Py_INCREF(Py_None);
    return Py_None;
}
Exemple #14
0
Gzb64* gzb64_init()
{
	int zret;

	Gzb64* gzb64 = (Gzb64*) malloc(sizeof(Gzb64));
	if( gzb64 == NULL ) { fprintf(stderr, "Failed to malloc\n"); exit(EXIT_FAILURE); }

	/* Encode */
	/* setup zlib encode struc */
    gzb64->gz_encode_strm.zalloc = Z_NULL;
    gzb64->gz_encode_strm.zfree  = Z_NULL;
    gzb64->gz_encode_strm.opaque = Z_NULL;
    zret = deflateInit2 (& gzb64->gz_encode_strm, Z_DEFAULT_COMPRESSION, Z_DEFLATED,
                             windowBits | GZIP_ENCODING, 8,
                             Z_DEFAULT_STRATEGY);
	if(zret < 0) zerr(zret);

	gzb64->encode_gzout_buffer = evbuffer_new();

	/* setup base64 encoder */
	gzb64->b64_encoder = BIO_new(BIO_f_base64());
	BIO_set_flags(gzb64->b64_encoder, BIO_FLAGS_BASE64_NO_NL); //Do not use newlines to flush buffer
	gzb64->encode_output_buffer = BIO_new(BIO_s_mem());
	BIO_set_mem_eof_return(gzb64->encode_output_buffer, 0);
    gzb64->b64_encoder = BIO_push(gzb64->b64_encoder, gzb64->encode_output_buffer);

	/* Decode */
	gzb64->decode_input_buffer = evbuffer_new();

	/* setup base64 decoder */
	gzb64->b64_decoder = BIO_new(BIO_f_base64());
	BIO_set_flags(gzb64->b64_decoder, BIO_FLAGS_BASE64_NO_NL); //Do not use newlines to flush buffer

	gzb64->decode_output_buffer = evbuffer_new();

	/* setup zlib decode struc */
    gzb64->gz_decode_strm.avail_in = 0;
    gzb64->gz_decode_strm.next_in = Z_NULL;
	zret = inflateInit2 (& gzb64->gz_decode_strm, windowBits | ENABLE_ZLIB_GZIP);
	if(zret < 0) zerr(zret);

	/* State */
	gzb64->encoded_last_chunk = false;
	gzb64->decoded_last_chunk = false;

	return gzb64;
}
Exemple #15
0
int CMS_dataFinal(CMS_ContentInfo *cms, BIO *cmsbio)
	{
	ASN1_OCTET_STRING **pos = CMS_get0_content(cms);
	if (!pos)
		return 0;
	/* If ebmedded content find memory BIO and set content */
	if (*pos && ((*pos)->flags & ASN1_STRING_FLAG_CONT))
		{
		BIO *mbio;
		unsigned char *cont;
		long contlen;
		mbio = BIO_find_type(cmsbio, BIO_TYPE_MEM);
		if (!mbio)
			{
			CMSerr(CMS_F_CMS_DATAFINAL, CMS_R_CONTENT_NOT_FOUND);
			return 0;
			}
		contlen = BIO_get_mem_data(mbio, &cont);
		/* Set bio as read only so its content can't be clobbered */
		BIO_set_flags(mbio, BIO_FLAGS_MEM_RDONLY);
		BIO_set_mem_eof_return(mbio, 0);
		ASN1_STRING_set0(*pos, cont, contlen);
		(*pos)->flags &= ~ASN1_STRING_FLAG_CONT;
		}

	switch (OBJ_obj2nid(cms->contentType))
		{

		case NID_pkcs7_data:
		case NID_pkcs7_enveloped:
		case NID_pkcs7_encrypted:
		case NID_id_smime_ct_compressedData:
		/* Nothing to do */
		return 1;

		case NID_pkcs7_signed:
		return cms_SignedData_final(cms, cmsbio);

		case NID_pkcs7_digest:
		return cms_DigestedData_do_final(cms, cmsbio, 0);

		default:
		CMSerr(CMS_F_CMS_DATAFINAL, CMS_R_UNSUPPORTED_TYPE);
		return 0;
		}
	}
Exemple #16
0
SSLStream::SSLStream(Stream::ptr parent, bool client, bool own, SSL_CTX *ctx)
: MutatingFilterStream(parent, own)
{
    MORDOR_ASSERT(parent);
    clearSSLError();
    if (ctx)
        m_ctx.reset(ctx, &nop<SSL_CTX *>);
    else
        m_ctx.reset(SSL_CTX_new(client ? SSLv23_client_method() :
            SSLv23_server_method()), &SSL_CTX_free);
    if (!m_ctx) {
        MORDOR_ASSERT(hasOpenSSLError());
        MORDOR_THROW_EXCEPTION(OpenSSLException(getOpenSSLErrorMessage()))
           // << boost::errinfo_api_function("SSL_CTX_new");
        ;
    }
    // Auto-generate self-signed server cert
    if (!ctx && !client) {
        std::shared_ptr<X509> cert;
        std::shared_ptr<EVP_PKEY> pkey;
        mkcert(cert, pkey, 1024, rand(), 365);
        SSL_CTX_use_certificate(m_ctx.get(), cert.get());
        SSL_CTX_use_PrivateKey(m_ctx.get(), pkey.get());
    }
    m_ssl.reset(SSL_new(m_ctx.get()), &SSL_free);
    if (!m_ssl) {
        MORDOR_ASSERT(hasOpenSSLError());
        MORDOR_THROW_EXCEPTION(OpenSSLException(getOpenSSLErrorMessage()))
          //  << boost::errinfo_api_function("SSL_CTX_new");
        ;
    }
    m_readBio = BIO_new(BIO_s_mem());
    m_writeBio = BIO_new(BIO_s_mem());
    if (!m_readBio || !m_writeBio) {
        if (m_readBio) BIO_free(m_readBio);
        if (m_writeBio) BIO_free(m_writeBio);
        MORDOR_ASSERT(hasOpenSSLError());
        MORDOR_THROW_EXCEPTION(OpenSSLException(getOpenSSLErrorMessage()))
          //  << boost::errinfo_api_function("BIO_new");
        ;
    }
    BIO_set_mem_eof_return(m_readBio, -1);

    SSL_set_bio(m_ssl.get(), m_readBio, m_writeBio);
}
Exemple #17
0
OpenSSLCertificate* OpenSSLCertificate::FromPEMString(
    const std::string& pem_string, int* pem_length) {
  BIO* bio = BIO_new_mem_buf(const_cast<char*>(pem_string.c_str()), -1);
  if (!bio)
    return NULL;
  (void)BIO_set_close(bio, BIO_NOCLOSE);
  BIO_set_mem_eof_return(bio, 0);
  X509 *x509 = PEM_read_bio_X509(bio, NULL, NULL,
                                 const_cast<char*>("\0"));
  char *ptr;
  int remaining_length = BIO_get_mem_data(bio, &ptr);
  BIO_free(bio);
  if (pem_length)
    *pem_length = pem_string.length() - remaining_length;
  if (x509)
    return new OpenSSLCertificate(x509);
  else
    return NULL;
}
Exemple #18
0
IoSecureSocket *IoSecureServer_dtlsWrap(IoSecureServer *self, IoObject *locals, IoMessage *msg)
{
	SSL_CTX *ctx = OCTX(self);
	IoSocket *sock = IoObject_getSlot_(self, IOSYMBOL("socket"));
	IoIPAddress *ioip = IoMessage_locals_addressArgAt_(msg, locals, 0);
	IPAddress *ip = IoIPAddress_rawIPAddress(ioip);
	struct sockaddr *addr = IPAddress_sockaddr(ip);
	IoNumber *port = IoObject_getSlot_(sock, IOSYMBOL("port"));
	int fd = IoSocket_rawDescriptor(sock);
	SSL *ssl = SSL_new(ctx);
	BIO *rbio = BIO_new(BIO_s_mem());
	BIO_set_mem_eof_return(rbio, -1);
	BIO *wbio = BIO_new_dgram(fd, BIO_NOCLOSE);
	BIO_dgram_set_peer(wbio, addr);
	SSL_set_bio(ssl, rbio, wbio);
	SSL_set_accept_state(ssl);
	set_nonblocking(wbio);
	SSL_set_mode(ssl, SSL_MODE_ENABLE_PARTIAL_WRITE |
		SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
	IoSecureSocket *ssock = IoSecureSocket_newWithSSL_IP_(IoObject_state(self), ssl, ioip);
	return ssock;
}
Exemple #19
0
void
SSLStream::wantRead()
{
    if (m_readBuffer.readAvailable() == 0) {
        MORDOR_LOG_TRACE(g_log) << this << " parent()->read(32768)";
        const size_t result = parent()->read(m_readBuffer, 32768);
        MORDOR_LOG_TRACE(g_log) << this << " parent()->read(32768): " << result;
        if (result == 0) {
            BIO_set_mem_eof_return(m_readBio, 0);
            return;
        }
    }
    MORDOR_ASSERT(m_readBuffer.readAvailable());
    const iovec iov = m_readBuffer.readBuffer(~0, false);
    MORDOR_ASSERT(iov.iov_len > 0);
    const int written = BIO_write(m_readBio, (char *)iov.iov_base, iov.iov_len);
    MORDOR_ASSERT(written > 0);
    if (written > 0) {
        m_readBuffer.consume(written);
    }
    MORDOR_LOG_DEBUG(g_log) << this << " wantRead(): " << written;
}
Exemple #20
0
struct sctp_transport *
create_sctp_transport(struct rtcdc_peer_connection *peer)
{
    if (peer == NULL || peer->transport == NULL)
        return NULL;

    struct sctp_transport *sctp = (struct sctp_transport *)calloc(1, sizeof *sctp);
    if (sctp == NULL)
        return NULL;
    peer->transport->sctp = sctp;
    sctp->local_port = random_integer(10000, 60000);

    if (g_sctp_ref == 0) {
        usrsctp_init(0, sctp_data_ready_cb, NULL);
        usrsctp_sysctl_set_sctp_ecn_enable(1);
    }
    g_sctp_ref++;

    usrsctp_register_address(sctp);
    struct socket *s = usrsctp_socket(AF_CONN, SOCK_STREAM, IPPROTO_SCTP,
            sctp_data_received_cb, NULL, 0, peer);
    if (s == NULL)
        goto trans_err;
    sctp->sock = s;

    BIO *bio = BIO_new(BIO_s_mem());
    if (bio == NULL)
        goto trans_err;
    BIO_set_mem_eof_return(bio, -1);
    sctp->incoming_bio = bio;

    bio = BIO_new(BIO_s_mem());
    if (bio == NULL)
        goto trans_err;
    BIO_set_mem_eof_return(bio, -1);
    sctp->outgoing_bio = bio;


#ifdef DEBUG_SCTP
    int sd;
    struct sockaddr_in stub_addr;
    memset(&stub_addr, 0, sizeof stub_addr);
    inet_pton(AF_INET, "127.0.0.1", &stub_addr.sin_addr);
    stub_addr.sin_family = AF_INET;

    sd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
    stub_addr.sin_port = htons(60001);
    bind(sd, (const struct sockaddr *)&stub_addr, sizeof stub_addr);
    stub_addr.sin_port = htons(60002);
    connect(sd, (const struct sockaddr *)&stub_addr, sizeof stub_addr);
    sctp->incoming_stub = sd;

    sd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
    stub_addr.sin_port = htons(60002);
    bind(sd, (const struct sockaddr *)&stub_addr, sizeof stub_addr);
    stub_addr.sin_port = htons(60001);
    connect(sd, (const struct sockaddr *)&stub_addr, sizeof stub_addr);
    sctp->outgoing_stub = sd;
#endif

    struct linger lopt;
    lopt.l_onoff = 1;
    lopt.l_linger = 0;
    usrsctp_setsockopt(s, SOL_SOCKET, SO_LINGER, &lopt, sizeof lopt);

    struct sctp_paddrparams peer_param;
    memset(&peer_param, 0, sizeof peer_param);
    peer_param.spp_flags = SPP_PMTUD_DISABLE;
    peer_param.spp_pathmtu = 1200;
    usrsctp_setsockopt(s, IPPROTO_SCTP, SCTP_PEER_ADDR_PARAMS, &peer_param, sizeof peer_param);

    struct sctp_assoc_value av;
    av.assoc_id = SCTP_ALL_ASSOC;
    av.assoc_value = 1;
    usrsctp_setsockopt(s, IPPROTO_SCTP, SCTP_ENABLE_STREAM_RESET, &av, sizeof av);

    uint32_t nodelay = 1;
    usrsctp_setsockopt(s, IPPROTO_SCTP, SCTP_NODELAY, &nodelay, sizeof nodelay);

    struct sctp_initmsg init_msg;
    memset(&init_msg, 0, sizeof init_msg);
    init_msg.sinit_num_ostreams = RTCDC_MAX_OUT_STREAM;
    init_msg.sinit_max_instreams = RTCDC_MAX_IN_STREAM;
    usrsctp_setsockopt(s, IPPROTO_SCTP, SCTP_INITMSG, &init_msg, sizeof init_msg);

    struct sockaddr_conn sconn;
    memset(&sconn, 0, sizeof sconn);
    sconn.sconn_family = AF_CONN;
    sconn.sconn_port = htons(sctp->local_port);
    sconn.sconn_addr = (void *)sctp;
#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__OpenBSD__)
    sconn.sconn_len = sizeof *sctp;
#endif
    usrsctp_bind(s, (struct sockaddr *)&sconn, sizeof sconn);

    sctp->deferred_messages = g_async_queue_new();

    // modified by uniray7
    sctp->peer = peer;
    //====================

    if (0) {
trans_err:
        peer->transport->sctp = NULL;
        usrsctp_finish();
        free(sctp);
        sctp = NULL;
    }

    return sctp;
}
Exemple #21
0
int PKCS7_dataFinal(PKCS7 *p7, BIO *bio)
{
    int ret = 0;
    int i, j;
    BIO *btmp;
    PKCS7_SIGNER_INFO *si;
    EVP_MD_CTX *mdc, ctx_tmp;
    STACK_OF(X509_ATTRIBUTE) *sk;
    STACK_OF(PKCS7_SIGNER_INFO) *si_sk = NULL;
    ASN1_OCTET_STRING *os = NULL;

    if (p7 == NULL) {
        PKCS7err(PKCS7_F_PKCS7_DATAFINAL, PKCS7_R_INVALID_NULL_POINTER);
        return 0;
    }

    if (p7->d.ptr == NULL) {
        PKCS7err(PKCS7_F_PKCS7_DATAFINAL, PKCS7_R_NO_CONTENT);
        return 0;
    }

    EVP_MD_CTX_init(&ctx_tmp);
    i = OBJ_obj2nid(p7->type);
    p7->state = PKCS7_S_HEADER;

    switch (i) {
    case NID_pkcs7_data:
        os = p7->d.data;
        break;
    case NID_pkcs7_signedAndEnveloped:
        /* XXXXXXXXXXXXXXXX */
        si_sk = p7->d.signed_and_enveloped->signer_info;
        os = p7->d.signed_and_enveloped->enc_data->enc_data;
        if (!os) {
            os = M_ASN1_OCTET_STRING_new();
            if (!os) {
                PKCS7err(PKCS7_F_PKCS7_DATAFINAL, ERR_R_MALLOC_FAILURE);
                goto err;
            }
            p7->d.signed_and_enveloped->enc_data->enc_data = os;
        }
        break;
    case NID_pkcs7_enveloped:
        /* XXXXXXXXXXXXXXXX */
        os = p7->d.enveloped->enc_data->enc_data;
        if (!os) {
            os = M_ASN1_OCTET_STRING_new();
            if (!os) {
                PKCS7err(PKCS7_F_PKCS7_DATAFINAL, ERR_R_MALLOC_FAILURE);
                goto err;
            }
            p7->d.enveloped->enc_data->enc_data = os;
        }
        break;
    case NID_pkcs7_signed:
        si_sk = p7->d.sign->signer_info;
        os = PKCS7_get_octet_string(p7->d.sign->contents);
        /* If detached data then the content is excluded */
        if (PKCS7_type_is_data(p7->d.sign->contents) && p7->detached) {
            M_ASN1_OCTET_STRING_free(os);
            os = NULL;
            p7->d.sign->contents->d.data = NULL;
        }
        break;

    case NID_pkcs7_digest:
        os = PKCS7_get_octet_string(p7->d.digest->contents);
        /* If detached data then the content is excluded */
        if (PKCS7_type_is_data(p7->d.digest->contents) && p7->detached) {
            M_ASN1_OCTET_STRING_free(os);
            os = NULL;
            p7->d.digest->contents->d.data = NULL;
        }
        break;

    default:
        PKCS7err(PKCS7_F_PKCS7_DATAFINAL, PKCS7_R_UNSUPPORTED_CONTENT_TYPE);
        goto err;
    }

    if (si_sk != NULL) {
        for (i = 0; i < sk_PKCS7_SIGNER_INFO_num(si_sk); i++) {
            si = sk_PKCS7_SIGNER_INFO_value(si_sk, i);
            if (si->pkey == NULL)
                continue;

            j = OBJ_obj2nid(si->digest_alg->algorithm);

            btmp = bio;

            btmp = PKCS7_find_digest(&mdc, btmp, j);

            if (btmp == NULL)
                goto err;

            /*
             * We now have the EVP_MD_CTX, lets do the signing.
             */
            if (!EVP_MD_CTX_copy_ex(&ctx_tmp, mdc))
                goto err;

            sk = si->auth_attr;

            /*
             * If there are attributes, we add the digest attribute and only
             * sign the attributes
             */
            if (sk_X509_ATTRIBUTE_num(sk) > 0) {
                if (!do_pkcs7_signed_attrib(si, &ctx_tmp))
                    goto err;
            } else {
                unsigned char *abuf = NULL;
                unsigned int abuflen;
                abuflen = EVP_PKEY_size(si->pkey);
                abuf = OPENSSL_malloc(abuflen);
                if (!abuf)
                    goto err;

                if (!EVP_SignFinal(&ctx_tmp, abuf, &abuflen, si->pkey)) {
                    PKCS7err(PKCS7_F_PKCS7_DATAFINAL, ERR_R_EVP_LIB);
                    goto err;
                }
                ASN1_STRING_set0(si->enc_digest, abuf, abuflen);
            }
        }
    } else if (i == NID_pkcs7_digest) {
        unsigned char md_data[EVP_MAX_MD_SIZE];
        unsigned int md_len;
        if (!PKCS7_find_digest(&mdc, bio,
                               OBJ_obj2nid(p7->d.digest->md->algorithm)))
            goto err;
        if (!EVP_DigestFinal_ex(mdc, md_data, &md_len))
            goto err;
        M_ASN1_OCTET_STRING_set(p7->d.digest->digest, md_data, md_len);
    }

    if (!PKCS7_is_detached(p7)) {
        /*
         * NOTE(emilia): I think we only reach os == NULL here because detached
         * digested data support is broken.
         */
        if (os == NULL)
            goto err;
        if (!(os->flags & ASN1_STRING_FLAG_NDEF)) {
            char *cont;
            long contlen;
            btmp = BIO_find_type(bio, BIO_TYPE_MEM);
            if (btmp == NULL) {
                PKCS7err(PKCS7_F_PKCS7_DATAFINAL, PKCS7_R_UNABLE_TO_FIND_MEM_BIO);
                goto err;
            }
            contlen = BIO_get_mem_data(btmp, &cont);
            /*
             * Mark the BIO read only then we can use its copy of the data
             * instead of making an extra copy.
             */
            BIO_set_flags(btmp, BIO_FLAGS_MEM_RDONLY);
            BIO_set_mem_eof_return(btmp, 0);
            ASN1_STRING_set0(os, (unsigned char *)cont, contlen);
        }
    }
    ret = 1;
 err:
    EVP_MD_CTX_cleanup(&ctx_tmp);
    return (ret);
}
Exemple #22
0
/* int */
BIO *PKCS7_dataDecode(PKCS7 *p7, EVP_PKEY *pkey, BIO *in_bio, X509 *pcert)
{
    int i, j;
    BIO *out = NULL, *btmp = NULL, *etmp = NULL, *bio = NULL;
    X509_ALGOR *xa;
    ASN1_OCTET_STRING *data_body = NULL;
    const EVP_MD *evp_md;
    const EVP_CIPHER *evp_cipher = NULL;
    EVP_CIPHER_CTX *evp_ctx = NULL;
    X509_ALGOR *enc_alg = NULL;
    STACK_OF(X509_ALGOR) *md_sk = NULL;
    STACK_OF(PKCS7_RECIP_INFO) *rsk = NULL;
    PKCS7_RECIP_INFO *ri = NULL;
    unsigned char *ek = NULL, *tkey = NULL;
    int eklen = 0, tkeylen = 0;

    if (p7 == NULL) {
        PKCS7err(PKCS7_F_PKCS7_DATADECODE, PKCS7_R_INVALID_NULL_POINTER);
        return NULL;
    }

    if (p7->d.ptr == NULL) {
        PKCS7err(PKCS7_F_PKCS7_DATADECODE, PKCS7_R_NO_CONTENT);
        return NULL;
    }

    i = OBJ_obj2nid(p7->type);
    p7->state = PKCS7_S_HEADER;

    switch (i) {
    case NID_pkcs7_signed:
        data_body = PKCS7_get_octet_string(p7->d.sign->contents);
        if (!PKCS7_is_detached(p7) && data_body == NULL) {
            PKCS7err(PKCS7_F_PKCS7_DATADECODE,
                     PKCS7_R_INVALID_SIGNED_DATA_TYPE);
            goto err;
        }
        md_sk = p7->d.sign->md_algs;
        break;
    case NID_pkcs7_signedAndEnveloped:
        rsk = p7->d.signed_and_enveloped->recipientinfo;
        md_sk = p7->d.signed_and_enveloped->md_algs;
        data_body = p7->d.signed_and_enveloped->enc_data->enc_data;
        enc_alg = p7->d.signed_and_enveloped->enc_data->algorithm;
        evp_cipher = EVP_get_cipherbyobj(enc_alg->algorithm);
        if (evp_cipher == NULL) {
            PKCS7err(PKCS7_F_PKCS7_DATADECODE,
                     PKCS7_R_UNSUPPORTED_CIPHER_TYPE);
            goto err;
        }
        break;
    case NID_pkcs7_enveloped:
        rsk = p7->d.enveloped->recipientinfo;
        enc_alg = p7->d.enveloped->enc_data->algorithm;
        data_body = p7->d.enveloped->enc_data->enc_data;
        evp_cipher = EVP_get_cipherbyobj(enc_alg->algorithm);
        if (evp_cipher == NULL) {
            PKCS7err(PKCS7_F_PKCS7_DATADECODE,
                     PKCS7_R_UNSUPPORTED_CIPHER_TYPE);
            goto err;
        }
        break;
    default:
        PKCS7err(PKCS7_F_PKCS7_DATADECODE, PKCS7_R_UNSUPPORTED_CONTENT_TYPE);
        goto err;
    }

    /* We will be checking the signature */
    if (md_sk != NULL) {
        for (i = 0; i < sk_X509_ALGOR_num(md_sk); i++) {
            xa = sk_X509_ALGOR_value(md_sk, i);
            if ((btmp = BIO_new(BIO_f_md())) == NULL) {
                PKCS7err(PKCS7_F_PKCS7_DATADECODE, ERR_R_BIO_LIB);
                goto err;
            }

            j = OBJ_obj2nid(xa->algorithm);
            evp_md = EVP_get_digestbynid(j);
            if (evp_md == NULL) {
                PKCS7err(PKCS7_F_PKCS7_DATADECODE,
                         PKCS7_R_UNKNOWN_DIGEST_TYPE);
                goto err;
            }

            BIO_set_md(btmp, evp_md);
            if (out == NULL)
                out = btmp;
            else
                BIO_push(out, btmp);
            btmp = NULL;
        }
    }

    if (evp_cipher != NULL) {
#if 0
        unsigned char key[EVP_MAX_KEY_LENGTH];
        unsigned char iv[EVP_MAX_IV_LENGTH];
        unsigned char *p;
        int keylen, ivlen;
        int max;
        X509_OBJECT ret;
#endif

        if ((etmp = BIO_new(BIO_f_cipher())) == NULL) {
            PKCS7err(PKCS7_F_PKCS7_DATADECODE, ERR_R_BIO_LIB);
            goto err;
        }

        /*
         * It was encrypted, we need to decrypt the secret key with the
         * private key
         */

        /*
         * Find the recipientInfo which matches the passed certificate (if
         * any)
         */

        if (pcert) {
            for (i = 0; i < sk_PKCS7_RECIP_INFO_num(rsk); i++) {
                ri = sk_PKCS7_RECIP_INFO_value(rsk, i);
                if (!pkcs7_cmp_ri(ri, pcert))
                    break;
                ri = NULL;
            }
            if (ri == NULL) {
                PKCS7err(PKCS7_F_PKCS7_DATADECODE,
                         PKCS7_R_NO_RECIPIENT_MATCHES_CERTIFICATE);
                goto err;
            }
        }

        /* If we haven't got a certificate try each ri in turn */
        if (pcert == NULL) {
            /*
             * Always attempt to decrypt all rinfo even after sucess as a
             * defence against MMA timing attacks.
             */
            for (i = 0; i < sk_PKCS7_RECIP_INFO_num(rsk); i++) {
                ri = sk_PKCS7_RECIP_INFO_value(rsk, i);

                if (pkcs7_decrypt_rinfo(&ek, &eklen, ri, pkey) < 0)
                    goto err;
                ERR_clear_error();
            }
        } else {
            /* Only exit on fatal errors, not decrypt failure */
            if (pkcs7_decrypt_rinfo(&ek, &eklen, ri, pkey) < 0)
                goto err;
            ERR_clear_error();
        }

        evp_ctx = NULL;
        BIO_get_cipher_ctx(etmp, &evp_ctx);
        if (EVP_CipherInit_ex(evp_ctx, evp_cipher, NULL, NULL, NULL, 0) <= 0)
            goto err;
        if (EVP_CIPHER_asn1_to_param(evp_ctx, enc_alg->parameter) < 0)
            goto err;
        /* Generate random key as MMA defence */
        tkeylen = EVP_CIPHER_CTX_key_length(evp_ctx);
        tkey = OPENSSL_malloc(tkeylen);
        if (!tkey)
            goto err;
        if (EVP_CIPHER_CTX_rand_key(evp_ctx, tkey) <= 0)
            goto err;
        if (ek == NULL) {
            ek = tkey;
            eklen = tkeylen;
            tkey = NULL;
        }

        if (eklen != EVP_CIPHER_CTX_key_length(evp_ctx)) {
            /*
             * Some S/MIME clients don't use the same key and effective key
             * length. The key length is determined by the size of the
             * decrypted RSA key.
             */
            if (!EVP_CIPHER_CTX_set_key_length(evp_ctx, eklen)) {
                /* Use random key as MMA defence */
                OPENSSL_cleanse(ek, eklen);
                OPENSSL_free(ek);
                ek = tkey;
                eklen = tkeylen;
                tkey = NULL;
            }
        }
        /* Clear errors so we don't leak information useful in MMA */
        ERR_clear_error();
        if (EVP_CipherInit_ex(evp_ctx, NULL, NULL, ek, NULL, 0) <= 0)
            goto err;

        if (ek) {
            OPENSSL_cleanse(ek, eklen);
            OPENSSL_free(ek);
            ek = NULL;
        }
        if (tkey) {
            OPENSSL_cleanse(tkey, tkeylen);
            OPENSSL_free(tkey);
            tkey = NULL;
        }

        if (out == NULL)
            out = etmp;
        else
            BIO_push(out, etmp);
        etmp = NULL;
    }
#if 1
    if (PKCS7_is_detached(p7) || (in_bio != NULL)) {
        bio = in_bio;
    } else {
# if 0
        bio = BIO_new(BIO_s_mem());
        /*
         * We need to set this so that when we have read all the data, the
         * encrypt BIO, if present, will read EOF and encode the last few
         * bytes
         */
        BIO_set_mem_eof_return(bio, 0);

        if (data_body->length > 0)
            BIO_write(bio, (char *)data_body->data, data_body->length);
# else
        if (data_body->length > 0)
            bio = BIO_new_mem_buf(data_body->data, data_body->length);
        else {
            bio = BIO_new(BIO_s_mem());
            BIO_set_mem_eof_return(bio, 0);
        }
        if (bio == NULL)
            goto err;
# endif
    }
    BIO_push(out, bio);
    bio = NULL;
#endif
    if (0) {
 err:
        if (ek) {
            OPENSSL_cleanse(ek, eklen);
            OPENSSL_free(ek);
        }
        if (tkey) {
            OPENSSL_cleanse(tkey, tkeylen);
            OPENSSL_free(tkey);
        }
        if (out != NULL)
            BIO_free_all(out);
        if (btmp != NULL)
            BIO_free_all(btmp);
        if (etmp != NULL)
            BIO_free_all(etmp);
        if (bio != NULL)
            BIO_free_all(bio);
        out = NULL;
    }
    return (out);
}
Exemple #23
0
BIO *PKCS7_dataInit(PKCS7 *p7, BIO *bio)
{
    int i;
    BIO *out = NULL, *btmp = NULL;
    X509_ALGOR *xa = NULL;
    const EVP_CIPHER *evp_cipher = NULL;
    STACK_OF(X509_ALGOR) *md_sk = NULL;
    STACK_OF(PKCS7_RECIP_INFO) *rsk = NULL;
    X509_ALGOR *xalg = NULL;
    PKCS7_RECIP_INFO *ri = NULL;
    ASN1_OCTET_STRING *os = NULL;

    if (p7 == NULL) {
        PKCS7err(PKCS7_F_PKCS7_DATAINIT, PKCS7_R_INVALID_NULL_POINTER);
        return NULL;
    }
    /*
     * The content field in the PKCS7 ContentInfo is optional, but that really
     * only applies to inner content (precisely, detached signatures).
     *
     * When reading content, missing outer content is therefore treated as an
     * error.
     *
     * When creating content, PKCS7_content_new() must be called before
     * calling this method, so a NULL p7->d is always an error.
     */
    if (p7->d.ptr == NULL) {
        PKCS7err(PKCS7_F_PKCS7_DATAINIT, PKCS7_R_NO_CONTENT);
        return NULL;
    }

    i = OBJ_obj2nid(p7->type);
    p7->state = PKCS7_S_HEADER;

    switch (i) {
    case NID_pkcs7_signed:
        md_sk = p7->d.sign->md_algs;
        os = PKCS7_get_octet_string(p7->d.sign->contents);
        break;
    case NID_pkcs7_signedAndEnveloped:
        rsk = p7->d.signed_and_enveloped->recipientinfo;
        md_sk = p7->d.signed_and_enveloped->md_algs;
        xalg = p7->d.signed_and_enveloped->enc_data->algorithm;
        evp_cipher = p7->d.signed_and_enveloped->enc_data->cipher;
        if (evp_cipher == NULL) {
            PKCS7err(PKCS7_F_PKCS7_DATAINIT, PKCS7_R_CIPHER_NOT_INITIALIZED);
            goto err;
        }
        break;
    case NID_pkcs7_enveloped:
        rsk = p7->d.enveloped->recipientinfo;
        xalg = p7->d.enveloped->enc_data->algorithm;
        evp_cipher = p7->d.enveloped->enc_data->cipher;
        if (evp_cipher == NULL) {
            PKCS7err(PKCS7_F_PKCS7_DATAINIT, PKCS7_R_CIPHER_NOT_INITIALIZED);
            goto err;
        }
        break;
    case NID_pkcs7_digest:
        xa = p7->d.digest->md;
        os = PKCS7_get_octet_string(p7->d.digest->contents);
        break;
    case NID_pkcs7_data:
        break;
    default:
        PKCS7err(PKCS7_F_PKCS7_DATAINIT, PKCS7_R_UNSUPPORTED_CONTENT_TYPE);
        goto err;
    }

    for (i = 0; i < sk_X509_ALGOR_num(md_sk); i++)
        if (!PKCS7_bio_add_digest(&out, sk_X509_ALGOR_value(md_sk, i)))
            goto err;

    if (xa && !PKCS7_bio_add_digest(&out, xa))
        goto err;

    if (evp_cipher != NULL) {
        unsigned char key[EVP_MAX_KEY_LENGTH];
        unsigned char iv[EVP_MAX_IV_LENGTH];
        int keylen, ivlen;
        EVP_CIPHER_CTX *ctx;

        if ((btmp = BIO_new(BIO_f_cipher())) == NULL) {
            PKCS7err(PKCS7_F_PKCS7_DATAINIT, ERR_R_BIO_LIB);
            goto err;
        }
        BIO_get_cipher_ctx(btmp, &ctx);
        keylen = EVP_CIPHER_key_length(evp_cipher);
        ivlen = EVP_CIPHER_iv_length(evp_cipher);
        xalg->algorithm = OBJ_nid2obj(EVP_CIPHER_type(evp_cipher));
        if (ivlen > 0)
            if (RAND_pseudo_bytes(iv, ivlen) <= 0)
                goto err;
        if (EVP_CipherInit_ex(ctx, evp_cipher, NULL, NULL, NULL, 1) <= 0)
            goto err;
        if (EVP_CIPHER_CTX_rand_key(ctx, key) <= 0)
            goto err;
        if (EVP_CipherInit_ex(ctx, NULL, NULL, key, iv, 1) <= 0)
            goto err;

        if (ivlen > 0) {
            if (xalg->parameter == NULL) {
                xalg->parameter = ASN1_TYPE_new();
                if (xalg->parameter == NULL)
                    goto err;
            }
            if (EVP_CIPHER_param_to_asn1(ctx, xalg->parameter) < 0)
                goto err;
        }

        /* Lets do the pub key stuff :-) */
        for (i = 0; i < sk_PKCS7_RECIP_INFO_num(rsk); i++) {
            ri = sk_PKCS7_RECIP_INFO_value(rsk, i);
            if (pkcs7_encode_rinfo(ri, key, keylen) <= 0)
                goto err;
        }
        OPENSSL_cleanse(key, keylen);

        if (out == NULL)
            out = btmp;
        else
            BIO_push(out, btmp);
        btmp = NULL;
    }

    if (bio == NULL) {
        if (PKCS7_is_detached(p7))
            bio = BIO_new(BIO_s_null());
        else if (os && os->length > 0)
            bio = BIO_new_mem_buf(os->data, os->length);
        if (bio == NULL) {
            bio = BIO_new(BIO_s_mem());
            if (bio == NULL)
                goto err;
            BIO_set_mem_eof_return(bio, 0);
        }
    }
    if (out)
        BIO_push(out, bio);
    else
        out = bio;
    bio = NULL;
    if (0) {
 err:
        if (out != NULL)
            BIO_free_all(out);
        if (btmp != NULL)
            BIO_free_all(btmp);
        out = NULL;
    }
    return (out);
}
Exemple #24
0
/*
 * NOTE: Transfers control of the BIOs - this function will free them on error
 */
int create_ssl_connection(SSL_CTX *serverctx, SSL_CTX *clientctx, SSL **sssl,
                          SSL **cssl, BIO *s_to_c_fbio, BIO *c_to_s_fbio)
{
    int retc = -1, rets = -1, err, abortctr = 0;
    int clienterr = 0, servererr = 0;
    SSL *serverssl, *clientssl;
    BIO *s_to_c_bio = NULL, *c_to_s_bio = NULL;

    if (*sssl == NULL)
        serverssl = SSL_new(serverctx);
    else
        serverssl = *sssl;
    if (*cssl == NULL)
        clientssl = SSL_new(clientctx);
    else
        clientssl = *cssl;

    if (serverssl == NULL || clientssl == NULL) {
        printf("Failed to create SSL object\n");
        goto error;
    }

    s_to_c_bio = BIO_new(BIO_s_mem());
    c_to_s_bio = BIO_new(BIO_s_mem());
    if (s_to_c_bio == NULL || c_to_s_bio == NULL) {
        printf("Failed to create mem BIOs\n");
        goto error;
    }

    if (s_to_c_fbio != NULL)
        s_to_c_bio = BIO_push(s_to_c_fbio, s_to_c_bio);
    if (c_to_s_fbio != NULL)
        c_to_s_bio = BIO_push(c_to_s_fbio, c_to_s_bio);
    if (s_to_c_bio == NULL || c_to_s_bio == NULL) {
        printf("Failed to create chained BIOs\n");
        goto error;
    }

    /* Set Non-blocking IO behaviour */
    BIO_set_mem_eof_return(s_to_c_bio, -1);
    BIO_set_mem_eof_return(c_to_s_bio, -1);

    /* Up ref these as we are passing them to two SSL objects */
    BIO_up_ref(s_to_c_bio);
    BIO_up_ref(c_to_s_bio);

    SSL_set_bio(serverssl, c_to_s_bio, s_to_c_bio);
    SSL_set_bio(clientssl, s_to_c_bio, c_to_s_bio);

    /* BIOs will now be freed when SSL objects are freed */
    s_to_c_bio = c_to_s_bio = NULL;
    s_to_c_fbio = c_to_s_fbio = NULL;

    do {
        err = SSL_ERROR_WANT_WRITE;
        while (!clienterr && retc <= 0 && err == SSL_ERROR_WANT_WRITE) {
            retc = SSL_connect(clientssl);
            if (retc <= 0)
                err = SSL_get_error(clientssl, retc);
        }

        if (!clienterr && retc <= 0 && err != SSL_ERROR_WANT_READ) {
            printf("SSL_connect() failed %d, %d\n", retc, err);
            clienterr = 1;
        }

        err = SSL_ERROR_WANT_WRITE;
        while (!servererr && rets <= 0 && err == SSL_ERROR_WANT_WRITE) {
            rets = SSL_accept(serverssl);
            if (rets <= 0)
                err = SSL_get_error(serverssl, rets);
        }

        if (!servererr && rets <= 0 && err != SSL_ERROR_WANT_READ) {
            printf("SSL_accept() failed %d, %d\n", retc, err);
            servererr = 1;
        }
        if (clienterr && servererr)
            goto error;
        if (++abortctr == MAXLOOPS) {
            printf("No progress made\n");
            goto error;
        }
    } while (retc <=0 || rets <= 0);

    *sssl = serverssl;
    *cssl = clientssl;

    return 1;

 error:
    if (*sssl == NULL) {
        SSL_free(serverssl);
        BIO_free(s_to_c_bio);
        BIO_free(s_to_c_fbio);
    }
    if (*cssl == NULL) {
        SSL_free(clientssl);
        BIO_free(c_to_s_bio);
        BIO_free(c_to_s_fbio);
    }

    return 0;
}
Exemple #25
0
int dtls_netsock_init(const STREAM_DTLS_CTXT_T *pDtlsCtxt, 
                      NETIO_SOCK_T *pnetsock, 
                      const DTLS_FINGERPRINT_VERIFY_T *pFingerprintVerify,
                      const DTLS_KEY_UPDATE_CTXT_T *pKeysUpdateCtxt) {
  int rc = 0;

  if(!pDtlsCtxt || !pnetsock) {
    return -1;
  }

  if(!pnetsock || PNETIOSOCK_FD(pnetsock) == INVALID_SOCKET) {
    return -1;
  }

  pthread_mutex_lock(&((STREAM_DTLS_CTXT_T *) pDtlsCtxt)->mtx);

  if(pDtlsCtxt->active != 1) {
    pthread_mutex_unlock(&((STREAM_DTLS_CTXT_T *) pDtlsCtxt)->mtx);
    return -1;
  }

  if(!(pnetsock->ssl.pCtxt = SSL_new(pDtlsCtxt->pctx))) {
    LOG(X_ERROR("DTLS SSL_new failed: %s"), ERR_reason_error_string(ERR_get_error()));
    rc = -1;
  }
  pnetsock->ssl.ownCtxt = 1;

  if(rc >= 0 && !(pnetsock->ssl.pBioRd = BIO_new(BIO_s_mem()))) {
    LOG(X_ERROR("DTLS BIO_new (reader) failed: %s"), ERR_reason_error_string(ERR_get_error()));
    rc = -1;
  }
  pnetsock->ssl.ownBioRd = 1;

  if(rc >= 0 && !(pnetsock->ssl.pBioWr = BIO_new(BIO_s_mem()))) {
    LOG(X_ERROR("DTLS BIO_new (writer) failed: %s"), ERR_reason_error_string(ERR_get_error()));
    rc = -1;
  }
  pnetsock->ssl.ownBioWr = 1;

  if(rc >= 0) {

    BIO_set_mem_eof_return(pnetsock->ssl.pBioRd, -1);
    BIO_set_mem_eof_return(pnetsock->ssl.pBioWr, -1);

    SSL_set_bio(pnetsock->ssl.pCtxt, pnetsock->ssl.pBioRd, pnetsock->ssl.pBioWr);
    pnetsock->ssl.ownBioRd = 0;
    pnetsock->ssl.ownBioWr = 0;

    SSL_set_mode(pnetsock->ssl.pCtxt, SSL_MODE_AUTO_RETRY);

    SSL_set_read_ahead(pnetsock->ssl.pCtxt, 1);

    //SSL_set_connect_state(pnetsock->ssl.pCtxt);
    //SSL_set_accept_state(pnetsock->ssl.pCtxt);

    if(pFingerprintVerify) {
      if(s_sslCbDataIndex == -1) {
        s_sslCbDataIndex = SSL_get_ex_new_index(0, "verifycbIndex", NULL, NULL, NULL);
      }
      SSL_set_verify(pnetsock->ssl.pCtxt, (SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT), dtls_verify_cb);
      SSL_set_ex_data(pnetsock->ssl.pCtxt, s_sslCbDataIndex, (void *) pFingerprintVerify);
      //LOG(X_DEBUG("SSL_set_ex_data index:%d, pFingerprintVerify: 0x%x"), s_sslCbDataIndex, pFingerprintVerify);
    }

  }

  pnetsock->ssl.pDtlsCtxt = pDtlsCtxt;

  pnetsock->flags |= NETIO_FLAG_SSL_DTLS;
  if(pDtlsCtxt->dtls_srtp) {
    pnetsock->flags |= NETIO_FLAG_SRTP;
    if(pKeysUpdateCtxt) {
      memcpy(&pnetsock->ssl.dtlsKeysUpdateCtxt, pKeysUpdateCtxt, sizeof(pnetsock->ssl.dtlsKeysUpdateCtxt));
    }
  }

  pthread_mutex_unlock(&((STREAM_DTLS_CTXT_T *) pDtlsCtxt)->mtx);

  return rc;
}
int PKCS7_dataFinal(PKCS7 *p7, BIO *bio)
	{
	int ret=0;
	int i,j;
	BIO *btmp;
	BUF_MEM *buf_mem=NULL;
	BUF_MEM *buf=NULL;
	PKCS7_SIGNER_INFO *si;
	EVP_MD_CTX *mdc,ctx_tmp;
	STACK_OF(X509_ATTRIBUTE) *sk;
	STACK_OF(PKCS7_SIGNER_INFO) *si_sk=NULL;
	ASN1_OCTET_STRING *os=NULL;

	EVP_MD_CTX_init(&ctx_tmp);
	i=OBJ_obj2nid(p7->type);
	p7->state=PKCS7_S_HEADER;

	switch (i)
		{
	case NID_pkcs7_signedAndEnveloped:
		/* XXXXXXXXXXXXXXXX */
		si_sk=p7->d.signed_and_enveloped->signer_info;
		if (!(os=M_ASN1_OCTET_STRING_new()))
			{
			PKCS7err(PKCS7_F_PKCS7_DATAFINAL,ERR_R_MALLOC_FAILURE);
			goto err;
			}
		p7->d.signed_and_enveloped->enc_data->enc_data=os;
		break;
	case NID_pkcs7_enveloped:
		/* XXXXXXXXXXXXXXXX */
		if (!(os=M_ASN1_OCTET_STRING_new()))
			{
			PKCS7err(PKCS7_F_PKCS7_DATAFINAL,ERR_R_MALLOC_FAILURE);
			goto err;
			}
		p7->d.enveloped->enc_data->enc_data=os;
		break;
	case NID_pkcs7_signed:
		si_sk=p7->d.sign->signer_info;
		os=PKCS7_get_octet_string(p7->d.sign->contents);
		/* If detached data then the content is excluded */
		if(PKCS7_type_is_data(p7->d.sign->contents) && p7->detached) {
			M_ASN1_OCTET_STRING_free(os);
			p7->d.sign->contents->d.data = NULL;
		}
		break;

	case NID_pkcs7_digest:
		os=PKCS7_get_octet_string(p7->d.digest->contents);
		/* If detached data then the content is excluded */
		if(PKCS7_type_is_data(p7->d.digest->contents) && p7->detached)
			{
			M_ASN1_OCTET_STRING_free(os);
			p7->d.digest->contents->d.data = NULL;
			}
		break;

		}

	if (si_sk != NULL)
		{
		if ((buf=BUF_MEM_new()) == NULL)
			{
			PKCS7err(PKCS7_F_PKCS7_DATAFINAL,ERR_R_BIO_LIB);
			goto err;
			}
		for (i=0; i<sk_PKCS7_SIGNER_INFO_num(si_sk); i++)
			{
			si=sk_PKCS7_SIGNER_INFO_value(si_sk,i);
			if (si->pkey == NULL) continue;

			j=OBJ_obj2nid(si->digest_alg->algorithm);

			btmp=bio;

			btmp = PKCS7_find_digest(&mdc, btmp, j);

			if (btmp == NULL)
				goto err;

			/* We now have the EVP_MD_CTX, lets do the
			 * signing. */
			EVP_MD_CTX_copy_ex(&ctx_tmp,mdc);
			if (!BUF_MEM_grow_clean(buf,EVP_PKEY_size(si->pkey)))
				{
				PKCS7err(PKCS7_F_PKCS7_DATAFINAL,ERR_R_BIO_LIB);
				goto err;
				}

			sk=si->auth_attr;

			/* If there are attributes, we add the digest
			 * attribute and only sign the attributes */
			if ((sk != NULL) && (sk_X509_ATTRIBUTE_num(sk) != 0))
				{
				unsigned char md_data[EVP_MAX_MD_SIZE], *abuf=NULL;
				unsigned int md_len, alen;
				ASN1_OCTET_STRING *digest;
				ASN1_UTCTIME *sign_time;
				const EVP_MD *md_tmp;

				/* Add signing time if not already present */
				if (!PKCS7_get_signed_attribute(si,
							NID_pkcs9_signingTime))
					{
					if (!(sign_time=X509_gmtime_adj(NULL,0)))
						{
						PKCS7err(PKCS7_F_PKCS7_DATAFINAL,
							ERR_R_MALLOC_FAILURE);
						goto err;
						}
					PKCS7_add_signed_attribute(si,
						NID_pkcs9_signingTime,
						V_ASN1_UTCTIME,sign_time);
					}

				/* Add digest */
				md_tmp=EVP_MD_CTX_md(&ctx_tmp);
				EVP_DigestFinal_ex(&ctx_tmp,md_data,&md_len);
				if (!(digest=M_ASN1_OCTET_STRING_new()))
					{
					PKCS7err(PKCS7_F_PKCS7_DATAFINAL,
						ERR_R_MALLOC_FAILURE);
					goto err;
					}
				if (!M_ASN1_OCTET_STRING_set(digest,md_data,
								md_len))
					{
					PKCS7err(PKCS7_F_PKCS7_DATAFINAL,
						ERR_R_MALLOC_FAILURE);
					goto err;
					}
				PKCS7_add_signed_attribute(si,
					NID_pkcs9_messageDigest,
					V_ASN1_OCTET_STRING,digest);

				/* Now sign the attributes */
				EVP_SignInit_ex(&ctx_tmp,md_tmp,NULL);
				alen = ASN1_item_i2d((ASN1_VALUE *)sk,&abuf,
							ASN1_ITEM_rptr(PKCS7_ATTR_SIGN));
				if(!abuf) goto err;
				EVP_SignUpdate(&ctx_tmp,abuf,alen);
				OPENSSL_free(abuf);
				}

#ifndef OPENSSL_NO_DSA
			if (si->pkey->type == EVP_PKEY_DSA)
				ctx_tmp.digest=EVP_dss1();
#endif
#ifndef OPENSSL_NO_ECDSA
 			if (si->pkey->type == EVP_PKEY_EC)
 				ctx_tmp.digest=EVP_ecdsa();
#endif

			if (!EVP_SignFinal(&ctx_tmp,(unsigned char *)buf->data,
				(unsigned int *)&buf->length,si->pkey))
				{
				PKCS7err(PKCS7_F_PKCS7_DATAFINAL,ERR_R_EVP_LIB);
				goto err;
				}
			if (!ASN1_STRING_set(si->enc_digest,
				(unsigned char *)buf->data,buf->length))
				{
				PKCS7err(PKCS7_F_PKCS7_DATAFINAL,ERR_R_ASN1_LIB);
				goto err;
				}
			}
		}
	else if (i == NID_pkcs7_digest)
		{
		unsigned char md_data[EVP_MAX_MD_SIZE];
		unsigned int md_len;
		if (!PKCS7_find_digest(&mdc, bio,
				OBJ_obj2nid(p7->d.digest->md->algorithm)))
			goto err;
		EVP_DigestFinal_ex(mdc,md_data,&md_len);
		M_ASN1_OCTET_STRING_set(p7->d.digest->digest, md_data, md_len);
		}

	if (!PKCS7_is_detached(p7))
		{
		btmp=BIO_find_type(bio,BIO_TYPE_MEM);
		if (btmp == NULL)
			{
			PKCS7err(PKCS7_F_PKCS7_DATAFINAL,PKCS7_R_UNABLE_TO_FIND_MEM_BIO);
			goto err;
			}
		BIO_get_mem_ptr(btmp,&buf_mem);
		/* Mark the BIO read only then we can use its copy of the data
		 * instead of making an extra copy.
		 */
		BIO_set_flags(btmp, BIO_FLAGS_MEM_RDONLY);
		BIO_set_mem_eof_return(btmp, 0);
		os->data = (unsigned char *)buf_mem->data;
		os->length = buf_mem->length;
#if 0
		M_ASN1_OCTET_STRING_set(os,
			(unsigned char *)buf_mem->data,buf_mem->length);
#endif
		}
	ret=1;
err:
	EVP_MD_CTX_cleanup(&ctx_tmp);
	if (buf != NULL) BUF_MEM_free(buf);
	return(ret);
	}
/* int */
BIO *PKCS7_dataDecode(PKCS7 *p7, EVP_PKEY *pkey, BIO *in_bio, X509 *pcert)
	{
	int i,j;
	BIO *out=NULL,*btmp=NULL,*etmp=NULL,*bio=NULL;
	unsigned char *tmp=NULL;
	X509_ALGOR *xa;
	ASN1_OCTET_STRING *data_body=NULL;
	const EVP_MD *evp_md;
	const EVP_CIPHER *evp_cipher=NULL;
	EVP_CIPHER_CTX *evp_ctx=NULL;
	X509_ALGOR *enc_alg=NULL;
	STACK_OF(X509_ALGOR) *md_sk=NULL;
	STACK_OF(PKCS7_RECIP_INFO) *rsk=NULL;
	X509_ALGOR *xalg=NULL;
	PKCS7_RECIP_INFO *ri=NULL;

	i=OBJ_obj2nid(p7->type);
	p7->state=PKCS7_S_HEADER;

	switch (i)
		{
	case NID_pkcs7_signed:
		data_body=PKCS7_get_octet_string(p7->d.sign->contents);
		md_sk=p7->d.sign->md_algs;
		break;
	case NID_pkcs7_signedAndEnveloped:
		rsk=p7->d.signed_and_enveloped->recipientinfo;
		md_sk=p7->d.signed_and_enveloped->md_algs;
		data_body=p7->d.signed_and_enveloped->enc_data->enc_data;
		enc_alg=p7->d.signed_and_enveloped->enc_data->algorithm;
		evp_cipher=EVP_get_cipherbyobj(enc_alg->algorithm);
		if (evp_cipher == NULL)
			{
			PKCS7err(PKCS7_F_PKCS7_DATADECODE,PKCS7_R_UNSUPPORTED_CIPHER_TYPE);
			goto err;
			}
		xalg=p7->d.signed_and_enveloped->enc_data->algorithm;
		break;
	case NID_pkcs7_enveloped:
		rsk=p7->d.enveloped->recipientinfo;
		enc_alg=p7->d.enveloped->enc_data->algorithm;
		data_body=p7->d.enveloped->enc_data->enc_data;
		evp_cipher=EVP_get_cipherbyobj(enc_alg->algorithm);
		if (evp_cipher == NULL)
			{
			PKCS7err(PKCS7_F_PKCS7_DATADECODE,PKCS7_R_UNSUPPORTED_CIPHER_TYPE);
			goto err;
			}
		xalg=p7->d.enveloped->enc_data->algorithm;
		break;
	default:
		PKCS7err(PKCS7_F_PKCS7_DATADECODE,PKCS7_R_UNSUPPORTED_CONTENT_TYPE);
	        goto err;
		}

	/* We will be checking the signature */
	if (md_sk != NULL)
		{
		for (i=0; i<sk_X509_ALGOR_num(md_sk); i++)
			{
			xa=sk_X509_ALGOR_value(md_sk,i);
			if ((btmp=BIO_new(BIO_f_md())) == NULL)
				{
				PKCS7err(PKCS7_F_PKCS7_DATADECODE,ERR_R_BIO_LIB);
				goto err;
				}

			j=OBJ_obj2nid(xa->algorithm);
			evp_md=EVP_get_digestbynid(j);
			if (evp_md == NULL)
				{
				PKCS7err(PKCS7_F_PKCS7_DATADECODE,PKCS7_R_UNKNOWN_DIGEST_TYPE);
				goto err;
				}

			BIO_set_md(btmp,evp_md);
			if (out == NULL)
				out=btmp;
			else
				BIO_push(out,btmp);
			btmp=NULL;
			}
		}

	if (evp_cipher != NULL)
		{
#if 0
		unsigned char key[EVP_MAX_KEY_LENGTH];
		unsigned char iv[EVP_MAX_IV_LENGTH];
		unsigned char *p;
		int keylen,ivlen;
		int max;
		X509_OBJECT ret;
#endif
		int jj;

		if ((etmp=BIO_new(BIO_f_cipher())) == NULL)
			{
			PKCS7err(PKCS7_F_PKCS7_DATADECODE,ERR_R_BIO_LIB);
			goto err;
			}

		/* It was encrypted, we need to decrypt the secret key
		 * with the private key */

		/* Find the recipientInfo which matches the passed certificate
		 * (if any)
		 */

		if (pcert) {
			for (i=0; i<sk_PKCS7_RECIP_INFO_num(rsk); i++) {
				ri=sk_PKCS7_RECIP_INFO_value(rsk,i);
				if (!pkcs7_cmp_ri(ri, pcert))
					break;
				ri=NULL;
			}
			if (ri == NULL) {
				PKCS7err(PKCS7_F_PKCS7_DATADECODE,
				      PKCS7_R_NO_RECIPIENT_MATCHES_CERTIFICATE);
				goto err;
			}
		}

		jj=EVP_PKEY_size(pkey);
		tmp=(unsigned char *)OPENSSL_malloc(jj+10);
		if (tmp == NULL)
			{
			PKCS7err(PKCS7_F_PKCS7_DATADECODE,ERR_R_MALLOC_FAILURE);
			goto err;
			}

		/* If we haven't got a certificate try each ri in turn */

		if (pcert == NULL)
			{
			for (i=0; i<sk_PKCS7_RECIP_INFO_num(rsk); i++)
				{
				ri=sk_PKCS7_RECIP_INFO_value(rsk,i);
				jj=EVP_PKEY_decrypt(tmp,
					M_ASN1_STRING_data(ri->enc_key),
					M_ASN1_STRING_length(ri->enc_key),
						pkey);
				if (jj > 0)
					break;
				ERR_clear_error();
				ri = NULL;
				}
			if (ri == NULL)
				{
				PKCS7err(PKCS7_F_PKCS7_DATADECODE,
				      PKCS7_R_NO_RECIPIENT_MATCHES_KEY);
				goto err;
				}
			}
		else
			{
			jj=EVP_PKEY_decrypt(tmp,
				M_ASN1_STRING_data(ri->enc_key),
				M_ASN1_STRING_length(ri->enc_key), pkey);
			if (jj <= 0)
				{
				PKCS7err(PKCS7_F_PKCS7_DATADECODE,
								ERR_R_EVP_LIB);
				goto err;
				}
			}

		evp_ctx=NULL;
		BIO_get_cipher_ctx(etmp,&evp_ctx);
		if (EVP_CipherInit_ex(evp_ctx,evp_cipher,NULL,NULL,NULL,0) <= 0)
			goto err;
		if (EVP_CIPHER_asn1_to_param(evp_ctx,enc_alg->parameter) < 0)
			goto err;

		if (jj != EVP_CIPHER_CTX_key_length(evp_ctx)) {
			/* Some S/MIME clients don't use the same key
			 * and effective key length. The key length is
			 * determined by the size of the decrypted RSA key.
			 */
			if(!EVP_CIPHER_CTX_set_key_length(evp_ctx, jj))
				{
				PKCS7err(PKCS7_F_PKCS7_DATADECODE,
					PKCS7_R_DECRYPTED_KEY_IS_WRONG_LENGTH);
				goto err;
				}
		} 
		if (EVP_CipherInit_ex(evp_ctx,NULL,NULL,tmp,NULL,0) <= 0)
			goto err;

		OPENSSL_cleanse(tmp,jj);

		if (out == NULL)
			out=etmp;
		else
			BIO_push(out,etmp);
		etmp=NULL;
		}

#if 1
	if (PKCS7_is_detached(p7) || (in_bio != NULL))
		{
		bio=in_bio;
		}
	else 
		{
#if 0
		bio=BIO_new(BIO_s_mem());
		/* We need to set this so that when we have read all
		 * the data, the encrypt BIO, if present, will read
		 * EOF and encode the last few bytes */
		BIO_set_mem_eof_return(bio,0);

		if (data_body->length > 0)
			BIO_write(bio,(char *)data_body->data,data_body->length);
#else
		if (data_body->length > 0)
		      bio = BIO_new_mem_buf(data_body->data,data_body->length);
		else {
			bio=BIO_new(BIO_s_mem());
			BIO_set_mem_eof_return(bio,0);
		}
#endif
		}
	BIO_push(out,bio);
	bio=NULL;
#endif
	if (0)
		{
err:
		if (out != NULL) BIO_free_all(out);
		if (btmp != NULL) BIO_free_all(btmp);
		if (etmp != NULL) BIO_free_all(etmp);
		if (bio != NULL) BIO_free_all(bio);
		out=NULL;
		}
	if (tmp != NULL)
		OPENSSL_free(tmp);
	return(out);
	}
BIO *PKCS7_dataInit(PKCS7 *p7, BIO *bio)
	{
	int i;
	BIO *out=NULL,*btmp=NULL;
	X509_ALGOR *xa = NULL;
	const EVP_CIPHER *evp_cipher=NULL;
	STACK_OF(X509_ALGOR) *md_sk=NULL;
	STACK_OF(PKCS7_RECIP_INFO) *rsk=NULL;
	X509_ALGOR *xalg=NULL;
	PKCS7_RECIP_INFO *ri=NULL;
	EVP_PKEY *pkey;
	ASN1_OCTET_STRING *os=NULL;

	i=OBJ_obj2nid(p7->type);
	p7->state=PKCS7_S_HEADER;

	switch (i)
		{
	case NID_pkcs7_signed:
		md_sk=p7->d.sign->md_algs;
		os = PKCS7_get_octet_string(p7->d.sign->contents);
		break;
	case NID_pkcs7_signedAndEnveloped:
		rsk=p7->d.signed_and_enveloped->recipientinfo;
		md_sk=p7->d.signed_and_enveloped->md_algs;
		xalg=p7->d.signed_and_enveloped->enc_data->algorithm;
		evp_cipher=p7->d.signed_and_enveloped->enc_data->cipher;
		if (evp_cipher == NULL)
			{
			PKCS7err(PKCS7_F_PKCS7_DATAINIT,
						PKCS7_R_CIPHER_NOT_INITIALIZED);
			goto err;
			}
		break;
	case NID_pkcs7_enveloped:
		rsk=p7->d.enveloped->recipientinfo;
		xalg=p7->d.enveloped->enc_data->algorithm;
		evp_cipher=p7->d.enveloped->enc_data->cipher;
		if (evp_cipher == NULL)
			{
			PKCS7err(PKCS7_F_PKCS7_DATAINIT,
						PKCS7_R_CIPHER_NOT_INITIALIZED);
			goto err;
			}
		break;
	case NID_pkcs7_digest:
		xa = p7->d.digest->md;
		os = PKCS7_get_octet_string(p7->d.digest->contents);
		break;
	default:
		PKCS7err(PKCS7_F_PKCS7_DATAINIT,PKCS7_R_UNSUPPORTED_CONTENT_TYPE);
	        goto err;
		}

	for (i=0; i<sk_X509_ALGOR_num(md_sk); i++)
		if (!PKCS7_bio_add_digest(&out, sk_X509_ALGOR_value(md_sk, i)))
			goto err;

	if (xa && !PKCS7_bio_add_digest(&out, xa))
			goto err;

	if (evp_cipher != NULL)
		{
		unsigned char key[EVP_MAX_KEY_LENGTH];
		unsigned char iv[EVP_MAX_IV_LENGTH];
		int keylen,ivlen;
		int jj,max;
		unsigned char *tmp;
		EVP_CIPHER_CTX *ctx;

		if ((btmp=BIO_new(BIO_f_cipher())) == NULL)
			{
			PKCS7err(PKCS7_F_PKCS7_DATAINIT,ERR_R_BIO_LIB);
			goto err;
			}
		BIO_get_cipher_ctx(btmp, &ctx);
		keylen=EVP_CIPHER_key_length(evp_cipher);
		ivlen=EVP_CIPHER_iv_length(evp_cipher);
		xalg->algorithm = OBJ_nid2obj(EVP_CIPHER_type(evp_cipher));
		if (ivlen > 0) RAND_pseudo_bytes(iv,ivlen);
		if (EVP_CipherInit_ex(ctx, evp_cipher, NULL, NULL, NULL, 1)<=0)
			goto err;
		if (EVP_CIPHER_CTX_rand_key(ctx, key) <= 0)
			goto err;
		if (EVP_CipherInit_ex(ctx, NULL, NULL, key, iv, 1) <= 0)
			goto err;

		if (ivlen > 0) {
			if (xalg->parameter == NULL) 
						xalg->parameter=ASN1_TYPE_new();
			if(EVP_CIPHER_param_to_asn1(ctx, xalg->parameter) < 0)
								       goto err;
		}

		/* Lets do the pub key stuff :-) */
		max=0;
		for (i=0; i<sk_PKCS7_RECIP_INFO_num(rsk); i++)
			{
			ri=sk_PKCS7_RECIP_INFO_value(rsk,i);
			if (ri->cert == NULL)
				{
				PKCS7err(PKCS7_F_PKCS7_DATAINIT,PKCS7_R_MISSING_CERIPEND_INFO);
				goto err;
				}
			pkey=X509_get_pubkey(ri->cert);
			jj=EVP_PKEY_size(pkey);
			EVP_PKEY_free(pkey);
			if (max < jj) max=jj;
			}
		if ((tmp=(unsigned char *)OPENSSL_malloc(max)) == NULL)
			{
			PKCS7err(PKCS7_F_PKCS7_DATAINIT,ERR_R_MALLOC_FAILURE);
			goto err;
			}
		for (i=0; i<sk_PKCS7_RECIP_INFO_num(rsk); i++)
			{
			ri=sk_PKCS7_RECIP_INFO_value(rsk,i);
			pkey=X509_get_pubkey(ri->cert);
			jj=EVP_PKEY_encrypt(tmp,key,keylen,pkey);
			EVP_PKEY_free(pkey);
			if (jj <= 0)
				{
				PKCS7err(PKCS7_F_PKCS7_DATAINIT,ERR_R_EVP_LIB);
				OPENSSL_free(tmp);
				goto err;
				}
			if (!M_ASN1_OCTET_STRING_set(ri->enc_key,tmp,jj))
				{
				PKCS7err(PKCS7_F_PKCS7_DATAINIT,
					ERR_R_MALLOC_FAILURE);
				OPENSSL_free(tmp);
				goto err;
				}
			}
		OPENSSL_free(tmp);
		OPENSSL_cleanse(key, keylen);

		if (out == NULL)
			out=btmp;
		else
			BIO_push(out,btmp);
		btmp=NULL;
		}

	if (bio == NULL)
		{
		if (PKCS7_is_detached(p7))
			bio=BIO_new(BIO_s_null());
		else if (os && os->length > 0)
			bio = BIO_new_mem_buf(os->data, os->length);
		if(bio == NULL)
			{
			bio=BIO_new(BIO_s_mem());
			BIO_set_mem_eof_return(bio,0);
			}
		}
	BIO_push(out,bio);
	bio=NULL;
	if (0)
		{
err:
		if (out != NULL)
			BIO_free_all(out);
		if (btmp != NULL)
			BIO_free_all(btmp);
		out=NULL;
		}
	return(out);
	}
Exemple #29
0
void BIO_set_mem_eof_return_shim(BIO *b, int v) {
    BIO_set_mem_eof_return(b, v);
}
unsigned int OpenSSLCryptoKeyRSA::signSHA1PKCS1Base64Signature(unsigned char * hashBuf,
		unsigned int hashLen,
		char * base64SignatureBuf,
		unsigned int base64SignatureBufLen,
		hashMethod hm) {

	// Sign a pre-calculated hash using this key

	if (mp_rsaKey == NULL) {

		throw XSECCryptoException(XSECCryptoException::RSAError,
			"OpenSSL:RSA - Attempt to sign data with empty key");
	}

	// Build the buffer to be encrypted by prepending the SHA1 OID to the hash

	unsigned char * encryptBuf;
	unsigned char * preEncryptBuf;
	unsigned char * oid;
	int oidLen;
	int encryptLen;
	int preEncryptLen;

	oid = getRSASigOID(hm, oidLen);

	if (oid == NULL) {
		throw XSECCryptoException(XSECCryptoException::RSAError,
			"OpenSSL:RSA::sign() - Unsupported HASH algorithm for RSA");
	}

	if (hashLen != oid[oidLen-1]) {
		throw XSECCryptoException(XSECCryptoException::RSAError,
			"OpenSSL:RSA::sign() - hashLen incorrect for hash type");
	}

	preEncryptLen = hashLen + oidLen;
	preEncryptBuf = new unsigned char[preEncryptLen];
	encryptBuf = new unsigned char[RSA_size(mp_rsaKey)];

	memcpy(preEncryptBuf, oid, oidLen);
	memcpy(&preEncryptBuf[oidLen], hashBuf, hashLen);

	// Now encrypt

	encryptLen = RSA_private_encrypt(preEncryptLen,
								     preEncryptBuf,
									 encryptBuf,
									 mp_rsaKey,
									 RSA_PKCS1_PADDING);

	delete[] preEncryptBuf;

	if (encryptLen < 0) {

		delete[] encryptBuf;
		throw XSECCryptoException(XSECCryptoException::RSAError,
			"OpenSSL:RSA::sign() - Error encrypting hash");
	}

	// Now convert to Base 64

	BIO * b64 = BIO_new(BIO_f_base64());
	BIO * bmem = BIO_new(BIO_s_mem());

	BIO_set_mem_eof_return(bmem, 0);
	b64 = BIO_push(b64, bmem);

	// Translate signature to Base64

	BIO_write(b64, encryptBuf, encryptLen);
	BIO_flush(b64);

	unsigned int sigValLen = BIO_read(bmem, base64SignatureBuf, base64SignatureBufLen);

	BIO_free_all(b64);

	delete[] encryptBuf;

	if (sigValLen <= 0) {

		throw XSECCryptoException(XSECCryptoException::DSAError,
			"OpenSSL:RSA - Error base64 encoding signature");
	}

	return sigValLen;
}