/*
 * Sort comparision function for a sequence of ASIdOrRange elements.
 */
static int ASIdOrRange_cmp(const ASIdOrRange * const *a_,
			   const ASIdOrRange * const *b_)
{
  const ASIdOrRange *a = *a_, *b = *b_;

  TINYCLR_SSL_ASSERT((a->type == ASIdOrRange_id && a->u.id != NULL) ||
	 (a->type == ASIdOrRange_range && a->u.range != NULL &&
	  a->u.range->min != NULL && a->u.range->max != NULL));

  TINYCLR_SSL_ASSERT((b->type == ASIdOrRange_id && b->u.id != NULL) ||
	 (b->type == ASIdOrRange_range && b->u.range != NULL &&
	  b->u.range->min != NULL && b->u.range->max != NULL));

  if (a->type == ASIdOrRange_id && b->type == ASIdOrRange_id)
    return ASN1_INTEGER_cmp(a->u.id, b->u.id);

  if (a->type == ASIdOrRange_range && b->type == ASIdOrRange_range) {
    int r = ASN1_INTEGER_cmp(a->u.range->min, b->u.range->min);
    return r != 0 ? r : ASN1_INTEGER_cmp(a->u.range->max, b->u.range->max);
  }

  if (a->type == ASIdOrRange_id)
    return ASN1_INTEGER_cmp(a->u.id, b->u.range->min);
  else
    return ASN1_INTEGER_cmp(a->u.range->min, b->u.id);
}
Пример #2
0
int ssl2_enc_init(SSL *s, int client)
	{
	/* Max number of bytes needed */
	EVP_CIPHER_CTX *rs,*ws;
	const EVP_CIPHER *c;
	const EVP_MD *md;
	int num;

	if (!ssl_cipher_get_evp(s->session,&c,&md,NULL,NULL,NULL))
		{
		ssl2_return_error(s,SSL2_PE_NO_CIPHER);
		SSLerr(SSL_F_SSL2_ENC_INIT,SSL_R_PROBLEMS_MAPPING_CIPHER_FUNCTIONS);
		return(0);
		}
	ssl_replace_hash(&s->read_hash,md);
	ssl_replace_hash(&s->write_hash,md);

	if ((s->enc_read_ctx == NULL) &&
		((s->enc_read_ctx=(EVP_CIPHER_CTX *)
		OPENSSL_malloc(sizeof(EVP_CIPHER_CTX))) == NULL))
		goto err;

	/* make sure it's intialized in case the malloc for enc_write_ctx fails
	 * and we exit with an error */
	rs= s->enc_read_ctx;
	EVP_CIPHER_CTX_init(rs);

	if ((s->enc_write_ctx == NULL) &&
		((s->enc_write_ctx=(EVP_CIPHER_CTX *)
		OPENSSL_malloc(sizeof(EVP_CIPHER_CTX))) == NULL))
		goto err;

	ws= s->enc_write_ctx;
	EVP_CIPHER_CTX_init(ws);

	num=c->key_len;
	s->s2->key_material_length=num*2;
	TINYCLR_SSL_ASSERT(s->s2->key_material_length <= sizeof s->s2->key_material);

	if (ssl2_generate_key_material(s) <= 0)
		return 0;

	TINYCLR_SSL_ASSERT(c->iv_len <= (int)sizeof(s->session->key_arg));
	EVP_EncryptInit_ex(ws,c,NULL,&(s->s2->key_material[(client)?num:0]),
		s->session->key_arg);
	EVP_DecryptInit_ex(rs,c,NULL,&(s->s2->key_material[(client)?0:num]),
		s->session->key_arg);
	s->s2->read_key=  &(s->s2->key_material[(client)?0:num]);
	s->s2->write_key= &(s->s2->key_material[(client)?num:0]);
	return(1);
err:
	SSLerr(SSL_F_SSL2_ENC_INIT,ERR_R_MALLOC_FAILURE);
	return(0);
	}
int ssl3_send_finished(SSL *s, int a, int b, const char *sender, int slen)
	{
	unsigned char *p,*d;
	int i;
	unsigned long l;

	if (s->state == a)
		{
		d=(unsigned char *)s->init_buf->data;
		p= &(d[4]);

		i=s->method->ssl3_enc->final_finish_mac(s,
			sender,slen,s->s3->tmp.finish_md);
		s->s3->tmp.finish_md_len = i;
		TINYCLR_SSL_MEMCPY(p, s->s3->tmp.finish_md, i);
		p+=i;
		l=i;

                /* Copy the finished so we can use it for
                   renegotiation checks */
                if(s->type == SSL_ST_CONNECT)
                        {
                         TINYCLR_SSL_ASSERT(i <= EVP_MAX_MD_SIZE);
                         TINYCLR_SSL_MEMCPY(s->s3->previous_client_finished, 
                             s->s3->tmp.finish_md, i);
                         s->s3->previous_client_finished_len=i;
                        }
                else
                        {
                        TINYCLR_SSL_ASSERT(i <= EVP_MAX_MD_SIZE);
                        TINYCLR_SSL_MEMCPY(s->s3->previous_server_finished, 
                            s->s3->tmp.finish_md, i);
                        s->s3->previous_server_finished_len=i;
                        }

#ifdef OPENSSL_SYS_WIN16
		/* MSVC 1.5 does not clear the top bytes of the word unless
		 * I do this.
		 */
		l&=0xffff;
#endif

		*(d++)=SSL3_MT_FINISHED;
		l2n3(l,d);
		s->init_num=(int)l+4;
		s->init_off=0;

		s->state=b;
		}

	/* SSL3_ST_SEND_xxxxxx_HELLO_B */
	return(ssl3_do_write(s,SSL3_RT_HANDSHAKE));
	}
static int dev_crypto_init(session_op *ses)
    {
    if(dev_failed)
	return 0;
    if(!fd)
	{
	int cryptodev_fd;

        if ((cryptodev_fd=open("/dev/crypto",O_RDWR,0)) < 0)
	    {
	    err("/dev/crypto");
	    dev_failed=1;
	    return 0;
	    }
        if (TINYCLR_SSL_IOCTL(cryptodev_fd,CRIOGET,&fd) == -1)
	    {
	    err("CRIOGET failed");
	    close(cryptodev_fd);
	    dev_failed=1;
	    return 0;
	    }
	close(cryptodev_fd);
	}
    TINYCLR_SSL_ASSERT(ses);
    TINYCLR_SSL_MEMSET(ses,'\0',sizeof *ses);

    return 1;
    }
/*
 * Add an inherit element.
 */
int v3_asid_add_inherit(ASIdentifiers *asid, int which)
{
  ASIdentifierChoice **choice;
  if (asid == NULL)
    return 0;
  switch (which) {
  case V3_ASID_ASNUM:
    choice = &asid->asnum;
    break;
  case V3_ASID_RDI:
    choice = &asid->rdi;
    break;
  default:
    return 0;
  }
  if (*choice == NULL) {
    if ((*choice = ASIdentifierChoice_new()) == NULL)
      return 0;
    TINYCLR_SSL_ASSERT((*choice)->u.inherit == NULL);
    if (((*choice)->u.inherit = ASN1_NULL_new()) == NULL)
      return 0;
    (*choice)->type = ASIdentifierChoice_inherit;
  }
  return (*choice)->type == ASIdentifierChoice_inherit;
}
Пример #6
0
static void hashlength(SHA_CTX *sha, size_t l)
    {
    unsigned char b[2];

    TINYCLR_SSL_ASSERT(l <= 0xffff);
    b[0] = l >> 8;
    b[1] = l&0xff;
    SHA1_Update(sha, b, 2);
    }
/*
 * Add an ID or range to an ASIdentifierChoice.
 */
int v3_asid_add_id_or_range(ASIdentifiers *asid,
			    int which,
			    ASN1_INTEGER *min,
			    ASN1_INTEGER *max)
{
  ASIdentifierChoice **choice;
  ASIdOrRange *aor;
  if (asid == NULL)
    return 0;
  switch (which) {
  case V3_ASID_ASNUM:
    choice = &asid->asnum;
    break;
  case V3_ASID_RDI:
    choice = &asid->rdi;
    break;
  default:
    return 0;
  }
  if (*choice != NULL && (*choice)->type == ASIdentifierChoice_inherit)
    return 0;
  if (*choice == NULL) {
    if ((*choice = ASIdentifierChoice_new()) == NULL)
      return 0;
    TINYCLR_SSL_ASSERT((*choice)->u.asIdsOrRanges == NULL);
    (*choice)->u.asIdsOrRanges = sk_ASIdOrRange_new(ASIdOrRange_cmp);
    if ((*choice)->u.asIdsOrRanges == NULL)
      return 0;
    (*choice)->type = ASIdentifierChoice_asIdsOrRanges;
  }
  if ((aor = ASIdOrRange_new()) == NULL)
    return 0;
  if (max == NULL) {
    aor->type = ASIdOrRange_id;
    aor->u.id = min;
  } else {
    aor->type = ASIdOrRange_range;
    if ((aor->u.range = ASRange_new()) == NULL)
      goto err;
    ASN1_INTEGER_free(aor->u.range->min);
    aor->u.range->min = min;
    ASN1_INTEGER_free(aor->u.range->max);
    aor->u.range->max = max;
  }
  if (!(sk_ASIdOrRange_push((*choice)->u.asIdsOrRanges, aor)))
    goto err;
  return 1;

 err:
  ASIdOrRange_free(aor);
  return 0;
}
static int dev_crypto_md5_copy(EVP_MD_CTX *to,const EVP_MD_CTX *from)
    {
    const MD_DATA *from_md=from->md_data;
    MD_DATA *to_md=to->md_data;

    // How do we copy sessions?
    TINYCLR_SSL_ASSERT(from->digest->flags&EVP_MD_FLAG_ONESHOT);

    to_md->data=OPENSSL_malloc(from_md->len);
    TINYCLR_SSL_MEMCPY(to_md->data,from_md->data,from_md->len);

    return 1;
    }
TS_VERIFY_CTX *TS_REQ_to_TS_VERIFY_CTX(TS_REQ *req, TS_VERIFY_CTX *ctx)
	{
	TS_VERIFY_CTX *ret = ctx;
	ASN1_OBJECT *policy;
	TS_MSG_IMPRINT *imprint;
	X509_ALGOR *md_alg;
	ASN1_OCTET_STRING *msg;
	const ASN1_INTEGER *nonce;

	TINYCLR_SSL_ASSERT(req != NULL);
	if (ret)
		TS_VERIFY_CTX_cleanup(ret);
	else
		if (!(ret = TS_VERIFY_CTX_new())) return NULL;

	/* Setting flags. */
	ret->flags = TS_VFY_ALL_IMPRINT & ~(TS_VFY_TSA_NAME | TS_VFY_SIGNATURE);

	/* Setting policy. */
	if ((policy = TS_REQ_get_policy_id(req)) != NULL)
		{
		if (!(ret->policy = OBJ_dup(policy))) goto err;
		}
	else
		ret->flags &= ~TS_VFY_POLICY;

	/* Setting md_alg, imprint and imprint_len. */
	imprint = TS_REQ_get_msg_imprint(req);
	md_alg = TS_MSG_IMPRINT_get_algo(imprint);
	if (!(ret->md_alg = X509_ALGOR_dup(md_alg))) goto err;
	msg = TS_MSG_IMPRINT_get_msg(imprint);
	ret->imprint_len = ASN1_STRING_length(msg);
	if (!(ret->imprint = (unsigned char*)OPENSSL_malloc(ret->imprint_len))) goto err;
	TINYCLR_SSL_MEMCPY(ret->imprint, ASN1_STRING_data(msg), ret->imprint_len);

	/* Setting nonce. */
	if ((nonce = TS_REQ_get_nonce(req)) != NULL)
		{
		if (!(ret->nonce = ASN1_INTEGER_dup(nonce))) goto err;
		}
	else
		ret->flags &= ~TS_VFY_NONCE;

	return ret;
 err:
	if (ctx)
		TS_VERIFY_CTX_cleanup(ctx);
	else
		TS_VERIFY_CTX_free(ret);
	return NULL;
	}
