Esempio n. 1
0
/*
 * Class:     org_jitsi_impl_neomedia_transform_srtp_OpenSSLHMAC
 * Method:    EVP_MD_size
 * Signature: (J)I
 */
JNIEXPORT jint JNICALL
Java_org_jitsi_impl_neomedia_transform_srtp_OpenSSLHMAC_EVP_1MD_1size
    (JNIEnv *env, jclass clazz, jlong md)
{
    return EVP_MD_size((const EVP_MD *) (intptr_t) md);
}
Esempio n. 2
0
// tls1_P_hash computes the TLS P_<hash> function as described in RFC 5246,
// section 5. It XORs |out_len| bytes to |out|, using |md| as the hash and
// |secret| as the secret. |label|, |seed1|, and |seed2| are concatenated to
// form the seed parameter. It returns true on success and false on failure.
static int tls1_P_hash(uint8_t *out, size_t out_len,
                       const EVP_MD *md,
                       const uint8_t *secret, size_t secret_len,
                       const char *label, size_t label_len,
                       const uint8_t *seed1, size_t seed1_len,
                       const uint8_t *seed2, size_t seed2_len) {
  HMAC_CTX ctx, ctx_tmp, ctx_init;
  uint8_t A1[EVP_MAX_MD_SIZE];
  unsigned A1_len;
  int ret = 0;

  const size_t chunk = EVP_MD_size(md);
  HMAC_CTX_init(&ctx);
  HMAC_CTX_init(&ctx_tmp);
  HMAC_CTX_init(&ctx_init);

  if (!HMAC_Init_ex(&ctx_init, secret, secret_len, md, NULL) ||
      !HMAC_CTX_copy_ex(&ctx, &ctx_init) ||
      !HMAC_Update(&ctx, (const uint8_t *) label, label_len) ||
      !HMAC_Update(&ctx, seed1, seed1_len) ||
      !HMAC_Update(&ctx, seed2, seed2_len) ||
      !HMAC_Final(&ctx, A1, &A1_len)) {
    goto err;
  }

  for (;;) {
    unsigned len;
    uint8_t hmac[EVP_MAX_MD_SIZE];
    if (!HMAC_CTX_copy_ex(&ctx, &ctx_init) ||
        !HMAC_Update(&ctx, A1, A1_len) ||
        // Save a copy of |ctx| to compute the next A1 value below.
        (out_len > chunk && !HMAC_CTX_copy_ex(&ctx_tmp, &ctx)) ||
        !HMAC_Update(&ctx, (const uint8_t *) label, label_len) ||
        !HMAC_Update(&ctx, seed1, seed1_len) ||
        !HMAC_Update(&ctx, seed2, seed2_len) ||
        !HMAC_Final(&ctx, hmac, &len)) {
      goto err;
    }
    assert(len == chunk);

    // XOR the result into |out|.
    if (len > out_len) {
      len = out_len;
    }
    for (unsigned i = 0; i < len; i++) {
      out[i] ^= hmac[i];
    }
    out += len;
    out_len -= len;

    if (out_len == 0) {
      break;
    }

    // Calculate the next A1 value.
    if (!HMAC_Final(&ctx_tmp, A1, &A1_len)) {
      goto err;
    }
  }

  ret = 1;

err:
  OPENSSL_cleanse(A1, sizeof(A1));
  HMAC_CTX_cleanup(&ctx);
  HMAC_CTX_cleanup(&ctx_tmp);
  HMAC_CTX_cleanup(&ctx_init);
  return ret;
}
int tls1_change_cipher_state(SSL *s, int which)
	{
	static const unsigned char empty[]="";
	unsigned char *p,*key_block,*mac_secret;
	unsigned char *exp_label,buf[TLS_MD_MAX_CONST_SIZE+
		SSL3_RANDOM_SIZE*2];
	unsigned char tmp1[EVP_MAX_KEY_LENGTH];
	unsigned char tmp2[EVP_MAX_KEY_LENGTH];
	unsigned char iv1[EVP_MAX_IV_LENGTH*2];
	unsigned char iv2[EVP_MAX_IV_LENGTH*2];
	unsigned char *ms,*key,*iv,*er1,*er2;
	int client_write;
	EVP_CIPHER_CTX *dd;
	const EVP_CIPHER *c;
	const SSL_COMP *comp;
	const EVP_MD *m;
	int _exp,n,i,j,k,exp_label_len,cl;

	_exp=SSL_C_IS_EXPORT(s->s3->tmp.new_cipher);
	c=s->s3->tmp.new_sym_enc;
	m=s->s3->tmp.new_hash;
	comp=s->s3->tmp.new_compression;
	key_block=s->s3->tmp.key_block;

	if (which & SSL3_CC_READ)
		{
		if ((s->enc_read_ctx == NULL) &&
			((s->enc_read_ctx=(EVP_CIPHER_CTX *)
			OPENSSL_malloc(sizeof(EVP_CIPHER_CTX))) == NULL))
			goto err;
		dd= s->enc_read_ctx;
		s->read_hash=m;
		if (s->expand != NULL)
			{
			COMP_CTX_free(s->expand);
			s->expand=NULL;
			}
		if (comp != NULL)
			{
			s->expand=COMP_CTX_new(comp->method);
			if (s->expand == NULL)
				{
				SSLerr(SSL_F_TLS1_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_ENCRYPTED_LENGTH);
			if (s->s3->rrec.comp == NULL)
				goto err;
			}
		memset(&(s->s3->read_sequence[0]),0,8);
		mac_secret= &(s->s3->read_mac_secret[0]);
		}
	else
		{
		if ((s->enc_write_ctx == NULL) &&
			((s->enc_write_ctx=(EVP_CIPHER_CTX *)
			OPENSSL_malloc(sizeof(EVP_CIPHER_CTX))) == NULL))
			goto err;
		dd= s->enc_write_ctx;
		s->write_hash=m;
		if (s->compress != NULL)
			{
			COMP_CTX_free(s->compress);
			s->compress=NULL;
			}
		if (comp != NULL)
			{
			s->compress=COMP_CTX_new(comp->method);
			if (s->compress == NULL)
				{
				SSLerr(SSL_F_TLS1_CHANGE_CIPHER_STATE,SSL_R_COMPRESSION_LIBRARY_ERROR);
				goto err2;
				}
			}
		memset(&(s->s3->write_sequence[0]),0,8);
		mac_secret= &(s->s3->write_mac_secret[0]);
		}

	EVP_CIPHER_CTX_init(dd);

	p=s->s3->tmp.key_block;
	i=EVP_MD_size(m);
	cl=EVP_CIPHER_key_length(c);
	j=_exp ? (cl < SSL_C_EXPORT_KEYLENGTH(s->s3->tmp.new_cipher) ?
		  cl : SSL_C_EXPORT_KEYLENGTH(s->s3->tmp.new_cipher)) : cl;
	/* Was j=(exp)?5:EVP_CIPHER_key_length(c); */
	k=EVP_CIPHER_iv_length(c);
	er1= &(s->s3->client_random[0]);
	er2= &(s->s3->server_random[0]);
	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;
		exp_label=(unsigned char *)TLS_MD_CLIENT_WRITE_KEY_CONST;
		exp_label_len=TLS_MD_CLIENT_WRITE_KEY_CONST_SIZE;
		client_write=1;
		}
	else
		{
		n=i;
		ms=  &(p[ n]); n+=i+j;
		key= &(p[ n]); n+=j+k;
		iv=  &(p[ n]); n+=k;
		exp_label=(unsigned char *)TLS_MD_SERVER_WRITE_KEY_CONST;
		exp_label_len=TLS_MD_SERVER_WRITE_KEY_CONST_SIZE;
		client_write=0;
		}

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

	memcpy(mac_secret,ms,i);
#ifdef TLS_DEBUG
printf("which = %04X\nmac key=",which);
{ int z; for (z=0; z<i; z++) printf("%02X%c",ms[z],((z+1)%16)?' ':'\n'); }
#endif
	if (_exp)
		{
		/* In here I set both the read and write key/iv to the
		 * same value since only the correct one will be used :-).
		 */
		p=buf;
		memcpy(p,exp_label,exp_label_len);
		p+=exp_label_len;
		memcpy(p,s->s3->client_random,SSL3_RANDOM_SIZE);
		p+=SSL3_RANDOM_SIZE;
		memcpy(p,s->s3->server_random,SSL3_RANDOM_SIZE);
		p+=SSL3_RANDOM_SIZE;
		tls1_PRF(s->ctx->md5,s->ctx->sha1,buf,(int)(p-buf),key,j,
			 tmp1,tmp2,EVP_CIPHER_key_length(c));
		key=tmp1;

		if (k > 0)
			{
			p=buf;
			memcpy(p,TLS_MD_IV_BLOCK_CONST,
				TLS_MD_IV_BLOCK_CONST_SIZE);
			p+=TLS_MD_IV_BLOCK_CONST_SIZE;
			memcpy(p,s->s3->client_random,SSL3_RANDOM_SIZE);
			p+=SSL3_RANDOM_SIZE;
			memcpy(p,s->s3->server_random,SSL3_RANDOM_SIZE);
			p+=SSL3_RANDOM_SIZE;
			tls1_PRF(s->ctx->md5,s->ctx->sha1,buf,p-buf,empty,0,
				 iv1,iv2,k*2);
			if (client_write)
				iv=iv1;
			else
				iv= &(iv1[k]);
			}
		}

	s->session->key_arg_length=0;

	EVP_CipherInit(dd,c,key,iv,(which & SSL3_CC_WRITE));
#ifdef TLS_DEBUG
printf("which = %04X\nkey=",which);
{ int z; for (z=0; z<EVP_CIPHER_key_length(c); z++) printf("%02X%c",key[z],((z+1)%16)?' ':'\n'); }
printf("\niv=");
{ int z; for (z=0; z<k; z++) printf("%02X%c",iv[z],((z+1)%16)?' ':'\n'); }
printf("\n");
#endif

	memset(tmp1,0,sizeof(tmp1));
	memset(tmp2,0,sizeof(tmp1));
	memset(iv1,0,sizeof(iv1));
	memset(iv2,0,sizeof(iv2));
	return(1);
err:
	SSLerr(SSL_F_TLS1_CHANGE_CIPHER_STATE,ERR_R_MALLOC_FAILURE);
err2:
	return(0);
	}
