PKCS12_SAFEBAG *PKCS12_MAKE_SHKEYBAG(int pbe_nid, const char *pass,
	     int passlen, unsigned char *salt, int saltlen, int iter,
	     PKCS8_PRIV_KEY_INFO *p8)
{
	PKCS12_SAFEBAG *bag;
	const EVP_CIPHER *pbe_ciph;

	/* Set up the safe bag */
	if (!(bag = PKCS12_SAFEBAG_new())) {
		PKCS12err(PKCS12_F_PKCS12_MAKE_SHKEYBAG, ERR_R_MALLOC_FAILURE);
		return NULL;
	}

	bag->type = OBJ_nid2obj(NID_pkcs8ShroudedKeyBag);

	pbe_ciph = EVP_get_cipherbynid(pbe_nid);

	if (pbe_ciph)
		pbe_nid = -1;

	if (!(bag->value.shkeybag = 
	  PKCS8_encrypt(pbe_nid, pbe_ciph, pass, passlen, salt, saltlen, iter,
									 p8))) {
		PKCS12err(PKCS12_F_PKCS12_MAKE_SHKEYBAG, ERR_R_MALLOC_FAILURE);
		return NULL;
	}

	return bag;
}
PKCS12_SAFEBAG *PKCS12_SAFEBAG_create_pkcs8_encrypt(int pbe_nid,
                                                    const char *pass,
                                                    int passlen,
                                                    unsigned char *salt,
                                                    int saltlen, int iter,
                                                    PKCS8_PRIV_KEY_INFO *p8inf)
{
    PKCS12_SAFEBAG *bag;
    const EVP_CIPHER *pbe_ciph;
    X509_SIG *p8;

    pbe_ciph = EVP_get_cipherbynid(pbe_nid);
    if (pbe_ciph)
        pbe_nid = -1;

    p8 = PKCS8_encrypt(pbe_nid, pbe_ciph, pass, passlen, salt, saltlen, iter,
                       p8inf);
    if (p8 == NULL)
        return NULL;

    bag = PKCS12_SAFEBAG_create0_pkcs8(p8);
    if (bag == NULL)
        X509_SIG_free(p8);

    return bag;
}
Exemple #3
0
const EVP_CIPHER* get_cipher(lua_State*L, int idx, const char* def_alg)
{
  const EVP_CIPHER* cipher = NULL;

  switch (lua_type(L, idx))
  {
  case LUA_TSTRING:
    cipher = EVP_get_cipherbyname(lua_tostring(L, idx));
    break;
  case LUA_TNUMBER:
    cipher = EVP_get_cipherbynid(lua_tointeger(L, idx));
    break;
  case LUA_TUSERDATA:
    if (auxiliar_getclassudata(L, "openssl.asn1_object", idx))
      cipher = EVP_get_cipherbyobj(CHECK_OBJECT(idx, ASN1_OBJECT, "openssl.asn1_object"));
    else if (auxiliar_getclassudata(L, "openssl.evp_cipher", idx))
      cipher = CHECK_OBJECT(idx, EVP_CIPHER, "openssl.evp_cipher");
    break;
  case LUA_TNONE:
  case LUA_TNIL:
    if (def_alg != NULL)
      cipher = EVP_get_cipherbyname(def_alg);
    break;
  }

  if (cipher==NULL)
    luaL_argerror(L, idx, "must be a string, NID number or asn1_object identity cipher method");

  return cipher;
}
Exemple #4
0
void
show_available_ciphers ()
{
  int nid;

#ifndef ENABLE_SMALL
  printf ("The following ciphers and cipher modes are available\n"
	  "for use with " PACKAGE_NAME ".  Each cipher shown below may be\n"
	  "used as a parameter to the --cipher option.  The default\n"
	  "key size is shown as well as whether or not it can be\n"
          "changed with the --keysize directive.  Using a CBC mode\n"
	  "is recommended.\n\n");
#endif

  for (nid = 0; nid < 10000; ++nid)	/* is there a better way to get the size of the nid list? */
    {
      const EVP_CIPHER *cipher = EVP_get_cipherbynid (nid);
      if (cipher)
	{
	  const unsigned int mode = EVP_CIPHER_mode (cipher);
	  if (mode == EVP_CIPH_CBC_MODE
#ifdef ALLOW_NON_CBC_CIPHERS
	      || mode == EVP_CIPH_CFB_MODE || mode == EVP_CIPH_OFB_MODE
#endif
	      )
	    printf ("%s %d bit default key (%s)\n",
		    OBJ_nid2sn (nid),
		    EVP_CIPHER_key_length (cipher) * 8,
		    ((EVP_CIPHER_flags (cipher) & EVP_CIPH_VARIABLE_LENGTH) ?
		     "variable" : "fixed"));
	}
    }
  printf ("\n");
}
Exemple #5
0
void
show_available_ciphers(void)
{
    int nid;
    size_t i;

    /* If we ever exceed this, we must be more selective */
    const EVP_CIPHER *cipher_list[1000];
    size_t num_ciphers = 0;
#ifndef ENABLE_SMALL
    printf("The following ciphers and cipher modes are available for use\n"
           "with " PACKAGE_NAME ".  Each cipher shown below may be use as a\n"
           "parameter to the --cipher option.  The default key size is\n"
           "shown as well as whether or not it can be changed with the\n"
           "--keysize directive.  Using a CBC or GCM mode is recommended.\n"
           "In static key mode only CBC mode is allowed.\n\n");
#endif

    for (nid = 0; nid < 10000; ++nid)
    {
        const EVP_CIPHER *cipher = EVP_get_cipherbynid(nid);
        if (cipher && (cipher_kt_mode_cbc(cipher)
#ifdef ENABLE_OFB_CFB_MODE
                       || cipher_kt_mode_ofb_cfb(cipher)
#endif
#ifdef HAVE_AEAD_CIPHER_MODES
                       || cipher_kt_mode_aead(cipher)
#endif
                       ))
        {
            cipher_list[num_ciphers++] = cipher;
        }
        if (num_ciphers == (sizeof(cipher_list)/sizeof(*cipher_list)))
        {
            msg(M_WARN, "WARNING: Too many ciphers, not showing all");
            break;
        }
    }

    qsort(cipher_list, num_ciphers, sizeof(*cipher_list), cipher_name_cmp);

    for (i = 0; i < num_ciphers; i++) {
        if (!cipher_kt_insecure(cipher_list[i]))
        {
            print_cipher(cipher_list[i]);
        }
    }

    printf("\nThe following ciphers have a block size of less than 128 bits, \n"
           "and are therefore deprecated.  Do not use unless you have to.\n\n");
    for (i = 0; i < num_ciphers; i++) {
        if (cipher_kt_insecure(cipher_list[i]))
        {
            print_cipher(cipher_list[i]);
        }
    }
    printf("\n");
}
static int pbe_cipher_init(ASN1_OBJECT *pbe_obj,
                           const uint8_t *pass_raw, size_t pass_raw_len,
                           ASN1_TYPE *param,
                           EVP_CIPHER_CTX *ctx, int is_encrypt) {
  const EVP_CIPHER *cipher;
  const EVP_MD *md;
  unsigned i;

  const struct pbe_suite *suite = NULL;
  const int pbe_nid = OBJ_obj2nid(pbe_obj);

  for (i = 0; i < sizeof(kBuiltinPBE) / sizeof(struct pbe_suite); i++) {
    suite = &kBuiltinPBE[i];
    if (suite->pbe_nid == pbe_nid) {
      break;
    }
  }

  if (suite == NULL) {
    char obj_str[80];
    OPENSSL_PUT_ERROR(PKCS8, pbe_cipher_init, PKCS8_R_UNKNOWN_ALGORITHM);
    if (!pbe_obj) {
      strncpy(obj_str, "NULL", sizeof(obj_str));
    } else {
      i2t_ASN1_OBJECT(obj_str, sizeof(obj_str), pbe_obj);
    }
    ERR_add_error_data(2, "TYPE=", obj_str);
    return 0;
  }

  if (suite->cipher_nid == -1) {
    cipher = NULL;
  } else {
    cipher = EVP_get_cipherbynid(suite->cipher_nid);
    if (!cipher) {
      OPENSSL_PUT_ERROR(PKCS8, pbe_cipher_init, PKCS8_R_UNKNOWN_CIPHER);
      return 0;
    }
  }

  if (suite->md_nid == -1) {
    md = NULL;
  } else {
    md = EVP_get_digestbynid(suite->md_nid);
    if (!md) {
      OPENSSL_PUT_ERROR(PKCS8, pbe_cipher_init, PKCS8_R_UNKNOWN_DIGEST);
      return 0;
    }
  }

  if (!suite->keygen(ctx, pass_raw, pass_raw_len, param, cipher, md,
                     is_encrypt)) {
    OPENSSL_PUT_ERROR(PKCS8, pbe_cipher_init, PKCS8_R_KEYGEN_FAILURE);
    return 0;
  }

  return 1;
}
Exemple #7
0
int EVP_PBE_CipherInit(ASN1_OBJECT *pbe_obj, const char *pass, int passlen,
		       ASN1_TYPE *param, EVP_CIPHER_CTX *ctx, int en_de)
	{
	const EVP_CIPHER *cipher;
	const EVP_MD *md;
	int cipher_nid, md_nid;
	EVP_PBE_KEYGEN *keygen;

	if (!EVP_PBE_find(EVP_PBE_TYPE_OUTER, OBJ_obj2nid(pbe_obj),
					&cipher_nid, &md_nid, &keygen))
		{
		char obj_tmp[80];
		EVPerr(EVP_F_EVP_PBE_CIPHERINIT,EVP_R_UNKNOWN_PBE_ALGORITHM);
		if (!pbe_obj) BUF_strlcpy (obj_tmp, "NULL", sizeof obj_tmp);
		else i2t_ASN1_OBJECT(obj_tmp, sizeof obj_tmp, pbe_obj);
		ERR_add_error_data(2, "TYPE=", obj_tmp);
		return 0;
		}

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

	if (cipher_nid == -1)
		cipher = NULL;
	else
		{
		cipher = EVP_get_cipherbynid(cipher_nid);
		if (!cipher)
			{
			EVPerr(EVP_F_EVP_PBE_CIPHERINIT,EVP_R_UNKNOWN_CIPHER);
			return 0;
			}
		}

	if (md_nid == -1)
		md = NULL;
	else
		{
		md = EVP_get_digestbynid(md_nid);
		if (!md)
			{
			EVPerr(EVP_F_EVP_PBE_CIPHERINIT,EVP_R_UNKNOWN_DIGEST);
			return 0;
			}
		}

	if (!keygen(ctx, pass, passlen, param, cipher, md, en_de))
		{
		EVPerr(EVP_F_EVP_PBE_CIPHERINIT,EVP_R_KEYGEN_FAILURE);
		return 0;
		}
	return 1;	
}
Exemple #8
0
bool Crypto_t::symmetricCipher(const std::vector<unsigned char>& in_buffer, int nid, const std::string& key, const std::string& iv, bool encode, std::vector<unsigned char>& buffer)
{
	// load all cipher modules
	OpenSSL_add_all_ciphers();

	// Select the specific cipher module
	const EVP_CIPHER* cipher = EVP_get_cipherbynid(nid);
	if (!cipher) return false;

	// Each cipher has its own taste for the key and IV. So we need to check if the input key and IV is appropriate
	// for the specific cipher module
	if (key.size() < static_cast<size_t>(EVP_CIPHER_key_length(cipher)) || iv.size() < static_cast<size_t>(EVP_CIPHER_iv_length(cipher)))
	{
		return false;
	}

	EVP_CIPHER_CTX ctx;
	EVP_CIPHER_CTX_init(&ctx);
	EVP_CipherInit_ex(&ctx, cipher, NULL, (const unsigned char*)key.c_str(), (const unsigned char*)iv.c_str(), encode);
	size_t block_size = EVP_CIPHER_block_size(cipher);
	unsigned char* encrypt_buffer = (unsigned char*) malloc(block_size + in_buffer.size());

	// Read the raw buffer and convert to encrypt one. And then collect to the output buffer

	int out_count = 0;
	buffer.clear();
	bool fail = false;

	while (true)
	{
		if (!EVP_CipherUpdate(&ctx, encrypt_buffer, &out_count, &in_buffer[0], in_buffer.size()))
		{
			fail = true;
			break;
		}
		for (int i = 0; i < out_count; i++)
			buffer.push_back(encrypt_buffer[i]);

		// handling the last block
		unsigned char* block = encrypt_buffer + out_count;
		if (!EVP_CipherFinal_ex(&ctx, block, &out_count))
		{
			fail = true;
			break;
		}
		for (int i = 0; i < out_count; i++)
			buffer.push_back(block[i]);
		break;
	}

	// free resource
	free(encrypt_buffer);
	EVP_CIPHER_CTX_cleanup(&ctx);
	return (fail == true) ? (false) : (true);
}
Exemple #9
0
static void
get_EVP_CIPHER_once_cb(void *d)
{
    struct once_init_cipher_ctx *arg = d;
    const EVP_CIPHER *ossl_evp;
    hc_EVP_CIPHER *hc_evp;

    hc_evp = arg->hc_memoize;

    /*
     * We lookup EVP_CIPHER *s by NID so that we don't fail to find a
     * symbol such as EVP_aes...() when libcrypto changes after build
     * time (e.g., updates, LD_LIBRARY_PATH/LD_PRELOAD).
     */
    ossl_evp = EVP_get_cipherbynid(arg->nid);
    if (ossl_evp == NULL) {
        (void) memset(hc_evp, 0, sizeof(*hc_evp));
#if HCRYPTO_FALLBACK
        *arg->hc_memoizep = arg->fallback;
#endif
        return;
    }

    /* Build the hc_EVP_CIPHER */
    hc_evp->nid = EVP_CIPHER_nid(ossl_evp); /* We would an hcrypto NIDs if we had them */
    hc_evp->block_size = EVP_CIPHER_block_size(ossl_evp);
    hc_evp->key_len = EVP_CIPHER_key_length(ossl_evp);
    hc_evp->iv_len = EVP_CIPHER_iv_length(ossl_evp);

    /*
     * We force hc_EVP_CipherInit_ex to always call our init() function,
     * otherwise we don't get a chance to call EVP_CipherInit_ex()
     * correctly.
     */
    hc_evp->flags = hc_EVP_CIPH_ALWAYS_CALL_INIT | arg->flags;

    /* Our cipher context */
    hc_evp->ctx_size = sizeof(struct ossl_cipher_ctx);

    /* Our wrappers */
    hc_evp->init = cipher_ctx_init;
    hc_evp->do_cipher = cipher_do_cipher;
    hc_evp->cleanup = cipher_cleanup;
    hc_evp->set_asn1_parameters = NULL;
    hc_evp->get_asn1_parameters = NULL;
    hc_evp->ctrl = cipher_ctrl;

    /* Our link to the OpenSSL EVP_CIPHER */
    hc_evp->app_data = (void *)ossl_evp;

    /* Finally, set the static hc_EVP_CIPHER * to the one we just built */
    *arg->hc_memoizep = hc_evp;
}
Exemple #10
0
CipherContext *crypto_decrypt_init(Encryption *params) {
    EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
    if (!ctx) crypto_handle_error();

    int nid = crypto_get_cipher_nid(params->algorithm, params->mode);
    const EVP_CIPHER *cipher = EVP_get_cipherbynid(nid);

    unsigned char key[64], iv[64];
    crypto_get_key(cipher, params->password, key, iv);

    if (EVP_DecryptInit_ex(ctx, cipher, NULL, key, iv) != 1) crypto_handle_error();

    return ctx;
}
Exemple #11
0
/** Returns the OpenSSL keyblock size
 *
 * @copyright (c) 2002-2016, Jouni Malinen <*****@*****.**> and contributors
 * All Rights Reserved.
 *
 * These programs are licensed under the BSD license (the one with
 * advertisement clause removed).
 *
 * this function shamelessly stolen from from
 * hostap:src/crypto/tls_openssl.c:openssl_get_keyblock_size()
 *
 * @param[in] request The current request.
 * @param[in] ssl The current SSL session.
 * @return
 *	- -1 problem with the session.
 *	- >=0 length of the block.
 */