/*
 * Extract min and max values from an ASIdOrRange.
 */
static void extract_min_max(ASIdOrRange *aor,
			    ASN1_INTEGER **min,
			    ASN1_INTEGER **max)
{
  TINYCLR_SSL_ASSERT(aor != NULL && min != NULL && max != NULL);
  switch (aor->type) {
  case ASIdOrRange_id:
    *min = aor->u.id;
    *max = aor->u.id;
    return;
  case ASIdOrRange_range:
    *min = aor->u.range->min;
    *max = aor->u.range->max;
    return;
  }
}
Пример #11
0
/* The caller can assume that this removes any secret data from the context */
int EVP_DigestFinal_ex(EVP_MD_CTX *ctx, unsigned char *md, unsigned int *size)
	{
	int ret;

	TINYCLR_SSL_ASSERT(ctx->digest->md_size <= EVP_MAX_MD_SIZE);
	ret=ctx->digest->final(ctx,md);
	if (size != NULL)
		*size=ctx->digest->md_size;
	if (ctx->digest->cleanup)
		{
		ctx->digest->cleanup(ctx);
		EVP_MD_CTX_set_flags(ctx,EVP_MD_CTX_FLAG_CLEANED);
		}
	TINYCLR_SSL_MEMSET(ctx->md_data,0,ctx->digest->ctx_size);
	return ret;
	}
Пример #12
0
void CRYPTO_lock(int mode, int type, const char *file, int line)
	{
#ifdef LOCK_DEBUG
		{
		CRYPTO_THREADID id;
		char *rw_text,*operation_text;

		if (mode & CRYPTO_LOCK)
			operation_text="lock  ";
		else if (mode & CRYPTO_UNLOCK)
			operation_text="unlock";
		else
			operation_text="ERROR ";

		if (mode & CRYPTO_READ)
			rw_text="r";
		else if (mode & CRYPTO_WRITE)
			rw_text="w";
		else
			rw_text="ERROR";

		CRYPTO_THREADID_current(&id);
		TINYCLR_SSL_FPRINTF(OPENSSL_TYPE__FILE_STDERR,"lock:%08lx:(%s)%s %-18s %s:%d\n",
			CRYPTO_THREADID_hash(&id), rw_text, operation_text,
			CRYPTO_get_lock_name(type), file, line);
		}
#endif
	if (type < 0)
		{
		if (dynlock_lock_callback != NULL)
			{
			struct CRYPTO_dynlock_value *pointer
				= CRYPTO_get_dynlock_value(type);

			TINYCLR_SSL_ASSERT(pointer != NULL);

			dynlock_lock_callback(mode, pointer, file, line);

			CRYPTO_destroy_dynlockid(type);
			}
		}
	else
		if (locking_callback != NULL)
			locking_callback(mode,type,file,line);
	}
Пример #13
0
/* h=hash(g, g^r, g^x, name) */
static void zkp_hash(BIGNUM *h, const BIGNUM *zkpg, const JPAKE_STEP_PART *p,
		     const char *proof_name)
    {
    unsigned char md[SHA_DIGEST_LENGTH];
    SHA_CTX sha;

   /*
    * XXX: hash should not allow moving of the boundaries - Java code
    * is flawed in this respect. Length encoding seems simplest.
    */
    SHA1_Init(&sha);
    hashbn(&sha, zkpg);
    TINYCLR_SSL_ASSERT(!BN_is_zero(p->zkpx.gr));
    hashbn(&sha, p->zkpx.gr);
    hashbn(&sha, p->gx);
    hashstring(&sha, proof_name);
    SHA1_Final(md, &sha);
    BN_bin2bn(md, SHA_DIGEST_LENGTH, h);
    }
Пример #14
0
void EVP_EncodeUpdate(EVP_ENCODE_CTX *ctx, unsigned char *out, int *outl,
	     const unsigned char *in, int inl)
	{
	int i,j;
	unsigned int total=0;

	*outl=0;
	if (inl == 0) return;
	TINYCLR_SSL_ASSERT(ctx->length <= (int)sizeof(ctx->enc_data));
	if ((ctx->num+inl) < ctx->length)
		{
		TINYCLR_SSL_MEMCPY(&(ctx->enc_data[ctx->num]),in,inl);
		ctx->num+=inl;
		return;
		}
	if (ctx->num != 0)
		{
		i=ctx->length-ctx->num;
		TINYCLR_SSL_MEMCPY(&(ctx->enc_data[ctx->num]),in,i);
		in+=i;
		inl-=i;
		j=EVP_EncodeBlock(out,ctx->enc_data,ctx->length);
		ctx->num=0;
		out+=j;
		*(out++)='\n';
		*out='\0';
		total=j+1;
		}
	while (inl >= ctx->length)
		{
		j=EVP_EncodeBlock(out,in,ctx->length);
		in+=ctx->length;
		inl-=ctx->length;
		out+=j;
		*(out++)='\n';
		*out='\0';
		total+=j+1;
		}
	if (inl != 0)
		TINYCLR_SSL_MEMCPY(&(ctx->enc_data[0]),in,inl);
	ctx->num=inl;
	*outl=total;
	}
static int dev_crypto_init_key(EVP_CIPHER_CTX *ctx,int cipher,
			       const unsigned char *key,int klen)
    {
    if(!dev_crypto_init(CDATA(ctx)))
	return 0;

    CDATA(ctx)->key=OPENSSL_malloc(MAX_HW_KEY);

    TINYCLR_SSL_ASSERT(ctx->cipher->iv_len <= MAX_HW_IV);

    TINYCLR_SSL_MEMCPY(CDATA(ctx)->key,key,klen);
    
    CDATA(ctx)->cipher=cipher;
    CDATA(ctx)->keylen=klen;

    if (TINYCLR_SSL_IOCTL(fd,CIOCGSESSION,CDATA(ctx)) == -1)
	{
	err("CIOCGSESSION failed");
	return 0;
	}
    return 1;
    }
Пример #16
0
static void block_in(BIO* b)
{
    BIO_OK_CTX *ctx;
    EVP_MD_CTX *md;
    unsigned long tl= 0;
    unsigned char tmp[EVP_MAX_MD_SIZE];

    ctx=(BIO_OK_CTX *)b->ptr;
    md=&ctx->md;

    TINYCLR_SSL_ASSERT(sizeof(tl)>=OK_BLOCK_BLOCK);	/* always true */
    tl =ctx->buf[0];
    tl<<=8;
    tl|=ctx->buf[1];
    tl<<=8;
    tl|=ctx->buf[2];
    tl<<=8;
    tl|=ctx->buf[3];

    if (ctx->buf_len < tl+ OK_BLOCK_BLOCK+ md->digest->md_size) return;

    EVP_DigestUpdate(md, (unsigned char*) &(ctx->buf[OK_BLOCK_BLOCK]), tl);
    EVP_DigestFinal_ex(md, tmp, NULL);
    if(TINYCLR_SSL_MEMCMP(&(ctx->buf[tl+ OK_BLOCK_BLOCK]), tmp, md->digest->md_size) == 0)
    {
        /* there might be parts from next block lurking around ! */
        ctx->buf_off_save= tl+ OK_BLOCK_BLOCK+ md->digest->md_size;
        ctx->buf_len_save= ctx->buf_len;
        ctx->buf_off= OK_BLOCK_BLOCK;
        ctx->buf_len= tl+ OK_BLOCK_BLOCK;
        ctx->blockout= 1;
    }
    else
    {
        ctx->cont= 0;
    }
}
Пример #17
0
int tls1_mac(SSL *ssl, unsigned char *md, int send)
	{
	SSL3_RECORD *rec;
	unsigned char *seq;
	EVP_MD_CTX *hash;
	size_t md_size;
	int i;
	EVP_MD_CTX hmac, *mac_ctx;
	unsigned char buf[5]; 
	int stream_mac = (send?(ssl->mac_flags & SSL_MAC_FLAG_WRITE_MAC_STREAM):(ssl->mac_flags&SSL_MAC_FLAG_READ_MAC_STREAM));
	int t;

	if (send)
		{
		rec= &(ssl->s3->wrec);
		seq= &(ssl->s3->write_sequence[0]);
		hash=ssl->write_hash;
		}
	else
		{
		rec= &(ssl->s3->rrec);
		seq= &(ssl->s3->read_sequence[0]);
		hash=ssl->read_hash;
		}

	t=EVP_MD_CTX_size(hash);
	TINYCLR_SSL_ASSERT(t >= 0);
	md_size=t;

	buf[0]=rec->type;
	buf[1]=(unsigned char)(ssl->version>>8);
	buf[2]=(unsigned char)(ssl->version);
	buf[3]=rec->length>>8;
	buf[4]=rec->length&0xff;

	/* I should fix this up TLS TLS TLS TLS TLS XXXXXXXX */
	if (stream_mac) 
		{
			mac_ctx = hash;
		}
		else
		{
			EVP_MD_CTX_copy(&hmac,hash);
			mac_ctx = &hmac;
		}

	if (ssl->version == DTLS1_VERSION || ssl->version == DTLS1_BAD_VER)
		{
		unsigned char dtlsseq[8],*p=dtlsseq;

		s2n(send?ssl->d1->w_epoch:ssl->d1->r_epoch, p);
		TINYCLR_SSL_MEMCPY (p,&seq[2],6);

		EVP_DigestSignUpdate(mac_ctx,dtlsseq,8);
		}
	else
		EVP_DigestSignUpdate(mac_ctx,seq,8);

	EVP_DigestSignUpdate(mac_ctx,buf,5);
	EVP_DigestSignUpdate(mac_ctx,rec->input,rec->length);
	t=EVP_DigestSignFinal(mac_ctx,md,&md_size);
	TINYCLR_SSL_ASSERT(t > 0);
		
	if (!stream_mac) EVP_MD_CTX_cleanup(&hmac);
#ifdef TLS_DEBUG
TINYCLR_SSL_PRINTF("sec=");
{unsigned int z; for (z=0; z<md_size; z++) TINYCLR_SSL_PRINTF("%02X ",mac_sec[z]); TINYCLR_SSL_PRINTF("\n"); }
TINYCLR_SSL_PRINTF("seq=");
{int z; for (z=0; z<8; z++) TINYCLR_SSL_PRINTF("%02X ",seq[z]); TINYCLR_SSL_PRINTF("\n"); }
TINYCLR_SSL_PRINTF("buf=");
{int z; for (z=0; z<5; z++) TINYCLR_SSL_PRINTF("%02X ",buf[z]); TINYCLR_SSL_PRINTF("\n"); }
TINYCLR_SSL_PRINTF("rec=");
{unsigned int z; for (z=0; z<rec->length; z++) TINYCLR_SSL_PRINTF("%02X ",buf[z]); TINYCLR_SSL_PRINTF("\n"); }
#endif

	if (ssl->version != DTLS1_VERSION && ssl->version != DTLS1_BAD_VER)
		{
		for (i=7; i>=0; i--)
			{
			++seq[i];
			if (seq[i] != 0) break; 
			}
		}

#ifdef TLS_DEBUG
{unsigned int z; for (z=0; z<md_size; z++) TINYCLR_SSL_PRINTF("%02X ",md[z]); TINYCLR_SSL_PRINTF("\n"); }
#endif
	return(md_size);
	}