Esempio n. 4
0
int SM2_do_decrypt(const EVP_MD *kdf_md, const EVP_MD *mac_md,
	const SM2_CIPHERTEXT_VALUE *cv, unsigned char *out, size_t *outlen,
	EC_KEY *ec_key)
{
	int ret = 0;
	const EC_GROUP *ec_group = EC_KEY_get0_group(ec_key);
	const BIGNUM *pri_key = EC_KEY_get0_private_key(ec_key);
	KDF_FUNC kdf = KDF_get_x9_63(kdf_md);
	EC_POINT *point = NULL;
	BIGNUM *n = NULL;
	BIGNUM *h = NULL;
	BN_CTX *bn_ctx = NULL;
	EVP_MD_CTX *md_ctx = NULL;
	unsigned char buf[(OPENSSL_ECC_MAX_FIELD_BITS + 7)/4 + 1];
	unsigned char mac[EVP_MAX_MD_SIZE];
	unsigned int maclen;
	int nbytes;
	size_t size;
	int i;

	OPENSSL_assert(kdf_md && mac_md && cv && ec_key);
	OPENSSL_assert(cv->ephem_point && cv->ciphertext);

	if (!ec_group || !pri_key) {
		goto end;
	}
	if (!kdf) {
		goto end;
	}

	if (!out) {
		*outlen = cv->ciphertext_size;
		return 1;
	}
	if (*outlen < cv->ciphertext_size) {
		goto end;
	}

	/* init vars */
	point = EC_POINT_new(ec_group);
	n = BN_new();
	h = BN_new();
	bn_ctx = BN_CTX_new();
	md_ctx = EVP_MD_CTX_create();
	if (!point || !n || !h || !bn_ctx || !md_ctx) {
		goto end;
	}
	
	/* init ec domain parameters */
	if (!EC_GROUP_get_order(ec_group, n, bn_ctx)) {
		goto end;
	}
	if (!EC_GROUP_get_cofactor(ec_group, h, bn_ctx)) {
		goto end;
	}
	nbytes = (EC_GROUP_get_degree(ec_group) + 7) / 8;
	//OPENSSL_assert(nbytes == BN_num_bytes(n));

#if 0
	/* check sm2 curve and md is 256 bits */
	OPENSSL_assert(nbytes == 32);
	OPENSSL_assert(EVP_MD_size(kdf_md) == 32);
	OPENSSL_assert(EVP_MD_size(mac_md) == 32);
#endif

	/* B2: check [h]C1 != O */
	if (!EC_POINT_mul(ec_group, point, NULL, cv->ephem_point, h, bn_ctx)) {
		goto end;
	}
	if (EC_POINT_is_at_infinity(ec_group, point)) {
		goto end;
	}

	/* B3: compute ECDH [d]C1 = (x2, y2) */	
	if (!EC_POINT_mul(ec_group, point, NULL, cv->ephem_point, pri_key, bn_ctx)) {
		goto end;
	}
	if (!(size = EC_POINT_point2oct(ec_group, point,
		POINT_CONVERSION_UNCOMPRESSED, buf, sizeof(buf), bn_ctx))) {
		goto end;
	}
	OPENSSL_assert(size == 1 + nbytes * 2);

	/* B4: compute t = KDF(x2 || y2, clen) */

	*outlen = cv->ciphertext_size; //FIXME: duplicated code
	kdf(buf + 1, size - 1, out, outlen);


	/* B5: compute M = C2 xor t */
	for (i = 0; i < cv->ciphertext_size; i++) {
		out[i] ^= cv->ciphertext[i];
	}
	*outlen = cv->ciphertext_size;

	/* B6: check Hash(x2 || M || y2) == C3 */
	if (!EVP_DigestInit_ex(md_ctx, mac_md, NULL)) {
		goto end;
	}
	if (!EVP_DigestUpdate(md_ctx, buf + 1, nbytes)) {
		goto end;
	}
	if (!EVP_DigestUpdate(md_ctx, out, *outlen)) {
		goto end;
	}
	if (!EVP_DigestUpdate(md_ctx, buf + 1 + nbytes, nbytes)) {
		goto end;
	}
	if (!EVP_DigestFinal_ex(md_ctx, mac, &maclen)) {
		goto end;
	}
	if (cv->mactag_size != maclen ||
		memcmp(cv->mactag, mac, maclen)) {
		goto end;
	}

	ret = 1;
end:
	if (point) EC_POINT_free(point);
	if (n) BN_free(n);	
	if (h) BN_free(h);
	if (bn_ctx) BN_CTX_free(bn_ctx);
	if (md_ctx) EVP_MD_CTX_destroy(md_ctx);

	return ret;
}
Esempio n. 5
0
TLS_APPL_STATE *tls_client_init(const TLS_CLIENT_INIT_PROPS *props)
{
    long    off = 0;
    int     cachable;
    SSL_CTX *client_ctx;
    TLS_APPL_STATE *app_ctx;
    const EVP_MD *md_alg;
    unsigned int md_len;
    int     log_mask;

    /*
     * Convert user loglevel to internal logmask.
     */
    log_mask = tls_log_mask(props->log_param, props->log_level);

    if (log_mask & TLS_LOG_VERBOSE)
	msg_info("initializing the client-side TLS engine");

    /*
     * Load (mostly cipher related) TLS-library internal main.cf parameters.
     */
    tls_param_init();

    /*
     * Detect mismatch between compile-time headers and run-time library.
     */
    tls_check_version();

    /*
     * Initialize the OpenSSL library by the book! To start with, we must
     * initialize the algorithms. We want cleartext error messages instead of
     * just error codes, so we load the error_strings.
     */
    SSL_load_error_strings();
    OpenSSL_add_ssl_algorithms();

    /*
     * Create an application data index for SSL objects, so that we can
     * attach TLScontext information; this information is needed inside
     * tls_verify_certificate_callback().
     */
    if (TLScontext_index < 0) {
	if ((TLScontext_index = SSL_get_ex_new_index(0, 0, 0, 0, 0)) < 0) {
	    msg_warn("Cannot allocate SSL application data index: "
		     "disabling TLS support");
	    return (0);
	}
    }

    /*
     * If the administrator specifies an unsupported digest algorithm, fail
     * now, rather than in the middle of a TLS handshake.
     */
    if ((md_alg = EVP_get_digestbyname(props->fpt_dgst)) == 0) {
	msg_warn("Digest algorithm \"%s\" not found: disabling TLS support",
		 props->fpt_dgst);
	return (0);
    }

    /*
     * Sanity check: Newer shared libraries may use larger digests.
     */
    if ((md_len = EVP_MD_size(md_alg)) > EVP_MAX_MD_SIZE) {
	msg_warn("Digest algorithm \"%s\" output size %u too large:"
		 " disabling TLS support", props->fpt_dgst, md_len);
	return (0);
    }

    /*
     * Initialize the PRNG (Pseudo Random Number Generator) with some seed
     * from external and internal sources. Don't enable TLS without some real
     * entropy.
     */
    if (tls_ext_seed(var_tls_daemon_rand_bytes) < 0) {
	msg_warn("no entropy for TLS key generation: disabling TLS support");
	return (0);
    }
    tls_int_seed();

    /*
     * The SSL/TLS specifications require the client to send a message in the
     * oldest specification it understands with the highest level it
     * understands in the message. RFC2487 is only specified for TLSv1, but
     * we want to be as compatible as possible, so we will start off with a
     * SSLv2 greeting allowing the best we can offer: TLSv1. We can restrict
     * this with the options setting later, anyhow.
     */
    ERR_clear_error();
    if ((client_ctx = SSL_CTX_new(SSLv23_client_method())) == 0) {
	msg_warn("cannot allocate client SSL_CTX: disabling TLS support");
	tls_print_errors();
	return (0);
    }

    /*
     * See the verify callback in tls_verify.c
     */
    SSL_CTX_set_verify_depth(client_ctx, props->verifydepth + 1);

    /*
     * Protocol selection is destination dependent, so we delay the protocol
     * selection options to the per-session SSL object.
     */
    off |= tls_bug_bits();
    SSL_CTX_set_options(client_ctx, off);

    /*
     * Set the call-back routine for verbose logging.
     */
    if (log_mask & TLS_LOG_DEBUG)
	SSL_CTX_set_info_callback(client_ctx, tls_info_callback);

    /*
     * Load the CA public key certificates for both the client cert and for
     * the verification of server certificates. As provided by OpenSSL we
     * support two types of CA certificate handling: One possibility is to
     * add all CA certificates to one large CAfile, the other possibility is
     * a directory pointed to by CApath, containing separate files for each
     * CA with softlinks named after the hash values of the certificate. The
     * first alternative has the advantage that the file is opened and read
     * at startup time, so that you don't have the hassle to maintain another
     * copy of the CApath directory for chroot-jail.
     */
    if (tls_set_ca_certificate_info(client_ctx,
				    props->CAfile, props->CApath) < 0) {
	/* tls_set_ca_certificate_info() already logs a warning. */
	SSL_CTX_free(client_ctx);		/* 200411 */
	return (0);
    }

    /*
     * We do not need a client certificate, so the certificates are only
     * loaded (and checked) if supplied. A clever client would handle
     * multiple client certificates and decide based on the list of
     * acceptable CAs, sent by the server, which certificate to submit.
     * OpenSSL does however not do this and also has no call-back hooks to
     * easily implement it.
     * 
     * Load the client public key certificate and private key from file and
     * check whether the cert matches the key. We can use RSA certificates
     * ("cert") DSA certificates ("dcert") or ECDSA certificates ("eccert").
     * All three can be made available at the same time. The CA certificates
     * for all three are handled in the same setup already finished. Which
     * one is used depends on the cipher negotiated (that is: the first
     * cipher listed by the client which does match the server). The client
     * certificate is presented after the server chooses the session cipher,
     * so we will just present the right cert for the chosen cipher (if it
     * uses certificates).
     */
    if (tls_set_my_certificate_key_info(client_ctx,
					props->cert_file,
					props->key_file,
					props->dcert_file,
					props->dkey_file,
					props->eccert_file,
					props->eckey_file) < 0) {
	/* tls_set_my_certificate_key_info() already logs a warning. */
	SSL_CTX_free(client_ctx);		/* 200411 */
	return (0);
    }

    /*
     * According to the OpenSSL documentation, temporary RSA key is needed
     * export ciphers are in use. We have to provide one, so well, we just do
     * it.
     */
    SSL_CTX_set_tmp_rsa_callback(client_ctx, tls_tmp_rsa_cb);

    /*
     * Finally, the setup for the server certificate checking, done "by the
     * book".
     */
    SSL_CTX_set_verify(client_ctx, SSL_VERIFY_NONE,
		       tls_verify_certificate_callback);

    /*
     * Initialize the session cache.
     * 
     * Since the client does not search an internal cache, we simply disable it.
     * It is only useful for expiring old sessions, but we do that in the
     * tlsmgr(8).
     * 
     * This makes SSL_CTX_remove_session() not useful for flushing broken
     * sessions from the external cache, so we must delete them directly (not
     * via a callback).
     */
    if (tls_mgr_policy(props->cache_type, &cachable) != TLS_MGR_STAT_OK)
	cachable = 0;

    /*
     * Allocate an application context, and populate with mandatory protocol
     * and cipher data.
     */
    app_ctx = tls_alloc_app_context(client_ctx, log_mask);

    /*
     * The external session cache is implemented by the tlsmgr(8) process.
     */
    if (cachable) {

	app_ctx->cache_type = mystrdup(props->cache_type);

	/*
	 * OpenSSL does not use callbacks to load sessions from a client
	 * cache, so we must invoke that function directly. Apparently,
	 * OpenSSL does not provide a way to pass session names from here to
	 * call-back routines that do session lookup.
	 * 
	 * OpenSSL can, however, automatically save newly created sessions for
	 * us by callback (we create the session name in the call-back
	 * function).
	 * 
	 * XXX gcc 2.95 can't compile #ifdef .. #endif in the expansion of
	 * SSL_SESS_CACHE_CLIENT | SSL_SESS_CACHE_NO_INTERNAL_STORE |
	 * SSL_SESS_CACHE_NO_AUTO_CLEAR.
	 */
#ifndef SSL_SESS_CACHE_NO_INTERNAL_STORE
#define SSL_SESS_CACHE_NO_INTERNAL_STORE 0
#endif

	SSL_CTX_set_session_cache_mode(client_ctx,
				       SSL_SESS_CACHE_CLIENT |
				       SSL_SESS_CACHE_NO_INTERNAL_STORE |
				       SSL_SESS_CACHE_NO_AUTO_CLEAR);
	SSL_CTX_sess_set_new_cb(client_ctx, new_client_session_cb);
    }
    return (app_ctx);
}
Esempio n. 6
0
int int_rsa_verify(int dtype, const uint8_t *m,
                   unsigned int m_len,
                   uint8_t *rm, size_t *prm_len,
                   const uint8_t *sigbuf, size_t siglen,
                   RSA *rsa)
{
    int i, ret = 0, sigtype;
    uint8_t *s;
    X509_SIG *sig = NULL;

    if (siglen != (unsigned int)RSA_size(rsa)) {
        RSAerr(RSA_F_INT_RSA_VERIFY, RSA_R_WRONG_SIGNATURE_LENGTH);
        return (0);
    }

    if ((dtype == NID_md5_sha1) && rm) {
        i = RSA_public_decrypt((int)siglen,
                               sigbuf, rm, rsa, RSA_PKCS1_PADDING);
        if (i <= 0)
            return 0;
        *prm_len = i;
        return 1;
    }

    s = malloc((unsigned int)siglen);
    if (s == NULL) {
        RSAerr(RSA_F_INT_RSA_VERIFY, ERR_R_MALLOC_FAILURE);
        goto err;
    }
    if ((dtype == NID_md5_sha1) && (m_len != SSL_SIG_LENGTH)) {
        RSAerr(RSA_F_INT_RSA_VERIFY, RSA_R_INVALID_MESSAGE_LENGTH);
        goto err;
    }
    i = RSA_public_decrypt((int)siglen, sigbuf, s, rsa, RSA_PKCS1_PADDING);

    if (i <= 0)
        goto err;

    /* Special case: SSL signature */
    if (dtype == NID_md5_sha1) {
        if ((i != SSL_SIG_LENGTH) || memcmp(s, m, SSL_SIG_LENGTH))
            RSAerr(RSA_F_INT_RSA_VERIFY, RSA_R_BAD_SIGNATURE);
        else
            ret = 1;
    } else {
        const uint8_t *p = s;
        sig = d2i_X509_SIG(NULL, &p, (long)i);

        if (sig == NULL)
            goto err;

        /* Excess data can be used to create forgeries */
        if (p != s + i || !rsa_check_digestinfo(sig, s, i)) {
            RSAerr(RSA_F_INT_RSA_VERIFY, RSA_R_BAD_SIGNATURE);
            goto err;
        }

        /* Parameters to the signature algorithm can also be used to
           create forgeries */
        if (sig->algor->parameter
            && ASN1_TYPE_get(sig->algor->parameter) != V_ASN1_NULL) {
            RSAerr(RSA_F_INT_RSA_VERIFY, RSA_R_BAD_SIGNATURE);
            goto err;
        }

        sigtype = OBJ_obj2nid(sig->algor->algorithm);
        if (sigtype != dtype) {
            RSAerr(RSA_F_INT_RSA_VERIFY, RSA_R_ALGORITHM_MISMATCH);
            goto err;
        }
        if (rm) {
            const EVP_MD *md;
            md = EVP_get_digestbynid(dtype);
            if (md && (EVP_MD_size(md) != sig->digest->length))
                RSAerr(RSA_F_INT_RSA_VERIFY,
                       RSA_R_INVALID_DIGEST_LENGTH);
            else {
                memcpy(rm, sig->digest->data,
                       sig->digest->length);
                *prm_len = sig->digest->length;
                ret = 1;
            }
        } else if (((unsigned int)sig->digest->length != m_len) || (memcmp(m, sig->digest->data, m_len) != 0)) {
            RSAerr(RSA_F_INT_RSA_VERIFY, RSA_R_BAD_SIGNATURE);
        } else
            ret = 1;
    }
err:
    X509_SIG_free(sig);
    if (s != NULL) {
        vigortls_zeroize(s, (unsigned int)siglen);
        free(s);
    }
    return (ret);
}
Esempio n. 7
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;
	size_t j;
	EVP_MD_CTX ctx, ctx_tmp;
	EVP_PKEY *mac_key;
	unsigned char A1[EVP_MAX_MD_SIZE];
	size_t A1_len;
	int ret = 0;
	
	chunk=EVP_MD_size(md);
	OPENSSL_assert(chunk >= 0);

	EVP_MD_CTX_init(&ctx);
	EVP_MD_CTX_init(&ctx_tmp);
	EVP_MD_CTX_set_flags(&ctx, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);
	EVP_MD_CTX_set_flags(&ctx_tmp, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);
	mac_key = EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, NULL, sec, sec_len);
	if (!mac_key)
		goto err;
	if (!EVP_DigestSignInit(&ctx,NULL,md, NULL, mac_key))
		goto err;
	if (!EVP_DigestSignInit(&ctx_tmp,NULL,md, NULL, mac_key))
		goto err;
	if (seed1 && !EVP_DigestSignUpdate(&ctx,seed1,seed1_len))
		goto err;
	if (seed2 && !EVP_DigestSignUpdate(&ctx,seed2,seed2_len))
		goto err;
	if (seed3 && !EVP_DigestSignUpdate(&ctx,seed3,seed3_len))
		goto err;
	if (seed4 && !EVP_DigestSignUpdate(&ctx,seed4,seed4_len))
		goto err;
	if (seed5 && !EVP_DigestSignUpdate(&ctx,seed5,seed5_len))
		goto err;
	if (!EVP_DigestSignFinal(&ctx,A1,&A1_len))
		goto err;

	for (;;)
		{
		/* Reinit mac contexts */
		if (!EVP_DigestSignInit(&ctx,NULL,md, NULL, mac_key))
			goto err;
		if (!EVP_DigestSignInit(&ctx_tmp,NULL,md, NULL, mac_key))
			goto err;
		if (!EVP_DigestSignUpdate(&ctx,A1,A1_len))
			goto err;
		if (!EVP_DigestSignUpdate(&ctx_tmp,A1,A1_len))
			goto err;
		if (seed1 && !EVP_DigestSignUpdate(&ctx,seed1,seed1_len))
			goto err;
		if (seed2 && !EVP_DigestSignUpdate(&ctx,seed2,seed2_len))
			goto err;
		if (seed3 && !EVP_DigestSignUpdate(&ctx,seed3,seed3_len))
			goto err;
		if (seed4 && !EVP_DigestSignUpdate(&ctx,seed4,seed4_len))
			goto err;
		if (seed5 && !EVP_DigestSignUpdate(&ctx,seed5,seed5_len))
			goto err;

		if (olen > chunk)
			{
			if (!EVP_DigestSignFinal(&ctx,out,&j))
				goto err;
			out+=j;
			olen-=j;
			/* calc the next A1 value */
			if (!EVP_DigestSignFinal(&ctx_tmp,A1,&A1_len))
				goto err;
			}
		else	/* last one */
			{
			if (!EVP_DigestSignFinal(&ctx,A1,&A1_len))
				goto err;
			memcpy(out,A1,olen);
			break;
			}
		}
	ret = 1;
