static int get_server_hello(SSL *s)
	{
	unsigned char *buf;
	unsigned char *p;
	int i,j;
	unsigned long len;
	STACK_OF(SSL_CIPHER) *sk=NULL,*cl, *prio, *allow;

	buf=(unsigned char *)s->init_buf->data;
	p=buf;
	if (s->state == SSL2_ST_GET_SERVER_HELLO_A)
		{
		i=ssl2_read(s,(char *)&(buf[s->init_num]),11-s->init_num);
		if (i < (11-s->init_num)) 
			return(ssl2_part_read(s,SSL_F_GET_SERVER_HELLO,i));
		s->init_num = 11;

		if (*(p++) != SSL2_MT_SERVER_HELLO)
			{
			if (p[-1] != SSL2_MT_ERROR)
				{
				ssl2_return_error(s,SSL2_PE_UNDEFINED_ERROR);
				SSLerr(SSL_F_GET_SERVER_HELLO,
					SSL_R_READ_WRONG_PACKET_TYPE);
				}
			else
				SSLerr(SSL_F_GET_SERVER_HELLO,
					SSL_R_PEER_ERROR);
			return(-1);
			}
#ifdef __APPLE_CC__
		/* The Rhapsody 5.5 (a.k.a. MacOS X) compiler bug
		 * workaround. <*****@*****.**> */
		s->hit=(i=*(p++))?1:0;
#else
		s->hit=(*(p++))?1:0;
#endif
		s->s2->tmp.cert_type= *(p++);
		n2s(p,i);
		if (i < s->version) s->version=i;
		n2s(p,i); s->s2->tmp.cert_length=i;
		n2s(p,i); s->s2->tmp.csl=i;
		n2s(p,i); s->s2->tmp.conn_id_length=i;
		s->state=SSL2_ST_GET_SERVER_HELLO_B;
		}

	/* SSL2_ST_GET_SERVER_HELLO_B */
	len = 11 + (unsigned long)s->s2->tmp.cert_length + (unsigned long)s->s2->tmp.csl + (unsigned long)s->s2->tmp.conn_id_length;
	if (len > SSL2_MAX_RECORD_LENGTH_3_BYTE_HEADER)
		{
		SSLerr(SSL_F_GET_SERVER_HELLO,SSL_R_MESSAGE_TOO_LONG);
		return -1;
		}
	j = (int)len - s->init_num;
	i = ssl2_read(s,(char *)&(buf[s->init_num]),j);
	if (i != j) return(ssl2_part_read(s,SSL_F_GET_SERVER_HELLO,i));
	if (s->msg_callback)
		s->msg_callback(0, s->version, 0, buf, (size_t)len, s, s->msg_callback_arg); /* SERVER-HELLO */

	/* things are looking good */

	p = buf + 11;
	if (s->hit)
		{
		if (s->s2->tmp.cert_length != 0) 
			{
			SSLerr(SSL_F_GET_SERVER_HELLO,SSL_R_REUSE_CERT_LENGTH_NOT_ZERO);
			return(-1);
			}
		if (s->s2->tmp.cert_type != 0)
			{
			if (!(s->options &
				SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG))
				{
				SSLerr(SSL_F_GET_SERVER_HELLO,SSL_R_REUSE_CERT_TYPE_NOT_ZERO);
				return(-1);
				}
			}
		if (s->s2->tmp.csl != 0)
			{
			SSLerr(SSL_F_GET_SERVER_HELLO,SSL_R_REUSE_CIPHER_LIST_NOT_ZERO);
			return(-1);
			}
		}
	else
		{
#ifdef undef
		/* very bad */
		TINYCLR_SSL_MEMSET(s->session->session_id,0,
			SSL_MAX_SSL_SESSION_ID_LENGTH_IN_BYTES);
		s->session->session_id_length=0;
		*/
#endif

		/* we need to do this in case we were trying to reuse a 
		 * client session but others are already reusing it.
		 * If this was a new 'blank' session ID, the session-id
		 * length will still be 0 */
		if (s->session->session_id_length > 0)
			{
			if (!ssl_get_new_session(s,0))
				{
				ssl2_return_error(s,SSL2_PE_UNDEFINED_ERROR);
				return(-1);
				}
			}

		if (ssl2_set_certificate(s,s->s2->tmp.cert_type,
			s->s2->tmp.cert_length,p) <= 0)
			{
			ssl2_return_error(s,SSL2_PE_BAD_CERTIFICATE);
			return(-1);
			}
		p+=s->s2->tmp.cert_length;

		if (s->s2->tmp.csl == 0)
			{
			ssl2_return_error(s,SSL2_PE_NO_CIPHER);
			SSLerr(SSL_F_GET_SERVER_HELLO,SSL_R_NO_CIPHER_LIST);
			return(-1);
			}

		/* We have just received a list of ciphers back from the
		 * server.  We need to get the ones that match, then select
		 * the one we want the most :-). */

		/* load the ciphers */
		sk=ssl_bytes_to_cipher_list(s,p,s->s2->tmp.csl,
					    &s->session->ciphers);
		p+=s->s2->tmp.csl;
		if (sk == NULL)
			{
			ssl2_return_error(s,SSL2_PE_UNDEFINED_ERROR);
			SSLerr(SSL_F_GET_SERVER_HELLO,ERR_R_MALLOC_FAILURE);
			return(-1);
			}

		(void)sk_SSL_CIPHER_set_cmp_func(sk,ssl_cipher_ptr_id_cmp);

		/* get the array of ciphers we will accept */
		cl=SSL_get_ciphers(s);
		(void)sk_SSL_CIPHER_set_cmp_func(cl,ssl_cipher_ptr_id_cmp);

		/*
		 * If server preference flag set, choose the first
		 * (highest priority) cipher the server sends, otherwise
		 * client preference has priority.
		 */
		if (s->options & SSL_OP_CIPHER_SERVER_PREFERENCE)
		    {
		    prio = sk;
		    allow = cl;
		    }
		else
		    {
		    prio = cl;
		    allow = sk;
		    }
		/* In theory we could have ciphers sent back that we
		 * don't want to use but that does not matter since we
		 * will check against the list we originally sent and
		 * for performance reasons we should not bother to match
		 * the two lists up just to check. */
		for (i=0; i<sk_SSL_CIPHER_num(prio); i++)
			{
			if (sk_SSL_CIPHER_find(allow,
					     sk_SSL_CIPHER_value(prio,i)) >= 0)
				break;
			}

		if (i >= sk_SSL_CIPHER_num(prio))
			{
			ssl2_return_error(s,SSL2_PE_NO_CIPHER);
			SSLerr(SSL_F_GET_SERVER_HELLO,SSL_R_NO_CIPHER_MATCH);
			return(-1);
			}
		s->session->cipher=sk_SSL_CIPHER_value(prio,i);


		if (s->session->peer != NULL) /* can't happen*/
			{
			ssl2_return_error(s, SSL2_PE_UNDEFINED_ERROR);
			SSLerr(SSL_F_GET_SERVER_HELLO, ERR_R_INTERNAL_ERROR);
			return(-1);
			}

		s->session->peer = s->session->sess_cert->peer_key->x509;
		/* peer_key->x509 has been set by ssl2_set_certificate. */
		CRYPTO_add(&s->session->peer->references, 1, CRYPTO_LOCK_X509);
		}

	if (s->session->sess_cert == NULL 
      || s->session->peer != s->session->sess_cert->peer_key->x509)
		/* can't happen */
		{
		ssl2_return_error(s, SSL2_PE_UNDEFINED_ERROR);
		SSLerr(SSL_F_GET_SERVER_HELLO, ERR_R_INTERNAL_ERROR);
		return(-1);
		}
		
	s->s2->conn_id_length=s->s2->tmp.conn_id_length;
	if (s->s2->conn_id_length > sizeof s->s2->conn_id)
		{
		ssl2_return_error(s, SSL2_PE_UNDEFINED_ERROR);
		SSLerr(SSL_F_GET_SERVER_HELLO, SSL_R_SSL2_CONNECTION_ID_TOO_LONG);
		return -1;
		}
	TINYCLR_SSL_MEMCPY(s->s2->conn_id,p,s->s2->tmp.conn_id_length);
	return(1);
	}
static int dev_crypto_cipher(EVP_CIPHER_CTX *ctx,unsigned char *out,
			     const unsigned char *in,unsigned int inl)
    {
    struct crypt_op cryp;
    unsigned char lb[MAX_HW_IV];

    if(!inl)
	return 1;

    TINYCLR_SSL_ASSERT(CDATA(ctx));
    TINYCLR_SSL_ASSERT(!dev_failed);

    TINYCLR_SSL_MEMSET(&cryp,'\0',sizeof cryp);
    cryp.ses=CDATA(ctx)->ses;
    cryp.op=ctx->encrypt ? COP_ENCRYPT : COP_DECRYPT;
    cryp.flags=0;
    cryp.len=inl;
    TINYCLR_SSL_ASSERT((inl&(ctx->cipher->block_size-1)) == 0);
    cryp.src=(caddr_t)in;
    cryp.dst=(caddr_t)out;
    cryp.mac=0;
    if(ctx->cipher->iv_len)
	cryp.iv=(caddr_t)ctx->iv;

    if(!ctx->encrypt)
	TINYCLR_SSL_MEMCPY(lb,&in[cryp.len-ctx->cipher->iv_len],ctx->cipher->iv_len);

    if(TINYCLR_SSL_IOCTL(fd, CIOCCRYPT, &cryp) == -1)
	{
	if(errno == EINVAL) /* buffers are misaligned */
	    {
	    unsigned int cinl=0;
	    char *cin=NULL;
	    char *cout=NULL;

	    /* NB: this can only make cinl != inl with stream ciphers */
	    cinl=(inl+3)/4*4;

	    if(((unsigned long)in&3) || cinl != inl)
		{
		cin=OPENSSL_malloc(cinl);
		TINYCLR_SSL_MEMCPY(cin,in,inl);
		cryp.src=cin;
		}

	    if(((unsigned long)out&3) || cinl != inl)
		{
		cout=OPENSSL_malloc(cinl);
		cryp.dst=cout;
		}

	    cryp.len=cinl;

	    if(TINYCLR_SSL_IOCTL(fd, CIOCCRYPT, &cryp) == -1)
		{
		err("CIOCCRYPT(2) failed");
		TINYCLR_SSL_PRINTF("src=%p dst=%p\n",cryp.src,cryp.dst);
		TINYCLR_SSL_ABORT();
		return 0;
		}
		
	    if(cout)
		{
		TINYCLR_SSL_MEMCPY(out,cout,inl);
		OPENSSL_free(cout);
		}
	    if(cin)
		OPENSSL_free(cin);
	    }
	else 
	    {	    
	    err("CIOCCRYPT failed");
	    TINYCLR_SSL_ABORT();
	    return 0;
	    }
	}

    if(ctx->encrypt)
	TINYCLR_SSL_MEMCPY(ctx->iv,&out[cryp.len-ctx->cipher->iv_len],ctx->cipher->iv_len);
    else
	TINYCLR_SSL_MEMCPY(ctx->iv,lb,ctx->cipher->iv_len);

    return 1;
    }
const char *LP_find_file(LP_DIR_CTX **ctx, const char *directory)
{
  int status;
  char *p, *r;
  size_t l;
  unsigned long flags = 0;
#ifdef NAML$C_MAXRSS
  flags |= LIB$M_FIL_LONG_NAMES;
#endif

  if (ctx == NULL || directory == NULL)
    {
      errno = EINVAL;
      return 0;
    }

  errno = 0;
  if (*ctx == NULL)
    {
      size_t filespeclen = TINYCLR_SSL_STRLEN(directory);
      char *filespec = NULL;

      /* MUST be a VMS directory specification!  Let's estimate if it is. */
      if (directory[filespeclen-1] != ']'
	  && directory[filespeclen-1] != '>'
	  && directory[filespeclen-1] != ':')
	{
	  errno = EINVAL;
	  return 0;
	}

      filespeclen += 4;		/* "*.*;" */

      if (filespeclen >
#ifdef NAML$C_MAXRSS
	  NAML$C_MAXRSS
#else
	  255
#endif
	  )
	{
	  errno = ENAMETOOLONG;
	  return 0;
	}

      *ctx = (LP_DIR_CTX *)OPENSSL_malloc(sizeof(LP_DIR_CTX));
      if (*ctx == NULL)
	{
	  errno = ENOMEM;
	  return 0;
	}
      TINYCLR_SSL_MEMSET(*ctx, '\0', sizeof(LP_DIR_CTX));

      TINYCLR_SSL_STRCPY((*ctx)->filespec,directory);
      TINYCLR_SSL_STRCAT((*ctx)->filespec,"*.*;");
      (*ctx)->filespec_dsc.dsc$w_length = filespeclen;
      (*ctx)->filespec_dsc.dsc$b_dtype = DSC$K_DTYPE_T;
      (*ctx)->filespec_dsc.dsc$b_class = DSC$K_CLASS_S;
      (*ctx)->filespec_dsc.dsc$a_pointer = (*ctx)->filespec;
      (*ctx)->result_dsc.dsc$w_length = 0;
      (*ctx)->result_dsc.dsc$b_dtype = DSC$K_DTYPE_T;
      (*ctx)->result_dsc.dsc$b_class = DSC$K_CLASS_D;
      (*ctx)->result_dsc.dsc$a_pointer = 0;
    }

  (*ctx)->result_dsc.dsc$w_length = 0;
  (*ctx)->result_dsc.dsc$b_dtype = DSC$K_DTYPE_T;
  (*ctx)->result_dsc.dsc$b_class = DSC$K_CLASS_D;
  (*ctx)->result_dsc.dsc$a_pointer = 0;

  status = lib$find_file(&(*ctx)->filespec_dsc, &(*ctx)->result_dsc,
			 &(*ctx)->VMS_context, 0, 0, 0, &flags);

  if (status == RMS$_NMF)
    {
      errno = 0;
      vaxc$errno = status;
      return NULL;
    }

  if(!$VMS_STATUS_SUCCESS(status))
    {
      errno = EVMSERR;
      vaxc$errno = status;
      return NULL;
    }

  /* Quick, cheap and dirty way to discard any device and directory,
     since we only want file names */
  l = (*ctx)->result_dsc.dsc$w_length;
  p = (*ctx)->result_dsc.dsc$a_pointer;
  r = p;
  for (; *p; p++)
    {
      if (*p == '^' && p[1] != '\0') /* Take care of ODS-5 escapes */
	{
	  p++;
	}
      else if (*p == ':' || *p == '>' || *p == ']')
	{
	  l -= p + 1 - r;
	  r = p + 1;
	}
      else if (*p == ';')
	{
	  l = p - r;
	  break;
	}
    }

  TINYCLR_SSL_STRNCPY((*ctx)->result, r, l);
  (*ctx)->result[l] = '\0';
  str$free1_dx(&(*ctx)->result_dsc);

  return (*ctx)->result;
}
void TS_VERIFY_CTX_init(TS_VERIFY_CTX *ctx)
	{
	TINYCLR_SSL_ASSERT(ctx != NULL);
	TINYCLR_SSL_MEMSET(ctx, 0, sizeof(TS_VERIFY_CTX));
	}