Пример #18
0
/* seed1 through seed5 are virtually concatenated */
static int tls1_P_hash(const EVP_MD *md, const unsigned char *sec,
			int sec_len,
			const void *seed1, int seed1_len,
			const void *seed2, int seed2_len,
			const void *seed3, int seed3_len,
			const void *seed4, int seed4_len,
			const void *seed5, int seed5_len,
			unsigned char *out, int olen)
	{
	int chunk;
	unsigned int j;
	HMAC_CTX ctx;
	HMAC_CTX ctx_tmp;
	unsigned char A1[EVP_MAX_MD_SIZE];
	unsigned int A1_len;
	int ret = 0;
	
	chunk=EVP_MD_size(md);
	TINYCLR_SSL_ASSERT(chunk >= 0);

	HMAC_CTX_init(&ctx);
	HMAC_CTX_init(&ctx_tmp);
	if (!HMAC_Init_ex(&ctx,sec,sec_len,md, NULL))
		goto err;
	if (!HMAC_Init_ex(&ctx_tmp,sec,sec_len,md, NULL))
		goto err;
	if (seed1 != NULL && !HMAC_Update(&ctx,(const unsigned char*)seed1,seed1_len))
		goto err;
	if (seed2 != NULL && !HMAC_Update(&ctx,(const unsigned char*)seed2,seed2_len))
		goto err;
	if (seed3 != NULL && !HMAC_Update(&ctx,(const unsigned char*)seed3,seed3_len))
		goto err;
	if (seed4 != NULL && !HMAC_Update(&ctx,(const unsigned char*)seed4,seed4_len))
		goto err;
	if (seed5 != NULL && !HMAC_Update(&ctx,(const unsigned char*)seed5,seed5_len))
		goto err;
	if (!HMAC_Final(&ctx,A1,&A1_len))
		goto err;

	for (;;)
		{
		if (!HMAC_Init_ex(&ctx,NULL,0,NULL,NULL)) /* re-init */
			goto err;
		if (!HMAC_Init_ex(&ctx_tmp,NULL,0,NULL,NULL)) /* re-init */
			goto err;
		if (!HMAC_Update(&ctx,A1,A1_len))
			goto err;
		if (!HMAC_Update(&ctx_tmp,A1,A1_len))
			goto err;
		if (seed1 != NULL && !HMAC_Update(&ctx,(const unsigned char*)seed1,seed1_len))
			goto err;
		if (seed2 != NULL && !HMAC_Update(&ctx,(const unsigned char*)seed2,seed2_len))
			goto err;
		if (seed3 != NULL && !HMAC_Update(&ctx,(const unsigned char*)seed3,seed3_len))
			goto err;
		if (seed4 != NULL && !HMAC_Update(&ctx,(const unsigned char*)seed4,seed4_len))
			goto err;
		if (seed5 != NULL && !HMAC_Update(&ctx,(const unsigned char*)seed5,seed5_len))
			goto err;

		if (olen > chunk)
			{
			if (!HMAC_Final(&ctx,out,&j))
				goto err;
			out+=j;
			olen-=j;
			if (!HMAC_Final(&ctx_tmp,A1,&A1_len)) /* calc the next A1 value */
				goto err;
			}
		else	/* last one */
			{
			if (!HMAC_Final(&ctx,A1,&A1_len))
				goto err;
			TINYCLR_SSL_MEMCPY(out,A1,olen);
			break;
			}
		}
	ret = 1;
err:
	HMAC_CTX_cleanup(&ctx);
	HMAC_CTX_cleanup(&ctx_tmp);
	OPENSSL_cleanse(A1,sizeof(A1));
	return ret;
	}
Пример #19
0
int tls1_enc(SSL *s, int send)
	{
	SSL3_RECORD *rec;
	EVP_CIPHER_CTX *ds;
	unsigned long l;
	int bs,i,ii,j,k,n=0;
	const EVP_CIPHER *enc;

	if (send)
		{
		if (EVP_MD_CTX_md(s->write_hash))
			{
			n=EVP_MD_CTX_size(s->write_hash);
			TINYCLR_SSL_ASSERT(n >= 0);
			}
		ds=s->enc_write_ctx;
		rec= &(s->s3->wrec);
		if (s->enc_write_ctx == NULL)
			enc=NULL;
		else
			enc=EVP_CIPHER_CTX_cipher(s->enc_write_ctx);
		}
	else
		{
		if (EVP_MD_CTX_md(s->read_hash))
			{
			n=EVP_MD_CTX_size(s->read_hash);
			TINYCLR_SSL_ASSERT(n >= 0);
			}
		ds=s->enc_read_ctx;
		rec= &(s->s3->rrec);
		if (s->enc_read_ctx == NULL)
			enc=NULL;
		else
			enc=EVP_CIPHER_CTX_cipher(s->enc_read_ctx);
		}

#ifdef KSSL_DEBUG
	TINYCLR_SSL_PRINTF("tls1_enc(%d)\n", send);
#endif    /* KSSL_DEBUG */

	if ((s->session == NULL) || (ds == NULL) ||
		(enc == NULL))
		{
		TINYCLR_SSL_MEMMOVE(rec->data,rec->input,rec->length);
		rec->input=rec->data;
		}
	else
		{
		l=rec->length;
		bs=EVP_CIPHER_block_size(ds->cipher);

		if ((bs != 1) && send)
			{
			i=bs-((int)l%bs);

			/* Add weird padding of upto 256 bytes */

			/* we need to add 'i' padding bytes of value j */
			j=i-1;
			if (s->options & SSL_OP_TLS_BLOCK_PADDING_BUG)
				{
				if (s->s3->flags & TLS1_FLAGS_TLS_PADDING_BUG)
					j++;
				}
			for (k=(int)l; k<(int)(l+i); k++)
				rec->input[k]=j;
			l+=i;
			rec->length+=i;
			}

#ifdef KSSL_DEBUG
		{
                unsigned long ui;
		TINYCLR_SSL_PRINTF("EVP_Cipher(ds=%p,rec->data=%p,rec->input=%p,l=%ld) ==>\n",
                        ds,rec->data,rec->input,l);
		TINYCLR_SSL_PRINTF("\tEVP_CIPHER_CTX: %d buf_len, %d key_len [%d %d], %d iv_len\n",
                        ds->buf_len, ds->cipher->key_len,
                        DES_KEY_SZ, DES_SCHEDULE_SZ,
                        ds->cipher->iv_len);
		TINYCLR_SSL_PRINTF("\t\tIV: ");
		for (i=0; i<ds->cipher->iv_len; i++) TINYCLR_SSL_PRINTF("%02X", ds->iv[i]);
		TINYCLR_SSL_PRINTF("\n");
		TINYCLR_SSL_PRINTF("\trec->input=");
		for (ui=0; ui<l; ui++) TINYCLR_SSL_PRINTF(" %02x", rec->input[ui]);
		TINYCLR_SSL_PRINTF("\n");
		}
#endif	/* KSSL_DEBUG */

		if (!send)
			{
			if (l == 0 || l%bs != 0)
				{
				SSLerr(SSL_F_TLS1_ENC,SSL_R_BLOCK_CIPHER_PAD_IS_WRONG);
				ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_DECRYPTION_FAILED);
				return 0;
				}
			}
		
		EVP_Cipher(ds,rec->data,rec->input,l);

#ifdef KSSL_DEBUG
		{
                unsigned long i;
                TINYCLR_SSL_PRINTF("\trec->data=");
		for (i=0; i<l; i++)
                        TINYCLR_SSL_PRINTF(" %02x", rec->data[i]);  TINYCLR_SSL_PRINTF("\n");
                }
#endif	/* KSSL_DEBUG */

		if ((bs != 1) && !send)
			{
			ii=i=rec->data[l-1]; /* padding_length */
			i++;
			/* NB: if compression is in operation the first packet
			 * may not be of even length so the padding bug check
			 * cannot be performed. This bug workaround has been
			 * around since SSLeay so hopefully it is either fixed
			 * now or no buggy implementation supports compression 
			 * [steve]
			 */
			if ( (s->options&SSL_OP_TLS_BLOCK_PADDING_BUG)
				&& !s->expand)
				{
				/* First packet is even in size, so check */
				if ((TINYCLR_SSL_MEMCMP(s->s3->read_sequence,
					"\0\0\0\0\0\0\0\0",8) == 0) && !(ii & 1))
					s->s3->flags|=TLS1_FLAGS_TLS_PADDING_BUG;
				if (s->s3->flags & TLS1_FLAGS_TLS_PADDING_BUG)
					i--;
				}
			/* TLS 1.0 does not bound the number of padding bytes by the block size.
			 * All of them must have value 'padding_length'. */
			if (i > (int)rec->length)
				{
				/* Incorrect padding. SSLerr() and ssl3_alert are done
				 * by caller: we don't want to reveal whether this is
				 * a decryption error or a MAC verification failure
				 * (see http://www.openssl.org/~bodo/tls-cbc.txt) */
				return -1;
				}
			for (j=(int)(l-i); j<(int)l; j++)
				{
				if (rec->data[j] != ii)
					{
					/* Incorrect padding */
					return -1;
					}
				}
			rec->length-=i;
			}
		}
	return(1);
	}
Пример #20
0
/* Parse the server's renegotiation binding and abort if it's not
   right */
int ssl_parse_serverhello_renegotiate_ext(SSL *s, unsigned char *d, int len,
					  int *al)
    {
    int expected_len=s->s3->previous_client_finished_len
	+ s->s3->previous_server_finished_len;
    int ilen;

    /* Check for logic errors */
    TINYCLR_SSL_ASSERT(!expected_len || s->s3->previous_client_finished_len);
    TINYCLR_SSL_ASSERT(!expected_len || s->s3->previous_server_finished_len);
    
    /* Parse the length byte */
    if(len < 1)
        {
        SSLerr(SSL_F_SSL_PARSE_SERVERHELLO_RENEGOTIATE_EXT,SSL_R_RENEGOTIATION_ENCODING_ERR);
        *al=SSL_AD_ILLEGAL_PARAMETER;
        return 0;
        }
    ilen = *d;
    d++;

    /* Consistency check */
    if(ilen+1 != len)
        {
        SSLerr(SSL_F_SSL_PARSE_SERVERHELLO_RENEGOTIATE_EXT,SSL_R_RENEGOTIATION_ENCODING_ERR);
        *al=SSL_AD_ILLEGAL_PARAMETER;
        return 0;
        }
    
    /* Check that the extension matches */
    if(ilen != expected_len)
        {
        SSLerr(SSL_F_SSL_PARSE_SERVERHELLO_RENEGOTIATE_EXT,SSL_R_RENEGOTIATION_MISMATCH);
        *al=SSL_AD_HANDSHAKE_FAILURE;
        return 0;
        }

    if(TINYCLR_SSL_MEMCMP(d, s->s3->previous_client_finished,
	      s->s3->previous_client_finished_len))
        {
        SSLerr(SSL_F_SSL_PARSE_SERVERHELLO_RENEGOTIATE_EXT,SSL_R_RENEGOTIATION_MISMATCH);
        *al=SSL_AD_HANDSHAKE_FAILURE;
        return 0;
        }
    d += s->s3->previous_client_finished_len;

    if(TINYCLR_SSL_MEMCMP(d, s->s3->previous_server_finished,
	      s->s3->previous_server_finished_len))
        {
        SSLerr(SSL_F_SSL_PARSE_SERVERHELLO_RENEGOTIATE_EXT,SSL_R_RENEGOTIATION_MISMATCH);
        *al=SSL_AD_ILLEGAL_PARAMETER;
        return 0;
        }
#ifdef OPENSSL_RI_DEBUG
    TINYCLR_SSL_FPRINTF(OPENSSL_TYPE__FILE_STDERR, "%s RI extension received by client\n",
				ilen ? "Non-empty" : "Empty");
#endif
    s->s3->send_connection_binding=1;

    return 1;
    }
/* The input encrypted as though 128bit counter mode is being
 * used.  The extra state information to record how much of the
 * 128bit block we have used is contained in *num, and the
 * encrypted counter is kept in ecount_buf.  Both *num and
 * ecount_buf must be initialised with zeros before the first
 * call to CRYPTO_ctr128_encrypt().
 *
 * This algorithm assumes that the counter is in the x lower bits
 * of the IV (ivec), and that the application has full control over
 * overflow and the rest of the IV.  This implementation takes NO
 * responsability for checking that the counter doesn't overflow
 * into the rest of the IV when incremented.
 */