err:
	EVP_PKEY_free(mac_key);
	EVP_MD_CTX_cleanup(&ctx);
	EVP_MD_CTX_cleanup(&ctx_tmp);
	OPENSSL_cleanse(A1,sizeof(A1));
	return ret;
	}
Esempio n. 8
0
int tls1_mac(SSL *ssl, unsigned char *md, int send)
	{
	SSL3_RECORD *rec;
	unsigned char *mac_sec,*seq;
	const EVP_MD *hash;
	unsigned int md_size;
	int i;
	HMAC_CTX hmac;
	unsigned char buf[5]; 

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

	md_size=EVP_MD_size(hash);

	buf[0]=rec->type;
	buf[1]=TLS1_VERSION_MAJOR;
	buf[2]=TLS1_VERSION_MINOR;
	buf[3]=rec->length>>8;
	buf[4]=rec->length&0xff;

	/* I should fix this up TLS TLS TLS TLS TLS XXXXXXXX */
	HMAC_CTX_init(&hmac);
	HMAC_Init_ex(&hmac,mac_sec,EVP_MD_size(hash),hash,NULL);
	HMAC_Update(&hmac,seq,8);
	HMAC_Update(&hmac,buf,5);
	HMAC_Update(&hmac,rec->input,rec->length);
	HMAC_Final(&hmac,md,&md_size);
	HMAC_CTX_cleanup(&hmac);

#ifdef TLS_DEBUG
printf("sec=");
{unsigned int z; for (z=0; z<md_size; z++) printf("%02X ",mac_sec[z]); printf("\n"); }
printf("seq=");
{int z; for (z=0; z<8; z++) printf("%02X ",seq[z]); printf("\n"); }
printf("buf=");
{int z; for (z=0; z<5; z++) printf("%02X ",buf[z]); printf("\n"); }
printf("rec=");
{unsigned int z; for (z=0; z<rec->length; z++) printf("%02X ",buf[z]); printf("\n"); }
#endif

	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++) printf("%02X ",md[z]); printf("\n"); }
#endif
	return(md_size);
	}
char *
ssh_gssapi_kex_mechs(gss_OID_set gss_supported, ssh_gssapi_check_fn *check,
    const char *data) {
	Buffer buf;
	size_t i;
	int oidpos, enclen;
	char *mechs, *encoded;
	u_char digest[EVP_MAX_MD_SIZE];
	char deroid[2];
	const EVP_MD *evp_md = EVP_md5();
	EVP_MD_CTX md;

	if (gss_enc2oid != NULL) {
		for (i = 0; gss_enc2oid[i].encoded != NULL; i++)
			xfree(gss_enc2oid[i].encoded);
		xfree(gss_enc2oid);
	}

	gss_enc2oid = xmalloc(sizeof(ssh_gss_kex_mapping) *
	    (gss_supported->count + 1));

	buffer_init(&buf);

	oidpos = 0;
	for (i = 0; i < gss_supported->count; i++) {
		if (gss_supported->elements[i].length < 128 &&
		    (*check)(NULL, &(gss_supported->elements[i]), data)) {

			deroid[0] = SSH_GSS_OIDTYPE;
			deroid[1] = gss_supported->elements[i].length;

			EVP_DigestInit(&md, evp_md);
			EVP_DigestUpdate(&md, deroid, 2);
			EVP_DigestUpdate(&md,
			    gss_supported->elements[i].elements,
			    gss_supported->elements[i].length);
			EVP_DigestFinal(&md, digest, NULL);

			encoded = xmalloc(EVP_MD_size(evp_md) * 2);
			enclen = __b64_ntop(digest, EVP_MD_size(evp_md),
			    encoded, EVP_MD_size(evp_md) * 2);

			if (oidpos != 0)
				buffer_put_char(&buf, ',');

			buffer_append(&buf, KEX_GSS_GEX_SHA1_ID,
			    sizeof(KEX_GSS_GEX_SHA1_ID) - 1);
			buffer_append(&buf, encoded, enclen);
			buffer_put_char(&buf, ',');
			buffer_append(&buf, KEX_GSS_GRP1_SHA1_ID, 
			    sizeof(KEX_GSS_GRP1_SHA1_ID) - 1);
			buffer_append(&buf, encoded, enclen);
			buffer_put_char(&buf, ',');
			buffer_append(&buf, KEX_GSS_GRP14_SHA1_ID,
			    sizeof(KEX_GSS_GRP14_SHA1_ID) - 1);
			buffer_append(&buf, encoded, enclen);

			gss_enc2oid[oidpos].oid = &(gss_supported->elements[i]);
			gss_enc2oid[oidpos].encoded = encoded;
			oidpos++;
		}
	}
	gss_enc2oid[oidpos].oid = NULL;
	gss_enc2oid[oidpos].encoded = NULL;

	buffer_put_char(&buf, '\0');

	mechs = xmalloc(buffer_len(&buf));
	buffer_get(&buf, mechs, buffer_len(&buf));
	buffer_free(&buf);

	if (strlen(mechs) == 0) {
		xfree(mechs);
		mechs = NULL;
	}
	
	return (mechs);
}
Esempio n. 10
0
int tls1_mac(SSL *ssl, unsigned char *md, int send)
	{
	SSL3_RECORD *rec;
	unsigned char *mac_sec,*seq;
	const EVP_MD *hash;
	unsigned int md_size;
	int i;
	HMAC_CTX hmac;
	unsigned char buf[5]; 

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

	md_size=EVP_MD_size(hash);

	buf[0]=rec->type;
	if (ssl->version == DTLS1_VERSION && ssl->client_version == DTLS1_BAD_VER)
		{
		buf[1]=TLS1_VERSION_MAJOR;
		buf[2]=TLS1_VERSION_MINOR;
		}
	else	{
		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 */
	HMAC_CTX_init(&hmac);
	HMAC_Init_ex(&hmac,mac_sec,EVP_MD_size(hash),hash,NULL);

	if (ssl->version == DTLS1_BAD_VER ||
	    (ssl->version == DTLS1_VERSION && ssl->client_version != DTLS1_BAD_VER))
		{
		unsigned char dtlsseq[8],*p=dtlsseq;
		s2n(send?ssl->d1->w_epoch:ssl->d1->r_epoch, p);
		memcpy (p,&seq[2],6);

		HMAC_Update(&hmac,dtlsseq,8);
		}
	else
		HMAC_Update(&hmac,seq,8);

	HMAC_Update(&hmac,buf,5);
	HMAC_Update(&hmac,rec->input,rec->length);
	HMAC_Final(&hmac,md,&md_size);
	HMAC_CTX_cleanup(&hmac);

#ifdef TLS_DEBUG
printf("sec=");
{unsigned int z; for (z=0; z<md_size; z++) printf("%02X ",mac_sec[z]); printf("\n"); }
printf("seq=");
{int z; for (z=0; z<8; z++) printf("%02X ",seq[z]); printf("\n"); }
printf("buf=");
{int z; for (z=0; z<5; z++) printf("%02X ",buf[z]); printf("\n"); }
printf("rec=");
{unsigned int z; for (z=0; z<rec->length; z++) printf("%02X ",buf[z]); printf("\n"); }
#endif

	if ( SSL_version(ssl) != DTLS1_VERSION && SSL_version(ssl) != 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++) printf("%02X ",md[z]); printf("\n"); }
#endif
	return(md_size);
	}