int ssl_test_engine(int argc, char *argv[])
	{
	ENGINE *block[512];
	char buf[256];
	const char *id, *name;
	ENGINE *ptr;
	int loop;
	int to_return = 1;
	ENGINE *new_h1 = NULL;
	ENGINE *new_h2 = NULL;
	ENGINE *new_h3 = NULL;
	ENGINE *new_h4 = NULL;

	/* enable memory leak checking unless explicitly disabled */
	if (!((TINYCLR_SSL_GETENV("OPENSSL_DEBUG_MEMORY") != NULL) && (0 == TINYCLR_SSL_STRCMP(TINYCLR_SSL_GETENV("OPENSSL_DEBUG_MEMORY"), "off"))))
		{
		CRYPTO_malloc_debug_init();
		CRYPTO_set_mem_debug_options(V_CRYPTO_MDEBUG_ALL);
		}
	else
		{
		/* OPENSSL_DEBUG_MEMORY=off */
		CRYPTO_set_mem_debug_functions(0, 0, 0, 0, 0);
		}
	CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON);
	ERR_load_crypto_strings();

	TINYCLR_SSL_MEMSET(block, 0, 512 * sizeof(ENGINE *));
	if(((new_h1 = ENGINE_new()) == NULL) ||
			!ENGINE_set_id(new_h1, "test_id0") ||
			!ENGINE_set_name(new_h1, "First test item") ||
			((new_h2 = ENGINE_new()) == NULL) ||
			!ENGINE_set_id(new_h2, "test_id1") ||
			!ENGINE_set_name(new_h2, "Second test item") ||
			((new_h3 = ENGINE_new()) == NULL) ||
			!ENGINE_set_id(new_h3, "test_id2") ||
			!ENGINE_set_name(new_h3, "Third test item") ||
			((new_h4 = ENGINE_new()) == NULL) ||
			!ENGINE_set_id(new_h4, "test_id3") ||
			!ENGINE_set_name(new_h4, "Fourth test item"))
		{
		TINYCLR_SSL_PRINTF("Couldn't set up test ENGINE structures\n");
		goto end;
		}
	TINYCLR_SSL_PRINTF("\nenginetest beginning\n\n");
	display_engine_list();
	if(!ENGINE_add(new_h1))
		{
		TINYCLR_SSL_PRINTF("Add failed!\n");
		goto end;
		}
	display_engine_list();
	ptr = ENGINE_get_first();
	if(!ENGINE_remove(ptr))
		{
		TINYCLR_SSL_PRINTF("Remove failed!\n");
		goto end;
		}
	if (ptr)
		ENGINE_free(ptr);
	display_engine_list();
	if(!ENGINE_add(new_h3) || !ENGINE_add(new_h2))
		{
		TINYCLR_SSL_PRINTF("Add failed!\n");
		goto end;
		}
	display_engine_list();
	if(!ENGINE_remove(new_h2))
		{
		TINYCLR_SSL_PRINTF("Remove failed!\n");
		goto end;
		}
	display_engine_list();
	if(!ENGINE_add(new_h4))
		{
		TINYCLR_SSL_PRINTF("Add failed!\n");
		goto end;
		}
	display_engine_list();
	if(ENGINE_add(new_h3))
		{
		TINYCLR_SSL_PRINTF("Add *should* have failed but didn't!\n");
		goto end;
		}
	else
		TINYCLR_SSL_PRINTF("Add that should fail did.\n");
	ERR_clear_error();
	if(ENGINE_remove(new_h2))
		{
		TINYCLR_SSL_PRINTF("Remove *should* have failed but didn't!\n");
		goto end;
		}
	else
		TINYCLR_SSL_PRINTF("Remove that should fail did.\n");
	ERR_clear_error();
	if(!ENGINE_remove(new_h3))
		{
		TINYCLR_SSL_PRINTF("Remove failed!\n");
		goto end;
		}
	display_engine_list();
	if(!ENGINE_remove(new_h4))
		{
		TINYCLR_SSL_PRINTF("Remove failed!\n");
		goto end;
		}
	display_engine_list();
	/* Depending on whether there's any hardware support compiled
	 * in, this remove may be destined to fail. */
	ptr = ENGINE_get_first();
	if(ptr)
		if(!ENGINE_remove(ptr))
			TINYCLR_SSL_PRINTF("Remove failed!i - probably no hardware "
				"support present.\n");
	if (ptr)
		ENGINE_free(ptr);
	display_engine_list();
	if(!ENGINE_add(new_h1) || !ENGINE_remove(new_h1))
		{
		TINYCLR_SSL_PRINTF("Couldn't add and remove to an empty list!\n");
		goto end;
		}
	else
		TINYCLR_SSL_PRINTF("Successfully added and removed to an empty list!\n");
	TINYCLR_SSL_PRINTF("About to beef up the engine-type list\n");
	for(loop = 0; loop < 512; loop++)
		{
		TINYCLR_SSL_SPRINTF(buf, "id%i", loop);
		id = BUF_strdup(buf);
		TINYCLR_SSL_SPRINTF(buf, "Fake engine type %i", loop);
		name = BUF_strdup(buf);
		if(((block[loop] = ENGINE_new()) == NULL) ||
				!ENGINE_set_id(block[loop], id) ||
				!ENGINE_set_name(block[loop], name))
			{
			TINYCLR_SSL_PRINTF("Couldn't create block of ENGINE structures.\n"
				"I'll probably also core-dump now, damn.\n");
			goto end;
			}
		}
	for(loop = 0; loop < 512; loop++)
		{
		if(!ENGINE_add(block[loop]))
			{
			TINYCLR_SSL_PRINTF("\nAdding stopped at %i, (%s,%s)\n",
				loop, ENGINE_get_id(block[loop]),
				ENGINE_get_name(block[loop]));
			goto cleanup_loop;
			}
		else
			TINYCLR_SSL_PRINTF("."); TINYCLR_SSL_FFLUSH(OPENSSL_TYPE__FILE_STDOUT);
		}
cleanup_loop:
	TINYCLR_SSL_PRINTF("\nAbout to empty the engine-type list\n");
	while((ptr = ENGINE_get_first()) != NULL)
		{
		if(!ENGINE_remove(ptr))
			{
			TINYCLR_SSL_PRINTF("\nRemove failed!\n");
			goto end;
			}
		ENGINE_free(ptr);
		TINYCLR_SSL_PRINTF("."); TINYCLR_SSL_FFLUSH(OPENSSL_TYPE__FILE_STDOUT);
		}
	for(loop = 0; loop < 512; loop++)
		{
		OPENSSL_free((void *)ENGINE_get_id(block[loop]));
		OPENSSL_free((void *)ENGINE_get_name(block[loop]));
		}
	TINYCLR_SSL_PRINTF("\nTests completed happily\n");
	to_return = 0;
end:
	if(to_return)
		ERR_print_errors_fp(OPENSSL_TYPE__FILE_STDERR);
	if(new_h1) ENGINE_free(new_h1);
	if(new_h2) ENGINE_free(new_h2);
	if(new_h3) ENGINE_free(new_h3);
	if(new_h4) ENGINE_free(new_h4);
	for(loop = 0; loop < 512; loop++)
		if(block[loop])
			ENGINE_free(block[loop]);
	ENGINE_cleanup();
	CRYPTO_cleanup_all_ex_data();
	ERR_free_strings();
	ERR_remove_thread_state(NULL);
	CRYPTO_mem_leaks_fp(OPENSSL_TYPE__FILE_STDERR);
	return to_return;
	}