void CRYPTO_ctr128_encrypt(const unsigned char *in, unsigned char *out,
			size_t len, const void *key,
			unsigned char ivec[16], unsigned char ecount_buf[16],
			unsigned int *num, block128_f block)
{
	unsigned int n;
	size_t l=0;

	TINYCLR_SSL_ASSERT(in && out && key && ecount_buf && num);
	TINYCLR_SSL_ASSERT(*num < 16);

	n = *num;

#if !defined(OPENSSL_SMALL_FOOTPRINT)
	if (16%sizeof(size_t) == 0) do { /* always true actually */
		while (n && len) {
			*(out++) = *(in++) ^ ecount_buf[n];
			--len;
			n = (n+1) % 16;
		}

#if defined(STRICT_ALIGNMENT)
		if (((size_t)in|(size_t)out|(size_t)ivec)%sizeof(size_t) != 0)
			break;
#endif
		while (len>=16) {
			(*block)(ivec, ecount_buf, key);
			ctr128_inc_aligned(ivec);
			for (n=0; n<16; n+=sizeof(size_t))
				*(size_t *)(out+n) =
				*(size_t *)(in+n) ^ *(size_t *)(ecount_buf+n);
			len -= 16;
			out += 16;
			in  += 16;
		}
		n = 0;
		if (len) {
			(*block)(ivec, ecount_buf, key);
 			ctr128_inc_aligned(ivec);
			while (len--) {
				out[n] = in[n] ^ ecount_buf[n];
				++n;
			}
		}
		*num = n;
		return;
	} while(0);
	/* the rest would be commonly eliminated by x86* compiler */
#endif
	while (l<len) {
		if (n==0) {
			(*block)(ivec, ecount_buf, key);
 			ctr128_inc(ivec);
		}
		out[l] = in[l] ^ ecount_buf[n];
		++l;
		n = (n+1) % 16;
	}

	*num=n;
}
/*
 * Whack an ASIdentifierChoice into canonical form.
 */
static int ASIdentifierChoice_canonize(ASIdentifierChoice *choice)
{
  ASN1_INTEGER *a_max_plus_one = NULL;
  BIGNUM *bn = NULL;
  int i, ret = 0;

  /*
   * Nothing to do for empty element or inheritance.
   */
  if (choice == NULL || choice->type == ASIdentifierChoice_inherit)
    return 1;

  /*
   * We have a list.  Sort it.
   */
  TINYCLR_SSL_ASSERT(choice->type == ASIdentifierChoice_asIdsOrRanges);
  sk_ASIdOrRange_sort(choice->u.asIdsOrRanges);

  /*
   * Now check for errors and suboptimal encoding, rejecting the
   * former and fixing the latter.
   */
  for (i = 0; i < sk_ASIdOrRange_num(choice->u.asIdsOrRanges) - 1; i++) {
    ASIdOrRange *a = sk_ASIdOrRange_value(choice->u.asIdsOrRanges, i);
    ASIdOrRange *b = sk_ASIdOrRange_value(choice->u.asIdsOrRanges, i + 1);
    ASN1_INTEGER *a_min, *a_max, *b_min, *b_max;

    extract_min_max(a, &a_min, &a_max);
    extract_min_max(b, &b_min, &b_max);

    /*
     * Make sure we're properly sorted (paranoia).
     */
    TINYCLR_SSL_ASSERT(ASN1_INTEGER_cmp(a_min, b_min) <= 0);

    /*
     * Check for overlaps.
     */
    if (ASN1_INTEGER_cmp(a_max, b_min) >= 0) {
      X509V3err(X509V3_F_ASIDENTIFIERCHOICE_CANONIZE,
		X509V3_R_EXTENSION_VALUE_ERROR);
      goto done;
    }

    /*
     * Calculate a_max + 1 to check for adjacency.
     */
    if ((bn == NULL && (bn = BN_new()) == NULL) ||
	ASN1_INTEGER_to_BN(a_max, bn) == NULL ||
	!BN_add_word(bn, 1) ||
	(a_max_plus_one = BN_to_ASN1_INTEGER(bn, a_max_plus_one)) == NULL) {
      X509V3err(X509V3_F_ASIDENTIFIERCHOICE_CANONIZE, ERR_R_MALLOC_FAILURE);
      goto done;
    }
    
    /*
     * If a and b are adjacent, merge them.
     */
    if (ASN1_INTEGER_cmp(a_max_plus_one, b_min) == 0) {
      ASRange *r;
      switch (a->type) {
      case ASIdOrRange_id:
	if ((r = OPENSSL_malloc(sizeof(ASRange))) == NULL) {
	  X509V3err(X509V3_F_ASIDENTIFIERCHOICE_CANONIZE,
		    ERR_R_MALLOC_FAILURE);
	  goto done;
	}
	r->min = a_min;
	r->max = b_max;
	a->type = ASIdOrRange_range;
	a->u.range = r;
	break;
      case ASIdOrRange_range:
	ASN1_INTEGER_free(a->u.range->max);
	a->u.range->max = b_max;
	break;
      }
      switch (b->type) {
      case ASIdOrRange_id:
	b->u.id = NULL;
	break;
      case ASIdOrRange_range:
	b->u.range->max = NULL;
	break;
      }
      ASIdOrRange_free(b);
      sk_ASIdOrRange_delete(choice->u.asIdsOrRanges, i + 1);
      i--;
      continue;
    }
  }

  TINYCLR_SSL_ASSERT(ASIdentifierChoice_is_canonical(choice)); /* Paranoia */

  ret = 1;

 done:
  ASN1_INTEGER_free(a_max_plus_one);
  BN_free(bn);
  return ret;
}
void TS_VERIFY_CTX_init(TS_VERIFY_CTX *ctx)
	{
	TINYCLR_SSL_ASSERT(ctx != NULL);
	TINYCLR_SSL_MEMSET(ctx, 0, sizeof(TS_VERIFY_CTX));
	}
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;
    }
Пример #25
0
int ssl3_change_cipher_state(SSL *s, int which)
	{
	unsigned char *p,*mac_secret;
	unsigned char exp_key[EVP_MAX_KEY_LENGTH];
	unsigned char exp_iv[EVP_MAX_IV_LENGTH];
	unsigned char *ms,*key,*iv,*er1,*er2;
	EVP_CIPHER_CTX *dd;
	const EVP_CIPHER *c;
#ifndef OPENSSL_NO_COMP
	COMP_METHOD *comp;
#endif
	const EVP_MD *m;
	EVP_MD_CTX md;
	int is_exp,n,i,j,k,cl;
	int reuse_dd = 0;

	is_exp=SSL_C_IS_EXPORT(s->s3->tmp.new_cipher);
	c=s->s3->tmp.new_sym_enc;
	m=s->s3->tmp.new_hash;
	/* m == NULL will lead to a crash later */
	TINYCLR_SSL_ASSERT(m);
#ifndef OPENSSL_NO_COMP
	if (s->s3->tmp.new_compression == NULL)
		comp=NULL;
	else
		comp=s->s3->tmp.new_compression->method;
#endif

	if (which & SSL3_CC_READ)
		{
		if (s->enc_read_ctx != NULL)
			reuse_dd = 1;
		else if ((s->enc_read_ctx=(EVP_CIPHER_CTX*)OPENSSL_malloc(sizeof(EVP_CIPHER_CTX))) == NULL)
			goto err;
		else
			/* make sure it's intialized in case we exit later with an error */
			EVP_CIPHER_CTX_init(s->enc_read_ctx);
		dd= s->enc_read_ctx;

		ssl_replace_hash(&s->read_hash,m);
#ifndef OPENSSL_NO_COMP
		/* COMPRESS */
		if (s->expand != NULL)
			{
			COMP_CTX_free(s->expand);
			s->expand=NULL;
			}
		if (comp != NULL)
			{
			s->expand=COMP_CTX_new(comp);
			if (s->expand == NULL)
				{
				SSLerr(SSL_F_SSL3_CHANGE_CIPHER_STATE,SSL_R_COMPRESSION_LIBRARY_ERROR);
				goto err2;
				}
			if (s->s3->rrec.comp == NULL)
				s->s3->rrec.comp=(unsigned char *)
					OPENSSL_malloc(SSL3_RT_MAX_PLAIN_LENGTH);
			if (s->s3->rrec.comp == NULL)
				goto err;
			}
#endif
		TINYCLR_SSL_MEMSET(&(s->s3->read_sequence[0]),0,8);
		mac_secret= &(s->s3->read_mac_secret[0]);
		}
	else
		{
		if (s->enc_write_ctx != NULL)
			reuse_dd = 1;
		else if ((s->enc_write_ctx=(EVP_CIPHER_CTX*)OPENSSL_malloc(sizeof(EVP_CIPHER_CTX))) == NULL)
			goto err;
		else
			/* make sure it's intialized in case we exit later with an error */
			EVP_CIPHER_CTX_init(s->enc_write_ctx);
		dd= s->enc_write_ctx;
		ssl_replace_hash(&s->write_hash,m);
#ifndef OPENSSL_NO_COMP
		/* COMPRESS */
		if (s->compress != NULL)
			{
			COMP_CTX_free(s->compress);
			s->compress=NULL;
			}
		if (comp != NULL)
			{
			s->compress=COMP_CTX_new(comp);
			if (s->compress == NULL)
				{
				SSLerr(SSL_F_SSL3_CHANGE_CIPHER_STATE,SSL_R_COMPRESSION_LIBRARY_ERROR);
				goto err2;
				}
			}
#endif
		TINYCLR_SSL_MEMSET(&(s->s3->write_sequence[0]),0,8);
		mac_secret= &(s->s3->write_mac_secret[0]);
		}

	if (reuse_dd)
		EVP_CIPHER_CTX_cleanup(dd);

	p=s->s3->tmp.key_block;
	i=EVP_MD_size(m);
	if (i < 0)
		goto err2;
	cl=EVP_CIPHER_key_length(c);
	j=is_exp ? (cl < SSL_C_EXPORT_KEYLENGTH(s->s3->tmp.new_cipher) ?
		 cl : SSL_C_EXPORT_KEYLENGTH(s->s3->tmp.new_cipher)) : cl;
	/* Was j=(is_exp)?5:EVP_CIPHER_key_length(c); */
	k=EVP_CIPHER_iv_length(c);
	if (	(which == SSL3_CHANGE_CIPHER_CLIENT_WRITE) ||
		(which == SSL3_CHANGE_CIPHER_SERVER_READ))
		{
		ms=  &(p[ 0]); n=i+i;
		key= &(p[ n]); n+=j+j;
		iv=  &(p[ n]); n+=k+k;
		er1= &(s->s3->client_random[0]);
		er2= &(s->s3->server_random[0]);
		}
	else
		{
		n=i;
		ms=  &(p[ n]); n+=i+j;
		key= &(p[ n]); n+=j+k;
		iv=  &(p[ n]); n+=k;
		er1= &(s->s3->server_random[0]);
		er2= &(s->s3->client_random[0]);
		}

	if (n > s->s3->tmp.key_block_length)
		{
		SSLerr(SSL_F_SSL3_CHANGE_CIPHER_STATE,ERR_R_INTERNAL_ERROR);
		goto err2;
		}

	EVP_MD_CTX_init(&md);
	TINYCLR_SSL_MEMCPY(mac_secret,ms,i);
	if (is_exp)
		{
		/* In here I set both the read and write key/iv to the
		 * same value since only the correct one will be used :-).
		 */
		EVP_DigestInit_ex(&md,EVP_md5(), NULL);
		EVP_DigestUpdate(&md,key,j);
		EVP_DigestUpdate(&md,er1,SSL3_RANDOM_SIZE);
		EVP_DigestUpdate(&md,er2,SSL3_RANDOM_SIZE);
		EVP_DigestFinal_ex(&md,&(exp_key[0]),NULL);
		key= &(exp_key[0]);

		if (k > 0)
			{
			EVP_DigestInit_ex(&md,EVP_md5(), NULL);
			EVP_DigestUpdate(&md,er1,SSL3_RANDOM_SIZE);
			EVP_DigestUpdate(&md,er2,SSL3_RANDOM_SIZE);
			EVP_DigestFinal_ex(&md,&(exp_iv[0]),NULL);
			iv= &(exp_iv[0]);
			}
		}

	s->session->key_arg_length=0;

	EVP_CipherInit_ex(dd,c,NULL,key,iv,(which & SSL3_CC_WRITE));

	OPENSSL_cleanse(&(exp_key[0]),sizeof(exp_key));
	OPENSSL_cleanse(&(exp_iv[0]),sizeof(exp_iv));
	EVP_MD_CTX_cleanup(&md);
	return(1);
err:
	SSLerr(SSL_F_SSL3_CHANGE_CIPHER_STATE,ERR_R_MALLOC_FAILURE);
err2:
	return(0);
	}