Esempio n. 11
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 (s->write_hash != NULL)
			n=EVP_MD_size(s->write_hash);
		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 (s->read_hash != NULL)
			n=EVP_MD_size(s->read_hash);
		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
	printf("tls1_enc(%d)\n", send);
#endif    /* KSSL_DEBUG */

	if ((s->session == NULL) || (ds == NULL) ||
		(enc == NULL))
		{
		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;
		printf("EVP_Cipher(ds=%p,rec->data=%p,rec->input=%p,l=%ld) ==>\n",
                        ds,rec->data,rec->input,l);
		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);
		printf("\t\tIV: ");
		for (i=0; i<ds->cipher->iv_len; i++) printf("%02X", ds->iv[i]);
		printf("\n");
		printf("\trec->input=");
		for (ui=0; ui<l; ui++) printf(" %02x", rec->input[ui]);
		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;
                printf("\trec->data=");
		for (i=0; i<l; i++)
                        printf(" %02x", rec->data[i]);  printf("\n");
                }
#endif	/* KSSL_DEBUG */

		if ((bs != 1) && !send)
			{
			ii=i=rec->data[l-1]; /* padding_length */
			i++;
			if (s->options&SSL_OP_TLS_BLOCK_PADDING_BUG)
				{
				/* First packet is even in size, so check */
				if ((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);
	}
Esempio n. 12
0
int tls1_change_cipher_state(SSL *s, int which)
	{
	static const unsigned char empty[]="";
	unsigned char *p,*key_block,*mac_secret;
	unsigned char *exp_label,buf[TLS_MD_MAX_CONST_SIZE+
		SSL3_RANDOM_SIZE*2];
	unsigned char tmp1[EVP_MAX_KEY_LENGTH];
	unsigned char tmp2[EVP_MAX_KEY_LENGTH];
	unsigned char iv1[EVP_MAX_IV_LENGTH*2];
	unsigned char iv2[EVP_MAX_IV_LENGTH*2];
	unsigned char *ms,*key,*iv,*er1,*er2;
	int client_write;
	EVP_CIPHER_CTX *dd;
	const EVP_CIPHER *c;
#ifndef OPENSSL_NO_COMP
	const SSL_COMP *comp;
#endif
	const EVP_MD *m;
	int is_export,n,i,j,k,exp_label_len,cl;
	int reuse_dd = 0;

	is_export=SSL_C_IS_EXPORT(s->s3->tmp.new_cipher);
	c=s->s3->tmp.new_sym_enc;
	m=s->s3->tmp.new_hash;
#ifndef OPENSSL_NO_COMP
	comp=s->s3->tmp.new_compression;
#endif
	key_block=s->s3->tmp.key_block;

#ifdef KSSL_DEBUG
	printf("tls1_change_cipher_state(which= %d) w/\n", which);
	printf("\talg= %ld, comp= %p\n", s->s3->tmp.new_cipher->algorithms,
                (void *)comp);
	printf("\tevp_cipher == %p ==? &d_cbc_ede_cipher3\n", (void *)c);
	printf("\tevp_cipher: nid, blksz= %d, %d, keylen=%d, ivlen=%d\n",
                c->nid,c->block_size,c->key_len,c->iv_len);
	printf("\tkey_block: len= %d, data= ", s->s3->tmp.key_block_length);
	{
        int ki;
        for (ki=0; ki<s->s3->tmp.key_block_length; ki++)
		printf("%02x", key_block[ki]);  printf("\n");
        }
#endif	/* KSSL_DEBUG */

	if (which & SSL3_CC_READ)
		{
		if (s->enc_read_ctx != NULL)
			reuse_dd = 1;
		else if ((s->enc_read_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;
		s->read_hash=m;
#ifndef OPENSSL_NO_COMP
		if (s->expand != NULL)
			{
			COMP_CTX_free(s->expand);
			s->expand=NULL;
			}
		if (comp != NULL)
			{
			s->expand=COMP_CTX_new(comp->method);
			if (s->expand == NULL)
				{
				SSLerr(SSL_F_TLS1_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_ENCRYPTED_LENGTH);
			if (s->s3->rrec.comp == NULL)
				goto err;
			}
#endif
		/* this is done by dtls1_reset_seq_numbers for DTLS1_VERSION */
 		if (s->version != DTLS1_VERSION)
			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=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;
		s->write_hash=m;
#ifndef OPENSSL_NO_COMP
		if (s->compress != NULL)
			{
			COMP_CTX_free(s->compress);
			s->compress=NULL;
			}
		if (comp != NULL)
			{
			s->compress=COMP_CTX_new(comp->method);
			if (s->compress == NULL)
				{
				SSLerr(SSL_F_TLS1_CHANGE_CIPHER_STATE,SSL_R_COMPRESSION_LIBRARY_ERROR);
				goto err2;
				}
			}
#endif
		/* this is done by dtls1_reset_seq_numbers for DTLS1_VERSION */
 		if (s->version != DTLS1_VERSION)
			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);
	cl=EVP_CIPHER_key_length(c);
	j=is_export ? (cl < SSL_C_EXPORT_KEYLENGTH(s->s3->tmp.new_cipher) ?
	               cl : SSL_C_EXPORT_KEYLENGTH(s->s3->tmp.new_cipher)) : cl;
	/* Was j=(exp)?5:EVP_CIPHER_key_length(c); */
	k=EVP_CIPHER_iv_length(c);
	er1= &(s->s3->client_random[0]);
	er2= &(s->s3->server_random[0]);
	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;
		exp_label=(unsigned char *)TLS_MD_CLIENT_WRITE_KEY_CONST;
		exp_label_len=TLS_MD_CLIENT_WRITE_KEY_CONST_SIZE;
		client_write=1;
		}
	else
		{
		n=i;
		ms=  &(p[ n]); n+=i+j;
		key= &(p[ n]); n+=j+k;
		iv=  &(p[ n]); n+=k;
		exp_label=(unsigned char *)TLS_MD_SERVER_WRITE_KEY_CONST;
		exp_label_len=TLS_MD_SERVER_WRITE_KEY_CONST_SIZE;
		client_write=0;
		}

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

	memcpy(mac_secret,ms,i);
#ifdef TLS_DEBUG
printf("which = %04X\nmac key=",which);
{ int z; for (z=0; z<i; z++) printf("%02X%c",ms[z],((z+1)%16)?' ':'\n'); }
#endif
	if (is_export)
		{
		/* In here I set both the read and write key/iv to the
		 * same value since only the correct one will be used :-).
		 */
		p=buf;
		memcpy(p,exp_label,exp_label_len);
		p+=exp_label_len;
		memcpy(p,s->s3->client_random,SSL3_RANDOM_SIZE);
		p+=SSL3_RANDOM_SIZE;
		memcpy(p,s->s3->server_random,SSL3_RANDOM_SIZE);
		p+=SSL3_RANDOM_SIZE;
		tls1_PRF(s->ctx->md5,s->ctx->sha1,buf,(int)(p-buf),key,j,
			 tmp1,tmp2,EVP_CIPHER_key_length(c));
		key=tmp1;

		if (k > 0)
			{
			p=buf;
			memcpy(p,TLS_MD_IV_BLOCK_CONST,
				TLS_MD_IV_BLOCK_CONST_SIZE);
			p+=TLS_MD_IV_BLOCK_CONST_SIZE;
			memcpy(p,s->s3->client_random,SSL3_RANDOM_SIZE);
			p+=SSL3_RANDOM_SIZE;
			memcpy(p,s->s3->server_random,SSL3_RANDOM_SIZE);
			p+=SSL3_RANDOM_SIZE;
			tls1_PRF(s->ctx->md5,s->ctx->sha1,buf,p-buf,empty,0,
				 iv1,iv2,k*2);
			if (client_write)
				iv=iv1;
			else
				iv= &(iv1[k]);
			}
		}

	s->session->key_arg_length=0;
#ifdef KSSL_DEBUG
	{
        int ki;
	printf("EVP_CipherInit_ex(dd,c,key=,iv=,which)\n");
	printf("\tkey= ");
	for (ki=0; ki<c->key_len; ki++) printf("%02x", key[ki]);
	printf("\n");
	printf("\t iv= ");
	for (ki=0; ki<c->iv_len; ki++) printf("%02x", iv[ki]);
	printf("\n");
	}
#endif	/* KSSL_DEBUG */

	EVP_CipherInit_ex(dd,c,NULL,key,iv,(which & SSL3_CC_WRITE));
#ifdef TLS_DEBUG
printf("which = %04X\nkey=",which);
{ int z; for (z=0; z<EVP_CIPHER_key_length(c); z++) printf("%02X%c",key[z],((z+1)%16)?' ':'\n'); }
printf("\niv=");
{ int z; for (z=0; z<k; z++) printf("%02X%c",iv[z],((z+1)%16)?' ':'\n'); }
printf("\n");
#endif

	OPENSSL_cleanse(tmp1,sizeof(tmp1));
	OPENSSL_cleanse(tmp2,sizeof(tmp1));
	OPENSSL_cleanse(iv1,sizeof(iv1));
	OPENSSL_cleanse(iv2,sizeof(iv2));
	return(1);
err:
	SSLerr(SSL_F_TLS1_CHANGE_CIPHER_STATE,ERR_R_MALLOC_FAILURE);
err2:
	return(0);
	}
Esempio n. 13
0
static unsigned char *HKDF_Expand(const EVP_MD *evp_md,
                                  const unsigned char *prk, size_t prk_len,
                                  const unsigned char *info, size_t info_len,
                                  unsigned char *okm, size_t okm_len)
{
    HMAC_CTX *hmac;

    unsigned int i;

    unsigned char prev[EVP_MAX_MD_SIZE];

    size_t done_len = 0, dig_len = EVP_MD_size(evp_md);

    size_t n = okm_len / dig_len;
    if (okm_len % dig_len)
        n++;

    if (n > 255)
        return NULL;

    if ((hmac = HMAC_CTX_new()) == NULL)
        return NULL;

    if (!HMAC_Init_ex(hmac, prk, prk_len, evp_md, NULL))
        goto err;

    for (i = 1; i <= n; i++) {
        size_t copy_len;
        const unsigned char ctr = i;

        if (i > 1) {
            if (!HMAC_Init_ex(hmac, NULL, 0, NULL, NULL))
                goto err;

            if (!HMAC_Update(hmac, prev, dig_len))
                goto err;
        }

        if (!HMAC_Update(hmac, info, info_len))
            goto err;

        if (!HMAC_Update(hmac, &ctr, 1))
            goto err;

        if (!HMAC_Final(hmac, prev, NULL))
            goto err;

        copy_len = (done_len + dig_len > okm_len) ?
                       okm_len - done_len :
                       dig_len;

        memcpy(okm + done_len, prev, copy_len);

        done_len += copy_len;
    }

    HMAC_CTX_free(hmac);
    return okm;

 err:
    HMAC_CTX_free(hmac);
    return NULL;
}
Esempio n. 14
0
int _ldapfull_set_hashed(moddata_t data, const char *scheme, const char *prefix, int saltlen, const char *passwd, char *buf, int buflen) {
    char *hash; // base64 hash
    EVP_MD_CTX mdctx;
    const EVP_MD *md;
    unsigned char *digest;
    unsigned char *salt;
    int hlen, plen, dlen, rc;

    md = EVP_get_digestbyname(scheme);
    if (!md) {
        return 0;
    }
    EVP_DigestInit(&mdctx, md);
    EVP_DigestUpdate(&mdctx, passwd, strlen(passwd));
    if (saltlen) {
        salt = (unsigned char *)malloc(saltlen);
        if( !salt ) {
            EVP_MD_CTX_cleanup(&mdctx);
            return 0;
        }
        if( !RAND_bytes(salt,saltlen) ) {
            EVP_MD_CTX_cleanup(&mdctx);
            free(salt);
        }
        EVP_DigestUpdate(&mdctx, salt, saltlen);
    }
    digest = (unsigned char *)malloc(EVP_MD_size(md) + saltlen);
    if( !digest ) {
        if (saltlen) {
            free(salt);
        }
        EVP_MD_CTX_cleanup(&mdctx);
        return 0;
    }
    EVP_DigestFinal(&mdctx, digest, &dlen);

    memcpy(digest+dlen,salt,saltlen);
    if (saltlen) {
        free(salt);
    }
    rc = _ldapfull_base64_encode(digest, dlen+saltlen, &hash, &hlen);
    if( hash[hlen-1] == '\n' ) {
        hash[--hlen] = '\0';
    }
    free(digest);
    if( !rc ) {
        free(hash);
        return 0;
    }

    plen = strlen(prefix);
    if( hlen + plen >= buflen ) {
        log_write(data->ar->c2s->log,LOG_ERR,"_ldapfull_set_hashed: buffer is too short (%i bytes)",buflen);
        free(hash);
        return 0;
    }
    memcpy(buf,prefix,plen);
    memcpy(buf+plen,hash,hlen);
    buf[hlen+plen]='\0';
    free(hash);

    return 1;
}
int ssl3_setup_key_block(SSL *s)
	{
	unsigned char *p;
	const EVP_CIPHER *c;
	const EVP_MD *hash;
	int num;
	int ret = 0;
	SSL_COMP *comp;

	if (s->s3->tmp.key_block_length != 0)
		return(1);

	if (!ssl_cipher_get_evp(s->session,&c,&hash,&comp))
		{
		SSLerr(SSL_F_SSL3_SETUP_KEY_BLOCK,SSL_R_CIPHER_OR_HASH_UNAVAILABLE);
		return(0);
		}

	s->s3->tmp.new_sym_enc=c;
	s->s3->tmp.new_hash=hash;
#ifdef OPENSSL_NO_COMP
	s->s3->tmp.new_compression=NULL;
#else
	s->s3->tmp.new_compression=comp;
#endif

	num=EVP_CIPHER_key_length(c)+EVP_MD_size(hash)+EVP_CIPHER_iv_length(c);
	num*=2;

	ssl3_cleanup_key_block(s);

	if ((p=OPENSSL_malloc(num)) == NULL)
		goto err;

	s->s3->tmp.key_block_length=num;
	s->s3->tmp.key_block=p;

	ret = ssl3_generate_key_block(s,p,num);

	if (!(s->options & SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS))
		{
		/* enable vulnerability countermeasure for CBC ciphers with
		 * known-IV problem (http://www.openssl.org/~bodo/tls-cbc.txt)
		 */
		s->s3->need_empty_fragments = 1;

		if (s->session->cipher != NULL)
			{
			if ((s->session->cipher->algorithms & SSL_ENC_MASK) == SSL_eNULL)
				s->s3->need_empty_fragments = 0;
			
#ifndef OPENSSL_NO_RC4
			if ((s->session->cipher->algorithms & SSL_ENC_MASK) == SSL_RC4)
				s->s3->need_empty_fragments = 0;
#endif
			}
		}

	return ret;
		
err:
	SSLerr(SSL_F_SSL3_SETUP_KEY_BLOCK,ERR_R_MALLOC_FAILURE);
	return(0);
	}
Esempio n. 16
0
int tls_parse_ctos_psk(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
                       size_t chainidx, int *al)
{
    PACKET identities, binders, binder;
    size_t binderoffset, hashsize;
    SSL_SESSION *sess = NULL;
    unsigned int id, i;
    const EVP_MD *md = NULL;
    uint32_t ticket_age = 0, now, agesec, agems;

    /*
     * If we have no PSK kex mode that we recognise then we can't resume so
     * ignore this extension
     */
    if ((s->ext.psk_kex_mode
            & (TLSEXT_KEX_MODE_FLAG_KE | TLSEXT_KEX_MODE_FLAG_KE_DHE)) == 0)
        return 1;

    if (!PACKET_get_length_prefixed_2(pkt, &identities)) {
        *al = SSL_AD_DECODE_ERROR;
        return 0;
    }

    for (id = 0; PACKET_remaining(&identities) != 0; id++) {
        PACKET identity;
        unsigned long ticket_agel;
        int ret;

        if (!PACKET_get_length_prefixed_2(&identities, &identity)
                || !PACKET_get_net_4(&identities, &ticket_agel)) {
            *al = SSL_AD_DECODE_ERROR;
            return 0;
        }

        ticket_age = (uint32_t)ticket_agel;

        ret = tls_decrypt_ticket(s, PACKET_data(&identity),
                                 PACKET_remaining(&identity), NULL, 0, &sess);
        if (ret == TICKET_FATAL_ERR_MALLOC || ret == TICKET_FATAL_ERR_OTHER) {
            *al = SSL_AD_INTERNAL_ERROR;
            return 0;
        }
        if (ret == TICKET_NO_DECRYPT)
            continue;

        md = ssl_md(sess->cipher->algorithm2);
        if (md == NULL) {
            /*
             * Don't recognise this cipher so we can't use the session.
             * Ignore it
             */
            SSL_SESSION_free(sess);
            sess = NULL;
            continue;
        }

        /*
         * TODO(TLS1.3): Somehow we need to handle the case of a ticket renewal.
         * Ignored for now
         */

        break;
    }

    if (sess == NULL)
        return 1;

    binderoffset = PACKET_data(pkt) - (const unsigned char *)s->init_buf->data;
    hashsize = EVP_MD_size(md);

    if (!PACKET_get_length_prefixed_2(pkt, &binders)) {
        *al = SSL_AD_DECODE_ERROR;
        goto err;
    }

    for (i = 0; i <= id; i++) {
        if (!PACKET_get_length_prefixed_1(&binders, &binder)) {
            *al = SSL_AD_DECODE_ERROR;
            goto err;
        }
    }

    if (PACKET_remaining(&binder) != hashsize
            || tls_psk_do_binder(s, md,
                                 (const unsigned char *)s->init_buf->data,
                                 binderoffset, PACKET_data(&binder), NULL,
                                 sess, 0) != 1) {
        *al = SSL_AD_DECODE_ERROR;
        SSLerr(SSL_F_TLS_PARSE_CTOS_PSK, ERR_R_INTERNAL_ERROR);
        goto err;
    }

    sess->ext.tick_identity = id;

    now = (uint32_t)time(NULL);
    agesec = now - (uint32_t)sess->time;
    agems = agesec * (uint32_t)1000;
    ticket_age -= sess->ext.tick_age_add;


    /*
     * For simplicity we do our age calculations in seconds. If the client does
     * it in ms then it could appear that their ticket age is longer than ours
     * (our ticket age calculation should always be slightly longer than the
     * client's due to the network latency). Therefore we add 1000ms to our age
     * calculation to adjust for rounding errors.
     */
    if (sess->timeout >= (long)agesec
            && agems / (uint32_t)1000 == agesec
            && ticket_age <= agems + 1000
            && ticket_age + TICKET_AGE_ALLOWANCE >= agems + 1000) {
        /*
         * Ticket age is within tolerance and not expired. We allow it for early
         * data
         */
        s->ext.early_data_ok = 1;
    }


    SSL_SESSION_free(s->session);
    s->session = sess;
    return 1;
err:
    SSL_SESSION_free(sess);
    return 0;
}
Esempio n. 17
0
size_t HMAC_size(HMAC_CTX *ctx)
{
    return EVP_MD_size((ctx)->md);
}
Esempio n. 18
0
static int sqlcipher_openssl_get_hmac_sz(void *ctx) {
  return EVP_MD_size(EVP_sha1());
}
Esempio n. 19
0
/* side effect: fills the ssl->fingerprint buffer */
static gboolean
ssl_verify_certificate (LmSSL *ssl, const gchar *server)
{
    gboolean retval = TRUE;
    gboolean match_result = FALSE;
    LmSSLBase *base;
    long verify_res;
    int rc;
    const EVP_MD *digest = EVP_sha256();
    unsigned int digest_len;
    guchar digest_bin[EVP_MD_size(digest)];
    X509 *srv_crt;
    gchar *cn;
    X509_NAME *crt_subj;

    base = LM_SSL_BASE(ssl);

    g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_SSL,
           "%s: Cipher: %s/%s/%i\n",
           __FILE__,
           SSL_get_cipher_version(ssl->ssl),
           SSL_get_cipher_name(ssl->ssl),
           SSL_get_cipher_bits(ssl->ssl, NULL));

    verify_res = SSL_get_verify_result(ssl->ssl);
    srv_crt = SSL_get_peer_certificate(ssl->ssl);
    rc = X509_digest(srv_crt, digest, digest_bin, &digest_len);
    if ((rc != 0) && (digest_len == EVP_MD_size(digest))) {
        _lm_ssl_base_set_fingerprint(base, digest_bin, digest_len);
        if (_lm_ssl_base_check_fingerprint(base) != 0) {
            if (base->func(ssl,
                           LM_SSL_STATUS_CERT_FINGERPRINT_MISMATCH,
                           base->func_data) != LM_SSL_RESPONSE_CONTINUE) {
                return FALSE;
            }
        }
    } else {
      if (base->func(ssl,
                     LM_SSL_STATUS_GENERIC_ERROR,
                     base->func_data) != LM_SSL_RESPONSE_CONTINUE) {
          return FALSE;
      }
    }
    g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_SSL,
           "%s: SSL_get_verify_result() = %ld\n",
           __FILE__,
           verify_res);
    switch (verify_res) {
    case X509_V_OK:
        break;
    case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
    case X509_V_ERR_UNABLE_TO_GET_CRL:
        if (base->func(ssl,
                       LM_SSL_STATUS_NO_CERT_FOUND,
                       base->func_data) != LM_SSL_RESPONSE_CONTINUE) {
            retval = FALSE;
        }
        break;
    case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
        /* special case for self signed certificates? */
    case X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE:
    case X509_V_ERR_INVALID_CA:
    case X509_V_ERR_CERT_UNTRUSTED:
    case X509_V_ERR_CERT_REVOKED:
        if (base->func(ssl,
                       LM_SSL_STATUS_UNTRUSTED_CERT,
                       base->func_data) != LM_SSL_RESPONSE_CONTINUE) {
            retval = FALSE;
        }
        break;
    case X509_V_ERR_CERT_NOT_YET_VALID:
    case X509_V_ERR_CRL_NOT_YET_VALID:
        if (base->func(ssl,
                       LM_SSL_STATUS_CERT_NOT_ACTIVATED,
                       base->func_data) != LM_SSL_RESPONSE_CONTINUE) {
            retval = FALSE;
        }
        break;
    case X509_V_ERR_CERT_HAS_EXPIRED:
    case X509_V_ERR_CRL_HAS_EXPIRED:
        if (base->func(ssl,
                       LM_SSL_STATUS_CERT_EXPIRED,
                       base->func_data) != LM_SSL_RESPONSE_CONTINUE) {
            retval = FALSE;
        }
        break;
    default:
        if (base->func(ssl, LM_SSL_STATUS_GENERIC_ERROR,
                       base->func_data) != LM_SSL_RESPONSE_CONTINUE) {
            retval = FALSE;
        }
    }
    /*if (retval == FALSE) {
      g_set_error (error, LM_ERROR, LM_ERROR_CONNECTION_OPEN,
      ssl_get_x509_err(verify_res), NULL);
      }*/
    crt_subj = X509_get_subject_name(srv_crt);
    cn = (gchar *) g_malloc0(LM_SSL_CN_MAX + 1);

    /* FWB: deprecated call, can only get first entry */
    if (X509_NAME_get_text_by_NID(crt_subj, NID_commonName, cn, LM_SSL_CN_MAX) > 0) {

        g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_SSL,
               "%s: server = '%s', cn = '%s'\n",
               __FILE__, server, cn);

        if (cn != NULL && ssl_match_domain_name(server, cn)) {
            match_result = TRUE;
        } else {
            /* g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_SSL, "%s: CN does not match server name\n", __FILE__); */
        }
    } else {
        g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_SSL,
               "X509_NAME_get_text_by_NID() failed");
    }

    /* RFC6125: "...However, it is perfectly acceptable for the subject field to be empty,
     * as long as the certificate contains a subject alternative name ("subjectAltName")
     * extension that includes at least one subjectAltName entry"
     */
    if (!match_result) {
        /* FWB: CN doesn't match, try SANs */
        int subject_alt_names_nb = -1;
        int san_counter;
        STACK_OF(GENERAL_NAME) *subject_alt_names = NULL;

        // Try to extract the names within the SAN extension from the certificate
        subject_alt_names = X509_get_ext_d2i((X509 *) srv_crt, NID_subject_alt_name, NULL, NULL);
        if (subject_alt_names != NULL) {

            // Check each name within the extension
            subject_alt_names_nb = sk_GENERAL_NAME_num(subject_alt_names);
            for (san_counter=0; san_counter<subject_alt_names_nb; san_counter++) {
                const GENERAL_NAME *current_name = sk_GENERAL_NAME_value(subject_alt_names, san_counter);
                if (current_name->type == GEN_DNS) {
                    // Current name is a DNS name, let's check it, it's ASCII
                    if (ssl_match_domain_name(server, (const char *)current_name->d.dNSName->data)) {
                        g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_SSL, "%s: found SAN '%s' - MATCH\n", __FILE__, current_name->d.dNSName->data);
                        match_result = TRUE; /* break; */
                    } else {
                        g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_SSL, "%s: found SAN '%s'\n", __FILE__, current_name->d.dNSName->data);
                    }
                }
            }

        }

        sk_GENERAL_NAME_pop_free(subject_alt_names, GENERAL_NAME_free);
    }

    if (!match_result) {
        if (base->func (ssl,
                        LM_SSL_STATUS_CERT_HOSTNAME_MISMATCH,
                        base->func_data) != LM_SSL_RESPONSE_CONTINUE) {
            retval = FALSE;
        }
    }

    g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_SSL,
           "%s:\n\tIssuer: %s\n\tSubject: %s\n\tFor: %s\n",
           __FILE__,
           X509_NAME_oneline(X509_get_issuer_name(srv_crt), NULL, 0),
           X509_NAME_oneline(X509_get_subject_name(srv_crt), NULL, 0),
           cn);

    g_free(cn);

    return retval;
}
Esempio n. 20
0
int EVP_DigestSignFinal(EVP_MD_CTX *ctx, unsigned char *sigret,
                        size_t *siglen)
{
    int sctx = 0, r = 0;
    EVP_PKEY_CTX *pctx = ctx->pctx;
    if (pctx->pmeth->flags & EVP_PKEY_FLAG_SIGCTX_CUSTOM) {
        if (!sigret)
            return pctx->pmeth->signctx(pctx, sigret, siglen, ctx);
        if (ctx->flags & EVP_MD_CTX_FLAG_FINALISE)
            r = pctx->pmeth->signctx(pctx, sigret, siglen, ctx);
        else {
            EVP_PKEY_CTX *dctx = EVP_PKEY_CTX_dup(ctx->pctx);
            if (!dctx)
                return 0;
            r = dctx->pmeth->signctx(dctx, sigret, siglen, ctx);
            EVP_PKEY_CTX_free(dctx);
        }
        return r;
    }
    if (pctx->pmeth->signctx)
        sctx = 1;
    else
        sctx = 0;
    if (sigret) {
        unsigned char md[EVP_MAX_MD_SIZE];
        unsigned int mdlen = 0;
        if (ctx->flags & EVP_MD_CTX_FLAG_FINALISE) {
            if (sctx)
                r = ctx->pctx->pmeth->signctx(ctx->pctx, sigret, siglen, ctx);
            else
                r = EVP_DigestFinal_ex(ctx, md, &mdlen);
        } else {
            EVP_MD_CTX *tmp_ctx = EVP_MD_CTX_new();
            if (tmp_ctx == NULL)
                return 0;
            if (!EVP_MD_CTX_copy_ex(tmp_ctx, ctx)) {
                EVP_MD_CTX_free(tmp_ctx);
                return 0;
            }
            if (sctx)
                r = tmp_ctx->pctx->pmeth->signctx(tmp_ctx->pctx,
                                                  sigret, siglen, tmp_ctx);
            else
                r = EVP_DigestFinal_ex(tmp_ctx, md, &mdlen);
            EVP_MD_CTX_free(tmp_ctx);
        }
        if (sctx || !r)
            return r;
        if (EVP_PKEY_sign(ctx->pctx, sigret, siglen, md, mdlen) <= 0)
            return 0;
    } else {
        if (sctx) {
            if (pctx->pmeth->signctx(pctx, sigret, siglen, ctx) <= 0)
                return 0;
        } else {
            int s = EVP_MD_size(ctx->digest);
            if (s < 0 || EVP_PKEY_sign(pctx, sigret, siglen, NULL, s) <= 0)
                return 0;
        }
    }
    return 1;
}
Esempio n. 21
0
SM2_CIPHERTEXT_VALUE *SM2_do_encrypt(const EVP_MD *kdf_md, const EVP_MD *mac_md,
	const unsigned char *in, size_t inlen, EC_KEY *ec_key)
{
	int ok = 0;
	SM2_CIPHERTEXT_VALUE *cv = NULL;
	const EC_GROUP *ec_group = EC_KEY_get0_group(ec_key);
	const EC_POINT *pub_key = EC_KEY_get0_public_key(ec_key);
	KDF_FUNC kdf = KDF_get_x9_63(kdf_md);
	EC_POINT *point = NULL;
	BIGNUM *n = NULL;
	BIGNUM *h = NULL;
	BIGNUM *k = NULL;
	BN_CTX *bn_ctx = NULL;
	EVP_MD_CTX *md_ctx = NULL;
	unsigned char buf[(OPENSSL_ECC_MAX_FIELD_BITS + 7)/4 + 1];
	int nbytes;
	size_t len;
	int i;

	if (!ec_group || !pub_key) {
		goto end;
	}
	if (!kdf) {
		goto end;
	}

	/* init ciphertext_value */
	if (!(cv = OPENSSL_malloc(sizeof(SM2_CIPHERTEXT_VALUE)))) {
		goto end;
	}
	bzero(cv, sizeof(SM2_CIPHERTEXT_VALUE));
	cv->ephem_point = EC_POINT_new(ec_group);
	cv->ciphertext = OPENSSL_malloc(inlen);
	cv->ciphertext_size = inlen;
	if (!cv->ephem_point || !cv->ciphertext) {
		goto end;
	}

	point = EC_POINT_new(ec_group);
	n = BN_new();
	h = BN_new();
	k = BN_new();
	bn_ctx = BN_CTX_new();
	md_ctx = EVP_MD_CTX_create();
	if (!point || !n || !h || !k || !bn_ctx || !md_ctx) {
		goto end;
	}

	/* init ec domain parameters */
	if (!EC_GROUP_get_order(ec_group, n, bn_ctx)) {
		goto end;
	}
	if (!EC_GROUP_get_cofactor(ec_group, h, bn_ctx)) {
		goto end;
	}
	nbytes = (EC_GROUP_get_degree(ec_group) + 7) / 8;


	//OPENSSL_assert(nbytes == BN_num_bytes(n));

#if 0
	/* check sm2 curve and md is 256 bits */
	OPENSSL_assert(nbytes == 32);
	OPENSSL_assert(EVP_MD_size(kdf_md) == 32);
	OPENSSL_assert(EVP_MD_size(mac_md) == 32);
#endif

	do
	{
		/* A1: rand k in [1, n-1] */
		do {
			BN_rand_range(k, n);
		} while (BN_is_zero(k));

	
		/* A2: C1 = [k]G = (x1, y1) */
		if (!EC_POINT_mul(ec_group, cv->ephem_point, k, NULL, NULL, bn_ctx)) {
			goto end;
		}
		
		/* A3: check [h]P_B != O */
		if (!EC_POINT_mul(ec_group, point, NULL, pub_key, h, bn_ctx)) {
			goto end;
		}
		if (EC_POINT_is_at_infinity(ec_group, point)) {
			goto end;
		}

		/* A4: compute ECDH [k]P_B = (x2, y2) */
		if (!EC_POINT_mul(ec_group, point, NULL, pub_key, k, bn_ctx)) {
			goto end;
		}
		if (!(len = EC_POINT_point2oct(ec_group, point,
			POINT_CONVERSION_UNCOMPRESSED, buf, sizeof(buf), bn_ctx))) {
			goto end;
		}
		OPENSSL_assert(len == nbytes * 2 + 1);
		
		/* A5: t = KDF(x2 || y2, klen) */
		kdf(buf + 1, len - 1, cv->ciphertext, &cv->ciphertext_size);

		for (i = 0; i < cv->ciphertext_size; i++) {
			if (cv->ciphertext[i]) {
				break;
			}
		}
		if (i == cv->ciphertext_size) {
			continue;
		}

		break;

	} while (1);


	/* A6: C2 = M xor t */
	for (i = 0; i < inlen; i++) {
		cv->ciphertext[i] ^= in[i];
	}
	
	/* A7: C3 = Hash(x2 || M || y2) */
	if (!EVP_DigestInit_ex(md_ctx, mac_md, NULL)) {
		goto end;
	}
	if (!EVP_DigestUpdate(md_ctx, buf + 1, nbytes)) {
		goto end;
	}
	if (!EVP_DigestUpdate(md_ctx, in, inlen)) {
		goto end;
	}
	if (!EVP_DigestUpdate(md_ctx, buf + 1 + nbytes, nbytes)) {
		goto end;
	}
	if (!EVP_DigestFinal_ex(md_ctx, cv->mactag, &cv->mactag_size)) {
		goto end;
	}


	ok = 1;

end:
	if (!ok && cv) {
		SM2_CIPHERTEXT_VALUE_free(cv);
		cv = NULL;
	}

	if (point) EC_POINT_free(point);
	if (n) BN_free(n);
	if (h) BN_free(h);
	if (k) BN_free(k);
	if (bn_ctx) BN_CTX_free(bn_ctx);
	if (md_ctx) EVP_MD_CTX_destroy(md_ctx);

	return cv;
}
Esempio n. 22
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;
    EVP_CIPHER_CTX *dd;
    const EVP_CIPHER *c;