Exemple #6
0
int PKCS12_key_gen_uni(unsigned char *pass, int passlen, unsigned char *salt,
	     int saltlen, int id, int iter, int n, unsigned char *out,
	     const EVP_MD *md_type)
{
	unsigned char *B, *D, *I, *p, *Ai;
	int Slen, Plen, Ilen, Ijlen;
	int i, j, u, v;
	BIGNUM *Ij, *Bpl1;	/* These hold Ij and B + 1 */
	EVP_MD_CTX ctx;
#ifdef  DEBUG_KEYGEN
	unsigned char *tmpout = out;
	int tmpn = n;
#endif

#if 0
	if (!pass) {
		PKCS12err(PKCS12_F_PKCS12_KEY_GEN_UNI,ERR_R_PASSED_NULL_PARAMETER);
		return 0;
	}
#endif

	EVP_MD_CTX_init(&ctx);
#ifdef  DEBUG_KEYGEN
	TINYCLR_SSL_FPRINTF(OPENSSL_TYPE__FILE_STDERR, "KEYGEN DEBUG\n");
	TINYCLR_SSL_FPRINTF(OPENSSL_TYPE__FILE_STDERR, "ID %d, ITER %d\n", id, iter);
	TINYCLR_SSL_FPRINTF(OPENSSL_TYPE__FILE_STDERR, "Password (length %d):\n", passlen);
	h__dump(pass, passlen);
	TINYCLR_SSL_FPRINTF(OPENSSL_TYPE__FILE_STDERR, "Salt (length %d):\n", saltlen);
	h__dump(salt, saltlen);
#endif
	v = EVP_MD_block_size (md_type);
	u = EVP_MD_size (md_type);
	if (u < 0)
	    return 0;
	D = (unsigned char*)OPENSSL_malloc (v);
	Ai = (unsigned char*)OPENSSL_malloc (u);
	B = (unsigned char*)OPENSSL_malloc (v + 1);
	Slen = v * ((saltlen+v-1)/v);
	if(passlen) Plen = v * ((passlen+v-1)/v);
	else Plen = 0;
	Ilen = Slen + Plen;
	I = (unsigned char*)OPENSSL_malloc (Ilen);
	Ij = BN_new();
	Bpl1 = BN_new();
	if (!D || !Ai || !B || !I || !Ij || !Bpl1) {
		PKCS12err(PKCS12_F_PKCS12_KEY_GEN_UNI,ERR_R_MALLOC_FAILURE);
		return 0;
	}
	for (i = 0; i < v; i++) D[i] = id;
	p = I;
	for (i = 0; i < Slen; i++) *p++ = salt[i % saltlen];
	for (i = 0; i < Plen; i++) *p++ = pass[i % passlen];
	for (;;) {
		EVP_DigestInit_ex(&ctx, md_type, NULL);
		EVP_DigestUpdate(&ctx, D, v);
		EVP_DigestUpdate(&ctx, I, Ilen);
		EVP_DigestFinal_ex(&ctx, Ai, NULL);
		for (j = 1; j < iter; j++) {
			EVP_DigestInit_ex(&ctx, md_type, NULL);
			EVP_DigestUpdate(&ctx, Ai, u);
			EVP_DigestFinal_ex(&ctx, Ai, NULL);
		}
		TINYCLR_SSL_MEMCPY (out, Ai, min (n, u));
		if (u >= n) {
			OPENSSL_free (Ai);
			OPENSSL_free (B);
			OPENSSL_free (D);
			OPENSSL_free (I);
			BN_free (Ij);
			BN_free (Bpl1);
			EVP_MD_CTX_cleanup(&ctx);
#ifdef DEBUG_KEYGEN
			TINYCLR_SSL_FPRINTF(OPENSSL_TYPE__FILE_STDERR, "Output KEY (length %d)\n", tmpn);
			h__dump(tmpout, tmpn);
#endif
			return 1;	
		}
		n -= u;
		out += u;
		for (j = 0; j < v; j++) B[j] = Ai[j % u];
		/* Work out B + 1 first then can use B as tmp space */
		BN_bin2bn (B, v, Bpl1);
		BN_add_word (Bpl1, 1);
		for (j = 0; j < Ilen ; j+=v) {
			BN_bin2bn (I + j, v, Ij);
			BN_add (Ij, Ij, Bpl1);
			BN_bn2bin (Ij, B);
			Ijlen = BN_num_bytes (Ij);
			/* If more than 2^(v*8) - 1 cut off MSB */
			if (Ijlen > v) {
				BN_bn2bin (Ij, B);
				TINYCLR_SSL_MEMCPY (I + j, B + 1, v);
#ifndef PKCS12_BROKEN_KEYGEN
			/* If less than v bytes pad with zeroes */
			} else if (Ijlen < v) {
				TINYCLR_SSL_MEMSET(I + j, 0, v - Ijlen);
				BN_bn2bin(Ij, I + j + v - Ijlen); 
#endif
			} else BN_bn2bin (Ij, I + j);
		}
	}
}
static int conn_state(BIO *b, BIO_CONNECT *c)
	{
	int ret= -1,i;
	unsigned long l;
	char *p,*q;
	int (*cb)(const BIO *,int,int)=NULL;

	if (c->info_callback != NULL)
		cb=c->info_callback;

	for (;;)
		{
		switch (c->state)
			{
		case BIO_CONN_S_BEFORE:
			p=c->param_hostname;
			if (p == NULL)
				{
				BIOerr(BIO_F_CONN_STATE,BIO_R_NO_HOSTNAME_SPECIFIED);
				goto exit_loop;
				}
			for ( ; *p != '\0'; p++)
				{
				if ((*p == ':') || (*p == '/')) break;
				}

			i= *p;
			if ((i == ':') || (i == '/'))
				{

				*(p++)='\0';
				if (i == ':')
					{
					for (q=p; *q; q++)
						if (*q == '/')
							{
							*q='\0';
							break;
							}
					if (c->param_port != NULL)
						OPENSSL_free(c->param_port);
					c->param_port=BUF_strdup(p);
					}
				}

			if (c->param_port == NULL)
				{
				BIOerr(BIO_F_CONN_STATE,BIO_R_NO_PORT_SPECIFIED);
				ERR_add_error_data(2,"host=",c->param_hostname);
				goto exit_loop;
				}
			c->state=BIO_CONN_S_GET_IP;
			break;

		case BIO_CONN_S_GET_IP:
			if (BIO_get_host_ip(c->param_hostname,&(c->ip[0])) <= 0)
				goto exit_loop;
			c->state=BIO_CONN_S_GET_PORT;
			break;

		case BIO_CONN_S_GET_PORT:
			if (c->param_port == NULL)
				{
				/* abort(); */
				goto exit_loop;
				}
			else if (BIO_get_port(c->param_port,&c->port) <= 0)
				goto exit_loop;
			c->state=BIO_CONN_S_CREATE_SOCKET;
			break;

		case BIO_CONN_S_CREATE_SOCKET:
			/* now setup address */
			TINYCLR_SSL_MEMSET((char *)&c->them,0,sizeof(c->them));
			c->them.sin_family=AF_INET;
			c->them.sin_port=TINYCLR_SSL_HTONS((unsigned short)c->port);
			l=(unsigned long)
				((unsigned long)c->ip[0]<<24L)|
				((unsigned long)c->ip[1]<<16L)|
				((unsigned long)c->ip[2]<< 8L)|
				((unsigned long)c->ip[3]);
			c->them.sin_addr.S_un.S_addr=TINYCLR_SSL_HTONL(l);
			c->state=BIO_CONN_S_CREATE_SOCKET;

			ret=TINYCLR_SSL_SOCKET(AF_INET,SOCK_STREAM,SOCKET_PROTOCOL);
			if (ret == INVALID_SOCKET)
				{
				SYSerr(SYS_F_SOCKET,get_last_socket_error());
				ERR_add_error_data(4,"host=",c->param_hostname,
					":",c->param_port);
				BIOerr(BIO_F_CONN_STATE,BIO_R_UNABLE_TO_CREATE_SOCKET);
				goto exit_loop;
				}
			b->num=ret;
			c->state=BIO_CONN_S_NBIO;
			break;

		case BIO_CONN_S_NBIO:
			if (c->nbio)
				{
				if (!BIO_socket_nbio(b->num,1))
					{
					BIOerr(BIO_F_CONN_STATE,BIO_R_ERROR_SETTING_NBIO);
					ERR_add_error_data(4,"host=",
						c->param_hostname,
						":",c->param_port);
					goto exit_loop;
					}
				}
			c->state=BIO_CONN_S_CONNECT;

#if defined(SO_KEEPALIVE) && !defined(OPENSSL_SYS_MPE)
			i=1;
			i=TINYCLR_SSL_SETSOCKOPT(b->num,SOL_SOCKET,SO_KEEPALIVE,(char *)&i,sizeof(i));
			if (i < 0)
				{
				SYSerr(SYS_F_SOCKET,get_last_socket_error());
				ERR_add_error_data(4,"host=",c->param_hostname,
					":",c->param_port);
				BIOerr(BIO_F_CONN_STATE,BIO_R_KEEPALIVE);
				goto exit_loop;
				}
#endif
			break;

		case BIO_CONN_S_CONNECT:
			BIO_clear_retry_flags(b);
			ret=TINYCLR_SSL_CONNECT(b->num,
				(struct TINYCLR_SSL_SOCKADDR *)&c->them,
				sizeof(c->them));
			b->retry_reason=0;
			if (ret < 0)
				{
				if (BIO_sock_should_retry(ret))
					{
					BIO_set_retry_special(b);
					c->state=BIO_CONN_S_BLOCKED_CONNECT;
					b->retry_reason=BIO_RR_CONNECT;
					}
				else
					{
					SYSerr(SYS_F_CONNECT,get_last_socket_error());
					ERR_add_error_data(4,"host=",
						c->param_hostname,
						":",c->param_port);
					BIOerr(BIO_F_CONN_STATE,BIO_R_CONNECT_ERROR);
					}
				goto exit_loop;
				}
			else
				c->state=BIO_CONN_S_OK;
			break;

		case BIO_CONN_S_BLOCKED_CONNECT:
			i=BIO_sock_error(b->num);
			if (i)
				{
				BIO_clear_retry_flags(b);
				SYSerr(SYS_F_CONNECT,i);
				ERR_add_error_data(4,"host=",
					c->param_hostname,
					":",c->param_port);
				BIOerr(BIO_F_CONN_STATE,BIO_R_NBIO_CONNECT_ERROR);
				ret=0;
				goto exit_loop;
				}
			else
				c->state=BIO_CONN_S_OK;
			break;

		case BIO_CONN_S_OK:
			ret=1;
			goto exit_loop;
		default:
			/* TINYCLR_SSL_ABORT(); */
			goto exit_loop;
			}

		if (cb != NULL)
			{
			if (!(ret=cb((BIO *)b,c->state,ret)))
				goto end;
			}
		}

	/* Loop does not exit */
exit_loop:
	if (cb != NULL)
		ret=cb((BIO *)b,c->state,ret);
end:
	return(ret);
	}
static int test(void)
	{
	unsigned char cbc_in[40],cbc_out[40],iv[8];
	int i,n,err=0;
	BF_KEY key;
	BF_LONG data[2]; 
	unsigned char out[8]; 
	BF_LONG len;

#ifdef CHARSET_EBCDIC
	ebcdic2ascii(cbc_data, cbc_data, TINYCLR_SSL_STRLEN(cbc_data));
#endif

	TINYCLR_SSL_PRINTF("testing blowfish in raw ecb mode\n");
	for (n=0; n<2; n++)
		{
#ifdef CHARSET_EBCDIC
		ebcdic2ascii(bf_key[n], bf_key[n], TINYCLR_SSL_STRLEN(bf_key[n]));
#endif
		BF_set_key(&key,TINYCLR_SSL_STRLEN(bf_key[n]),(unsigned char *)bf_key[n]);

		data[0]=bf_plain[n][0];
		data[1]=bf_plain[n][1];
		BF_encrypt(data,&key);
		if (TINYCLR_SSL_MEMCMP(&(bf_cipher[n][0]),&(data[0]),8) != 0)
			{
			TINYCLR_SSL_PRINTF("BF_encrypt error encrypting\n");
			TINYCLR_SSL_PRINTF("got     :");
			for (i=0; i<2; i++)
				TINYCLR_SSL_PRINTF("%08lX ",(unsigned long)data[i]);
			TINYCLR_SSL_PRINTF("\n");
			TINYCLR_SSL_PRINTF("expected:");
			for (i=0; i<2; i++)
				TINYCLR_SSL_PRINTF("%08lX ",(unsigned long)bf_cipher[n][i]);
			err=1;
			TINYCLR_SSL_PRINTF("\n");
			}

		BF_decrypt(&(data[0]),&key);
		if (TINYCLR_SSL_MEMCMP(&(bf_plain[n][0]),&(data[0]),8) != 0)
			{
			TINYCLR_SSL_PRINTF("BF_encrypt error decrypting\n");
			TINYCLR_SSL_PRINTF("got     :");
			for (i=0; i<2; i++)
				TINYCLR_SSL_PRINTF("%08lX ",(unsigned long)data[i]);
			TINYCLR_SSL_PRINTF("\n");
			TINYCLR_SSL_PRINTF("expected:");
			for (i=0; i<2; i++)
				TINYCLR_SSL_PRINTF("%08lX ",(unsigned long)bf_plain[n][i]);
			TINYCLR_SSL_PRINTF("\n");
			err=1;
			}
		}

	TINYCLR_SSL_PRINTF("testing blowfish in ecb mode\n");

	for (n=0; n<NUM_TESTS; n++)
		{
		BF_set_key(&key,8,ecb_data[n]);

		BF_ecb_encrypt(&(plain_data[n][0]),out,&key,BF_ENCRYPT);
		if (TINYCLR_SSL_MEMCMP(&(cipher_data[n][0]),out,8) != 0)
			{
			TINYCLR_SSL_PRINTF("BF_ecb_encrypt blowfish error encrypting\n");
			TINYCLR_SSL_PRINTF("got     :");
			for (i=0; i<8; i++)
				TINYCLR_SSL_PRINTF("%02X ",out[i]);
			TINYCLR_SSL_PRINTF("\n");
			TINYCLR_SSL_PRINTF("expected:");
			for (i=0; i<8; i++)
				TINYCLR_SSL_PRINTF("%02X ",cipher_data[n][i]);
			err=1;
			TINYCLR_SSL_PRINTF("\n");
			}

		BF_ecb_encrypt(out,out,&key,BF_DECRYPT);
		if (TINYCLR_SSL_MEMCMP(&(plain_data[n][0]),out,8) != 0)
			{
			TINYCLR_SSL_PRINTF("BF_ecb_encrypt error decrypting\n");
			TINYCLR_SSL_PRINTF("got     :");
			for (i=0; i<8; i++)
				TINYCLR_SSL_PRINTF("%02X ",out[i]);
			TINYCLR_SSL_PRINTF("\n");
			TINYCLR_SSL_PRINTF("expected:");
			for (i=0; i<8; i++)
				TINYCLR_SSL_PRINTF("%02X ",plain_data[n][i]);
			TINYCLR_SSL_PRINTF("\n");
			err=1;
			}
		}

	TINYCLR_SSL_PRINTF("testing blowfish set_key\n");
	for (n=1; n<KEY_TEST_NUM; n++)
		{
		BF_set_key(&key,n,key_test);
		BF_ecb_encrypt(key_data,out,&key,BF_ENCRYPT);
		/* mips-sgi-irix6.5-gcc  vv  -mabi=64 bug workaround */
		if (TINYCLR_SSL_MEMCMP(out,&(key_out[i=n-1][0]),8) != 0)
			{
			TINYCLR_SSL_PRINTF("blowfish setkey error\n");
			err=1;
			}
		}

	TINYCLR_SSL_PRINTF("testing blowfish in cbc mode\n");
	len=TINYCLR_SSL_STRLEN(cbc_data)+1;

	BF_set_key(&key,16,cbc_key);
	TINYCLR_SSL_MEMSET(cbc_in,0,sizeof cbc_in);
	TINYCLR_SSL_MEMSET(cbc_out,0,sizeof cbc_out);
	TINYCLR_SSL_MEMCPY(iv,cbc_iv,sizeof iv);
	BF_cbc_encrypt((unsigned char *)cbc_data,cbc_out,len,
		&key,iv,BF_ENCRYPT);
	if (TINYCLR_SSL_MEMCMP(cbc_out,cbc_ok,32) != 0)
		{
		err=1;
		TINYCLR_SSL_PRINTF("BF_cbc_encrypt encrypt error\n");
		for (i=0; i<32; i++) TINYCLR_SSL_PRINTF("0x%02X,",cbc_out[i]);
		}
	TINYCLR_SSL_MEMCPY(iv,cbc_iv,8);
	BF_cbc_encrypt(cbc_out,cbc_in,len,
		&key,iv,BF_DECRYPT);
	if (TINYCLR_SSL_MEMCMP(cbc_in,cbc_data,TINYCLR_SSL_STRLEN(cbc_data)+1) != 0)
		{
		TINYCLR_SSL_PRINTF("BF_cbc_encrypt decrypt error\n");
		err=1;
		}

	TINYCLR_SSL_PRINTF("testing blowfish in cfb64 mode\n");

	BF_set_key(&key,16,cbc_key);
	TINYCLR_SSL_MEMSET(cbc_in,0,40);
	TINYCLR_SSL_MEMSET(cbc_out,0,40);
	TINYCLR_SSL_MEMCPY(iv,cbc_iv,8);
	n=0;
	BF_cfb64_encrypt((unsigned char *)cbc_data,cbc_out,(long)13,
		&key,iv,&n,BF_ENCRYPT);
	BF_cfb64_encrypt((unsigned char *)&(cbc_data[13]),&(cbc_out[13]),len-13,
		&key,iv,&n,BF_ENCRYPT);
	if (TINYCLR_SSL_MEMCMP(cbc_out,cfb64_ok,(int)len) != 0)
		{
		err=1;
		TINYCLR_SSL_PRINTF("BF_cfb64_encrypt encrypt error\n");
		for (i=0; i<(int)len; i++) TINYCLR_SSL_PRINTF("0x%02X,",cbc_out[i]);
		}
	n=0;
	TINYCLR_SSL_MEMCPY(iv,cbc_iv,8);
	BF_cfb64_encrypt(cbc_out,cbc_in,17,
		&key,iv,&n,BF_DECRYPT);
	BF_cfb64_encrypt(&(cbc_out[17]),&(cbc_in[17]),len-17,
		&key,iv,&n,BF_DECRYPT);
	if (TINYCLR_SSL_MEMCMP(cbc_in,cbc_data,(int)len) != 0)
		{
		TINYCLR_SSL_PRINTF("BF_cfb64_encrypt decrypt error\n");
		err=1;
		}

	TINYCLR_SSL_PRINTF("testing blowfish in ofb64\n");

	BF_set_key(&key,16,cbc_key);
	TINYCLR_SSL_MEMSET(cbc_in,0,40);
	TINYCLR_SSL_MEMSET(cbc_out,0,40);
	TINYCLR_SSL_MEMCPY(iv,cbc_iv,8);
	n=0;
	BF_ofb64_encrypt((unsigned char *)cbc_data,cbc_out,(long)13,&key,iv,&n);
	BF_ofb64_encrypt((unsigned char *)&(cbc_data[13]),
		&(cbc_out[13]),len-13,&key,iv,&n);
	if (TINYCLR_SSL_MEMCMP(cbc_out,ofb64_ok,(int)len) != 0)
		{
		err=1;
		TINYCLR_SSL_PRINTF("BF_ofb64_encrypt encrypt error\n");
		for (i=0; i<(int)len; i++) TINYCLR_SSL_PRINTF("0x%02X,",cbc_out[i]);
		}
	n=0;
	TINYCLR_SSL_MEMCPY(iv,cbc_iv,8);
	BF_ofb64_encrypt(cbc_out,cbc_in,17,&key,iv,&n);
	BF_ofb64_encrypt(&(cbc_out[17]),&(cbc_in[17]),len-17,&key,iv,&n);
	if (TINYCLR_SSL_MEMCMP(cbc_in,cbc_data,(int)len) != 0)
		{
		TINYCLR_SSL_PRINTF("BF_ofb64_encrypt decrypt error\n");
		err=1;
		}

	return(err);
	}