Пример #26
0
static void ssleay_rand_add(const void *buf, int num, double add)
	{
	int i,j,k,st_idx;
	long md_c[2];
	unsigned char local_md[MD_DIGEST_LENGTH];
	EVP_MD_CTX m;
	int do_not_lock;

	/*
	 * (Based on the rand(3) manpage)
	 *
	 * The input is chopped up into units of 20 bytes (or less for
	 * the last block).  Each of these blocks is run through the hash
	 * function as follows:  The data passed to the hash function
	 * is the current 'md', the same number of bytes from the 'state'
	 * (the location determined by in incremented looping index) as
	 * the current 'block', the new key data 'block', and 'count'
	 * (which is incremented after each use).
	 * The result of this is kept in 'md' and also xored into the
	 * 'state' at the same locations that were used as input into the
         * hash function.
	 */

	/* check if we already have the lock */
	if (crypto_lock_rand)
		{
		CRYPTO_THREADID cur;
		CRYPTO_THREADID_current(&cur);
		CRYPTO_r_lock(CRYPTO_LOCK_RAND2);
		do_not_lock = !CRYPTO_THREADID_cmp(&locking_threadid, &cur);
		CRYPTO_r_unlock(CRYPTO_LOCK_RAND2);
		}
	else
		do_not_lock = 0;

	if (!do_not_lock) CRYPTO_w_lock(CRYPTO_LOCK_RAND);
	st_idx=state_index;

	/* use our own copies of the counters so that even
	 * if a concurrent thread seeds with exactly the
	 * same data and uses the same subarray there's _some_
	 * difference */
	md_c[0] = md_count[0];
	md_c[1] = md_count[1];

	TINYCLR_SSL_MEMCPY(local_md, md, sizeof md);

	/* state_index <= state_num <= STATE_SIZE */
	state_index += num;
	if (state_index >= STATE_SIZE)
		{
		state_index%=STATE_SIZE;
		state_num=STATE_SIZE;
		}
	else if (state_num < STATE_SIZE)	
		{
		if (state_index > state_num)
			state_num=state_index;
		}
	/* state_index <= state_num <= STATE_SIZE */

	/* state[st_idx], ..., state[(st_idx + num - 1) % STATE_SIZE]
	 * are what we will use now, but other threads may use them
	 * as well */

	md_count[1] += (num / MD_DIGEST_LENGTH) + (num % MD_DIGEST_LENGTH > 0);

	if (!do_not_lock) CRYPTO_w_unlock(CRYPTO_LOCK_RAND);

	EVP_MD_CTX_init(&m);
	for (i=0; i<num; i+=MD_DIGEST_LENGTH)
		{
		j=(num-i);
		j=(j > MD_DIGEST_LENGTH)?MD_DIGEST_LENGTH:j;

		MD_Init(&m);
		MD_Update(&m,local_md,MD_DIGEST_LENGTH);
		k=(st_idx+j)-STATE_SIZE;
		if (k > 0)
			{
			MD_Update(&m,&(state[st_idx]),j-k);
			MD_Update(&m,&(state[0]),k);
			}
		else
			MD_Update(&m,&(state[st_idx]),j);

		/* DO NOT REMOVE THE FOLLOWING CALL TO MD_Update()! */
		MD_Update(&m,buf,j);
		/* We know that line may cause programs such as
		   purify and valgrind to complain about use of
		   uninitialized data.  The problem is not, it's
		   with the caller.  Removing that line will make
		   sure you get really bad randomness and thereby
		   other problems such as very insecure keys. */

		MD_Update(&m,(unsigned char *)&(md_c[0]),sizeof(md_c));
		MD_Final(&m,local_md);
		md_c[1]++;

		buf=(const char *)buf + j;

		for (k=0; k<j; k++)
			{
			/* Parallel threads may interfere with this,
			 * but always each byte of the new state is
			 * the XOR of some previous value of its
			 * and local_md (itermediate values may be lost).
			 * Alway using locking could hurt performance more
			 * than necessary given that conflicts occur only
			 * when the total seeding is longer than the random
			 * state. */
			state[st_idx++]^=local_md[k];
			if (st_idx >= STATE_SIZE)
				st_idx=0;
			}
		}
	EVP_MD_CTX_cleanup(&m);

	if (!do_not_lock) CRYPTO_w_lock(CRYPTO_LOCK_RAND);
	/* Don't just copy back local_md into md -- this could mean that
	 * other thread's seeding remains without effect (except for
	 * the incremented counter).  By XORing it we keep at least as
	 * much entropy as fits into md. */
	for (k = 0; k < (int)sizeof(md); k++)
		{
		md[k] ^= local_md[k];
		}
	if (entropy < ENTROPY_NEEDED) /* stop counting when we have enough */
	    entropy += add;
	if (!do_not_lock) CRYPTO_w_unlock(CRYPTO_LOCK_RAND);
	
#if !defined(OPENSSL_THREADS) && !defined(OPENSSL_SYS_WIN32) && !defined(OPENSSL_SYS_ARM) && !defined(OPENSSL_SYS_SH)
	TINYCLR_SSL_ASSERT(md_c[1] == md_count[1]);
#endif
	}