int tls_utils_keyblock_size_get(REQUEST *request, SSL *ssl)
{
	const EVP_CIPHER *c;
	const EVP_MD *h;
#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
	int md_size;

	if (ssl->enc_read_ctx == NULL || ssl->enc_read_ctx->cipher == NULL || ssl->read_hash == NULL)
		return -1;

	c = ssl->enc_read_ctx->cipher;
	h = EVP_MD_CTX_md(ssl->read_hash);
	if (h)
		md_size = EVP_MD_size(h);
	else if (ssl->s3)
		md_size = ssl->s3->tmp.new_mac_secret_size;
	else
		return -1;

	RDEBUG2("OpenSSL: keyblock size: key_len=%d MD_size=%d "
		   "IV_len=%d", EVP_CIPHER_key_length(c), md_size,
		   EVP_CIPHER_iv_length(c));
	return 2 * (EVP_CIPHER_key_length(c) +
		    md_size +
		    EVP_CIPHER_iv_length(c));
#else
	const SSL_CIPHER *ssl_cipher;
	int cipher, digest;

	ssl_cipher = SSL_get_current_cipher(ssl);
	if (!ssl_cipher)
		return -1;
	cipher = SSL_CIPHER_get_cipher_nid(ssl_cipher);
	digest = SSL_CIPHER_get_digest_nid(ssl_cipher);
	RDEBUG2("OpenSSL: cipher nid %d digest nid %d", cipher, digest);
	if (cipher < 0 || digest < 0)
		return -1;
	c = EVP_get_cipherbynid(cipher);
	h = EVP_get_digestbynid(digest);
	if (!c || !h)
		return -1;

	RDEBUG2("OpenSSL: keyblock size: key_len=%d MD_size=%d IV_len=%d",
		   EVP_CIPHER_key_length(c), EVP_MD_size(h),
		   EVP_CIPHER_iv_length(c));
	return 2 * (EVP_CIPHER_key_length(c) + EVP_MD_size(h) +
		    EVP_CIPHER_iv_length(c));
#endif
}
void
show_available_ciphers ()
{
  int nid;

#ifndef ENABLE_SMALL
  printf ("The following ciphers and cipher modes are available for use\n"
	  "with " PACKAGE_NAME ".  Each cipher shown below may be use as a\n"
	  "parameter to the --cipher option.  The default key size is\n"
	  "shown as well as whether or not it can be changed with the\n"
          "--keysize directive.  Using a CBC or GCM mode is recommended.\n"
	  "In static key mode only CBC mode is allowed.\n\n");
#endif

  for (nid = 0; nid < 10000; ++nid)	/* is there a better way to get the size of the nid list? */
    {
      const EVP_CIPHER *cipher = EVP_get_cipherbynid (nid);
      if (cipher)
	{
	  if (cipher_kt_mode_cbc(cipher)
#ifdef ENABLE_OFB_CFB_MODE
	      || cipher_kt_mode_ofb_cfb(cipher)
#endif
#ifdef HAVE_AEAD_CIPHER_MODES
	      || cipher_kt_mode_aead(cipher)
#endif
	      )
	    {
	      const char *var_key_size =
		  (EVP_CIPHER_flags (cipher) & EVP_CIPH_VARIABLE_LENGTH) ?
		       "variable" : "fixed";
	      const char *ssl_only = cipher_kt_mode_cbc(cipher) ?
		  "" : " (TLS client/server mode)";

	      printf ("%s %d bit default key (%s)%s\n",
		  translate_cipher_name_to_openvpn(OBJ_nid2sn (nid)),
		  EVP_CIPHER_key_length (cipher) * 8, var_key_size, ssl_only);
	    }
	}
    }
  printf ("\n");
}
Exemple #13
0
const EVP_CIPHER* get_cipher(lua_State*L, int idx, const char* def_alg)
{
    const EVP_CIPHER* cipher = NULL;
    if (lua_isstring(L, idx))
        cipher = EVP_get_cipherbyname(lua_tostring(L, idx));
    else if (lua_isnumber(L, idx))
        cipher = EVP_get_cipherbynid(lua_tointeger(L, idx));
    else if (auxiliar_isclass(L, "openssl.asn1_object", idx))
        cipher = EVP_get_cipherbyobj(CHECK_OBJECT(1, ASN1_OBJECT, "openssl.asn1_object"));
    else if (auxiliar_isclass(L, "openssl.evp_cipher", idx))
        cipher = CHECK_OBJECT(idx, EVP_CIPHER, "openssl.evp_cipher");
    else if (lua_isnoneornil(L, idx) && def_alg)
        cipher = EVP_get_cipherbyname(def_alg);
    else
        luaL_argerror(L, idx, "must be a string, NID number or asn1_object identity cipher method");
    if (cipher == NULL)
        luaL_argerror(L, idx, "not valid cipher alg");

    return cipher;
}
Exemple #14
0
/* This equivalent functionality was submitted for OpenSSL 1.1.1+ in
 * https://github.com/openssl/openssl/pull/1666 */