#ifndef OPENSSL_NO_COMP
    COMP_METHOD *comp;
#endif
    const EVP_MD *m;
    int n, i, j, k, cl;
    int reuse_dd = 0;

    c = s->s3->tmp.new_sym_enc;
    m = s->s3->tmp.new_hash;
    /* m == NULL will lead to a crash later */
    OPENSSL_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_new()) == NULL)
            goto err;
        else
            /*
             * make sure it's intialized in case we exit later with an error
             */
            EVP_CIPHER_CTX_reset(s->enc_read_ctx);
        dd = s->enc_read_ctx;

        if (ssl_replace_hash(&s->read_hash, m) == NULL) {
                SSLerr(SSL_F_SSL3_CHANGE_CIPHER_STATE, ERR_R_INTERNAL_ERROR);
                goto err2;
        }
#ifndef OPENSSL_NO_COMP
        /* COMPRESS */
        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 (!RECORD_LAYER_setup_comp_buffer(&s->rlayer))
                goto err;
        }
#endif
        RECORD_LAYER_reset_read_sequence(&s->rlayer);
        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_new()) == NULL)
            goto err;
        else
            /*
             * make sure it's intialized in case we exit later with an error
             */
            EVP_CIPHER_CTX_reset(s->enc_write_ctx);
        dd = s->enc_write_ctx;
        if (ssl_replace_hash(&s->write_hash, m) == NULL) {
                SSLerr(SSL_F_SSL3_CHANGE_CIPHER_STATE, ERR_R_INTERNAL_ERROR);
                goto err2;
        }