int PKCS5_PBE_keyivgen(EVP_CIPHER_CTX *cctx, const char *pass, int passlen,
			 ASN1_TYPE *param, const EVP_CIPHER *cipher, const EVP_MD *md,
			 int en_de)
{
	EVP_MD_CTX ctx;
	unsigned char md_tmp[EVP_MAX_MD_SIZE];
	unsigned char key[EVP_MAX_KEY_LENGTH], iv[EVP_MAX_IV_LENGTH];
	int i;
	PBEPARAM *pbe;
	int saltlen, iter;
	unsigned char *salt;
	const unsigned char *pbuf;
	int mdsize;

	/* Extract useful info from parameter */
	if (param == NULL || param->type != V_ASN1_SEQUENCE ||
	    param->value.sequence == NULL) {
		EVPerr(EVP_F_PKCS5_PBE_KEYIVGEN,EVP_R_DECODE_ERROR);
		return 0;
	}

	pbuf = param->value.sequence->data;
	if (!(pbe = d2i_PBEPARAM(NULL, &pbuf, param->value.sequence->length))) {
		EVPerr(EVP_F_PKCS5_PBE_KEYIVGEN,EVP_R_DECODE_ERROR);
		return 0;
	}

	if (!pbe->iter) iter = 1;
	else iter = ASN1_INTEGER_get (pbe->iter);
	salt = pbe->salt->data;
	saltlen = pbe->salt->length;

	if(!pass) passlen = 0;
	else if(passlen == -1) passlen = TINYCLR_SSL_STRLEN(pass);

	EVP_MD_CTX_init(&ctx);
	EVP_DigestInit_ex(&ctx, md, NULL);
	EVP_DigestUpdate(&ctx, pass, passlen);
	EVP_DigestUpdate(&ctx, salt, saltlen);
	PBEPARAM_free(pbe);
	EVP_DigestFinal_ex(&ctx, md_tmp, NULL);
	mdsize = EVP_MD_size(md);
	if (mdsize < 0)
	    return 0;
	for (i = 1; i < iter; i++) {
		EVP_DigestInit_ex(&ctx, md, NULL);
		EVP_DigestUpdate(&ctx, md_tmp, mdsize);
		EVP_DigestFinal_ex (&ctx, md_tmp, NULL);
	}
	EVP_MD_CTX_cleanup(&ctx);
	TINYCLR_SSL_ASSERT(EVP_CIPHER_key_length(cipher) <= (int)sizeof(md_tmp));
	TINYCLR_SSL_MEMCPY(key, md_tmp, EVP_CIPHER_key_length(cipher));
	TINYCLR_SSL_ASSERT(EVP_CIPHER_iv_length(cipher) <= 16);
	TINYCLR_SSL_MEMCPY(iv, md_tmp + (16 - EVP_CIPHER_iv_length(cipher)),
						 EVP_CIPHER_iv_length(cipher));
	EVP_CipherInit_ex(cctx, cipher, NULL, key, iv, en_de);
	OPENSSL_cleanse(md_tmp, EVP_MAX_MD_SIZE);
	OPENSSL_cleanse(key, EVP_MAX_KEY_LENGTH);
	OPENSSL_cleanse(iv, EVP_MAX_IV_LENGTH);
	return 1;
}
static int b64_read(BIO *b, char *out, int outl)
	{
	int ret=0,i,ii,j,k,x,n,num,ret_code=0;
	BIO_B64_CTX *ctx;
	unsigned char *p,*q;

	if (out == NULL) return(0);
	ctx=(BIO_B64_CTX *)b->ptr;

	if ((ctx == NULL) || (b->next_bio == NULL)) return(0);

	BIO_clear_retry_flags(b);

	if (ctx->encode != B64_DECODE)
		{
		ctx->encode=B64_DECODE;
		ctx->buf_len=0;
		ctx->buf_off=0;
		ctx->tmp_len=0;
		EVP_DecodeInit(&(ctx->base64));
		}

	/* First check if there are bytes decoded/encoded */
	if (ctx->buf_len > 0)
		{
		TINYCLR_SSL_ASSERT(ctx->buf_len >= ctx->buf_off);
		i=ctx->buf_len-ctx->buf_off;
		if (i > outl) i=outl;
		TINYCLR_SSL_ASSERT(ctx->buf_off+i < (int)sizeof(ctx->buf));
		TINYCLR_SSL_MEMCPY(out,&(ctx->buf[ctx->buf_off]),i);
		ret=i;
		out+=i;
		outl-=i;
		ctx->buf_off+=i;
		if (ctx->buf_len == ctx->buf_off)
			{
			ctx->buf_len=0;
			ctx->buf_off=0;
			}
		}

	/* At this point, we have room of outl bytes and an empty
	 * buffer, so we should read in some more. */

	ret_code=0;
	while (outl > 0)
		{
		if (ctx->cont <= 0)
			break;

		i=BIO_read(b->next_bio,&(ctx->tmp[ctx->tmp_len]),
			B64_BLOCK_SIZE-ctx->tmp_len);

		if (i <= 0)
			{
			ret_code=i;

			/* Should we continue next time we are called? */
			if (!BIO_should_retry(b->next_bio))
				{
				ctx->cont=i;
				/* If buffer empty break */
				if(ctx->tmp_len == 0)
					break;
				/* Fall through and process what we have */
				else
					i = 0;
				}
			/* else we retry and add more data to buffer */
			else
				break;
			}
		i+=ctx->tmp_len;
		ctx->tmp_len = i;

		/* We need to scan, a line at a time until we
		 * have a valid line if we are starting. */
		if (ctx->start && (BIO_get_flags(b) & BIO_FLAGS_BASE64_NO_NL))
			{
			/* ctx->start=1; */
			ctx->tmp_len=0;
			}
		else if (ctx->start)
			{
			q=p=(unsigned char *)ctx->tmp;
			for (j=0; j<i; j++)
				{
				if (*(q++) != '\n') continue;

				/* due to a previous very long line,
				 * we need to keep on scanning for a '\n'
				 * before we even start looking for
				 * base64 encoded stuff. */
				if (ctx->tmp_nl)
					{
					p=q;
					ctx->tmp_nl=0;
					continue;
					}

				k=EVP_DecodeUpdate(&(ctx->base64),
					(unsigned char *)ctx->buf,
					&num,p,q-p);
				if ((k <= 0) && (num == 0) && (ctx->start))
					EVP_DecodeInit(&ctx->base64);
				else 
					{
					if (p != (unsigned char *)
						&(ctx->tmp[0]))
						{
						i-=(p- (unsigned char *)
							&(ctx->tmp[0]));
						for (x=0; x < i; x++)
							ctx->tmp[x]=p[x];
						}
					EVP_DecodeInit(&ctx->base64);
					ctx->start=0;
					break;
					}
				p=q;
				}

			/* we fell off the end without starting */
			if (j == i)
				{
				/* Is this is one long chunk?, if so, keep on
				 * reading until a new line. */
				if (p == (unsigned char *)&(ctx->tmp[0]))
					{
					/* Check buffer full */
					if (i == B64_BLOCK_SIZE)
						{
						ctx->tmp_nl=1;
						ctx->tmp_len=0;
						}
					}
				else if (p != q) /* finished on a '\n' */
					{
					n=q-p;
					for (ii=0; ii<n; ii++)
						ctx->tmp[ii]=p[ii];
					ctx->tmp_len=n;
					}
				/* else finished on a '\n' */
				continue;
				}
			else
			{
				ctx->tmp_len=0;
			}
		}
		else if ((i < B64_BLOCK_SIZE) && (ctx->cont > 0))
		{
			/* If buffer isn't full and we can retry then
			 * restart to read in more data.
			 */
			continue;
		}

		if (BIO_get_flags(b) & BIO_FLAGS_BASE64_NO_NL)
			{
			int z,jj;

#if 0
			jj=(i>>2)<<2;
#else
			jj = i & ~3; /* process per 4 */
#endif
			z=EVP_DecodeBlock((unsigned char *)ctx->buf,
				(unsigned char *)ctx->tmp,jj);
			if (jj > 2)
				{
				if (ctx->tmp[jj-1] == '=')
					{
					z--;
					if (ctx->tmp[jj-2] == '=')
						z--;
					}
				}
			/* z is now number of output bytes and jj is the
			 * number consumed */
			if (jj != i)
				{
				TINYCLR_SSL_MEMMOVE((unsigned char *)ctx->tmp,(unsigned char *)&ctx->tmp[jj],i-jj);
				ctx->tmp_len=i-jj;
				}
			ctx->buf_len=0;
			if (z > 0)
				{
				ctx->buf_len=z;
				}
			i=z;
			}
		else
			{
int MAIN(int argc, char **argv)
	{
	EC_GROUP *group = NULL;
	point_conversion_form_t form = POINT_CONVERSION_UNCOMPRESSED; 
	int 	new_form = 0;
	int 	asn1_flag = OPENSSL_EC_NAMED_CURVE;
	int 	new_asn1_flag = 0;
	char 	*curve_name = NULL, *inrand = NULL;
	int	list_curves = 0, no_seed = 0, check = 0,
		badops = 0, text = 0, i, need_rand = 0, genkey = 0;
	char	*infile = NULL, *outfile = NULL, *prog;
	BIO 	*in = NULL, *out = NULL;
	int 	informat, outformat, noout = 0, C = 0, ret = 1;
#ifndef OPENSSL_NO_ENGINE
	ENGINE	*e = NULL;
#endif
	char	*engine = NULL;

	BIGNUM	*ec_p = NULL, *ec_a = NULL, *ec_b = NULL,
		*ec_gen = NULL, *ec_order = NULL, *ec_cofactor = NULL;
	unsigned char *buffer = NULL;

	apps_startup();

	if (bio_err == NULL)
		if ((bio_err=BIO_new(BIO_s_file())) != NULL)
			BIO_set_fp(bio_err,OPENSSL_TYPE__FILE_STDERR,BIO_NOCLOSE|BIO_FP_TEXT);

	if (!load_config(bio_err, NULL))
		goto end;

	informat=FORMAT_PEM;
	outformat=FORMAT_PEM;

	prog=argv[0];
	argc--;
	argv++;
	while (argc >= 1)
		{
		if 	(TINYCLR_SSL_STRCMP(*argv,"-inform") == 0)
			{
			if (--argc < 1) goto bad;
			informat=str2fmt(*(++argv));
			}
		else if (TINYCLR_SSL_STRCMP(*argv,"-outform") == 0)
			{
			if (--argc < 1) goto bad;
			outformat=str2fmt(*(++argv));
			}
		else if (TINYCLR_SSL_STRCMP(*argv,"-in") == 0)
			{
			if (--argc < 1) goto bad;
			infile= *(++argv);
			}
		else if (TINYCLR_SSL_STRCMP(*argv,"-out") == 0)
			{
			if (--argc < 1) goto bad;
			outfile= *(++argv);
			}
		else if (TINYCLR_SSL_STRCMP(*argv,"-text") == 0)
			text = 1;
		else if (TINYCLR_SSL_STRCMP(*argv,"-C") == 0)
			C = 1;
		else if (TINYCLR_SSL_STRCMP(*argv,"-check") == 0)
			check = 1;
		else if (TINYCLR_SSL_STRCMP (*argv, "-name") == 0)
			{
			if (--argc < 1)
				goto bad;
			curve_name = *(++argv);
			}
		else if (TINYCLR_SSL_STRCMP(*argv, "-list_curves") == 0)
			list_curves = 1;
		else if (TINYCLR_SSL_STRCMP(*argv, "-conv_form") == 0)
			{
			if (--argc < 1)
				goto bad;
			++argv;
			new_form = 1;
			if (TINYCLR_SSL_STRCMP(*argv, "compressed") == 0)
				form = POINT_CONVERSION_COMPRESSED;
			else if (TINYCLR_SSL_STRCMP(*argv, "uncompressed") == 0)
				form = POINT_CONVERSION_UNCOMPRESSED;
			else if (TINYCLR_SSL_STRCMP(*argv, "hybrid") == 0)
				form = POINT_CONVERSION_HYBRID;
			else
				goto bad;
			}
		else if (TINYCLR_SSL_STRCMP(*argv, "-param_enc") == 0)
			{
			if (--argc < 1)
				goto bad;
			++argv;
			new_asn1_flag = 1;
			if (TINYCLR_SSL_STRCMP(*argv, "named_curve") == 0)
				asn1_flag = OPENSSL_EC_NAMED_CURVE;
			else if (TINYCLR_SSL_STRCMP(*argv, "explicit") == 0)
				asn1_flag = 0;
			else
				goto bad;
			}
		else if (TINYCLR_SSL_STRCMP(*argv, "-no_seed") == 0)
			no_seed = 1;
		else if (TINYCLR_SSL_STRCMP(*argv, "-noout") == 0)
			noout=1;
		else if (TINYCLR_SSL_STRCMP(*argv,"-genkey") == 0)
			{
			genkey=1;
			need_rand=1;
			}
		else if (TINYCLR_SSL_STRCMP(*argv, "-rand") == 0)
			{
			if (--argc < 1) goto bad;
			inrand= *(++argv);
			need_rand=1;
			}
		else if(TINYCLR_SSL_STRCMP(*argv, "-engine") == 0)
			{
			if (--argc < 1) goto bad;
			engine = *(++argv);
			}	
		else
			{
			BIO_printf(bio_err,"unknown option %s\n",*argv);
			badops=1;
			break;
			}
		argc--;
		argv++;
		}

	if (badops)
		{
bad:
		BIO_printf(bio_err, "%s [options] <infile >outfile\n",prog);
		BIO_printf(bio_err, "where options are\n");
		BIO_printf(bio_err, " -inform arg       input format - "
				"default PEM (DER or PEM)\n");
		BIO_printf(bio_err, " -outform arg      output format - "
				"default PEM\n");
		BIO_printf(bio_err, " -in  arg          input file  - "
				"default OPENSSL_TYPE__FILE_STDIN\n");
		BIO_printf(bio_err, " -out arg          output file - "
				"default OPENSSL_TYPE__FILE_STDOUT\n");
		BIO_printf(bio_err, " -noout            do not print the "
				"ec parameter\n");
		BIO_printf(bio_err, " -text             print the ec "
				"parameters in text form\n");
		BIO_printf(bio_err, " -check            validate the ec "
				"parameters\n");
		BIO_printf(bio_err, " -C                print a 'C' "
				"function creating the parameters\n");
		BIO_printf(bio_err, " -name arg         use the "
				"ec parameters with 'short name' name\n");
		BIO_printf(bio_err, " -list_curves      prints a list of "
				"all currently available curve 'short names'\n");
		BIO_printf(bio_err, " -conv_form arg    specifies the "
				"point conversion form \n");
		BIO_printf(bio_err, "                   possible values:"
				" compressed\n");
		BIO_printf(bio_err, "                                   "
				" uncompressed (default)\n");
		BIO_printf(bio_err, "                                   "
				" hybrid\n");
		BIO_printf(bio_err, " -param_enc arg    specifies the way"
				" the ec parameters are encoded\n");
		BIO_printf(bio_err, "                   in the asn1 der "
				"encoding\n");
		BIO_printf(bio_err, "                   possible values:"
				" named_curve (default)\n");
		BIO_printf(bio_err, "                                   "
				" explicit\n");
		BIO_printf(bio_err, " -no_seed          if 'explicit'"
				" parameters are choosen do not"
				" use the seed\n");
		BIO_printf(bio_err, " -genkey           generate ec"
				" key\n");
		BIO_printf(bio_err, " -rand file        files to use for"
				" random number input\n");
		BIO_printf(bio_err, " -engine e         use engine e, "
				"possibly a hardware device\n");
		goto end;
		}

	ERR_load_crypto_strings();

	in=BIO_new(BIO_s_file());
	out=BIO_new(BIO_s_file());
	if ((in == NULL) || (out == NULL))
		{
		ERR_print_errors(bio_err);
		goto end;
		}

	if (infile == NULL)
		BIO_set_fp(in,OPENSSL_TYPE__FILE_STDIN,BIO_NOCLOSE);
	else
		{
		if (BIO_read_filename(in,infile) <= 0)
			{
			TINYCLR_SSL_PERROR(infile);
			goto end;
			}
		}
	if (outfile == NULL)
		{
		BIO_set_fp(out,OPENSSL_TYPE__FILE_STDOUT,BIO_NOCLOSE);
#ifdef OPENSSL_SYS_VMS
		{
		BIO *tmpbio = BIO_new(BIO_f_linebuffer());
		out = BIO_push(tmpbio, out);
		}
#endif
		}
	else
		{
		if (BIO_write_filename(out,outfile) <= 0)
			{
			TINYCLR_SSL_PERROR(outfile);
			goto end;
			}
		}

#ifndef OPENSSL_NO_ENGINE
	e = setup_engine(bio_err, engine, 0);
#endif

	if (list_curves)
		{
		EC_builtin_curve *curves = NULL;
		size_t crv_len = 0;
		size_t n = 0;

		crv_len = EC_get_builtin_curves(NULL, 0);

		curves = (EC_builtin_curve*)OPENSSL_malloc((int)(sizeof(EC_builtin_curve) * crv_len));

		if (curves == NULL)
			goto end;

		if (!EC_get_builtin_curves(curves, crv_len))
			{
			OPENSSL_free(curves);
			goto end;
			}

		
		for (n = 0; n < crv_len; n++)
			{
			const char *comment;
			const char *sname;
			comment = curves[n].comment;
			sname   = OBJ_nid2sn(curves[n].nid);
			if (comment == NULL)
				comment = "CURVE DESCRIPTION NOT AVAILABLE";
			if (sname == NULL)
				sname = "";

			BIO_printf(out, "  %-10s: ", sname);
			BIO_printf(out, "%s\n", comment);
			} 

		OPENSSL_free(curves);
		ret = 0;
		goto end;
		}

	if (curve_name != NULL)
		{
		int nid;

		/* workaround for the SECG curve names secp192r1
		 * and secp256r1 (which are the same as the curves
		 * prime192v1 and prime256v1 defined in X9.62)
		 */
		if (!TINYCLR_SSL_STRCMP(curve_name, "secp192r1"))
			{
			BIO_printf(bio_err, "using curve name prime192v1 "
				"instead of secp192r1\n");
			nid = NID_X9_62_prime192v1;
			}
		else if (!TINYCLR_SSL_STRCMP(curve_name, "secp256r1"))
			{
			BIO_printf(bio_err, "using curve name prime256v1 "
				"instead of secp256r1\n");
			nid = NID_X9_62_prime256v1;
			}
		else
			nid = OBJ_sn2nid(curve_name);
	
		if (nid == 0)
			{
			BIO_printf(bio_err, "unknown curve name (%s)\n", 
				curve_name);
			goto end;
			}

		group = EC_GROUP_new_by_curve_name(nid);
		if (group == NULL)
			{
			BIO_printf(bio_err, "unable to create curve (%s)\n", 
				curve_name);
			goto end;
			}
		EC_GROUP_set_asn1_flag(group, asn1_flag);
		EC_GROUP_set_point_conversion_form(group, form);
		}
	else if (informat == FORMAT_ASN1)
		{
		group = d2i_ECPKParameters_bio(in, NULL);
		}
	else if (informat == FORMAT_PEM)
		{
		group = PEM_read_bio_ECPKParameters(in,NULL,NULL,NULL);
		}
	else
		{
		BIO_printf(bio_err, "bad input format specified\n");
		goto end;
		}

	if (group == NULL)
		{
		BIO_printf(bio_err, 
			"unable to load elliptic curve parameters\n");
		ERR_print_errors(bio_err);
		goto end;
		}

	if (new_form)
		EC_GROUP_set_point_conversion_form(group, form);

	if (new_asn1_flag)
		EC_GROUP_set_asn1_flag(group, asn1_flag);

	if (no_seed)
		{
		EC_GROUP_set_seed(group, NULL, 0);
		}

	if (text)
		{
		if (!ECPKParameters_print(out, group, 0))
			goto end;
		}

	if (check)
		{
		if (group == NULL)
			BIO_printf(bio_err, "no elliptic curve parameters\n");
		BIO_printf(bio_err, "checking elliptic curve parameters: ");
		if (!EC_GROUP_check(group, NULL))
			{
			BIO_printf(bio_err, "failed\n");
			ERR_print_errors(bio_err);
			}
		else
			BIO_printf(bio_err, "ok\n");
			
		}

	if (C)
		{
		size_t	buf_len = 0, tmp_len = 0;
		const EC_POINT *point;
		int	is_prime, len = 0;
		const EC_METHOD *meth = EC_GROUP_method_of(group);

		if ((ec_p = BN_new()) == NULL || (ec_a = BN_new()) == NULL ||
		    (ec_b = BN_new()) == NULL || (ec_gen = BN_new()) == NULL ||
		    (ec_order = BN_new()) == NULL || 
		    (ec_cofactor = BN_new()) == NULL )
			{
			TINYCLR_SSL_PERROR("OPENSSL_malloc");
			goto end;
			}

		is_prime = (EC_METHOD_get_field_type(meth) == 
			NID_X9_62_prime_field);

		if (is_prime)
			{
			if (!EC_GROUP_get_curve_GFp(group, ec_p, ec_a,
				ec_b, NULL))
				goto end;
			}
		else
			{
			/* TODO */
			goto end;
			}

		if ((point = EC_GROUP_get0_generator(group)) == NULL)
			goto end;
		if (!EC_POINT_point2bn(group, point, 
			EC_GROUP_get_point_conversion_form(group), ec_gen, 
			NULL))
			goto end;
		if (!EC_GROUP_get_order(group, ec_order, NULL))
			goto end;
		if (!EC_GROUP_get_cofactor(group, ec_cofactor, NULL))
			goto end;

		if (!ec_p || !ec_a || !ec_b || !ec_gen || 
			!ec_order || !ec_cofactor)
			goto end;

		len = BN_num_bits(ec_order);

		if ((tmp_len = (size_t)BN_num_bytes(ec_p)) > buf_len)
			buf_len = tmp_len;
		if ((tmp_len = (size_t)BN_num_bytes(ec_a)) > buf_len)
			buf_len = tmp_len;
		if ((tmp_len = (size_t)BN_num_bytes(ec_b)) > buf_len)
			buf_len = tmp_len;
		if ((tmp_len = (size_t)BN_num_bytes(ec_gen)) > buf_len)
			buf_len = tmp_len;
		if ((tmp_len = (size_t)BN_num_bytes(ec_order)) > buf_len)
			buf_len = tmp_len;
		if ((tmp_len = (size_t)BN_num_bytes(ec_cofactor)) > buf_len)
			buf_len = tmp_len;

		buffer = (unsigned char *)OPENSSL_malloc(buf_len);

		if (buffer == NULL)
			{
			TINYCLR_SSL_PERROR("OPENSSL_malloc");
			goto end;
			}

		ecparam_print_var(out, ec_p, "ec_p", len, buffer);
		ecparam_print_var(out, ec_a, "ec_a", len, buffer);
		ecparam_print_var(out, ec_b, "ec_b", len, buffer);
		ecparam_print_var(out, ec_gen, "ec_gen", len, buffer);
		ecparam_print_var(out, ec_order, "ec_order", len, buffer);
		ecparam_print_var(out, ec_cofactor, "ec_cofactor", len, 
			buffer);

		BIO_printf(out, "\n\n");

		BIO_printf(out, "EC_GROUP *get_ec_group_%d(void)\n\t{\n", len);
		BIO_printf(out, "\tint ok=0;\n");
		BIO_printf(out, "\tEC_GROUP *group = NULL;\n");
		BIO_printf(out, "\tEC_POINT *point = NULL;\n");
		BIO_printf(out, "\tBIGNUM   *tmp_1 = NULL, *tmp_2 = NULL, "
				"*tmp_3 = NULL;\n\n");
		BIO_printf(out, "\tif ((tmp_1 = BN_bin2bn(ec_p_%d, "
				"sizeof(ec_p_%d), NULL)) == NULL)\n\t\t"
				"goto err;\n", len, len);
		BIO_printf(out, "\tif ((tmp_2 = BN_bin2bn(ec_a_%d, "
				"sizeof(ec_a_%d), NULL)) == NULL)\n\t\t"
				"goto err;\n", len, len);
		BIO_printf(out, "\tif ((tmp_3 = BN_bin2bn(ec_b_%d, "
				"sizeof(ec_b_%d), NULL)) == NULL)\n\t\t"
				"goto err;\n", len, len);
		if (is_prime)
			{
			BIO_printf(out, "\tif ((group = EC_GROUP_new_curve_"
				"GFp(tmp_1, tmp_2, tmp_3, NULL)) == NULL)"
				"\n\t\tgoto err;\n\n");
			}
		else
			{
			/* TODO */
			goto end;
			}
		BIO_printf(out, "\t/* build generator */\n");
		BIO_printf(out, "\tif ((tmp_1 = BN_bin2bn(ec_gen_%d, "
				"sizeof(ec_gen_%d), tmp_1)) == NULL)"
				"\n\t\tgoto err;\n", len, len);
		BIO_printf(out, "\tpoint = EC_POINT_bn2point(group, tmp_1, "
				"NULL, NULL);\n");
		BIO_printf(out, "\tif (point == NULL)\n\t\tgoto err;\n");
		BIO_printf(out, "\tif ((tmp_2 = BN_bin2bn(ec_order_%d, "
				"sizeof(ec_order_%d), tmp_2)) == NULL)"
				"\n\t\tgoto err;\n", len, len);
		BIO_printf(out, "\tif ((tmp_3 = BN_bin2bn(ec_cofactor_%d, "
				"sizeof(ec_cofactor_%d), tmp_3)) == NULL)"
				"\n\t\tgoto err;\n", len, len);
		BIO_printf(out, "\tif (!EC_GROUP_set_generator(group, point,"
				" tmp_2, tmp_3))\n\t\tgoto err;\n");
		BIO_printf(out, "\n\tok=1;\n");
		BIO_printf(out, "err:\n");
		BIO_printf(out, "\tif (tmp_1)\n\t\tBN_free(tmp_1);\n");
		BIO_printf(out, "\tif (tmp_2)\n\t\tBN_free(tmp_2);\n");
		BIO_printf(out, "\tif (tmp_3)\n\t\tBN_free(tmp_3);\n");
		BIO_printf(out, "\tif (point)\n\t\tEC_POINT_free(point);\n");
		BIO_printf(out, "\tif (!ok)\n");
		BIO_printf(out, "\t\t{\n");
		BIO_printf(out, "\t\tEC_GROUP_free(group);\n");
		BIO_printf(out, "\t\tgroup = NULL;\n");
		BIO_printf(out, "\t\t}\n");
		BIO_printf(out, "\treturn(group);\n\t}\n");
	}

	if (!noout)
		{
		if (outformat == FORMAT_ASN1)
			i = i2d_ECPKParameters_bio(out, group);
		else if (outformat == FORMAT_PEM)
			i = PEM_write_bio_ECPKParameters(out, group);
		else	
			{
			BIO_printf(bio_err,"bad output format specified for"
				" outfile\n");
			goto end;
			}
		if (!i)
			{
			BIO_printf(bio_err, "unable to write elliptic "
				"curve parameters\n");
			ERR_print_errors(bio_err);
			goto end;
			}
		}
	
	if (need_rand)
		{
		app_RAND_load_file(NULL, bio_err, (inrand != NULL));
		if (inrand != NULL)
			BIO_printf(bio_err,"%ld semi-random bytes loaded\n",
				app_RAND_load_files(inrand));
		}

	if (genkey)
		{
		EC_KEY *eckey = EC_KEY_new();

		if (eckey == NULL)
			goto end;

		TINYCLR_SSL_ASSERT(need_rand);

		if (EC_KEY_set_group(eckey, group) == 0)
			goto end;
		
		if (!EC_KEY_generate_key(eckey))
			{
			EC_KEY_free(eckey);
			goto end;
			}
		if (outformat == FORMAT_ASN1)
			i = i2d_ECPrivateKey_bio(out, eckey);
		else if (outformat == FORMAT_PEM)
			i = PEM_write_bio_ECPrivateKey(out, eckey, NULL,
				NULL, 0, NULL, NULL);
		else	
			{
			BIO_printf(bio_err, "bad output format specified "
				"for outfile\n");
			EC_KEY_free(eckey);
			goto end;
			}
		EC_KEY_free(eckey);
		}

	if (need_rand)
		app_RAND_write_file(NULL, bio_err);

	ret=0;
end:
	if (ec_p)
		BN_free(ec_p);
	if (ec_a)
		BN_free(ec_a);
	if (ec_b)
		BN_free(ec_b);
	if (ec_gen)
		BN_free(ec_gen);
	if (ec_order)
		BN_free(ec_order);
	if (ec_cofactor)
		BN_free(ec_cofactor);
	if (buffer)
		OPENSSL_free(buffer);
	if (in != NULL)
		BIO_free(in);
	if (out != NULL)
		BIO_free_all(out);
	if (group != NULL)
		EC_GROUP_free(group);
	apps_shutdown();
	OPENSSL_EXIT(ret);
}
Пример #30
0
int MAIN(int argc, char **argv)
	{
	DSA *dsa=NULL;
	int i,badops=0,text=0;
	BIO *in=NULL,*out=NULL;
	int informat,outformat,noout=0,C=0,ret=1;
	char *infile,*outfile,*prog,*inrand=NULL;
	int numbits= -1,num,genkey=0;
	int need_rand=0;
#ifndef OPENSSL_NO_ENGINE
	char *engine=NULL;
#endif
#ifdef GENCB_TEST
	int timebomb=0;
#endif

	apps_startup();

	if (bio_err == NULL)
		if ((bio_err=BIO_new(BIO_s_file())) != NULL)
			BIO_set_fp(bio_err,OPENSSL_TYPE__FILE_STDERR,BIO_NOCLOSE|BIO_FP_TEXT);

	if (!load_config(bio_err, NULL))
		goto end;

	infile=NULL;
	outfile=NULL;
	informat=FORMAT_PEM;
	outformat=FORMAT_PEM;

	prog=argv[0];
	argc--;
	argv++;
	while (argc >= 1)
		{
		if 	(TINYCLR_SSL_STRCMP(*argv,"-inform") == 0)
			{
			if (--argc < 1) goto bad;
			informat=str2fmt(*(++argv));
			}
		else if (TINYCLR_SSL_STRCMP(*argv,"-outform") == 0)
			{
			if (--argc < 1) goto bad;
			outformat=str2fmt(*(++argv));
			}
		else if (TINYCLR_SSL_STRCMP(*argv,"-in") == 0)
			{
			if (--argc < 1) goto bad;
			infile= *(++argv);
			}
		else if (TINYCLR_SSL_STRCMP(*argv,"-out") == 0)
			{
			if (--argc < 1) goto bad;
			outfile= *(++argv);
			}
#ifndef OPENSSL_NO_ENGINE
		else if(TINYCLR_SSL_STRCMP(*argv, "-engine") == 0)
			{
			if (--argc < 1) goto bad;
			engine = *(++argv);
			}
#endif
#ifdef GENCB_TEST
		else if(TINYCLR_SSL_STRCMP(*argv, "-timebomb") == 0)
			{
			if (--argc < 1) goto bad;
			timebomb = atoi(*(++argv));
			}
#endif
		else if (TINYCLR_SSL_STRCMP(*argv,"-text") == 0)
			text=1;
		else if (TINYCLR_SSL_STRCMP(*argv,"-C") == 0)
			C=1;
		else if (TINYCLR_SSL_STRCMP(*argv,"-genkey") == 0)
			{
			genkey=1;
			need_rand=1;
			}
		else if (TINYCLR_SSL_STRCMP(*argv,"-rand") == 0)
			{
			if (--argc < 1) goto bad;
			inrand= *(++argv);
			need_rand=1;
			}
		else if (TINYCLR_SSL_STRCMP(*argv,"-noout") == 0)
			noout=1;
		else if (sscanf(*argv,"%d",&num) == 1)
			{
			/* generate a key */
			numbits=num;
			need_rand=1;
			}
		else
			{
			BIO_printf(bio_err,"unknown option %s\n",*argv);
			badops=1;
			break;
			}
		argc--;
		argv++;
		}

	if (badops)
		{
bad:
		BIO_printf(bio_err,"%s [options] [bits] <infile >outfile\n",prog);
		BIO_printf(bio_err,"where options are\n");
		BIO_printf(bio_err," -inform arg   input format - DER or PEM\n");
		BIO_printf(bio_err," -outform arg  output format - DER or PEM\n");
		BIO_printf(bio_err," -in arg       input file\n");
		BIO_printf(bio_err," -out arg      output file\n");
		BIO_printf(bio_err," -text         print as text\n");
		BIO_printf(bio_err," -C            Output C code\n");
		BIO_printf(bio_err," -noout        no output\n");
		BIO_printf(bio_err," -genkey       generate a DSA key\n");
		BIO_printf(bio_err," -rand         files to use for random number input\n");
#ifndef OPENSSL_NO_ENGINE
		BIO_printf(bio_err," -engine e     use engine e, possibly a hardware device.\n");
#endif
#ifdef GENCB_TEST
		BIO_printf(bio_err," -timebomb n   interrupt keygen after <n> seconds\n");
#endif
		BIO_printf(bio_err," number        number of bits to use for generating private key\n");
		goto end;
		}

	ERR_load_crypto_strings();

	in=BIO_new(BIO_s_file());
	out=BIO_new(BIO_s_file());
	if ((in == NULL) || (out == NULL))
		{
		ERR_print_errors(bio_err);
		goto end;
		}

	if (infile == NULL)
		BIO_set_fp(in,OPENSSL_TYPE__FILE_STDIN,BIO_NOCLOSE);
	else
		{
		if (BIO_read_filename(in,infile) <= 0)
			{
			TINYCLR_SSL_PERROR(infile);
			goto end;
			}
		}
	if (outfile == NULL)
		{
		BIO_set_fp(out,OPENSSL_TYPE__FILE_STDOUT,BIO_NOCLOSE);
#ifdef OPENSSL_SYS_VMS
		{
		BIO *tmpbio = BIO_new(BIO_f_linebuffer());
		out = BIO_push(tmpbio, out);
		}
#endif
		}
	else
		{
		if (BIO_write_filename(out,outfile) <= 0)
			{
			TINYCLR_SSL_PERROR(outfile);
			goto end;
			}
		}

#ifndef OPENSSL_NO_ENGINE
        setup_engine(bio_err, engine, 0);
#endif

	if (need_rand)
		{
		app_RAND_load_file(NULL, bio_err, (inrand != NULL));
		if (inrand != NULL)
			BIO_printf(bio_err,"%ld semi-random bytes loaded\n",
				app_RAND_load_files(inrand));
		}

	if (numbits > 0)
		{
		BN_GENCB cb;
		BN_GENCB_set(&cb, dsa_cb, bio_err);
		TINYCLR_SSL_ASSERT(need_rand);
		dsa = DSA_new();
		if(!dsa)
			{
			BIO_printf(bio_err,"Error allocating DSA object\n");
			goto end;
			}
		BIO_printf(bio_err,"Generating DSA parameters, %d bit long prime\n",num);
	        BIO_printf(bio_err,"This could take some time\n");
#ifdef GENCB_TEST
		if(timebomb > 0)
	{
		struct sigaction act;
		act.sa_handler = timebomb_sigalarm;
		act.sa_flags = 0;
		BIO_printf(bio_err,"(though I'll stop it if not done within %d secs)\n",
				timebomb);
		if(sigaction(SIGALRM, &act, NULL) != 0)
			{
			BIO_printf(bio_err,"Error, couldn't set SIGALRM handler\n");
			goto end;
			}
		alarm(timebomb);
	}
#endif
	        if(!DSA_generate_parameters_ex(dsa,num,NULL,0,NULL,NULL, &cb))
			{
#ifdef GENCB_TEST
			if(stop_keygen_flag)
				{
				BIO_printf(bio_err,"DSA key generation time-stopped\n");
				/* This is an asked-for behaviour! */
				ret = 0;
				goto end;
				}
#endif
			BIO_printf(bio_err,"Error, DSA key generation failed\n");
			goto end;
			}
		}
	else if	(informat == FORMAT_ASN1)
		dsa=d2i_DSAparams_bio(in,NULL);
	else if (informat == FORMAT_PEM)
		dsa=PEM_read_bio_DSAparams(in,NULL,NULL,NULL);
	else
		{
		BIO_printf(bio_err,"bad input format specified\n");
		goto end;
		}
	if (dsa == NULL)
		{
		BIO_printf(bio_err,"unable to load DSA parameters\n");
		ERR_print_errors(bio_err);
		goto end;
		}

	if (text)
		{
		DSAparams_print(out,dsa);
		}
	
	if (C)
		{
		unsigned char *data;
		int l,len,bits_p;

		len=BN_num_bytes(dsa->p);
		bits_p=BN_num_bits(dsa->p);
		data=(unsigned char *)OPENSSL_malloc(len+20);
		if (data == NULL)
			{
			TINYCLR_SSL_PERROR("OPENSSL_malloc");
			goto end;
			}
		l=BN_bn2bin(dsa->p,data);
		TINYCLR_SSL_PRINTF("static unsigned char dsa%d_p[]={",bits_p);
		for (i=0; i<l; i++)
			{
			if ((i%12) == 0) TINYCLR_SSL_PRINTF("\n\t");
			TINYCLR_SSL_PRINTF("0x%02X,",data[i]);
			}
		TINYCLR_SSL_PRINTF("\n\t};\n");

		l=BN_bn2bin(dsa->q,data);
		TINYCLR_SSL_PRINTF("static unsigned char dsa%d_q[]={",bits_p);
		for (i=0; i<l; i++)
			{
			if ((i%12) == 0) TINYCLR_SSL_PRINTF("\n\t");
			TINYCLR_SSL_PRINTF("0x%02X,",data[i]);
			}
		TINYCLR_SSL_PRINTF("\n\t};\n");

		l=BN_bn2bin(dsa->g,data);
		TINYCLR_SSL_PRINTF("static unsigned char dsa%d_g[]={",bits_p);
		for (i=0; i<l; i++)
			{
			if ((i%12) == 0) TINYCLR_SSL_PRINTF("\n\t");
			TINYCLR_SSL_PRINTF("0x%02X,",data[i]);
			}
		TINYCLR_SSL_PRINTF("\n\t};\n\n");

		TINYCLR_SSL_PRINTF("DSA *get_dsa%d()\n\t{\n",bits_p);
		TINYCLR_SSL_PRINTF("\tDSA *dsa;\n\n");
		TINYCLR_SSL_PRINTF("\tif ((dsa=DSA_new()) == NULL) return(NULL);\n");
		TINYCLR_SSL_PRINTF("\tdsa->p=BN_bin2bn(dsa%d_p,sizeof(dsa%d_p),NULL);\n",
			bits_p,bits_p);
		TINYCLR_SSL_PRINTF("\tdsa->q=BN_bin2bn(dsa%d_q,sizeof(dsa%d_q),NULL);\n",
			bits_p,bits_p);
		TINYCLR_SSL_PRINTF("\tdsa->g=BN_bin2bn(dsa%d_g,sizeof(dsa%d_g),NULL);\n",
			bits_p,bits_p);
		TINYCLR_SSL_PRINTF("\tif ((dsa->p == NULL) || (dsa->q == NULL) || (dsa->g == NULL))\n");
		TINYCLR_SSL_PRINTF("\t\t{ DSA_free(dsa); return(NULL); }\n");
		TINYCLR_SSL_PRINTF("\treturn(dsa);\n\t}\n");
		}


	if (!noout)
		{
		if 	(outformat == FORMAT_ASN1)
			i=i2d_DSAparams_bio(out,dsa);
		else if (outformat == FORMAT_PEM)
			i=PEM_write_bio_DSAparams(out,dsa);
		else	{
			BIO_printf(bio_err,"bad output format specified for outfile\n");
			goto end;
			}
		if (!i)
			{
			BIO_printf(bio_err,"unable to write DSA parameters\n");
			ERR_print_errors(bio_err);
			goto end;
			}
		}
	if (genkey)
		{
		DSA *dsakey;

		TINYCLR_SSL_ASSERT(need_rand);
		if ((dsakey=DSAparams_dup(dsa)) == NULL) goto end;
		if (!DSA_generate_key(dsakey)) goto end;
		if 	(outformat == FORMAT_ASN1)
			i=i2d_DSAPrivateKey_bio(out,dsakey);
		else if (outformat == FORMAT_PEM)
			i=PEM_write_bio_DSAPrivateKey(out,dsakey,NULL,NULL,0,NULL,NULL);
		else	{
			BIO_printf(bio_err,"bad output format specified for outfile\n");
			goto end;
			}
		DSA_free(dsakey);
		}
	if (need_rand)
		app_RAND_write_file(NULL, bio_err);
	ret=0;
end:
	if (in != NULL) BIO_free(in);
	if (out != NULL) BIO_free_all(out);
	if (dsa != NULL) DSA_free(dsa);
	apps_shutdown();
	OPENSSL_EXIT(ret);
	}