static int BN_from_montgomery_word(BIGNUM *ret, BIGNUM *r, BN_MONT_CTX *mont)
	{
	BIGNUM *n;
	BN_ULONG *ap,*np,*rp,n0,v,*nrp;
	int al,nl,max,i,x,ri;

	n= &(mont->N);
	/* mont->ri is the size of mont->N in bits (rounded up
	   to the word size) */
	al=ri=mont->ri/BN_BITS2;

	nl=n->top;
	if ((al == 0) || (nl == 0)) { ret->top=0; return(1); }

	max=(nl+al+1); /* allow for overflow (no?) XXX */
	if (bn_wexpand(r,max) == NULL) return(0);

	r->neg^=n->neg;
	np=n->d;
	rp=r->d;
	nrp= &(r->d[nl]);

	/* clear the top words of T */
#if 1
	for (i=r->top; i<max; i++) /* memset? XXX */
		r->d[i]=0;
#else
	TINYCLR_SSL_MEMSET(&(r->d[r->top]),0,(max-r->top)*sizeof(BN_ULONG)); 
#endif

	r->top=max;
	n0=mont->n0[0];

#ifdef BN_COUNT
	TINYCLR_SSL_FPRINTF(OPENSSL_TYPE__FILE_STDERR,"word BN_from_montgomery_word %d * %d\n",nl,nl);
#endif
	for (i=0; i<nl; i++)
		{
#ifdef __TANDEM
                {
                   long long t1;
                   long long t2;
                   long long t3;
                   t1 = rp[0] * (n0 & 0177777);
                   t2 = 037777600000l;
                   t2 = n0 & t2;
                   t3 = rp[0] & 0177777;
                   t2 = (t3 * t2) & BN_MASK2;
                   t1 = t1 + t2;
                   v=bn_mul_add_words(rp,np,nl,(BN_ULONG) t1);
                }
#else
		v=bn_mul_add_words(rp,np,nl,(rp[0]*n0)&BN_MASK2);
#endif
		nrp++;
		rp++;
		if (((nrp[-1]+=v)&BN_MASK2) >= v)
			continue;
		else
			{
			if (((++nrp[0])&BN_MASK2) != 0) continue;
			if (((++nrp[1])&BN_MASK2) != 0) continue;
			for (x=2; (((++nrp[x])&BN_MASK2) == 0); x++) ;
			}
		}
	bn_correct_top(r);

	/* mont->ri will be a multiple of the word size and below code
	 * is kind of BN_rshift(ret,r,mont->ri) equivalent */
	if (r->top <= ri)
		{
		ret->top=0;
		return(1);
		}
	al=r->top-ri;

#define BRANCH_FREE 1
#if BRANCH_FREE
	if (bn_wexpand(ret,ri) == NULL) return(0);
	x=0-(((al-ri)>>(sizeof(al)*8-1))&1);
	ret->top=x=(ri&~x)|(al&x);	/* min(ri,al) */
	ret->neg=r->neg;

	rp=ret->d;
	ap=&(r->d[ri]);

	{
	size_t m1,m2;

	v=bn_sub_words(rp,ap,np,ri);
	/* this ----------------^^ works even in al<ri case
	 * thanks to zealous zeroing of top of the vector in the
	 * beginning. */

	/* if (al==ri && !v) || al>ri) nrp=rp; else nrp=ap; */
	/* in other words if subtraction result is real, then
	 * trick unconditional TINYCLR_SSL_MEMCPY below to perform in-place
	 * "refresh" instead of actual copy. */
	m1=0-(size_t)(((al-ri)>>(sizeof(al)*8-1))&1);	/* al<ri */
	m2=0-(size_t)(((ri-al)>>(sizeof(al)*8-1))&1);	/* al>ri */
	m1|=m2;			/* (al!=ri) */
	m1|=(0-(size_t)v);	/* (al!=ri || v) */
	m1&=~m2;		/* (al!=ri || v) && !al>ri */
	nrp=(BN_ULONG *)(((size_t)rp&~m1)|((size_t)ap&m1));
	}

	/* 'i<ri' is chosen to eliminate dependency on input data, even
	 * though it results in redundant copy in al<ri case. */
	for (i=0,ri-=4; i<ri; i+=4)
		{
		BN_ULONG t1,t2,t3,t4;
		
		t1=nrp[i+0];
		t2=nrp[i+1];
		t3=nrp[i+2];	ap[i+0]=0;
		t4=nrp[i+3];	ap[i+1]=0;
		rp[i+0]=t1;	ap[i+2]=0;
		rp[i+1]=t2;	ap[i+3]=0;
		rp[i+2]=t3;
		rp[i+3]=t4;
		}
	for (ri+=4; i<ri; i++)
		rp[i]=nrp[i], ap[i]=0;
	bn_correct_top(r);
	bn_correct_top(ret);
#else
	if (bn_wexpand(ret,al) == NULL) return(0);
	ret->top=al;
	ret->neg=r->neg;

	rp=ret->d;
	ap=&(r->d[ri]);
	al-=4;
	for (i=0; i<al; i+=4)
		{
		BN_ULONG t1,t2,t3,t4;
		
		t1=ap[i+0];
		t2=ap[i+1];
		t3=ap[i+2];
		t4=ap[i+3];
		rp[i+0]=t1;
		rp[i+1]=t2;
		rp[i+2]=t3;
		rp[i+3]=t4;
		}
	al+=4;
	for (; i<al; i++)
		rp[i]=ap[i];

	if (BN_ucmp(ret, &(mont->N)) >= 0)
		{
		if (!BN_usub(ret,ret,&(mont->N))) return(0);
		}
#endif
	bn_check_top(ret);

	return(1);
	}