#ifndef OPENSSL_NO_COMP
        /* COMPRESS */
        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
        RECORD_LAYER_reset_write_sequence(&s->rlayer);
        mac_secret = &(s->s3->write_mac_secret[0]);
    }

    if (reuse_dd)
        EVP_CIPHER_CTX_reset(dd);

    p = s->s3->tmp.key_block;
    i = EVP_MD_size(m);
    if (i < 0)
        goto err2;
    cl = EVP_CIPHER_key_length(c);
    j = cl;
    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;
    } else {
        n = i;
        ms = &(p[n]);
        n += i + j;
        key = &(p[n]);
        n += j + k;
        iv = &(p[n]);
        n += k;
    }

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

    memcpy(mac_secret, ms, i);

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

#ifdef OPENSSL_SSL_TRACE_CRYPTO
    if (s->msg_callback) {

        int wh = which & SSL3_CC_WRITE ?
            TLS1_RT_CRYPTO_WRITE : TLS1_RT_CRYPTO_READ;
        s->msg_callback(2, s->version, wh | TLS1_RT_CRYPTO_MAC,
                        mac_secret, EVP_MD_size(m), s, s->msg_callback_arg);
        if (c->key_len)
            s->msg_callback(2, s->version, wh | TLS1_RT_CRYPTO_KEY,
                            key, c->key_len, s, s->msg_callback_arg);
        if (k) {
            s->msg_callback(2, s->version, wh | TLS1_RT_CRYPTO_IV,
                            iv, k, s, s->msg_callback_arg);
        }
    }