static int dtls_get_data_mtu(struct openconnect_info *vpninfo, int mtu)
{
	int ivlen, maclen, blocksize = 0, pad = 0;
#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER)
	const SSL_CIPHER *s_ciph = SSL_get_current_cipher(vpninfo->dtls_ssl);
	int cipher_nid;
	const EVP_CIPHER *e_ciph;
	const EVP_MD *e_md;
	char wtf[128];

	cipher_nid = SSL_CIPHER_get_cipher_nid(s_ciph);
	if (cipher_nid == NID_chacha20_poly1305) {
		ivlen = 0; /* Automatically derived from handshake and seqno */
		maclen = 16; /* Poly1305 */
	} else {
		e_ciph = EVP_get_cipherbynid(cipher_nid);
		switch (EVP_CIPHER_mode(e_ciph)) {
		case EVP_CIPH_GCM_MODE:
			ivlen = EVP_GCM_TLS_EXPLICIT_IV_LEN;
			maclen = EVP_GCM_TLS_TAG_LEN;
			break;

		case EVP_CIPH_CCM_MODE:
			ivlen = EVP_CCM_TLS_EXPLICIT_IV_LEN;
			SSL_CIPHER_description(s_ciph, wtf, sizeof(wtf));
			if (strstr(wtf, "CCM8"))
				maclen = 8;
			else
				maclen = 16;
			break;

		case EVP_CIPH_CBC_MODE:
			blocksize = EVP_CIPHER_block_size(e_ciph);
			ivlen = EVP_CIPHER_iv_length(e_ciph);
			pad = 1;

			e_md = EVP_get_digestbynid(SSL_CIPHER_get_digest_nid(s_ciph));
			maclen = EVP_MD_size(e_md);
			break;

		default:
			vpn_progress(vpninfo, PRG_ERR,
				     _("Unable to calculate DTLS overhead for %s\n"),
				     SSL_CIPHER_get_name(s_ciph));
			ivlen = 0;
			maclen = DTLS_OVERHEAD;
			break;
		}
	}
#else
	/* OpenSSL <= 1.0.2 only supports CBC ciphers with PSK */
	ivlen = EVP_CIPHER_iv_length(EVP_CIPHER_CTX_cipher(vpninfo->dtls_ssl->enc_read_ctx));
	maclen = EVP_MD_CTX_size(vpninfo->dtls_ssl->read_hash);
	blocksize = ivlen;
	pad = 1;
#endif

	/* Even when it pretended to, OpenSSL never did encrypt-then-mac.
	 * So the MAC is *inside* the encryption, unconditionally.
	 * https://github.com/openssl/openssl/pull/1705 */
	if (mtu < DTLS1_RT_HEADER_LENGTH + ivlen)
		return 0;
	mtu -= DTLS1_RT_HEADER_LENGTH + ivlen;

	/* For CBC mode round down to blocksize */
	if (blocksize)
		mtu -= mtu % blocksize;

	/* Finally, CBC modes require at least one byte to indicate
	 * padding length, as well as the MAC. */
	if (mtu < pad + maclen)
		return 0;
	mtu -= pad + maclen;
	return mtu;
}
Exemple #15
0
bool ans_key_h(connection_t *c) {
	char from_name[MAX_STRING_SIZE];
	char to_name[MAX_STRING_SIZE];
	char key[MAX_STRING_SIZE];
	char address[MAX_STRING_SIZE] = "";
	char port[MAX_STRING_SIZE] = "";
	int cipher, digest, maclength, compression;
	node_t *from, *to;

	if(sscanf(c->buffer, "%*d "MAX_STRING" "MAX_STRING" "MAX_STRING" %d %d %d %d "MAX_STRING" "MAX_STRING,
		from_name, to_name, key, &cipher, &digest, &maclength,
		&compression, address, port) < 7) {
		logger(LOG_ERR, "Got bad %s from %s (%s)", "ANS_KEY", c->name,
			   c->hostname);
		return false;
	}

	if(!check_id(from_name) || !check_id(to_name)) {
		logger(LOG_ERR, "Got bad %s from %s (%s): %s", "ANS_KEY", c->name, c->hostname, "invalid name");
		return false;
	}

	from = lookup_node(from_name);

	if(!from) {
		logger(LOG_ERR, "Got %s from %s (%s) origin %s which does not exist in our connection list",
			   "ANS_KEY", c->name, c->hostname, from_name);
		return true;
	}

	to = lookup_node(to_name);

	if(!to) {
		logger(LOG_ERR, "Got %s from %s (%s) destination %s which does not exist in our connection list",
			   "ANS_KEY", c->name, c->hostname, to_name);
		return true;
	}

	/* Forward it if necessary */

	if(to != myself) {
		if(tunnelserver)
			return true;

		if(!to->status.reachable) {
			logger(LOG_WARNING, "Got %s from %s (%s) destination %s which is not reachable",
				"ANS_KEY", c->name, c->hostname, to_name);
			return true;
		}

		if(!*address && from->address.sa.sa_family != AF_UNSPEC) {
			char *address, *port;
			ifdebug(PROTOCOL) logger(LOG_DEBUG, "Appending reflexive UDP address to ANS_KEY from %s to %s", from->name, to->name);
			sockaddr2str(&from->address, &address, &port);
			send_request(to->nexthop->connection, "%s %s %s", c->buffer, address, port);
			free(address);
			free(port);
			return true;
		}

		return send_request(to->nexthop->connection, "%s", c->buffer);
	}

	/* Update our copy of the origin's packet key */
	from->outkey = xrealloc(from->outkey, strlen(key) / 2);
	from->outkeylength = strlen(key) / 2;
	hex2bin(key, from->outkey, from->outkeylength);

	/* Check and lookup cipher and digest algorithms */

	if(cipher) {
		from->outcipher = EVP_get_cipherbynid(cipher);

		if(!from->outcipher) {
			logger(LOG_ERR, "Node %s (%s) uses unknown cipher!", from->name,
				   from->hostname);
			return true;
		}

		if(from->outkeylength != from->outcipher->key_len + from->outcipher->iv_len) {
			logger(LOG_ERR, "Node %s (%s) uses wrong keylength!", from->name,
				   from->hostname);
			return true;
		}
	} else {
		from->outcipher = NULL;
	}

	from->outmaclength = maclength;

	if(digest) {
		from->outdigest = EVP_get_digestbynid(digest);

		if(!from->outdigest) {
			logger(LOG_ERR, "Node %s (%s) uses unknown digest!", from->name,
				   from->hostname);
			return true;
		}

		if(from->outmaclength > from->outdigest->md_size || from->outmaclength < 0) {
			logger(LOG_ERR, "Node %s (%s) uses bogus MAC length!",
				   from->name, from->hostname);
			return true;
		}
	} else {
		from->outdigest = NULL;
	}

	if(compression < 0 || compression > 11) {
		logger(LOG_ERR, "Node %s (%s) uses bogus compression level!", from->name, from->hostname);
		return true;
	}
	
	from->outcompression = compression;

	if(from->outcipher)
		if(!EVP_EncryptInit_ex(&from->outctx, from->outcipher, NULL, (unsigned char *)from->outkey, (unsigned char *)from->outkey + from->outcipher->key_len)) {
			logger(LOG_ERR, "Error during initialisation of key from %s (%s): %s",
					from->name, from->hostname, ERR_error_string(ERR_get_error(), NULL));
			return true;
		}

	from->status.validkey = true;
	from->sent_seqno = 0;

	if(*address && *port) {
		ifdebug(PROTOCOL) logger(LOG_DEBUG, "Using reflexive UDP address from %s: %s port %s", from->name, address, port);
		sockaddr_t sa = str2sockaddr(address, port);
		update_node_udp(from, &sa);
	}

	if(from->options & OPTION_PMTU_DISCOVERY && !from->mtuevent)
		send_mtu_probe(from);

	return true;
}
Exemple #16
0
int OTP_generate(const OTP_PARAMS *params, const void *event, size_t eventlen,
	unsigned int *otp, const unsigned char *key, size_t keylen)
{
	int ret = 0;
	time_t t = 0;
	unsigned char *id = NULL;
	size_t idlen;
	const EVP_MD *md;
	const EVP_CIPHER *cipher;
	EVP_MD_CTX *mdctx = NULL;
	CMAC_CTX *cmctx = NULL;
	unsigned char s[EVP_MAX_MD_SIZE];
	size_t slen;
	uint32_t od;
	int i, n;

	OPENSSL_assert(sizeof(time_t) == 8);

	if (!check_params(params)) {
		OTPerr(OTP_F_OTP_GENERATE, OTP_R_INVALID_PARAMS);
		return 0;
	}

	idlen = sizeof(uint64_t) + eventlen + params->option_size;
	if (idlen < 16) {
		idlen = 16;
	}
	if (!(id = OPENSSL_malloc(idlen))) {
		OTPerr(OTP_F_OTP_GENERATE, ERR_R_MALLOC_FAILURE);
		goto end;
	}
	memset(id, 0, idlen);

	t = time(NULL) + params->offset;
	t /= params->te;

	memcpy(id, &t, sizeof(t));
	memcpy(id + sizeof(t), event, eventlen);
	memcpy(id + sizeof(t) + eventlen, params->option, params->option_size);


	/* FIXME: try to get md and cipher, and check if cipher is ECB */
	if (params->type == NID_sm3) {
		md = EVP_get_digestbynid(params->type);
		if (!(mdctx = EVP_MD_CTX_new())) {
			OTPerr(OTP_F_OTP_GENERATE, ERR_R_MALLOC_FAILURE);
			goto end;
		}
		if (!EVP_DigestInit_ex(mdctx, md, NULL)) {
			OTPerr(OTP_F_OTP_GENERATE, ERR_R_EVP_LIB);
			goto end;
		}
		if (!EVP_DigestUpdate(mdctx, key, keylen)) {
			OTPerr(OTP_F_OTP_GENERATE, ERR_R_EVP_LIB);
			goto end;
		}
		if (!EVP_DigestUpdate(mdctx, id, idlen)) {
			OTPerr(OTP_F_OTP_GENERATE, ERR_R_EVP_LIB);
			goto end;
		}
		if (!EVP_DigestFinal_ex(mdctx, s, (unsigned int *)&slen)) {
			OTPerr(OTP_F_OTP_GENERATE, ERR_R_EVP_LIB);
			goto end;
		}
	} else if (params->type == NID_sms4_ecb) {
		cipher = EVP_get_cipherbynid(params->type);
		if (!(cmctx = CMAC_CTX_new())) {
			OTPerr(OTP_F_OTP_GENERATE, ERR_R_MALLOC_FAILURE);
			goto end;
		}
		if (!CMAC_Init(cmctx, key, keylen, cipher, NULL)) {
			OTPerr(OTP_F_OTP_GENERATE, OTP_R_CMAC_FAILURE);
			goto end;
		}
		if (!CMAC_Update(cmctx, id, idlen)) {
			OTPerr(OTP_F_OTP_GENERATE, OTP_R_CMAC_FAILURE);
			goto end;
		}
		if (!CMAC_Final(cmctx, s, &slen)) {
			OTPerr(OTP_F_OTP_GENERATE, OTP_R_CMAC_FAILURE);
			goto end;
		}
	} else {
		goto end;
	}
	OPENSSL_assert(slen % 4 == 0);

	od = 0;

	n = (int)slen;
	for (i = 0; i < n/4; i++) {
		od += GETU32(&s[i * 4]);
	}

	*otp = od % pow_table[params->otp_digits];
	ret = 1;
end:
	OPENSSL_free(id);
	EVP_MD_CTX_free(mdctx);
	CMAC_CTX_free(cmctx);
	return ret;
}
Exemple #17
0
int tls13_change_cipher_state(SSL *s, int which)
{
    static const unsigned char client_early_traffic[] = "c e traffic";
    static const unsigned char client_handshake_traffic[] = "c hs traffic";
    static const unsigned char client_application_traffic[] = "c ap traffic";
    static const unsigned char server_handshake_traffic[] = "s hs traffic";
    static const unsigned char server_application_traffic[] = "s ap traffic";
    static const unsigned char exporter_master_secret[] = "exp master";
    static const unsigned char resumption_master_secret[] = "res master";
    static const unsigned char early_exporter_master_secret[] = "e exp master";
    unsigned char *iv;
    unsigned char secret[EVP_MAX_MD_SIZE];
    unsigned char hashval[EVP_MAX_MD_SIZE];
    unsigned char *hash = hashval;
    unsigned char *insecret;
    unsigned char *finsecret = NULL;
    const char *log_label = NULL;
    EVP_CIPHER_CTX *ciph_ctx;
    size_t finsecretlen = 0;
    const unsigned char *label;
    size_t labellen, hashlen = 0;
    int ret = 0;
    const EVP_MD *md = NULL;
    const EVP_CIPHER *cipher = NULL;

    if (which & SSL3_CC_READ) {
        if (s->enc_read_ctx != NULL) {
            EVP_CIPHER_CTX_reset(s->enc_read_ctx);
        } else {
            s->enc_read_ctx = EVP_CIPHER_CTX_new();
            if (s->enc_read_ctx == NULL) {
                SSLfatal(s, SSL_AD_INTERNAL_ERROR,
                         SSL_F_TLS13_CHANGE_CIPHER_STATE, ERR_R_MALLOC_FAILURE);
                goto err;
            }
        }
        ciph_ctx = s->enc_read_ctx;
        iv = s->read_iv;

        RECORD_LAYER_reset_read_sequence(&s->rlayer);
    } else {
        s->statem.enc_write_state = ENC_WRITE_STATE_INVALID;
        if (s->enc_write_ctx != NULL) {
            EVP_CIPHER_CTX_reset(s->enc_write_ctx);
        } else {
            s->enc_write_ctx = EVP_CIPHER_CTX_new();
            if (s->enc_write_ctx == NULL) {
                SSLfatal(s, SSL_AD_INTERNAL_ERROR,
                         SSL_F_TLS13_CHANGE_CIPHER_STATE, ERR_R_MALLOC_FAILURE);
                goto err;
            }
        }
        ciph_ctx = s->enc_write_ctx;
        iv = s->write_iv;

        RECORD_LAYER_reset_write_sequence(&s->rlayer);
    }

    if (((which & SSL3_CC_CLIENT) && (which & SSL3_CC_WRITE))
            || ((which & SSL3_CC_SERVER) && (which & SSL3_CC_READ))) {
        if (which & SSL3_CC_EARLY) {
            EVP_MD_CTX *mdctx = NULL;
            long handlen;
            void *hdata;
            unsigned int hashlenui;
            const SSL_CIPHER *sslcipher = SSL_SESSION_get0_cipher(s->session);

            insecret = s->early_secret;
            label = client_early_traffic;
            labellen = sizeof(client_early_traffic) - 1;
            log_label = CLIENT_EARLY_LABEL;

            handlen = BIO_get_mem_data(s->s3->handshake_buffer, &hdata);
            if (handlen <= 0) {
                SSLfatal(s, SSL_AD_INTERNAL_ERROR,
                         SSL_F_TLS13_CHANGE_CIPHER_STATE,
                         SSL_R_BAD_HANDSHAKE_LENGTH);
                goto err;
            }

            if (s->early_data_state == SSL_EARLY_DATA_CONNECTING
                    && s->max_early_data > 0
                    && s->session->ext.max_early_data == 0) {
                /*
                 * If we are attempting to send early data, and we've decided to
                 * actually do it but max_early_data in s->session is 0 then we
                 * must be using an external PSK.
                 */
                if (!ossl_assert(s->psksession != NULL
                        && s->max_early_data ==
                           s->psksession->ext.max_early_data)) {
                    SSLfatal(s, SSL_AD_INTERNAL_ERROR,
                             SSL_F_TLS13_CHANGE_CIPHER_STATE,
                             ERR_R_INTERNAL_ERROR);
                    goto err;
                }
                sslcipher = SSL_SESSION_get0_cipher(s->psksession);
            }
            if (sslcipher == NULL) {
                SSLfatal(s, SSL_AD_INTERNAL_ERROR,
                         SSL_F_TLS13_CHANGE_CIPHER_STATE, SSL_R_BAD_PSK);
                goto err;
            }

            /*
             * We need to calculate the handshake digest using the digest from
             * the session. We haven't yet selected our ciphersuite so we can't
             * use ssl_handshake_md().
             */
            mdctx = EVP_MD_CTX_new();
            if (mdctx == NULL) {
                SSLfatal(s, SSL_AD_INTERNAL_ERROR,
                         SSL_F_TLS13_CHANGE_CIPHER_STATE, ERR_R_MALLOC_FAILURE);
                goto err;
            }
            cipher = EVP_get_cipherbynid(SSL_CIPHER_get_cipher_nid(sslcipher));
            md = ssl_md(sslcipher->algorithm2);
            if (md == NULL || !EVP_DigestInit_ex(mdctx, md, NULL)
                    || !EVP_DigestUpdate(mdctx, hdata, handlen)
                    || !EVP_DigestFinal_ex(mdctx, hashval, &hashlenui)) {
                SSLfatal(s, SSL_AD_INTERNAL_ERROR,
                         SSL_F_TLS13_CHANGE_CIPHER_STATE, ERR_R_INTERNAL_ERROR);
                EVP_MD_CTX_free(mdctx);
                goto err;
            }
            hashlen = hashlenui;
            EVP_MD_CTX_free(mdctx);

            if (!tls13_hkdf_expand(s, md, insecret,
                                   early_exporter_master_secret,
                                   sizeof(early_exporter_master_secret) - 1,
                                   hashval, hashlen,
                                   s->early_exporter_master_secret, hashlen,
                                   1)) {
                SSLfatal(s, SSL_AD_INTERNAL_ERROR,
                         SSL_F_TLS13_CHANGE_CIPHER_STATE, ERR_R_INTERNAL_ERROR);
                goto err;
            }

            if (!ssl_log_secret(s, EARLY_EXPORTER_SECRET_LABEL,
                                s->early_exporter_master_secret, hashlen)) {
                /* SSLfatal() already called */
                goto err;
            }
        } else if (which & SSL3_CC_HANDSHAKE) {
            insecret = s->handshake_secret;
            finsecret = s->client_finished_secret;
            finsecretlen = EVP_MD_size(ssl_handshake_md(s));
            label = client_handshake_traffic;
            labellen = sizeof(client_handshake_traffic) - 1;
            log_label = CLIENT_HANDSHAKE_LABEL;
            /*
             * The handshake hash used for the server read/client write handshake
             * traffic secret is the same as the hash for the server
             * write/client read handshake traffic secret. However, if we
             * processed early data then we delay changing the server
             * read/client write cipher state until later, and the handshake
             * hashes have moved on. Therefore we use the value saved earlier
             * when we did the server write/client read change cipher state.
             */
            hash = s->handshake_traffic_hash;
        } else {
            insecret = s->master_secret;
            label = client_application_traffic;
            labellen = sizeof(client_application_traffic) - 1;
            log_label = CLIENT_APPLICATION_LABEL;
            /*
             * For this we only use the handshake hashes up until the server
             * Finished hash. We do not include the client's Finished, which is
             * what ssl_handshake_hash() would give us. Instead we use the
             * previously saved value.
             */
            hash = s->server_finished_hash;
        }
    } else {
        /* Early data never applies to client-read/server-write */
        if (which & SSL3_CC_HANDSHAKE) {
            insecret = s->handshake_secret;
            finsecret = s->server_finished_secret;
            finsecretlen = EVP_MD_size(ssl_handshake_md(s));
            label = server_handshake_traffic;
            labellen = sizeof(server_handshake_traffic) - 1;
            log_label = SERVER_HANDSHAKE_LABEL;
        } else {
            insecret = s->master_secret;
            label = server_application_traffic;
            labellen = sizeof(server_application_traffic) - 1;
            log_label = SERVER_APPLICATION_LABEL;
        }
    }

    if (!(which & SSL3_CC_EARLY)) {
        md = ssl_handshake_md(s);
        cipher = s->s3->tmp.new_sym_enc;
        if (!ssl3_digest_cached_records(s, 1)
                || !ssl_handshake_hash(s, hashval, sizeof(hashval), &hashlen)) {
            /* SSLfatal() already called */;
            goto err;
        }
    }

    /*
     * Save the hash of handshakes up to now for use when we calculate the
     * client application traffic secret
     */
    if (label == server_application_traffic)
        memcpy(s->server_finished_hash, hashval, hashlen);

    if (label == server_handshake_traffic)
        memcpy(s->handshake_traffic_hash, hashval, hashlen);

    if (label == client_application_traffic) {
        /*
         * We also create the resumption master secret, but this time use the
         * hash for the whole handshake including the Client Finished
         */
        if (!tls13_hkdf_expand(s, ssl_handshake_md(s), insecret,
                               resumption_master_secret,
                               sizeof(resumption_master_secret) - 1,
                               hashval, hashlen, s->resumption_master_secret,
                               hashlen, 1)) {
            /* SSLfatal() already called */
            goto err;
        }
    }

    if (!derive_secret_key_and_iv(s, which & SSL3_CC_WRITE, md, cipher,
                                  insecret, hash, label, labellen, secret, iv,
                                  ciph_ctx)) {
        /* SSLfatal() already called */
        goto err;
    }

    if (label == server_application_traffic) {
        memcpy(s->server_app_traffic_secret, secret, hashlen);
        /* Now we create the exporter master secret */
        if (!tls13_hkdf_expand(s, ssl_handshake_md(s), insecret,
                               exporter_master_secret,
                               sizeof(exporter_master_secret) - 1,
                               hash, hashlen, s->exporter_master_secret,
                               hashlen, 1)) {
            /* SSLfatal() already called */
            goto err;
        }

        if (!ssl_log_secret(s, EXPORTER_SECRET_LABEL, s->exporter_master_secret,
                            hashlen)) {
            /* SSLfatal() already called */
            goto err;
        }
    } else if (label == client_application_traffic)
        memcpy(s->client_app_traffic_secret, secret, hashlen);

    if (!ssl_log_secret(s, log_label, secret, hashlen)) {
        /* SSLfatal() already called */
        goto err;
    }

    if (finsecret != NULL
            && !tls13_derive_finishedkey(s, ssl_handshake_md(s), secret,
                                         finsecret, finsecretlen)) {
        /* SSLfatal() already called */
        goto err;
    }

    if (!s->server && label == client_early_traffic)
        s->statem.enc_write_state = ENC_WRITE_STATE_WRITE_PLAIN_ALERTS;
    else
        s->statem.enc_write_state = ENC_WRITE_STATE_VALID;
    ret = 1;
 err:
    OPENSSL_cleanse(secret, sizeof(secret));
    return ret;
}
Exemple #18
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);
}