Exemple #10
0
int main(int argc, char *argv[])
	{
	int j,err=0;
	unsigned int i;
	des_cblock in,out,outin,iv3,iv2;
	des_key_schedule ks,ks2,ks3;
	unsigned char cbc_in[40];
	unsigned char cbc_out[40];
	DES_LONG cs;
	unsigned char cret[8];
#ifdef _CRAY
        struct {
            int a:32;
            int b:32;
        } lqret[2];
#else
        DES_LONG lqret[4];
#endif
	int num;
	char *str;

#ifndef OPENSSL_NO_DESCBCM
	TINYCLR_SSL_PRINTF("Doing cbcm\n");
	if ((j=DES_set_key_checked(&cbc_key,&ks)) != 0)
		{
		TINYCLR_SSL_PRINTF("Key error %d\n",j);
		err=1;
		}
	if ((j=DES_set_key_checked(&cbc2_key,&ks2)) != 0)
		{
		TINYCLR_SSL_PRINTF("Key error %d\n",j);
		err=1;
		}
	if ((j=DES_set_key_checked(&cbc3_key,&ks3)) != 0)
		{
		TINYCLR_SSL_PRINTF("Key error %d\n",j);
		err=1;
		}
	TINYCLR_SSL_MEMSET(cbc_out,0,40);
	TINYCLR_SSL_MEMSET(cbc_in,0,40);
	i=TINYCLR_SSL_STRLEN((char *)cbc_data)+1;
	/* i=((i+7)/8)*8; */
	TINYCLR_SSL_MEMCPY(iv3,cbc_iv,sizeof(cbc_iv));
	TINYCLR_SSL_MEMSET(iv2,'\0',sizeof iv2);

	DES_ede3_cbcm_encrypt(cbc_data,cbc_out,16L,&ks,&ks2,&ks3,&iv3,&iv2,
			      DES_ENCRYPT);
	DES_ede3_cbcm_encrypt(&cbc_data[16],&cbc_out[16],i-16,&ks,&ks2,&ks3,
			      &iv3,&iv2,DES_ENCRYPT);
	/*	if (memcmp(cbc_out,cbc3_ok,
		(unsigned int)(TINYCLR_SSL_STRLEN((char *)cbc_data)+1+7)/8*8) != 0)
		{
		TINYCLR_SSL_PRINTF("des_ede3_cbc_encrypt encrypt error\n");
		err=1;
		}
	*/
	TINYCLR_SSL_MEMCPY(iv3,cbc_iv,sizeof(cbc_iv));
	TINYCLR_SSL_MEMSET(iv2,'\0',sizeof iv2);
	DES_ede3_cbcm_encrypt(cbc_out,cbc_in,i,&ks,&ks2,&ks3,&iv3,&iv2,DES_DECRYPT);
	if (TINYCLR_SSL_MEMCMP(cbc_in,cbc_data,TINYCLR_SSL_STRLEN((char *)cbc_data)+1) != 0)
		{
		unsigned int n;

		TINYCLR_SSL_PRINTF("des_ede3_cbcm_encrypt decrypt error\n");
		for(n=0 ; n < i ; ++n)
		    TINYCLR_SSL_PRINTF(" %02x",cbc_data[n]);
		TINYCLR_SSL_PRINTF("\n");
		for(n=0 ; n < i ; ++n)
		    TINYCLR_SSL_PRINTF(" %02x",cbc_in[n]);
		TINYCLR_SSL_PRINTF("\n");
		err=1;
		}
#endif

	TINYCLR_SSL_PRINTF("Doing ecb\n");
	for (i=0; i<NUM_TESTS; i++)
		{
		DES_set_key_unchecked(&key_data[i],&ks);
		TINYCLR_SSL_MEMCPY(in,plain_data[i],8);
		TINYCLR_SSL_MEMSET(out,0,8);
		TINYCLR_SSL_MEMSET(outin,0,8);
		des_ecb_encrypt(&in,&out,ks,DES_ENCRYPT);
		des_ecb_encrypt(&out,&outin,ks,DES_DECRYPT);

		if (TINYCLR_SSL_MEMCMP(out,cipher_data[i],8) != 0)
			{
			TINYCLR_SSL_PRINTF("Encryption error %2d\nk=%s p=%s o=%s act=%s\n",
				i+1,pt(key_data[i]),pt(in),pt(cipher_data[i]),
				pt(out));
			err=1;
			}
		if (TINYCLR_SSL_MEMCMP(in,outin,8) != 0)
			{
			TINYCLR_SSL_PRINTF("Decryption error %2d\nk=%s p=%s o=%s act=%s\n",
				i+1,pt(key_data[i]),pt(out),pt(in),pt(outin));
			err=1;
			}
		}

#ifndef LIBDES_LIT
	TINYCLR_SSL_PRINTF("Doing ede ecb\n");
	for (i=0; i<(NUM_TESTS-2); i++)
		{
		DES_set_key_unchecked(&key_data[i],&ks);
		DES_set_key_unchecked(&key_data[i+1],&ks2);
		DES_set_key_unchecked(&key_data[i+2],&ks3);
		TINYCLR_SSL_MEMCPY(in,plain_data[i],8);
		TINYCLR_SSL_MEMSET(out,0,8);
		TINYCLR_SSL_MEMSET(outin,0,8);
		des_ecb2_encrypt(&in,&out,ks,ks2,DES_ENCRYPT);
		des_ecb2_encrypt(&out,&outin,ks,ks2,DES_DECRYPT);

		if (TINYCLR_SSL_MEMCMP(out,cipher_ecb2[i],8) != 0)
			{
			TINYCLR_SSL_PRINTF("Encryption error %2d\nk=%s p=%s o=%s act=%s\n",
				i+1,pt(key_data[i]),pt(in),pt(cipher_ecb2[i]),
				pt(out));
			err=1;
			}
		if (TINYCLR_SSL_MEMCMP(in,outin,8) != 0)
			{
			TINYCLR_SSL_PRINTF("Decryption error %2d\nk=%s p=%s o=%s act=%s\n",
				i+1,pt(key_data[i]),pt(out),pt(in),pt(outin));
			err=1;
			}
		}
#endif

	TINYCLR_SSL_PRINTF("Doing cbc\n");
	if ((j=DES_set_key_checked(&cbc_key,&ks)) != 0)
		{
		TINYCLR_SSL_PRINTF("Key error %d\n",j);
		err=1;
		}
	TINYCLR_SSL_MEMSET(cbc_out,0,40);
	TINYCLR_SSL_MEMSET(cbc_in,0,40);
	TINYCLR_SSL_MEMCPY(iv3,cbc_iv,sizeof(cbc_iv));
	des_ncbc_encrypt(cbc_data,cbc_out,TINYCLR_SSL_STRLEN((char *)cbc_data)+1,ks,
			 &iv3,DES_ENCRYPT);
	if (TINYCLR_SSL_MEMCMP(cbc_out,cbc_ok,32) != 0)
		{
		TINYCLR_SSL_PRINTF("cbc_encrypt encrypt error\n");
		err=1;
		}

	TINYCLR_SSL_MEMCPY(iv3,cbc_iv,sizeof(cbc_iv));
	des_ncbc_encrypt(cbc_out,cbc_in,TINYCLR_SSL_STRLEN((char *)cbc_data)+1,ks,
			 &iv3,DES_DECRYPT);
	if (TINYCLR_SSL_MEMCMP(cbc_in,cbc_data,TINYCLR_SSL_STRLEN((char *)cbc_data)) != 0)
		{
		TINYCLR_SSL_PRINTF("cbc_encrypt decrypt error\n");
		err=1;
		}

#ifndef LIBDES_LIT
	TINYCLR_SSL_PRINTF("Doing desx cbc\n");
	if ((j=DES_set_key_checked(&cbc_key,&ks)) != 0)
		{
		TINYCLR_SSL_PRINTF("Key error %d\n",j);
		err=1;
		}
	TINYCLR_SSL_MEMSET(cbc_out,0,40);
	TINYCLR_SSL_MEMSET(cbc_in,0,40);
	TINYCLR_SSL_MEMCPY(iv3,cbc_iv,sizeof(cbc_iv));
	des_xcbc_encrypt(cbc_data,cbc_out,TINYCLR_SSL_STRLEN((char *)cbc_data)+1,ks,
			 &iv3,&cbc2_key,&cbc3_key, DES_ENCRYPT);
	if (TINYCLR_SSL_MEMCMP(cbc_out,xcbc_ok,32) != 0)
		{
		TINYCLR_SSL_PRINTF("des_xcbc_encrypt encrypt error\n");
		err=1;
		}
	TINYCLR_SSL_MEMCPY(iv3,cbc_iv,sizeof(cbc_iv));
	des_xcbc_encrypt(cbc_out,cbc_in,TINYCLR_SSL_STRLEN((char *)cbc_data)+1,ks,
			 &iv3,&cbc2_key,&cbc3_key, DES_DECRYPT);
	if (TINYCLR_SSL_MEMCMP(cbc_in,cbc_data,TINYCLR_SSL_STRLEN((char *)cbc_data)+1) != 0)
		{
		TINYCLR_SSL_PRINTF("des_xcbc_encrypt decrypt error\n");
		err=1;
		}
#endif

	TINYCLR_SSL_PRINTF("Doing ede cbc\n");
	if ((j=DES_set_key_checked(&cbc_key,&ks)) != 0)
		{
		TINYCLR_SSL_PRINTF("Key error %d\n",j);
		err=1;
		}
	if ((j=DES_set_key_checked(&cbc2_key,&ks2)) != 0)
		{
		TINYCLR_SSL_PRINTF("Key error %d\n",j);
		err=1;
		}
	if ((j=DES_set_key_checked(&cbc3_key,&ks3)) != 0)
		{
		TINYCLR_SSL_PRINTF("Key error %d\n",j);
		err=1;
		}
	TINYCLR_SSL_MEMSET(cbc_out,0,40);
	TINYCLR_SSL_MEMSET(cbc_in,0,40);
	i=TINYCLR_SSL_STRLEN((char *)cbc_data)+1;
	/* i=((i+7)/8)*8; */
	TINYCLR_SSL_MEMCPY(iv3,cbc_iv,sizeof(cbc_iv));

	des_ede3_cbc_encrypt(cbc_data,cbc_out,16L,ks,ks2,ks3,&iv3,
			     DES_ENCRYPT);
	des_ede3_cbc_encrypt(&(cbc_data[16]),&(cbc_out[16]),i-16,ks,ks2,ks3,
			     &iv3,DES_ENCRYPT);
	if (TINYCLR_SSL_MEMCMP(cbc_out,cbc3_ok,
		(unsigned int)(TINYCLR_SSL_STRLEN((char *)cbc_data)+1+7)/8*8) != 0)
		{
		unsigned int n;

		TINYCLR_SSL_PRINTF("des_ede3_cbc_encrypt encrypt error\n");
		for(n=0 ; n < i ; ++n)
		    TINYCLR_SSL_PRINTF(" %02x",cbc_out[n]);
		TINYCLR_SSL_PRINTF("\n");
		for(n=0 ; n < i ; ++n)
		    TINYCLR_SSL_PRINTF(" %02x",cbc3_ok[n]);
		TINYCLR_SSL_PRINTF("\n");
		err=1;
		}

	TINYCLR_SSL_MEMCPY(iv3,cbc_iv,sizeof(cbc_iv));
	des_ede3_cbc_encrypt(cbc_out,cbc_in,i,ks,ks2,ks3,&iv3,DES_DECRYPT);
	if (TINYCLR_SSL_MEMCMP(cbc_in,cbc_data,TINYCLR_SSL_STRLEN((char *)cbc_data)+1) != 0)
		{
		unsigned int n;

		TINYCLR_SSL_PRINTF("des_ede3_cbc_encrypt decrypt error\n");
		for(n=0 ; n < i ; ++n)
		    TINYCLR_SSL_PRINTF(" %02x",cbc_data[n]);
		TINYCLR_SSL_PRINTF("\n");
		for(n=0 ; n < i ; ++n)
		    TINYCLR_SSL_PRINTF(" %02x",cbc_in[n]);
		TINYCLR_SSL_PRINTF("\n");
		err=1;
		}

#ifndef LIBDES_LIT
	TINYCLR_SSL_PRINTF("Doing pcbc\n");
	if ((j=DES_set_key_checked(&cbc_key,&ks)) != 0)
		{
		TINYCLR_SSL_PRINTF("Key error %d\n",j);
		err=1;
		}
	TINYCLR_SSL_MEMSET(cbc_out,0,40);
	TINYCLR_SSL_MEMSET(cbc_in,0,40);
	des_pcbc_encrypt(cbc_data,cbc_out,TINYCLR_SSL_STRLEN((char *)cbc_data)+1,ks,
			 &cbc_iv,DES_ENCRYPT);
	if (TINYCLR_SSL_MEMCMP(cbc_out,pcbc_ok,32) != 0)
		{
		TINYCLR_SSL_PRINTF("pcbc_encrypt encrypt error\n");
		err=1;
		}
	des_pcbc_encrypt(cbc_out,cbc_in,TINYCLR_SSL_STRLEN((char *)cbc_data)+1,ks,&cbc_iv,
			 DES_DECRYPT);
	if (TINYCLR_SSL_MEMCMP(cbc_in,cbc_data,TINYCLR_SSL_STRLEN((char *)cbc_data)+1) != 0)
		{
		TINYCLR_SSL_PRINTF("pcbc_encrypt decrypt error\n");
		err=1;
		}

	TINYCLR_SSL_PRINTF("Doing ");
	TINYCLR_SSL_PRINTF("cfb8 ");
	err+=cfb_test(8,cfb_cipher8);
	TINYCLR_SSL_PRINTF("cfb16 ");
	err+=cfb_test(16,cfb_cipher16);
	TINYCLR_SSL_PRINTF("cfb32 ");
	err+=cfb_test(32,cfb_cipher32);
	TINYCLR_SSL_PRINTF("cfb48 ");
	err+=cfb_test(48,cfb_cipher48);
	TINYCLR_SSL_PRINTF("cfb64 ");
	err+=cfb_test(64,cfb_cipher64);

	TINYCLR_SSL_PRINTF("cfb64() ");
	err+=cfb64_test(cfb_cipher64);

	TINYCLR_SSL_MEMCPY(cfb_tmp,cfb_iv,sizeof(cfb_iv));
	for (i=0; i<sizeof(plain); i++)
		des_cfb_encrypt(&(plain[i]),&(cfb_buf1[i]),
			8,1,ks,&cfb_tmp,DES_ENCRYPT);
	if (TINYCLR_SSL_MEMCMP(cfb_cipher8,cfb_buf1,sizeof(plain)) != 0)
		{
		TINYCLR_SSL_PRINTF("cfb_encrypt small encrypt error\n");
		err=1;
		}

	TINYCLR_SSL_MEMCPY(cfb_tmp,cfb_iv,sizeof(cfb_iv));
	for (i=0; i<sizeof(plain); i++)
		des_cfb_encrypt(&(cfb_buf1[i]),&(cfb_buf2[i]),
			8,1,ks,&cfb_tmp,DES_DECRYPT);
	if (TINYCLR_SSL_MEMCMP(plain,cfb_buf2,sizeof(plain)) != 0)
		{
		TINYCLR_SSL_PRINTF("cfb_encrypt small decrypt error\n");
		err=1;
		}

	TINYCLR_SSL_PRINTF("ede_cfb64() ");
	err+=ede_cfb64_test(cfb_cipher64);

	TINYCLR_SSL_PRINTF("done\n");

	TINYCLR_SSL_PRINTF("Doing ofb\n");
	DES_set_key_checked(&ofb_key,&ks);
	TINYCLR_SSL_MEMCPY(ofb_tmp,ofb_iv,sizeof(ofb_iv));
	des_ofb_encrypt(plain,ofb_buf1,64,sizeof(plain)/8,ks,&ofb_tmp);
	if (TINYCLR_SSL_MEMCMP(ofb_cipher,ofb_buf1,sizeof(ofb_buf1)) != 0)
		{
		TINYCLR_SSL_PRINTF("ofb_encrypt encrypt error\n");
TINYCLR_SSL_PRINTF("%02X %02X %02X %02X %02X %02X %02X %02X\n",
ofb_buf1[8+0], ofb_buf1[8+1], ofb_buf1[8+2], ofb_buf1[8+3],
ofb_buf1[8+4], ofb_buf1[8+5], ofb_buf1[8+6], ofb_buf1[8+7]);
TINYCLR_SSL_PRINTF("%02X %02X %02X %02X %02X %02X %02X %02X\n",
ofb_buf1[8+0], ofb_cipher[8+1], ofb_cipher[8+2], ofb_cipher[8+3],
ofb_buf1[8+4], ofb_cipher[8+5], ofb_cipher[8+6], ofb_cipher[8+7]);
		err=1;
		}
	TINYCLR_SSL_MEMCPY(ofb_tmp,ofb_iv,sizeof(ofb_iv));
	des_ofb_encrypt(ofb_buf1,ofb_buf2,64,sizeof(ofb_buf1)/8,ks,&ofb_tmp);
	if (TINYCLR_SSL_MEMCMP(plain,ofb_buf2,sizeof(ofb_buf2)) != 0)
		{
		TINYCLR_SSL_PRINTF("ofb_encrypt decrypt error\n");
TINYCLR_SSL_PRINTF("%02X %02X %02X %02X %02X %02X %02X %02X\n",
ofb_buf2[8+0], ofb_buf2[8+1], ofb_buf2[8+2], ofb_buf2[8+3],
ofb_buf2[8+4], ofb_buf2[8+5], ofb_buf2[8+6], ofb_buf2[8+7]);
TINYCLR_SSL_PRINTF("%02X %02X %02X %02X %02X %02X %02X %02X\n",
plain[8+0], plain[8+1], plain[8+2], plain[8+3],
plain[8+4], plain[8+5], plain[8+6], plain[8+7]);
		err=1;
		}

	TINYCLR_SSL_PRINTF("Doing ofb64\n");
	DES_set_key_checked(&ofb_key,&ks);
	TINYCLR_SSL_MEMCPY(ofb_tmp,ofb_iv,sizeof(ofb_iv));
	TINYCLR_SSL_MEMSET(ofb_buf1,0,sizeof(ofb_buf1));
	TINYCLR_SSL_MEMSET(ofb_buf2,0,sizeof(ofb_buf1));
	num=0;
	for (i=0; i<sizeof(plain); i++)
		{
		des_ofb64_encrypt(&(plain[i]),&(ofb_buf1[i]),1,ks,&ofb_tmp,
				  &num);
		}
	if (TINYCLR_SSL_MEMCMP(ofb_cipher,ofb_buf1,sizeof(ofb_buf1)) != 0)
		{
		TINYCLR_SSL_PRINTF("ofb64_encrypt encrypt error\n");
		err=1;
		}
	TINYCLR_SSL_MEMCPY(ofb_tmp,ofb_iv,sizeof(ofb_iv));
	num=0;
	des_ofb64_encrypt(ofb_buf1,ofb_buf2,sizeof(ofb_buf1),ks,&ofb_tmp,
			  &num);
	if (TINYCLR_SSL_MEMCMP(plain,ofb_buf2,sizeof(ofb_buf2)) != 0)
		{
		TINYCLR_SSL_PRINTF("ofb64_encrypt decrypt error\n");
		err=1;
		}

	TINYCLR_SSL_PRINTF("Doing ede_ofb64\n");
	DES_set_key_checked(&ofb_key,&ks);
	TINYCLR_SSL_MEMCPY(ofb_tmp,ofb_iv,sizeof(ofb_iv));
	TINYCLR_SSL_MEMSET(ofb_buf1,0,sizeof(ofb_buf1));
	TINYCLR_SSL_MEMSET(ofb_buf2,0,sizeof(ofb_buf1));
	num=0;
	for (i=0; i<sizeof(plain); i++)
		{
		des_ede3_ofb64_encrypt(&(plain[i]),&(ofb_buf1[i]),1,ks,ks,
				       ks,&ofb_tmp,&num);
		}
	if (TINYCLR_SSL_MEMCMP(ofb_cipher,ofb_buf1,sizeof(ofb_buf1)) != 0)
		{
		TINYCLR_SSL_PRINTF("ede_ofb64_encrypt encrypt error\n");
		err=1;
		}
	TINYCLR_SSL_MEMCPY(ofb_tmp,ofb_iv,sizeof(ofb_iv));
	num=0;
	des_ede3_ofb64_encrypt(ofb_buf1,ofb_buf2,sizeof(ofb_buf1),ks,ks,ks,
			       &ofb_tmp,&num);
	if (TINYCLR_SSL_MEMCMP(plain,ofb_buf2,sizeof(ofb_buf2)) != 0)
		{
		TINYCLR_SSL_PRINTF("ede_ofb64_encrypt decrypt error\n");
		err=1;
		}

	TINYCLR_SSL_PRINTF("Doing cbc_cksum\n");
	DES_set_key_checked(&cbc_key,&ks);
	cs=des_cbc_cksum(cbc_data,&cret,TINYCLR_SSL_STRLEN((char *)cbc_data),ks,&cbc_iv);
	if (cs != cbc_cksum_ret)
		{
		TINYCLR_SSL_PRINTF("bad return value (%08lX), should be %08lX\n",
			(unsigned long)cs,(unsigned long)cbc_cksum_ret);
		err=1;
		}
	if (TINYCLR_SSL_MEMCMP(cret,cbc_cksum_data,8) != 0)
		{
		TINYCLR_SSL_PRINTF("bad cbc_cksum block returned\n");
		err=1;
		}

	TINYCLR_SSL_PRINTF("Doing quad_cksum\n");
	cs=des_quad_cksum(cbc_data,(des_cblock *)lqret,
		(long)TINYCLR_SSL_STRLEN((char *)cbc_data),2,(des_cblock *)cbc_iv);
	if (cs != 0x70d7a63aL)
		{
		TINYCLR_SSL_PRINTF("quad_cksum error, ret %08lx should be 70d7a63a\n",
			(unsigned long)cs);
		err=1;
		}
#ifdef _CRAY
	if (lqret[0].a != 0x327eba8dL)
		{
		TINYCLR_SSL_PRINTF("quad_cksum error, out[0] %08lx is not %08lx\n",
			(unsigned long)lqret[0].a,0x327eba8dUL);
		err=1;
		}
	if (lqret[0].b != 0x201a49ccL)
		{
		TINYCLR_SSL_PRINTF("quad_cksum error, out[1] %08lx is not %08lx\n",
			(unsigned long)lqret[0].b,0x201a49ccUL);
		err=1;
		}
	if (lqret[1].a != 0x70d7a63aL)
		{
		TINYCLR_SSL_PRINTF("quad_cksum error, out[2] %08lx is not %08lx\n",
			(unsigned long)lqret[1].a,0x70d7a63aUL);
		err=1;
		}
	if (lqret[1].b != 0x501c2c26L)
		{
		TINYCLR_SSL_PRINTF("quad_cksum error, out[3] %08lx is not %08lx\n",
			(unsigned long)lqret[1].b,0x501c2c26UL);
		err=1;
		}
#else
	if (lqret[0] != 0x327eba8dL)
		{
		TINYCLR_SSL_PRINTF("quad_cksum error, out[0] %08lx is not %08lx\n",
			(unsigned long)lqret[0],0x327eba8dUL);
		err=1;
		}
	if (lqret[1] != 0x201a49ccL)
		{
		TINYCLR_SSL_PRINTF("quad_cksum error, out[1] %08lx is not %08lx\n",
			(unsigned long)lqret[1],0x201a49ccUL);
		err=1;
		}
	if (lqret[2] != 0x70d7a63aL)
		{
		TINYCLR_SSL_PRINTF("quad_cksum error, out[2] %08lx is not %08lx\n",
			(unsigned long)lqret[2],0x70d7a63aUL);
		err=1;
		}
	if (lqret[3] != 0x501c2c26L)
		{
		TINYCLR_SSL_PRINTF("quad_cksum error, out[3] %08lx is not %08lx\n",
			(unsigned long)lqret[3],0x501c2c26UL);
		err=1;
		}
#endif
#endif

	TINYCLR_SSL_PRINTF("input word alignment test");
	for (i=0; i<4; i++)
		{
		TINYCLR_SSL_PRINTF(" %d",i);
		des_ncbc_encrypt(&(cbc_out[i]),cbc_in,
				 TINYCLR_SSL_STRLEN((char *)cbc_data)+1,ks,
				 &cbc_iv,DES_ENCRYPT);
		}
	TINYCLR_SSL_PRINTF("\noutput word alignment test");
	for (i=0; i<4; i++)
		{
		TINYCLR_SSL_PRINTF(" %d",i);
		des_ncbc_encrypt(cbc_out,&(cbc_in[i]),
				 TINYCLR_SSL_STRLEN((char *)cbc_data)+1,ks,
				 &cbc_iv,DES_ENCRYPT);
		}
	TINYCLR_SSL_PRINTF("\n");
	TINYCLR_SSL_PRINTF("fast crypt test ");
	str=crypt("testing","ef");
	if (TINYCLR_SSL_STRCMP("efGnQx2725bI2",str) != 0)
		{
		TINYCLR_SSL_PRINTF("fast crypt error, %s should be efGnQx2725bI2\n",str);
		err=1;
		}
	str=crypt("bca76;23","yA");
	if (TINYCLR_SSL_STRCMP("yA1Rp/1hZXIJk",str) != 0)
		{
		TINYCLR_SSL_PRINTF("fast crypt error, %s should be yA1Rp/1hZXIJk\n",str);
		err=1;
		}
#ifdef OPENSSL_SYS_NETWARE
    if (err) TINYCLR_SSL_PRINTF("ERROR: %d\n", err);
#endif
	TINYCLR_SSL_PRINTF("\n");
	return(err);
	}