#endif

    OPENSSL_cleanse(exp_key, sizeof(exp_key));
    OPENSSL_cleanse(exp_iv, sizeof(exp_iv));
    return (1);
 err:
    SSLerr(SSL_F_SSL3_CHANGE_CIPHER_STATE, ERR_R_MALLOC_FAILURE);
 err2:
    OPENSSL_cleanse(exp_key, sizeof(exp_key));
    OPENSSL_cleanse(exp_iv, sizeof(exp_iv));
    return (0);
}
Esempio n. 23
0
static int pkcs5_pbkdf2(const char *hash,
			const char *P, size_t Plen,
			const char *S, size_t Slen,
			unsigned int c, unsigned int dkLen,
			char *DK, int perfcheck)
{
	char U[MAX_PRF_BLOCK_LEN];
	char T[MAX_PRF_BLOCK_LEN];
	const EVP_MD *PRF;
	HMAC_CTX ctx;
	int i, k, rc = -EINVAL;
	unsigned int u, hLen, l, r;
	unsigned char *p;
	size_t tmplen = Slen + 4;
	char *tmp;

	tmp = alloca(tmplen);
	if (tmp == NULL)
		return -ENOMEM;

	OpenSSL_add_all_digests();
	PRF = EVP_get_digestbyname(hash);
	if (PRF == NULL) {
		printf("pkcs5_pbkdf2: invalid hash %s\n", hash);
		return -EINVAL;
	}

	hLen = EVP_MD_size(PRF);
	if (hLen == 0 || hLen > MAX_PRF_BLOCK_LEN)
		return -EINVAL;

	if (c == 0)
		return -EINVAL;

	if (dkLen == 0)
		return -EINVAL;

	/*
	 *
	 *  Steps:
	 *
	 *     1. If dkLen > (2^32 - 1) * hLen, output "derived key too long" and
	 *        stop.
	 */

	if (dkLen > 4294967295U)
		return -EINVAL;

	/*
	 *     2. Let l be the number of hLen-octet blocks in the derived key,
	 *        rounding up, and let r be the number of octets in the last
	 *        block:
	 *
	 *                  l = CEIL (dkLen / hLen) ,
	 *                  r = dkLen - (l - 1) * hLen .
	 *
	 *        Here, CEIL (x) is the "ceiling" function, i.e. the smallest
	 *        integer greater than, or equal to, x.
	 */

	l = dkLen / hLen;
	if (dkLen % hLen)
		l++;
	r = dkLen - (l - 1) * hLen;

	/*
	 *     3. For each block of the derived key apply the function F defined
	 *        below to the password P, the salt S, the iteration count c, and
	 *        the block index to compute the block:
	 *
	 *                  T_1 = F (P, S, c, 1) ,
	 *                  T_2 = F (P, S, c, 2) ,
	 *                  ...
	 *                  T_l = F (P, S, c, l) ,
	 *
	 *        where the function F is defined as the exclusive-or sum of the
	 *        first c iterates of the underlying pseudorandom function PRF
	 *        applied to the password P and the concatenation of the salt S
	 *        and the block index i:
	 *
	 *                  F (P, S, c, i) = U_1 \xor U_2 \xor ... \xor U_c
	 *
	 *        where
	 *
	 *                  U_1 = PRF (P, S || INT (i)) ,
	 *                  U_2 = PRF (P, U_1) ,
	 *                  ...
	 *                  U_c = PRF (P, U_{c-1}) .
	 *
	 *        Here, INT (i) is a four-octet encoding of the integer i, most
	 *        significant octet first.
	 *
	 *     4. Concatenate the blocks and extract the first dkLen octets to
	 *        produce a derived key DK:
	 *
	 *                  DK = T_1 || T_2 ||  ...  || T_l<0..r-1>
	 *
	 *     5. Output the derived key DK.
	 *
	 *  Note. The construction of the function F follows a "belt-and-
	 *  suspenders" approach. The iterates U_i are computed recursively to
	 *  remove a degree of parallelism from an opponent; they are exclusive-
	 *  ored together to reduce concerns about the recursion degenerating
	 *  into a small set of values.
	 *
	 */
	HMAC_CTX_init(&ctx);

	for (i = 1; (uint) i <= l; i++) {
		memset(T, 0, hLen);

		for (u = 1; u <= c ; u++) {
			if (u == 1) {
				memcpy(tmp, S, Slen);
				tmp[Slen + 0] = (i & 0xff000000) >> 24;
				tmp[Slen + 1] = (i & 0x00ff0000) >> 16;
				tmp[Slen + 2] = (i & 0x0000ff00) >> 8;
				tmp[Slen + 3] = (i & 0x000000ff) >> 0;
				HMAC_Init_ex(&ctx, P, Plen, PRF, NULL);
				HMAC_Update(&ctx, tmp, tmplen);				
				HMAC_Final(&ctx, U, NULL);
			} else {
				HMAC(PRF, P, Plen, U, hLen, U, NULL);
			}

			for (k = 0; (uint) k < hLen; k++)
				T[k] ^= U[k];

			if (perfcheck && __PBKDF2_performance) {
				rc = 0;
				goto out;
			}

			if (perfcheck)
				__PBKDF2_global_j++;
		}
Esempio n. 24
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 = NULL, *D = NULL, *I = NULL, *p = NULL, *Ai = NULL;
    int Slen, Plen, Ilen, Ijlen;
    int i, j, u, v;
    int ret = 0;
    BIGNUM *Ij = NULL, *Bpl1 = NULL; /* These hold Ij and B + 1 */
    EVP_MD_CTX *ctx = NULL;
#ifdef  DEBUG_KEYGEN
    unsigned char *tmpout = out;
    int tmpn = n;
#endif

    ctx = EVP_MD_CTX_new();
    if (ctx == NULL)
        goto err;

#ifdef  DEBUG_KEYGEN
    fprintf(stderr, "KEYGEN DEBUG\n");
    fprintf(stderr, "ID %d, ITER %d\n", id, iter);
    fprintf(stderr, "Password (length %d):\n", passlen);
    h__dump(pass, passlen);
    fprintf(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 = OPENSSL_malloc(v);
    Ai = OPENSSL_malloc(u);
    B = 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 = OPENSSL_malloc(Ilen);
    Ij = BN_new();
    Bpl1 = BN_new();
    if (D == NULL || Ai == NULL || B == NULL || I == NULL || Ij == NULL
            || Bpl1 == NULL)
        goto err;
    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 (;;) {
        if (!EVP_DigestInit_ex(ctx, md_type, NULL)
            || !EVP_DigestUpdate(ctx, D, v)
            || !EVP_DigestUpdate(ctx, I, Ilen)
            || !EVP_DigestFinal_ex(ctx, Ai, NULL))
            goto err;
        for (j = 1; j < iter; j++) {
            if (!EVP_DigestInit_ex(ctx, md_type, NULL)
                || !EVP_DigestUpdate(ctx, Ai, u)
                || !EVP_DigestFinal_ex(ctx, Ai, NULL))
                goto err;
        }
        memcpy(out, Ai, min(n, u));
        if (u >= n) {
#ifdef DEBUG_KEYGEN
            fprintf(stderr, "Output KEY (length %d)\n", tmpn);
            h__dump(tmpout, tmpn);
#endif
            ret = 1;
            goto end;
        }
        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 */
        if (!BN_bin2bn(B, v, Bpl1))
            goto err;
        if (!BN_add_word(Bpl1, 1))
            goto err;
        for (j = 0; j < Ilen; j += v) {
            if (!BN_bin2bn(I + j, v, Ij))
                goto err;
            if (!BN_add(Ij, Ij, Bpl1))
                goto err;
            if (!BN_bn2bin(Ij, B))
                goto err;
            Ijlen = BN_num_bytes(Ij);
            /* If more than 2^(v*8) - 1 cut off MSB */
            if (Ijlen > v) {
                if (!BN_bn2bin(Ij, B))
                    goto err;
                memcpy(I + j, B + 1, v);
#ifndef PKCS12_BROKEN_KEYGEN
                /* If less than v bytes pad with zeroes */
            } else if (Ijlen < v) {
                memset(I + j, 0, v - Ijlen);
                if (!BN_bn2bin(Ij, I + j + v - Ijlen))
                    goto err;
#endif
            } else if (!BN_bn2bin(Ij, I + j))
                goto err;
        }
    }

 err:
    PKCS12err(PKCS12_F_PKCS12_KEY_GEN_UNI, ERR_R_MALLOC_FAILURE);

 end:
    OPENSSL_free(Ai);
    OPENSSL_free(B);
    OPENSSL_free(D);
    OPENSSL_free(I);
    BN_free(Ij);
    BN_free(Bpl1);
    EVP_MD_CTX_free(ctx);
    return ret;
}
Esempio n. 25
0
int int_rsa_verify(int dtype, const unsigned char *m,
			  unsigned int m_len,
			  unsigned char *rm, size_t *prm_len,
			  const unsigned char *sigbuf, size_t siglen,
			  RSA *rsa)
	{
	int i,ret=0,sigtype;
	unsigned char *s;
	X509_SIG *sig=NULL;

#ifdef OPENSSL_FIPS
	if (FIPS_mode() && !(rsa->meth->flags & RSA_FLAG_FIPS_METHOD)
			&& !(rsa->flags & RSA_FLAG_NON_FIPS_ALLOW))
		{
		RSAerr(RSA_F_INT_RSA_VERIFY, RSA_R_NON_FIPS_RSA_METHOD);
		return 0;
		}
#endif

	if (siglen != (unsigned int)RSA_size(rsa))
		{
		RSAerr(RSA_F_INT_RSA_VERIFY,RSA_R_WRONG_SIGNATURE_LENGTH);
		return(0);
		}

	if((dtype == NID_md5_sha1) && rm)
		{
		i = RSA_public_decrypt((int)siglen,
					sigbuf,rm,rsa,RSA_PKCS1_PADDING);
		if (i <= 0)
			return 0;
		*prm_len = i;
		return 1;
		}

	s=(unsigned char *)OPENSSL_malloc((unsigned int)siglen);
	if (s == NULL)
		{
		RSAerr(RSA_F_INT_RSA_VERIFY,ERR_R_MALLOC_FAILURE);
		goto err;
		}
	if((dtype == NID_md5_sha1) && (m_len != SSL_SIG_LENGTH) ) {
			RSAerr(RSA_F_INT_RSA_VERIFY,RSA_R_INVALID_MESSAGE_LENGTH);
			goto err;
	}
	i=RSA_public_decrypt((int)siglen,sigbuf,s,rsa,RSA_PKCS1_PADDING);

	if (i <= 0) goto err;
	/* Oddball MDC2 case: signature can be OCTET STRING.
	 * check for correct tag and length octets.
	 */
	if (dtype == NID_mdc2 && i == 18 && s[0] == 0x04 && s[1] == 0x10)
		{
		if (rm)
			{
			memcpy(rm, s + 2, 16);
			*prm_len = 16;
			ret = 1;
			}
		else if(memcmp(m, s + 2, 16))
			RSAerr(RSA_F_INT_RSA_VERIFY,RSA_R_BAD_SIGNATURE);
		else
			ret = 1;
		}

	/* Special case: SSL signature */
	if(dtype == NID_md5_sha1) {
		if((i != SSL_SIG_LENGTH) || memcmp(s, m, SSL_SIG_LENGTH))
				RSAerr(RSA_F_INT_RSA_VERIFY,RSA_R_BAD_SIGNATURE);
		else ret = 1;
	} else {
		const unsigned char *p=s;
		sig=d2i_X509_SIG(NULL,&p,(long)i);

		if (sig == NULL) goto err;

		/* Excess data can be used to create forgeries */
		if(p != s+i || !rsa_check_digestinfo(sig, s, i))
			{
			RSAerr(RSA_F_INT_RSA_VERIFY,RSA_R_BAD_SIGNATURE);
			goto err;
			}

		/* Parameters to the signature algorithm can also be used to
		   create forgeries */
		if(sig->algor->parameter
		   && ASN1_TYPE_get(sig->algor->parameter) != V_ASN1_NULL)
			{
			RSAerr(RSA_F_INT_RSA_VERIFY,RSA_R_BAD_SIGNATURE);
			goto err;
			}

		sigtype=OBJ_obj2nid(sig->algor->algorithm);


	#ifdef RSA_DEBUG
		/* put a backward compatibility flag in EAY */
		fprintf(stderr,"in(%s) expect(%s)\n",OBJ_nid2ln(sigtype),
			OBJ_nid2ln(dtype));
	#endif
		if (sigtype != dtype)
			{
			if (((dtype == NID_md5) &&
				(sigtype == NID_md5WithRSAEncryption)) ||
				((dtype == NID_md2) &&
				(sigtype == NID_md2WithRSAEncryption)))
				{
				/* ok, we will let it through */
#if !defined(OPENSSL_NO_STDIO) && !defined(OPENSSL_SYS_WIN16)
				fprintf(stderr,"signature has problems, re-make with post SSLeay045\n");
#endif
				}
			else
				{
				RSAerr(RSA_F_INT_RSA_VERIFY,
						RSA_R_ALGORITHM_MISMATCH);
				goto err;
				}
			}
		if (rm)
			{
			const EVP_MD *md;
			md = EVP_get_digestbynid(dtype);
			if (md && (EVP_MD_size(md) != sig->digest->length))
				RSAerr(RSA_F_INT_RSA_VERIFY,
						RSA_R_INVALID_DIGEST_LENGTH);
			else
				{
				memcpy(rm, sig->digest->data,
							sig->digest->length);
				*prm_len = sig->digest->length;
				ret = 1;
				}
			}
		else if (((unsigned int)sig->digest->length != m_len) ||
			(memcmp(m,sig->digest->data,m_len) != 0))
			{
			RSAerr(RSA_F_INT_RSA_VERIFY,RSA_R_BAD_SIGNATURE);
			}
		else
			ret=1;
	}
err:
	if (sig != NULL) X509_SIG_free(sig);
	if (s != NULL)
		{
		OPENSSL_cleanse(s,(unsigned int)siglen);
		OPENSSL_free(s);
		}
	return(ret);
	}
Esempio n. 26
0
int GTDataHash_create(int hash_algorithm,
		const unsigned char* data, size_t data_length, GTDataHash **data_hash)
{
	int res = GT_UNKNOWN_ERROR;
	EVP_MD_CTX md_ctx;
	const EVP_MD *evp_md;
	GTDataHash *tmp_data_hash = NULL;
	unsigned char* tmp_hash = NULL;
	size_t tmp_length;
	unsigned int digest_length;

	if ((data == NULL && data_length != 0) || data_hash == NULL) {
		res = GT_INVALID_ARGUMENT;
		goto cleanup;
	}

	if (!GT_isSupportedHashAlgorithm(hash_algorithm)) {
		res = GT_UNTRUSTED_HASH_ALGORITHM;
		goto cleanup;
	}

	evp_md = GT_hashChainIDToEVP(hash_algorithm);
	if (evp_md == NULL) {
		res = GT_OUT_OF_MEMORY;
		goto cleanup;
	}

	tmp_data_hash = GT_malloc(sizeof(GTDataHash));
	if (tmp_data_hash == NULL) {
		res = GT_OUT_OF_MEMORY;
		goto cleanup;
	}
	tmp_data_hash->digest = NULL;
	tmp_data_hash->context = NULL;

	tmp_length = EVP_MD_size(evp_md);
	tmp_hash = GT_malloc(tmp_length);
	if (tmp_hash == NULL) {
		res = GT_OUT_OF_MEMORY;
		goto cleanup;
	}

	EVP_DigestInit(&md_ctx, evp_md);
	EVP_DigestUpdate(&md_ctx, data, data_length);
	EVP_DigestFinal(&md_ctx, tmp_hash, &digest_length);
	assert(digest_length == tmp_length);

	tmp_data_hash->digest = tmp_hash;
	tmp_hash = NULL;
	tmp_data_hash->digest_length = tmp_length;
	tmp_data_hash->algorithm = hash_algorithm;
	*data_hash = tmp_data_hash;
	tmp_data_hash = NULL;

	res = GT_OK;

cleanup:
	GT_free(tmp_hash);
	GTDataHash_free(tmp_data_hash);

	return res;
}
/** @impl_interface_method{RTCRDIGESTDESC::pfnGetHashSize} */
static DECLCALLBACK(uint32_t) rtCrDigestOsslEvp_GetHashSize(void *pvState)
{
    EVP_MD_CTX *pThis = (EVP_MD_CTX *)pvState;
    return EVP_MD_size(EVP_MD_CTX_md(pThis));
}
int ssl3_change_cipher_state(SSL *s, int which)
	{
	unsigned char *p,*key_block,*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;
#ifndef OPENSSL_NO_COMP
	if (s->s3->tmp.new_compression == NULL)
		comp=NULL;
	else
		comp=s->s3->tmp.new_compression->method;
#endif
	key_block=s->s3->tmp.key_block;

	if (which & SSL3_CC_READ)
		{
		if (s->enc_read_ctx != NULL)
			reuse_dd = 1;
		else if ((s->enc_read_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;
		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
		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=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;
		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
		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);
	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);
	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);
	}
int tls1_setup_key_block(SSL *s)
	{
	unsigned char *p1,*p2;
	const EVP_CIPHER *c;
	const EVP_MD *hash;
	int num;
	SSL_COMP *comp;

	if (s->s3->tmp.key_block_length != 0)
		return(1);

	if (!ssl_cipher_get_evp(s->session,&c,&hash,&comp))
		{
		SSLerr(SSL_F_TLS1_SETUP_KEY_BLOCK,SSL_R_CIPHER_OR_HASH_UNAVAILABLE);
		return(0);
		}

	s->s3->tmp.new_sym_enc=c;
	s->s3->tmp.new_hash=hash;

	num=EVP_CIPHER_key_length(c)+EVP_MD_size(hash)+EVP_CIPHER_iv_length(c);
	num*=2;

	ssl3_cleanup_key_block(s);

	if ((p1=(unsigned char *)OPENSSL_malloc(num)) == NULL)
		goto err;
	if ((p2=(unsigned char *)OPENSSL_malloc(num)) == NULL)
		goto err;

	s->s3->tmp.key_block_length=num;
	s->s3->tmp.key_block=p1;


#ifdef TLS_DEBUG
printf("client random\n");
{ int z; for (z=0; z<SSL3_RANDOM_SIZE; z++) printf("%02X%c",s->s3->client_random[z],((z+1)%16)?' ':'\n'); }
printf("server random\n");
{ int z; for (z=0; z<SSL3_RANDOM_SIZE; z++) printf("%02X%c",s->s3->server_random[z],((z+1)%16)?' ':'\n'); }
printf("pre-master\n");
{ int z; for (z=0; z<s->session->master_key_length; z++) printf("%02X%c",s->session->master_key[z],((z+1)%16)?' ':'\n'); }
#endif
	tls1_generate_key_block(s,p1,p2,num);
	memset(p2,0,num);
	OPENSSL_free(p2);
#ifdef TLS_DEBUG
printf("\nkey block\n");
{ int z; for (z=0; z<num; z++) printf("%02X%c",p1[z],((z+1)%16)?' ':'\n'); }
#endif

	/* enable vulnerability countermeasure for CBC ciphers with
	 * known-IV problem (http://www.openssl.org/~bodo/tls-cbc.txt) */
	s->s3->need_empty_fragments = 1;
#ifndef NO_RC4
	if ((s->session->cipher != NULL) && ((s->session->cipher->algorithms & SSL_ENC_MASK) == SSL_RC4))
		s->s3->need_empty_fragments = 0;
#endif
		
	return(1);
err:
	SSLerr(SSL_F_TLS1_SETUP_KEY_BLOCK,ERR_R_MALLOC_FAILURE);
	return(0);
	}
Esempio n. 30
0
bool metakey_h(connection_t *c) {
	char buffer[MAX_STRING_SIZE];
	int cipher, digest, maclength, compression;
	int len;

	if(sscanf(c->buffer, "%*d %d %d %d %d " MAX_STRING, &cipher, &digest, &maclength, &compression, buffer) != 5) {
		logger(LOG_ERR, "Got bad %s from %s (%s)", "METAKEY", c->name,
		       c->hostname);
		return false;
	}

	len = RSA_size(myself->connection->rsa_key);

	/* Check if the length of the meta key is all right */

	if(strlen(buffer) != (size_t)len * 2) {
		logger(LOG_ERR, "Possible intruder %s (%s): %s", c->name, c->hostname, "wrong keylength");
		return false;
	}

	/* Allocate buffers for the meta key */

	c->inkey = xrealloc(c->inkey, len);

	if(!c->inctx) {
		c->inctx = EVP_CIPHER_CTX_new();

		if(!c->inctx) {
			abort();
		}
	}

	/* Convert the challenge from hexadecimal back to binary */

	if(!hex2bin(buffer, buffer, len)) {
		logger(LOG_ERR, "Got bad %s from %s(%s): %s", "METAKEY", c->name, c->hostname, "invalid key");
		return false;
	}

	/* Decrypt the meta key */

	if(RSA_private_decrypt(len, (unsigned char *)buffer, (unsigned char *)c->inkey, myself->connection->rsa_key, RSA_NO_PADDING) != len) {  /* See challenge() */
		logger(LOG_ERR, "Error during decryption of meta key for %s (%s): %s",
		       c->name, c->hostname, ERR_error_string(ERR_get_error(), NULL));
		return false;
	}

	ifdebug(SCARY_THINGS) {
		bin2hex(c->inkey, buffer, len);
		buffer[len * 2] = '\0';
		logger(LOG_DEBUG, "Received random meta key (unencrypted): %s", buffer);
	}

	/* All incoming requests will now be encrypted. */

	/* Check and lookup cipher and digest algorithms */

	if(cipher) {
		c->incipher = EVP_get_cipherbynid(cipher);

		if(!c->incipher) {
			logger(LOG_ERR, "%s (%s) uses unknown cipher!", c->name, c->hostname);
			return false;
		}

		if(!EVP_DecryptInit(c->inctx, c->incipher,
		                    (unsigned char *)c->inkey + len - EVP_CIPHER_key_length(c->incipher),
		                    (unsigned char *)c->inkey + len - EVP_CIPHER_key_length(c->incipher) -
		                    EVP_CIPHER_iv_length(c->incipher))) {
			logger(LOG_ERR, "Error during initialisation of cipher from %s (%s): %s",
			       c->name, c->hostname, ERR_error_string(ERR_get_error(), NULL));
			return false;
		}

		c->inbudget = byte_budget(c->incipher);
		c->status.decryptin = true;
	} else {
		logger(LOG_ERR, "%s (%s) uses null cipher!", c->name, c->hostname);
		return false;
	}

	c->inmaclength = maclength;

	if(digest) {
		c->indigest = EVP_get_digestbynid(digest);

		if(!c->indigest) {
			logger(LOG_ERR, "Node %s (%s) uses unknown digest!", c->name, c->hostname);
			return false;
		}

		if(c->inmaclength > EVP_MD_size(c->indigest) || c->inmaclength < 0) {
			logger(LOG_ERR, "%s (%s) uses bogus MAC length!", c->name, c->hostname);
			return false;
		}
	} else {
		logger(LOG_ERR, "%s (%s) uses null digest!", c->name, c->hostname);
		return false;
	}

	c->incompression = compression;

	c->allow_request = CHALLENGE;

	return send_challenge(c);
}