Exemple #11
0
int HMAC_Init_ex(HMAC_CTX *ctx, const void *key, int len,
                 const EVP_MD *md, ENGINE *impl)
{
    int i,j,reset=0;
    unsigned char pad[HMAC_MAX_MD_CBLOCK];

    if (md != NULL)
    {
        reset=1;
        ctx->md=md;
    }
    else
        md=ctx->md;

    if (key != NULL)
    {
        reset=1;
        j=EVP_MD_block_size(md);
        OPENSSL_assert(j <= (int)sizeof(ctx->key));
        if (j < len)
        {
            if (!EVP_DigestInit_ex(&ctx->md_ctx,md, impl))
                goto err;
            if (!EVP_DigestUpdate(&ctx->md_ctx,key,len))
                goto err;
            if (!EVP_DigestFinal_ex(&(ctx->md_ctx),ctx->key,
                                    &ctx->key_length))
                goto err;
        }
        else
        {
            OPENSSL_assert(len>=0 && len<=(int)sizeof(ctx->key));
            TINYCLR_SSL_MEMCPY(ctx->key,key,len);
            ctx->key_length=len;
        }
        if(ctx->key_length != HMAC_MAX_MD_CBLOCK)
            TINYCLR_SSL_MEMSET(&ctx->key[ctx->key_length], 0,
                               HMAC_MAX_MD_CBLOCK - ctx->key_length);
    }

    if (reset)
    {
        for (i=0; i<HMAC_MAX_MD_CBLOCK; i++)
            pad[i]=0x36^ctx->key[i];
        if (!EVP_DigestInit_ex(&ctx->i_ctx,md, impl))
            goto err;
        if (!EVP_DigestUpdate(&ctx->i_ctx,pad,EVP_MD_block_size(md)))
            goto err;

        for (i=0; i<HMAC_MAX_MD_CBLOCK; i++)
            pad[i]=0x5c^ctx->key[i];
        if (!EVP_DigestInit_ex(&ctx->o_ctx,md, impl))
            goto err;
        if (!EVP_DigestUpdate(&ctx->o_ctx,pad,EVP_MD_block_size(md)))
            goto err;
    }
    if (!EVP_MD_CTX_copy_ex(&ctx->md_ctx,&ctx->i_ctx))
        goto err;
    return 1;
err:
    return 0;
}
int ssl_test_rc4(int argc, char *argv[])
	{
	int i,err=0;
	int j;
	unsigned char *p;
	RC4_KEY key;
	unsigned char obuf[512];

	for (i=0; i<6; i++)
		{
		RC4_set_key(&key,keys[i][0],&(keys[i][1]));
		TINYCLR_SSL_MEMSET(obuf,0x00,sizeof(obuf));
		RC4(&key,data_len[i],&(data[i][0]),obuf);
		if (TINYCLR_SSL_MEMCMP(obuf,output[i],data_len[i]+1) != 0)
			{
			TINYCLR_SSL_PRINTF("error calculating RC4\n");
			TINYCLR_SSL_PRINTF("output:");
			for (j=0; j<data_len[i]+1; j++)
				TINYCLR_SSL_PRINTF(" %02x",obuf[j]);
			TINYCLR_SSL_PRINTF("\n");
			TINYCLR_SSL_PRINTF("expect:");
			p= &(output[i][0]);
			for (j=0; j<data_len[i]+1; j++)
				TINYCLR_SSL_PRINTF(" %02x",*(p++));
			TINYCLR_SSL_PRINTF("\n");
			err++;
			}
		else
			TINYCLR_SSL_PRINTF("test %d ok\n",i);
		}
	TINYCLR_SSL_PRINTF("test end processing ");
	for (i=0; i<data_len[3]; i++)
		{
		RC4_set_key(&key,keys[3][0],&(keys[3][1]));
		TINYCLR_SSL_MEMSET(obuf,0x00,sizeof(obuf));
		RC4(&key,i,&(data[3][0]),obuf);
		if ((TINYCLR_SSL_MEMCMP(obuf,output[3],i) != 0) || (obuf[i] != 0))
			{
			TINYCLR_SSL_PRINTF("error in RC4 length processing\n");
			TINYCLR_SSL_PRINTF("output:");
			for (j=0; j<i+1; j++)
				TINYCLR_SSL_PRINTF(" %02x",obuf[j]);
			TINYCLR_SSL_PRINTF("\n");
			TINYCLR_SSL_PRINTF("expect:");
			p= &(output[3][0]);
			for (j=0; j<i; j++)
				TINYCLR_SSL_PRINTF(" %02x",*(p++));
			TINYCLR_SSL_PRINTF(" 00\n");
			err++;
			}
		else
			{
			TINYCLR_SSL_PRINTF(".");
			TINYCLR_SSL_FFLUSH(OPENSSL_TYPE__FILE_STDOUT);
			}
		}
	TINYCLR_SSL_PRINTF("done\n");
	TINYCLR_SSL_PRINTF("test multi-call ");
	for (i=0; i<data_len[3]; i++)
		{
		RC4_set_key(&key,keys[3][0],&(keys[3][1]));
		TINYCLR_SSL_MEMSET(obuf,0x00,sizeof(obuf));
		RC4(&key,i,&(data[3][0]),obuf);
		RC4(&key,data_len[3]-i,&(data[3][i]),&(obuf[i]));
		if (TINYCLR_SSL_MEMCMP(obuf,output[3],data_len[3]+1) != 0)
			{
			TINYCLR_SSL_PRINTF("error in RC4 multi-call processing\n");
			TINYCLR_SSL_PRINTF("output:");
			for (j=0; j<data_len[3]+1; j++)
				TINYCLR_SSL_PRINTF(" %02x",obuf[j]);
			TINYCLR_SSL_PRINTF("\n");
			TINYCLR_SSL_PRINTF("expect:");
			p= &(output[3][0]);
			for (j=0; j<data_len[3]+1; j++)
				TINYCLR_SSL_PRINTF(" %02x",*(p++));
			err++;
			}
		else
			{
			TINYCLR_SSL_PRINTF(".");
			TINYCLR_SSL_FFLUSH(OPENSSL_TYPE__FILE_STDOUT);
			}
		}
	TINYCLR_SSL_PRINTF("done\n");
	TINYCLR_SSL_PRINTF("bulk test ");
	{   unsigned char buf[513];
	    SHA_CTX c;
	    unsigned char md[SHA_DIGEST_LENGTH];
	    static unsigned char expected[]={
		0xa4,0x7b,0xcc,0x00,0x3d,0xd0,0xbd,0xe1,0xac,0x5f,
		0x12,0x1e,0x45,0xbc,0xfb,0x1a,0xa1,0xf2,0x7f,0xc5 };

		RC4_set_key(&key,keys[0][0],&(keys[3][1]));
		TINYCLR_SSL_MEMSET(buf,'\0',sizeof(buf));
		SHA1_Init(&c);
		for (i=0;i<2571;i++) {
			RC4(&key,sizeof(buf),buf,buf);
			SHA1_Update(&c,buf,sizeof(buf));
		}
		SHA1_Final(md,&c);

		if (TINYCLR_SSL_MEMCMP(md,expected,sizeof(md))) {
			TINYCLR_SSL_PRINTF("error in RC4 bulk test\n");
			TINYCLR_SSL_PRINTF("output:");
			for (j=0; j<(int)sizeof(md); j++)
				TINYCLR_SSL_PRINTF(" %02x",md[j]);
			TINYCLR_SSL_PRINTF("\n");
			TINYCLR_SSL_PRINTF("expect:");
			for (j=0; j<(int)sizeof(md); j++)
				TINYCLR_SSL_PRINTF(" %02x",expected[j]);
			TINYCLR_SSL_PRINTF("\n");
			err++;
		}
		else	TINYCLR_SSL_PRINTF("ok\n");
	}
#ifdef OPENSSL_SYS_NETWARE
    if (err) TINYCLR_SSL_PRINTF("ERROR: %d\n", err);
#endif
	return(err);
	}
/* This implementation is based on the following primitives in the IEEE 1363 standard:
 *  - ECKAS-DH1
 *  - ECSVDP-DH
 * Finally an optional KDF is applied.
 */
static int ecdh_compute_key(void *out, size_t outlen, const EC_POINT *pub_key,
	EC_KEY *ecdh,
	void *(*KDF)(const void *in, size_t inlen, void *out, size_t *outlen))
	{
	BN_CTX *ctx;
	EC_POINT *tmp=NULL;
	BIGNUM *x=NULL, *y=NULL;
	const BIGNUM *priv_key;
	const EC_GROUP* group;
	int ret= -1;
	size_t buflen, len;
	unsigned char *buf=NULL;

	if (outlen > INT_MAX)
		{
		ECDHerr(ECDH_F_ECDH_COMPUTE_KEY,ERR_R_MALLOC_FAILURE); /* sort of, anyway */
		return -1;
		}

	if ((ctx = BN_CTX_new()) == NULL) goto err;
	BN_CTX_start(ctx);
	x = BN_CTX_get(ctx);
	y = BN_CTX_get(ctx);
	
	priv_key = EC_KEY_get0_private_key(ecdh);
	if (priv_key == NULL)
		{
		ECDHerr(ECDH_F_ECDH_COMPUTE_KEY,ECDH_R_NO_PRIVATE_VALUE);
		goto err;
		}

	group = EC_KEY_get0_group(ecdh);
	if ((tmp=EC_POINT_new(group)) == NULL)
		{
		ECDHerr(ECDH_F_ECDH_COMPUTE_KEY,ERR_R_MALLOC_FAILURE);
		goto err;
		}

	if (!EC_POINT_mul(group, tmp, NULL, pub_key, priv_key, ctx)) 
		{
		ECDHerr(ECDH_F_ECDH_COMPUTE_KEY,ECDH_R_POINT_ARITHMETIC_FAILURE);
		goto err;
		}
		
	if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) == NID_X9_62_prime_field) 
		{
		if (!EC_POINT_get_affine_coordinates_GFp(group, tmp, x, y, ctx)) 
			{
			ECDHerr(ECDH_F_ECDH_COMPUTE_KEY,ECDH_R_POINT_ARITHMETIC_FAILURE);
			goto err;
			}
		}
	else
		{
		if (!EC_POINT_get_affine_coordinates_GF2m(group, tmp, x, y, ctx)) 
			{
			ECDHerr(ECDH_F_ECDH_COMPUTE_KEY,ECDH_R_POINT_ARITHMETIC_FAILURE);
			goto err;
			}
		}

	buflen = (EC_GROUP_get_degree(group) + 7)/8;
	len = BN_num_bytes(x);
	if (len > buflen)
		{
		ECDHerr(ECDH_F_ECDH_COMPUTE_KEY,ERR_R_INTERNAL_ERROR);
		goto err;
		}
	if ((buf = (unsigned char*)OPENSSL_malloc(buflen)) == NULL)
		{
		ECDHerr(ECDH_F_ECDH_COMPUTE_KEY,ERR_R_MALLOC_FAILURE);
		goto err;
		}
	
	TINYCLR_SSL_MEMSET(buf, 0, buflen - len);
	if (len != (size_t)BN_bn2bin(x, buf + buflen - len))
		{
		ECDHerr(ECDH_F_ECDH_COMPUTE_KEY,ERR_R_BN_LIB);
		goto err;
		}

	if (KDF != 0)
		{
		if (KDF(buf, buflen, out, &outlen) == NULL)
			{
			ECDHerr(ECDH_F_ECDH_COMPUTE_KEY,ECDH_R_KDF_FAILED);
			goto err;
			}
		ret = outlen;
		}
	else
		{
		/* no KDF, just copy as much as we can */
		if (outlen > buflen)
			outlen = buflen;
		TINYCLR_SSL_MEMCPY(out, buf, outlen);
		ret = outlen;
		}
	
err:
	if (tmp) EC_POINT_free(tmp);
	if (ctx) BN_CTX_end(ctx);
	if (ctx) BN_CTX_free(ctx);
	if (buf) OPENSSL_free(buf);
	return(ret);
	}
const char *LP_find_file(LP_DIR_CTX **ctx, const char *directory)
{
  if (ctx == NULL || directory == NULL)
    {
      errno = EINVAL;
      return 0;
    }

  errno = 0;
  if (*ctx == NULL)
    {
      *ctx = (LP_DIR_CTX *)OPENSSL_malloc(sizeof(LP_DIR_CTX));
      if (*ctx == NULL)
	{
	  errno = ENOMEM;
	  return 0;
	}
      TINYCLR_SSL_MEMSET(*ctx, '\0', sizeof(LP_DIR_CTX));

      if (sizeof(TCHAR) != sizeof(char))
	{
	  TCHAR *wdir = NULL;
	  /* len_0 denotes string length *with* trailing 0 */ 
	  size_t index = 0,len_0 = TINYCLR_SSL_STRLEN(directory) + 1;

	  wdir = (TCHAR *)OPENSSL_malloc(len_0 * sizeof(TCHAR));
	  if (wdir == NULL)
	    {
	      OPENSSL_free(*ctx);
	      *ctx = NULL;
	      errno = ENOMEM;
	      return 0;
	    }

#ifdef LP_MULTIBYTE_AVAILABLE
	  if (!MultiByteToWideChar(CP_ACP, 0, directory, len_0, (WCHAR *)wdir, len_0))
#endif
	    for (index = 0; index < len_0; index++)
	      wdir[index] = (TCHAR)directory[index];

	  (*ctx)->handle = FindFirstFile(wdir, &(*ctx)->ctx);

	  OPENSSL_free(wdir);
	}
      else
	(*ctx)->handle = FindFirstFile((TCHAR *)directory, &(*ctx)->ctx);

      if ((*ctx)->handle == INVALID_HANDLE_VALUE)
	{
	  OPENSSL_free(*ctx);
	  *ctx = NULL;
	  errno = EINVAL;
	  return 0;
	}
    }
  else
    {
      if (FindNextFile((*ctx)->handle, &(*ctx)->ctx) == FALSE)
	{
	  return 0;
	}
    }

  if (sizeof(TCHAR) != sizeof(char))
    {
      TCHAR *wdir = (*ctx)->ctx.cFileName;
      size_t index, len_0 = 0;

      while (wdir[len_0] && len_0 < (sizeof((*ctx)->entry_name) - 1)) len_0++;
      len_0++;

#ifdef LP_MULTIBYTE_AVAILABLE
      if (!WideCharToMultiByte(CP_ACP, 0, (WCHAR *)wdir, len_0, (*ctx)->entry_name,
			       sizeof((*ctx)->entry_name), NULL, 0))
#endif
	for (index = 0; index < len_0; index++)
	  (*ctx)->entry_name[index] = (char)wdir[index];
    }
  else
    TINYCLR_SSL_STRNCPY((*ctx)->entry_name, (const char *)(*ctx)->ctx.cFileName,
	    sizeof((*ctx)->entry_name)-1);

  (*ctx)->entry_name[sizeof((*ctx)->entry_name)-1] = '\0';

  return (*ctx)->entry_name;
}
void EVP_MD_CTX_init(EVP_MD_CTX *ctx)
	{
	TINYCLR_SSL_MEMSET(ctx,'\0',sizeof *ctx);
	}
CK_RV PKCS11_Digest_OpenSSL::DigestInit(Cryptoki_Session_Context* pSessionCtx, CK_MECHANISM_PTR pMechanism)
{
    OPENSSL_HEADER();
    
    OpenSSLDigestData* pDigData;
    const EVP_MD*      pDigest;
    CK_OBJECT_HANDLE   hKey   = CK_OBJECT_HANDLE_INVALID;
    bool               isHMAC = false;

    if(pSessionCtx            == NULL) return CKR_SESSION_CLOSED;
    if(pSessionCtx->DigestCtx != NULL) return CKR_SESSION_PARALLEL_NOT_SUPPORTED; // another digest is in progress
    
    pDigData = (OpenSSLDigestData*)TINYCLR_SSL_MALLOC(sizeof(*pDigData));

    if(pDigData == NULL) return CKR_DEVICE_MEMORY;

    TINYCLR_SSL_MEMSET(pDigData, 0, sizeof(*pDigData));
    
    EVP_MD_CTX_init(&pDigData->CurrentCtx);
    
    switch(pMechanism->mechanism)
    {
        case CKM_SHA_1:
            pDigest = EVP_sha1();
            break;
        case CKM_SHA224:
            pDigest = EVP_sha224();
            break;
        case CKM_SHA256:
            pDigest = EVP_sha256();
            break;
        case CKM_SHA384:
            pDigest = EVP_sha384();
            break;
        case CKM_SHA512:
            pDigest = EVP_sha512();
            break;

        case CKM_MD5:
            pDigest = EVP_md5();
            break;

        case CKM_RIPEMD160:
            pDigest = EVP_ripemd160();
            break;

        case CKM_MD5_HMAC:
            pDigest = EVP_md5();
            isHMAC = true;
            break;

        case CKM_SHA_1_HMAC:
            pDigest = EVP_sha1();
            isHMAC = true;
            break;

        case CKM_SHA256_HMAC:
            pDigest = EVP_sha256();
            isHMAC = true;
            break;

        case CKM_SHA384_HMAC:
            pDigest = EVP_sha384();
            isHMAC = true;
            break;

        case CKM_SHA512_HMAC:
            pDigest = EVP_sha512();
            isHMAC = true;
            break;

        case CKM_RIPEMD160_HMAC:
            pDigest = EVP_ripemd160();
            isHMAC = true;
            break;
            

        default:
            OPENSSL_SET_AND_LEAVE(CKR_MECHANISM_INVALID);
    }


    if(isHMAC)
    {
        if(pMechanism->pParameter != NULL && pMechanism->ulParameterLen == sizeof(CK_OBJECT_HANDLE))
        {
            hKey = SwapEndianIfBEc32(*(CK_OBJECT_HANDLE*)pMechanism->pParameter);
        }
        else 
        {
            OPENSSL_SET_AND_LEAVE(CKR_MECHANISM_PARAM_INVALID);
        }

        pDigData->HmacKey = PKCS11_Keys_OpenSSL::GetKeyFromHandle(pSessionCtx, hKey, TRUE);

        if(pDigData->HmacKey==NULL) OPENSSL_SET_AND_LEAVE(CKR_MECHANISM_PARAM_INVALID);

        pDigData->HmacCtx.md = pDigest;

        OPENSSL_CHECKRESULT(HMAC_Init(&pDigData->HmacCtx, pDigData->HmacKey->key, pDigData->HmacKey->size/8, pDigData->HmacCtx.md));
    }
    else
    {
        OPENSSL_CHECKRESULT(EVP_DigestInit_ex(&pDigData->CurrentCtx, pDigest, NULL));
    }
    
    pSessionCtx->DigestCtx = pDigData;
    
    OPENSSL_CLEANUP();
    if(retVal != CKR_OK && pDigData != NULL)
    {
        TINYCLR_SSL_FREE(pDigData);
    }
    OPENSSL_RETURN();
}
static long dgram_ctrl(BIO *b, int cmd, long num, void *ptr)
	{
	long ret=1;
	int *ip;
	struct TINYCLR_SSL_SOCKADDR *to = NULL;
	bio_dgram_data *data = NULL;
#if defined(IP_MTU_DISCOVER) || defined(IP_MTU)
	long sockopt_val = 0;
	unsigned int sockopt_len = 0;
#endif
#ifdef OPENSSL_SYS_LINUX
	socklen_t addr_len;
	union	{
		struct TINYCLR_SSL_SOCKADDR	sa;
		struct TINYCLR_SSL_SOCKADDR_IN s4;
#if OPENSSL_USE_IPV6
		struct sockaddr_in6 s6;
#endif
		} addr;
#endif

	data = (bio_dgram_data *)b->ptr;

	switch (cmd)
		{
	case BIO_CTRL_RESET:
		num=0;
	case BIO_C_FILE_SEEK:
		ret=0;
		break;
	case BIO_C_FILE_TELL:
	case BIO_CTRL_INFO:
		ret=0;
		break;
	case BIO_C_SET_FD:
		dgram_clear(b);
		b->num= *((int *)ptr);
		b->shutdown=(int)num;
		b->init=1;
		break;
	case BIO_C_GET_FD:
		if (b->init)
			{
			ip=(int *)ptr;
			if (ip != NULL) *ip=b->num;
			ret=b->num;
			}
		else
			ret= -1;
		break;
	case BIO_CTRL_GET_CLOSE:
		ret=b->shutdown;
		break;
	case BIO_CTRL_SET_CLOSE:
		b->shutdown=(int)num;
		break;
	case BIO_CTRL_PENDING:
	case BIO_CTRL_WPENDING:
		ret=0;
		break;
	case BIO_CTRL_DUP:
	case BIO_CTRL_FLUSH:
		ret=1;
		break;
	case BIO_CTRL_DGRAM_CONNECT:
		to = (struct TINYCLR_SSL_SOCKADDR *)ptr;
#if 0
		if (TINYCLR_SSL_CONNECT(b->num, to, sizeof(struct TINYCLR_SSL_SOCKADDR)) < 0)
			{ TINYCLR_SSL_PERROR("connect"); ret = 0; }
		else
			{
#endif
			switch (to->sa_family)
				{
				case AF_INET:
					TINYCLR_SSL_MEMCPY(&data->peer,to,sizeof(data->peer.sa_in));
					break;
#if OPENSSL_USE_IPV6
				case AF_INET6:
					TINYCLR_SSL_MEMCPY(&data->peer,to,sizeof(data->peer.sa_in6));
					break;
#endif
				default:
					TINYCLR_SSL_MEMCPY(&data->peer,to,sizeof(data->peer.sa));
					break;
				}
#if 0
			}
#endif
		break;
		/* (Linux)kernel sets DF bit on outgoing IP packets */
	case BIO_CTRL_DGRAM_MTU_DISCOVER:
#ifdef OPENSSL_SYS_LINUX
		addr_len = (socklen_t)sizeof(addr);
		TINYCLR_SSL_MEMSET((void *)&addr, 0, sizeof(addr));
		if (getsockname(b->num, &addr.sa, &addr_len) < 0)
			{
			ret = 0;
			break;
			}
		sockopt_len = sizeof(sockopt_val);
		switch (addr.sa.sa_family)
			{
		case AF_INET:
			sockopt_val = IP_PMTUDISC_DO;
			if ((ret = TINYCLR_SSL_SETSOCKOPT(b->num, IPPROTO_IP, IP_MTU_DISCOVER,
				&sockopt_val, sizeof(sockopt_val))) < 0)
				TINYCLR_SSL_PERROR("setsockopt");
			break;
#if OPENSSL_USE_IPV6 && defined(IPV6_MTU_DISCOVER)
		case AF_INET6:
			sockopt_val = IPV6_PMTUDISC_DO;
			if ((ret = TINYCLR_SSL_SETSOCKOPT(b->num, IPPROTO_IPV6, IPV6_MTU_DISCOVER,
				&sockopt_val, sizeof(sockopt_val))) < 0)
				TINYCLR_SSL_PERROR("setsockopt");
			break;
#endif
		default:
			ret = -1;
			break;
			}
		ret = -1;
#else
		break;
#endif
	case BIO_CTRL_DGRAM_QUERY_MTU:
#ifdef OPENSSL_SYS_LINUX
		addr_len = (socklen_t)sizeof(addr);
		TINYCLR_SSL_MEMSET((void *)&addr, 0, sizeof(addr));
		if (getsockname(b->num, &addr.sa, &addr_len) < 0)
			{
			ret = 0;
			break;
			}
		sockopt_len = sizeof(sockopt_val);
		switch (addr.sa.sa_family)
			{
		case AF_INET:
			if ((ret = TINYCLR_SSL_GETSOCKOPT(b->num, IPPROTO_IP, IP_MTU, (void *)&sockopt_val,
				&sockopt_len)) < 0 || sockopt_val < 0)
				{
				ret = 0;
				}
			else
				{
				/* we assume that the transport protocol is UDP and no
				 * IP options are used.
				 */
				data->mtu = sockopt_val - 8 - 20;
				ret = data->mtu;
				}
			break;
#if OPENSSL_USE_IPV6 && defined(IPV6_MTU)
		case AF_INET6:
			if ((ret = TINYCLR_SSL_GETSOCKOPT(b->num, IPPROTO_IPV6, IPV6_MTU, (void *)&sockopt_val,
				&sockopt_len)) < 0 || sockopt_val < 0)
				{
				ret = 0;
				}
			else
				{
				/* we assume that the transport protocol is UDP and no
				 * IPV6 options are used.
				 */
				data->mtu = sockopt_val - 8 - 40;
				ret = data->mtu;
				}
			break;
#endif
		default:
			ret = 0;
			break;
			}
#else
		ret = 0;
#endif
		break;
	case BIO_CTRL_DGRAM_GET_MTU:
		return data->mtu;
		break;
	case BIO_CTRL_DGRAM_SET_MTU:
		data->mtu = num;
		ret = num;
		break;
	case BIO_CTRL_DGRAM_SET_CONNECTED:
		to = (struct TINYCLR_SSL_SOCKADDR *)ptr;

		if ( to != NULL)
			{
			data->connected = 1;
			switch (to->sa_family)
				{
				case AF_INET:
					TINYCLR_SSL_MEMCPY(&data->peer,to,sizeof(data->peer.sa_in));
					break;
#if OPENSSL_USE_IPV6
				case AF_INET6:
					TINYCLR_SSL_MEMCPY(&data->peer,to,sizeof(data->peer.sa_in6));
					break;
#endif
				default:
					TINYCLR_SSL_MEMCPY(&data->peer,to,sizeof(data->peer.sa));
					break;
				}
			}
		else
			{
			data->connected = 0;
			TINYCLR_SSL_MEMSET(&(data->peer), 0x00, sizeof(data->peer));
			}
		break;
	case BIO_CTRL_DGRAM_GET_PEER:
		switch (data->peer.sa.sa_family)
			{
			case AF_INET:
				ret=sizeof(data->peer.sa_in);
				break;
#if OPENSSL_USE_IPV6
			case AF_INET6:
				ret=sizeof(data->peer.sa_in6);
				break;
#endif
			default:
				ret=sizeof(data->peer.sa);
				break;
			}
		if (num==0 || num>ret)
			num=ret;
		TINYCLR_SSL_MEMCPY(ptr,&data->peer,(ret=num));
		break;
	case BIO_CTRL_DGRAM_SET_PEER:
		to = (struct TINYCLR_SSL_SOCKADDR *) ptr;
		switch (to->sa_family)
			{
			case AF_INET:
				TINYCLR_SSL_MEMCPY(&data->peer,to,sizeof(data->peer.sa_in));
				break;
#if OPENSSL_USE_IPV6
			case AF_INET6:
				TINYCLR_SSL_MEMCPY(&data->peer,to,sizeof(data->peer.sa_in6));
				break;
#endif
			default:
				TINYCLR_SSL_MEMCPY(&data->peer,to,sizeof(data->peer.sa));
				break;
			}
		break;
	case BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT:
		TINYCLR_SSL_MEMCPY(&(data->next_timeout), ptr, sizeof(struct TINYCLR_SSL_TIMEVAL));
		break;
#if defined(SO_RCVTIMEO)
	case BIO_CTRL_DGRAM_SET_RECV_TIMEOUT:
#ifdef OPENSSL_SYS_WINDOWS
		{
		struct TINYCLR_SSL_TIMEVAL *tv = (struct TINYCLR_SSL_TIMEVAL *)ptr;
		int timeout = tv->tv_sec * 1000 + tv->tv_usec/1000;
		if (TINYCLR_SSL_SETSOCKOPT(b->num, SOL_SOCKET, SO_RCVTIMEO,
			(const char*)&timeout, sizeof(timeout)) < 0)
			{ TINYCLR_SSL_PERROR("setsockopt"); ret = -1; }
		}
#else
		if ( TINYCLR_SSL_SETSOCKOPT(b->num, SOL_SOCKET, SO_RCVTIMEO, ptr,
			sizeof(struct TINYCLR_SSL_TIMEVAL)) < 0)
			{ TINYCLR_SSL_PERROR("setsockopt");	ret = -1; }
#endif
		break;
	case BIO_CTRL_DGRAM_GET_RECV_TIMEOUT:
#ifdef OPENSSL_SYS_WINDOWS
		{
		int timeout, sz = sizeof(timeout);
		struct TINYCLR_SSL_TIMEVAL *tv = (struct TINYCLR_SSL_TIMEVAL *)ptr;
		if (TINYCLR_SSL_GETSOCKOPT(b->num, SOL_SOCKET, SO_RCVTIMEO,
			(char*)&timeout, &sz) < 0)
			{ TINYCLR_SSL_PERROR("getsockopt"); ret = -1; }
		else
			{
			tv->tv_sec = timeout / 1000;
			tv->tv_usec = (timeout % 1000) * 1000;
			ret = sizeof(*tv);
			}
		}
#elif defined(OPENSSL_SYS_ARM) || defined(OPENSSL_SYS_SH)
		if ( TINYCLR_SSL_GETSOCKOPT(b->num, SOL_SOCKET, SO_RCVTIMEO, 
			ptr, (u32_t *)&ret) < 0)
			{ TINYCLR_SSL_PERROR("getsockopt"); ret = -1; }
#else
		if ( TINYCLR_SSL_GETSOCKOPT(b->num, SOL_SOCKET, SO_RCVTIMEO, 
			ptr, (void *)&ret) < 0)
			{ TINYCLR_SSL_PERROR("getsockopt"); ret = -1; }
#endif
		break;
#endif
#if defined(SO_SNDTIMEO)
	case BIO_CTRL_DGRAM_SET_SEND_TIMEOUT:
#ifdef OPENSSL_SYS_WINDOWS
		{
		struct TINYCLR_SSL_TIMEVAL *tv = (struct TINYCLR_SSL_TIMEVAL *)ptr;
		int timeout = tv->tv_sec * 1000 + tv->tv_usec/1000;
		if (TINYCLR_SSL_SETSOCKOPT(b->num, SOL_SOCKET, SO_SNDTIMEO,
			(const char*)&timeout, sizeof(timeout)) < 0)
			{ TINYCLR_SSL_PERROR("setsockopt"); ret = -1; }
		}
#else
		if ( TINYCLR_SSL_SETSOCKOPT(b->num, SOL_SOCKET, SO_SNDTIMEO, ptr,
			sizeof(struct TINYCLR_SSL_TIMEVAL)) < 0)
			{ TINYCLR_SSL_PERROR("setsockopt");	ret = -1; }
#endif
		break;
	case BIO_CTRL_DGRAM_GET_SEND_TIMEOUT:
#ifdef OPENSSL_SYS_WINDOWS
		{
		int timeout, sz = sizeof(timeout);
		struct TINYCLR_SSL_TIMEVAL *tv = (struct TINYCLR_SSL_TIMEVAL *)ptr;
		if (TINYCLR_SSL_GETSOCKOPT(b->num, SOL_SOCKET, SO_SNDTIMEO,
			(char*)&timeout, &sz) < 0)
			{ TINYCLR_SSL_PERROR("getsockopt"); ret = -1; }
		else
			{
			tv->tv_sec = timeout / 1000;
			tv->tv_usec = (timeout % 1000) * 1000;
			ret = sizeof(*tv);
			}
		}
#elif defined(OPENSSL_SYS_ARM) || defined(OPENSSL_SYS_SH)
		if ( TINYCLR_SSL_GETSOCKOPT(b->num, SOL_SOCKET, SO_SNDTIMEO, 
			ptr, (u32_t *)&ret) < 0)
			{ TINYCLR_SSL_PERROR("getsockopt"); ret = -1; }
#else
		if ( TINYCLR_SSL_GETSOCKOPT(b->num, SOL_SOCKET, SO_SNDTIMEO, 
			ptr, (void *)&ret) < 0)
			{ TINYCLR_SSL_PERROR("getsockopt"); ret = -1; }
#endif
		break;
#endif
	case BIO_CTRL_DGRAM_GET_SEND_TIMER_EXP:
		/* fall-through */
	case BIO_CTRL_DGRAM_GET_RECV_TIMER_EXP:
#ifdef OPENSSL_SYS_WINDOWS
		if ( data->_errno == WSAETIMEDOUT)
#else
		if ( data->_errno == EAGAIN)
#endif
			{
			ret = 1;
			data->_errno = 0;
			}
		else
			ret = 0;
		break;
#ifdef EMSGSIZE
	case BIO_CTRL_DGRAM_MTU_EXCEEDED:
		if ( data->_errno == EMSGSIZE)
			{
			ret = 1;
			data->_errno = 0;
			}
		else
			ret = 0;
		break;
#endif
	default:
		ret=0;
		break;
		}
	return(ret);
	}