Exemple #1
0
static int secdl_verify_mac(server *srv, plugin_config *config, const char* protected_path, const char* mac, size_t maclen) {
	UNUSED(srv);
	if (0 == maclen || secdl_algorithm_mac_length(config->algorithm) != maclen) return 0;

	switch (config->algorithm) {
	case SECDL_INVALID:
		break;
	case SECDL_MD5:
		{
			li_MD5_CTX Md5Ctx;
			HASH HA1;
			char hexmd5[33];
			const char *ts_str;
			const char *rel_uri;

			/* legacy message:
			 *   protected_path := '/' <timestamp-hex> <rel-path>
			 *   timestamp-hex := [0-9a-f]{8}
			 *   rel-path := '/' any*
			 *   (the protected path was already verified)
			 * message = <secret><rel-path><timestamp-hex>
			 */
			ts_str = protected_path + 1;
			rel_uri = ts_str + 8;

			li_MD5_Init(&Md5Ctx);
			li_MD5_Update(&Md5Ctx, CONST_BUF_LEN(config->secret));
			li_MD5_Update(&Md5Ctx, rel_uri, strlen(rel_uri));
			li_MD5_Update(&Md5Ctx, ts_str, 8);
			li_MD5_Final(HA1, &Md5Ctx);

			li_tohex(hexmd5, sizeof(hexmd5), (const char *)HA1, 16);

			return (32 == maclen) && const_time_memeq(mac, hexmd5, 32);
		}
	case SECDL_HMAC_SHA1:
#ifdef USE_OPENSSL_CRYPTO
		{
			unsigned char digest[20];
			char base64_digest[27];

			if (NULL == HMAC(
					EVP_sha1(),
					(unsigned char const*) CONST_BUF_LEN(config->secret),
					(unsigned char const*) protected_path, strlen(protected_path),
					digest, NULL)) {
				log_error_write(srv, __FILE__, __LINE__, "s",
					"hmac-sha1: HMAC() failed");
				return 0;
			}

			li_to_base64_no_padding(base64_digest, 27, digest, 20, BASE64_URL);

			return (27 == maclen) && const_time_memeq(mac, base64_digest, 27);
		}
#endif
		break;
	case SECDL_HMAC_SHA256:
#ifdef USE_OPENSSL_CRYPTO
		{
			unsigned char digest[32];
			char base64_digest[43];

			if (NULL == HMAC(
					EVP_sha256(),
					(unsigned char const*) CONST_BUF_LEN(config->secret),
					(unsigned char const*) protected_path, strlen(protected_path),
					digest, NULL)) {
				log_error_write(srv, __FILE__, __LINE__, "s",
					"hmac-sha256: HMAC() failed");
				return 0;
			}

			li_to_base64_no_padding(base64_digest, 43, digest, 32, BASE64_URL);

			return (43 == maclen) && const_time_memeq(mac, base64_digest, 43);
		}
#endif
		break;
	}

	return 0;
}
Exemple #2
0
/*
  Configure node_t myself and set up the local sockets (listen only)
*/
static bool setup_myself(void) {
	config_t *cfg;
	subnet_t *subnet;
	char *name, *hostname, *mode, *afname, *cipher, *digest, *type;
	char *fname = NULL;
	char *address = NULL;
	char *proxy = NULL;
	char *space;
	char *envp[5] = {NULL};
	struct addrinfo *ai, *aip, hint = {0};
	bool choice;
	int i, err;
	int replaywin_int;
	bool port_specified = false;

	myself = new_node();
	myself->connection = new_connection();

	myself->hostname = xstrdup("MYSELF");
	myself->connection->hostname = xstrdup("MYSELF");

	myself->connection->options = 0;
	myself->connection->protocol_version = PROT_CURRENT;

	if(!(name = get_name())) {
		logger(LOG_ERR, "Name for tinc daemon required!");
		return false;
	}

	/* Read tinc.conf and our own host config file */

	myself->name = name;
	myself->connection->name = xstrdup(name);
	xasprintf(&fname, "%s/hosts/%s", confbase, name);
	read_config_options(config_tree, name);
	read_config_file(config_tree, fname);
	free(fname);

	if(!read_rsa_private_key())
		return false;

	if(!get_config_string(lookup_config(config_tree, "Port"), &myport))
		myport = xstrdup("655");
	else
		port_specified = true;

	/* Ensure myport is numeric */

	if(!atoi(myport)) {
		struct addrinfo *ai = str2addrinfo("localhost", myport, SOCK_DGRAM);
		sockaddr_t sa;
		if(!ai || !ai->ai_addr)
			return false;
		free(myport);
		memcpy(&sa, ai->ai_addr, ai->ai_addrlen);
		sockaddr2str(&sa, NULL, &myport);
	}

	if(get_config_string(lookup_config(config_tree, "Proxy"), &proxy)) {
		if((space = strchr(proxy, ' ')))
			*space++ = 0;

		if(!strcasecmp(proxy, "none")) {
			proxytype = PROXY_NONE;
		} else if(!strcasecmp(proxy, "socks4")) {
			proxytype = PROXY_SOCKS4;
		} else if(!strcasecmp(proxy, "socks4a")) {
			proxytype = PROXY_SOCKS4A;
		} else if(!strcasecmp(proxy, "socks5")) {
			proxytype = PROXY_SOCKS5;
		} else if(!strcasecmp(proxy, "http")) {
			proxytype = PROXY_HTTP;
		} else if(!strcasecmp(proxy, "exec")) {
			proxytype = PROXY_EXEC;
		} else {
			logger(LOG_ERR, "Unknown proxy type %s!", proxy);
			free(proxy);
			return false;
		}

		switch(proxytype) {
			case PROXY_NONE:
			default:
				break;

			case PROXY_EXEC:
				if(!space || !*space) {
					logger(LOG_ERR, "Argument expected for proxy type exec!");
					free(proxy);
					return false;
				}
				proxyhost =  xstrdup(space);
				break;

			case PROXY_SOCKS4:
			case PROXY_SOCKS4A:
			case PROXY_SOCKS5:
			case PROXY_HTTP:
				proxyhost = space;
				if(space && (space = strchr(space, ' ')))
					*space++ = 0, proxyport = space;
				if(space && (space = strchr(space, ' ')))
					*space++ = 0, proxyuser = space;
				if(space && (space = strchr(space, ' ')))
					*space++ = 0, proxypass = space;
				if(!proxyhost || !*proxyhost || !proxyport || !*proxyport) {
					logger(LOG_ERR, "Host and port argument expected for proxy!");
					free(proxy);
					return false;
				}
				proxyhost = xstrdup(proxyhost);
				proxyport = xstrdup(proxyport);
				if(proxyuser && *proxyuser)
					proxyuser = xstrdup(proxyuser);
				if(proxypass && *proxypass)
					proxypass = xstrdup(proxypass);
				break;
		}

		free(proxy);
	}

	/* Read in all the subnets specified in the host configuration file */

	cfg = lookup_config(config_tree, "Subnet");

	while(cfg) {
		if(!get_config_subnet(cfg, &subnet))
			return false;

		subnet_add(myself, subnet);

		cfg = lookup_config_next(config_tree, cfg);
	}

	/* Check some options */

	if(get_config_bool(lookup_config(config_tree, "IndirectData"), &choice) && choice)
		myself->options |= OPTION_INDIRECT;

	if(get_config_bool(lookup_config(config_tree, "TCPOnly"), &choice) && choice)
		myself->options |= OPTION_TCPONLY;

	if(myself->options & OPTION_TCPONLY)
		myself->options |= OPTION_INDIRECT;

	get_config_bool(lookup_config(config_tree, "DirectOnly"), &directonly);
	get_config_bool(lookup_config(config_tree, "StrictSubnets"), &strictsubnets);
	get_config_bool(lookup_config(config_tree, "TunnelServer"), &tunnelserver);
	get_config_bool(lookup_config(config_tree, "LocalDiscovery"), &localdiscovery);
	strictsubnets |= tunnelserver;

	if(get_config_string(lookup_config(config_tree, "Mode"), &mode)) {
		if(!strcasecmp(mode, "router"))
			routing_mode = RMODE_ROUTER;
		else if(!strcasecmp(mode, "switch"))
			routing_mode = RMODE_SWITCH;
		else if(!strcasecmp(mode, "hub"))
			routing_mode = RMODE_HUB;
		else {
			logger(LOG_ERR, "Invalid routing mode!");
			free(mode);
			return false;
		}
		free(mode);
	}

	if(get_config_string(lookup_config(config_tree, "Forwarding"), &mode)) {
		if(!strcasecmp(mode, "off"))
			forwarding_mode = FMODE_OFF;
		else if(!strcasecmp(mode, "internal"))
			forwarding_mode = FMODE_INTERNAL;
		else if(!strcasecmp(mode, "kernel"))
			forwarding_mode = FMODE_KERNEL;
		else {
			logger(LOG_ERR, "Invalid forwarding mode!");
			free(mode);
			return false;
		}
		free(mode);
	}

	choice = true;
	get_config_bool(lookup_config(config_tree, "PMTUDiscovery"), &choice);
	if(choice)
		myself->options |= OPTION_PMTU_DISCOVERY;

	choice = true;
	get_config_bool(lookup_config(config_tree, "ClampMSS"), &choice);
	if(choice)
		myself->options |= OPTION_CLAMP_MSS;

	get_config_bool(lookup_config(config_tree, "PriorityInheritance"), &priorityinheritance);
	get_config_bool(lookup_config(config_tree, "DecrementTTL"), &decrement_ttl);
	if(get_config_string(lookup_config(config_tree, "Broadcast"), &mode)) {
		if(!strcasecmp(mode, "no"))
			broadcast_mode = BMODE_NONE;
		else if(!strcasecmp(mode, "yes") || !strcasecmp(mode, "mst"))
			broadcast_mode = BMODE_MST;
		else if(!strcasecmp(mode, "direct"))
			broadcast_mode = BMODE_DIRECT;
		else {
			logger(LOG_ERR, "Invalid broadcast mode!");
			free(mode);
			return false;
		}
		free(mode);
	}

#if !defined(SOL_IP) || !defined(IP_TOS)
	if(priorityinheritance)
		logger(LOG_WARNING, "%s not supported on this platform", "PriorityInheritance");
#endif

	if(!get_config_int(lookup_config(config_tree, "MACExpire"), &macexpire))
		macexpire = 600;

	if(get_config_int(lookup_config(config_tree, "MaxTimeout"), &maxtimeout)) {
		if(maxtimeout <= 0) {
			logger(LOG_ERR, "Bogus maximum timeout!");
			return false;
		}
	} else
		maxtimeout = 900;

	if(get_config_int(lookup_config(config_tree, "UDPRcvBuf"), &udp_rcvbuf)) {
		if(udp_rcvbuf <= 0) {
			logger(LOG_ERR, "UDPRcvBuf cannot be negative!");
			return false;
		}
	}

	if(get_config_int(lookup_config(config_tree, "UDPSndBuf"), &udp_sndbuf)) {
		if(udp_sndbuf <= 0) {
			logger(LOG_ERR, "UDPSndBuf cannot be negative!");
			return false;
		}
	}

	if(get_config_int(lookup_config(config_tree, "ReplayWindow"), &replaywin_int)) {
		if(replaywin_int < 0) {
			logger(LOG_ERR, "ReplayWindow cannot be negative!");
			return false;
		}
		replaywin = (unsigned)replaywin_int;
	}

	if(get_config_string(lookup_config(config_tree, "AddressFamily"), &afname)) {
		if(!strcasecmp(afname, "IPv4"))
			addressfamily = AF_INET;
		else if(!strcasecmp(afname, "IPv6"))
			addressfamily = AF_INET6;
		else if(!strcasecmp(afname, "any"))
			addressfamily = AF_UNSPEC;
		else {
			logger(LOG_ERR, "Invalid address family!");
			free(afname);
			return false;
		}
		free(afname);
	}

	get_config_bool(lookup_config(config_tree, "Hostnames"), &hostnames);

	/* Generate packet encryption key */

	if(get_config_string(lookup_config(config_tree, "Cipher"), &cipher)) {
		if(!strcasecmp(cipher, "none")) {
			myself->incipher = NULL;
		} else {
			myself->incipher = EVP_get_cipherbyname(cipher);

			if(!myself->incipher) {
				logger(LOG_ERR, "Unrecognized cipher type!");
				free(cipher);
				return false;
			}
		}
		free(cipher);
	} else
		myself->incipher = EVP_bf_cbc();

	if(myself->incipher)
		myself->inkeylength = myself->incipher->key_len + myself->incipher->iv_len;
	else
		myself->inkeylength = 1;

	myself->connection->outcipher = EVP_bf_ofb();

	if(!get_config_int(lookup_config(config_tree, "KeyExpire"), &keylifetime))
		keylifetime = 3600;

	keyexpires = now + keylifetime;
	
	/* Check if we want to use message authentication codes... */

	if(get_config_string(lookup_config(config_tree, "Digest"), &digest)) {
		if(!strcasecmp(digest, "none")) {
			myself->indigest = NULL;
		} else {
			myself->indigest = EVP_get_digestbyname(digest);

			if(!myself->indigest) {
				logger(LOG_ERR, "Unrecognized digest type!");
				free(digest);
				return false;
			}
		}

		free(digest);
	} else
		myself->indigest = EVP_sha1();

	myself->connection->outdigest = EVP_sha1();

	if(get_config_int(lookup_config(config_tree, "MACLength"), &myself->inmaclength)) {
		if(myself->indigest) {
			if(myself->inmaclength > myself->indigest->md_size) {
				logger(LOG_ERR, "MAC length exceeds size of digest!");
				return false;
			} else if(myself->inmaclength < 0) {
				logger(LOG_ERR, "Bogus MAC length!");
				return false;
			}
		}
	} else
		myself->inmaclength = 4;

	myself->connection->outmaclength = 0;

	/* Compression */

	if(get_config_int(lookup_config(config_tree, "Compression"), &myself->incompression)) {
		if(myself->incompression < 0 || myself->incompression > 11) {
			logger(LOG_ERR, "Bogus compression level!");
			return false;
		}
	} else
		myself->incompression = 0;

	myself->connection->outcompression = 0;

	/* Done */

	myself->nexthop = myself;
	myself->via = myself;
	myself->status.reachable = true;
	node_add(myself);

	graph();

	if(strictsubnets)
		load_all_subnets();

	/* Open device */

	devops = os_devops;

	if(get_config_string(lookup_config(config_tree, "DeviceType"), &type)) {
		if(!strcasecmp(type, "dummy"))
			devops = dummy_devops;
		else if(!strcasecmp(type, "raw_socket"))
			devops = raw_socket_devops;
		else if(!strcasecmp(type, "multicast"))
			devops = multicast_devops;
#ifdef ENABLE_UML
		else if(!strcasecmp(type, "uml"))
			devops = uml_devops;
#endif
#ifdef ENABLE_VDE
		else if(!strcasecmp(type, "vde"))
			devops = vde_devops;
#endif
		free(type);
	}

	if(!devops.setup())
		return false;

	/* Run tinc-up script to further initialize the tap interface */
	xasprintf(&envp[0], "NETNAME=%s", netname ? : "");
	xasprintf(&envp[1], "DEVICE=%s", device ? : "");
	xasprintf(&envp[2], "INTERFACE=%s", iface ? : "");
	xasprintf(&envp[3], "NAME=%s", myself->name);

#ifdef HAVE_MINGW
	Sleep(1000);
#endif
#ifdef HAVE_CYGWIN
	sleep(1);
#endif
	execute_script("tinc-up", envp);

	for(i = 0; i < 4; i++)
		free(envp[i]);

	/* Run subnet-up scripts for our own subnets */

	subnet_update(myself, NULL, true);

	/* Open sockets */

	if(!do_detach && getenv("LISTEN_FDS")) {
		sockaddr_t sa;
		socklen_t salen;

		listen_sockets = atoi(getenv("LISTEN_FDS"));
#ifdef HAVE_UNSETENV
		unsetenv("LISTEN_FDS");
#endif

		if(listen_sockets > MAXSOCKETS) {
			logger(LOG_ERR, "Too many listening sockets");
			return false;
		}

		for(i = 0; i < listen_sockets; i++) {
			salen = sizeof sa;
			if(getsockname(i + 3, &sa.sa, &salen) < 0) {
				logger(LOG_ERR, "Could not get address of listen fd %d: %s", i + 3, sockstrerror(errno));
				return false;
			}

			listen_socket[i].tcp = i + 3;

#ifdef FD_CLOEXEC
		        fcntl(i + 3, F_SETFD, FD_CLOEXEC);
#endif

			listen_socket[i].udp = setup_vpn_in_socket(&sa);
			if(listen_socket[i].udp < 0)
				return false;

			ifdebug(CONNECTIONS) {
				hostname = sockaddr2hostname(&sa);
				logger(LOG_NOTICE, "Listening on %s", hostname);
				free(hostname);
			}

			memcpy(&listen_socket[i].sa, &sa, salen);
		}
	} else {
Exemple #3
0
void pki_evp::encryptKey(const char *password)
{
	int outl, keylen;
	EVP_PKEY *pkey1 = NULL;
	EVP_CIPHER_CTX ctx;
	const EVP_CIPHER *cipher = EVP_des_ede3_cbc();
	unsigned char iv[EVP_MAX_IV_LENGTH], *punenc, *punenc1;
	unsigned char ckey[EVP_MAX_KEY_LENGTH];
	char ownPassBuf[MAX_PASS_LENGTH];

	/* This key has its own, private password */
	if (ownPass == ptPrivate) {
		int ret;
		pass_info p(XCA_TITLE, tr("Please enter the password to protect the private key: '%1'").
			arg(getIntName()));
		ret = MainWindow::passWrite(ownPassBuf, MAX_PASS_LENGTH, 0, &p);
		if (ret < 0)
			throw errorEx("Password input aborted", class_name);
	} else if (ownPass == ptBogus) { // BOGUS password
		ownPassBuf[0] = '\0';
	} else {
		if (password) {
			/* use the password parameter if this is a common password */
			strncpy(ownPassBuf, password, MAX_PASS_LENGTH);
		} else {
			int ret = 0;
			memcpy(ownPassBuf, passwd, MAX_PASS_LENGTH);
			pass_info p(XCA_TITLE, tr("Please enter the database password for encrypting the key"));
			while (md5passwd(ownPassBuf) != passHash &&
				sha512passwd(ownPassBuf, passHash) != passHash )
			{
				ret = MainWindow::passRead(ownPassBuf, MAX_PASS_LENGTH, 0,&p);
				if (ret < 0)
					throw errorEx("Password input aborted", class_name);
			}
		}
	}

	/* Prepare Encryption */
	memset(iv, 0, EVP_MAX_IV_LENGTH);
	RAND_pseudo_bytes(iv,8);      /* Generate a salt */
	EVP_BytesToKey(cipher, EVP_sha1(), iv, (unsigned char *)ownPassBuf,
			strlen(ownPassBuf), 1, ckey, NULL);
	EVP_CIPHER_CTX_init (&ctx);
	pki_openssl_error();

	/* reserve space for unencrypted and encrypted key */
	keylen = i2d_PrivateKey(key, NULL);
	encKey.resize(keylen + EVP_MAX_KEY_LENGTH + 8);
	punenc1 = punenc = (unsigned char *)OPENSSL_malloc(keylen);
	check_oom(punenc);
	keylen = i2d_PrivateKey(key, &punenc1);
	pki_openssl_error();

	memcpy(encKey.data(), iv, 8); /* store the iv */
	/*
	 * Now DER version of privkey is in punenc
	 * and privkey is still in key
	 */

	/* do the encryption */
	/* store key right after the iv */
	EVP_EncryptInit(&ctx, cipher, ckey, iv);
	unsigned char *penc = (unsigned char *)encKey.data() +8;
	EVP_EncryptUpdate(&ctx, penc, &outl, punenc, keylen);
	int encKey_len = outl;
	EVP_EncryptFinal(&ctx, penc + encKey_len, &outl);
	encKey.resize(encKey_len + outl +8);
	/* Cleanup */
	EVP_CIPHER_CTX_cleanup(&ctx);
	/* wipe out the memory */
	memset(punenc, 0, keylen);
	OPENSSL_free(punenc);
	pki_openssl_error();

	pkey1 = priv2pub(key);
	check_oom(pkey1);
	EVP_PKEY_free(key);
	key = pkey1;
	pki_openssl_error();

	//CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_OFF);

	//printf("Encrypt: encKey_len=%d\n", encKey_len);
	return;
}
Exemple #4
0
static int
pkey_rsa_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
{
	RSA_PKEY_CTX *rctx = ctx->data;

	switch (type) {
	case EVP_PKEY_CTRL_RSA_PADDING:
		if (p1 >= RSA_PKCS1_PADDING && p1 <= RSA_PKCS1_PSS_PADDING) {
			if (!check_padding_md(rctx->md, p1))
				return 0;
			if (p1 == RSA_PKCS1_PSS_PADDING) {
				if (!(ctx->operation &
				    (EVP_PKEY_OP_SIGN | EVP_PKEY_OP_VERIFY)))
					goto bad_pad;
				if (!rctx->md)
					rctx->md = EVP_sha1();
			}
			if (p1 == RSA_PKCS1_OAEP_PADDING) {
				if (!(ctx->operation & EVP_PKEY_OP_TYPE_CRYPT))
					goto bad_pad;
				if (!rctx->md)
					rctx->md = EVP_sha1();
			}
			rctx->pad_mode = p1;
			return 1;
		}
bad_pad:
		RSAerr(RSA_F_PKEY_RSA_CTRL,
		    RSA_R_ILLEGAL_OR_UNSUPPORTED_PADDING_MODE);
		return -2;

	case EVP_PKEY_CTRL_GET_RSA_PADDING:
		*(int *)p2 = rctx->pad_mode;
		return 1;

	case EVP_PKEY_CTRL_RSA_PSS_SALTLEN:
	case EVP_PKEY_CTRL_GET_RSA_PSS_SALTLEN:
		if (rctx->pad_mode != RSA_PKCS1_PSS_PADDING) {
			RSAerr(RSA_F_PKEY_RSA_CTRL, RSA_R_INVALID_PSS_SALTLEN);
			return -2;
		}
		if (type == EVP_PKEY_CTRL_GET_RSA_PSS_SALTLEN)
			*(int *)p2 = rctx->saltlen;
		else {
			if (p1 < -2)
				return -2;
			rctx->saltlen = p1;
		}
		return 1;

	case EVP_PKEY_CTRL_RSA_KEYGEN_BITS:
		if (p1 < 256) {
			RSAerr(RSA_F_PKEY_RSA_CTRL, RSA_R_INVALID_KEYBITS);
			return -2;
		}
		rctx->nbits = p1;
		return 1;

	case EVP_PKEY_CTRL_RSA_KEYGEN_PUBEXP:
		if (!p2)
			return -2;
		rctx->pub_exp = p2;
		return 1;

	case EVP_PKEY_CTRL_MD:
		if (!check_padding_md(p2, rctx->pad_mode))
			return 0;
		rctx->md = p2;
		return 1;

	case EVP_PKEY_CTRL_RSA_MGF1_MD:
	case EVP_PKEY_CTRL_GET_RSA_MGF1_MD:
		if (rctx->pad_mode != RSA_PKCS1_PSS_PADDING) {
			RSAerr(RSA_F_PKEY_RSA_CTRL, RSA_R_INVALID_MGF1_MD);
			return -2;
		}
		if (type == EVP_PKEY_CTRL_GET_RSA_MGF1_MD) {
			if (rctx->mgf1md)
				*(const EVP_MD **)p2 = rctx->mgf1md;
			else
				*(const EVP_MD **)p2 = rctx->md;
		} else
			rctx->mgf1md = p2;
		return 1;

	case EVP_PKEY_CTRL_DIGESTINIT:
	case EVP_PKEY_CTRL_PKCS7_ENCRYPT:
	case EVP_PKEY_CTRL_PKCS7_DECRYPT:
	case EVP_PKEY_CTRL_PKCS7_SIGN:
		return 1;
#ifndef OPENSSL_NO_CMS
	case EVP_PKEY_CTRL_CMS_DECRYPT:
		{
			X509_ALGOR *alg = NULL;
			ASN1_OBJECT *encalg = NULL;

			if (p2)
				CMS_RecipientInfo_ktri_get0_algs(p2, NULL,
				    NULL, &alg);
			if (alg)
				X509_ALGOR_get0(&encalg, NULL, NULL, alg);
			if (encalg && OBJ_obj2nid(encalg) == NID_rsaesOaep)
				rctx->pad_mode = RSA_PKCS1_OAEP_PADDING;
		}
		/* FALLTHROUGH */

	case EVP_PKEY_CTRL_CMS_ENCRYPT:
	case EVP_PKEY_CTRL_CMS_SIGN:
		return 1;
#endif
	case EVP_PKEY_CTRL_PEER_KEY:
		RSAerr(RSA_F_PKEY_RSA_CTRL,
		    RSA_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
		return -2;

	default:
		return -2;
	}
}
Exemple #5
0
/*
 * Create a fake X509v3 certificate, signed by the provided CA,
 * based on the original certificate retrieved from the real server.
 * The returned certificate is created using X509_new() and thus must
 * be freed by the caller using X509_free().
 * The optional argument extraname is added to subjectAltNames if provided.
 */
X509 *
ssl_x509_forge(X509 *cacrt, EVP_PKEY *cakey, X509 *origcrt,
               const char *extraname, EVP_PKEY *key)
{
	X509_NAME *subject, *issuer;
	GENERAL_NAMES *names;
	GENERAL_NAME *gn;
	X509 *crt;

	subject = X509_get_subject_name(origcrt);
	issuer = X509_get_subject_name(cacrt);
	if (!subject || !issuer)
		return NULL;

	crt = X509_new();
	if (!crt)
		return NULL;

	if (!X509_set_version(crt, 0x02) ||
	    !X509_set_subject_name(crt, subject) ||
	    !X509_set_issuer_name(crt, issuer) ||
	    ssl_x509_serial_copyrand(crt, origcrt) == -1 ||
	    !X509_gmtime_adj(X509_get_notBefore(crt), (long)-60*60*24) ||
	    !X509_gmtime_adj(X509_get_notAfter(crt), (long)60*60*24*364) ||
	    !X509_set_pubkey(crt, key))
		goto errout;

	/* add standard v3 extensions; cf. RFC 2459 */
	X509V3_CTX ctx;
	X509V3_set_ctx(&ctx, cacrt, crt, NULL, NULL, 0);
	if (ssl_x509_v3ext_add(&ctx, crt, "basicConstraints",
	                                  "CA:FALSE") == -1 ||
	    ssl_x509_v3ext_add(&ctx, crt, "keyUsage",
	                                  "digitalSignature,"
	                                  "keyEncipherment") == -1 ||
	    ssl_x509_v3ext_add(&ctx, crt, "extendedKeyUsage",
	                                  "serverAuth") == -1 ||
	    ssl_x509_v3ext_add(&ctx, crt, "subjectKeyIdentifier",
	                                  "hash") == -1 ||
	    ssl_x509_v3ext_add(&ctx, crt, "authorityKeyIdentifier",
	                                  "keyid,issuer:always") == -1)
		goto errout;

	if (!extraname) {
		/* no extraname provided: copy original subjectAltName ext */
		if (ssl_x509_v3ext_copy_by_nid(crt, origcrt,
		                               NID_subject_alt_name) == -1)
			goto errout;
	} else {
		names = X509_get_ext_d2i(origcrt, NID_subject_alt_name, 0, 0);
		if (!names) {
			/* no subjectAltName present: add new one */
			char *cfval;
			if (asprintf(&cfval, "DNS:%s", extraname) < 0)
				goto errout;
			if (ssl_x509_v3ext_add(&ctx, crt, "subjectAltName",
			                       cfval) == -1) {
				free(cfval);
				goto errout;
			}
			free(cfval);
		} else {
			/* add extraname to original subjectAltName
			 * and add it to the new certificate */
			gn = GENERAL_NAME_new();
			if (!gn)
				goto errout2;
			gn->type = GEN_DNS;
			gn->d.dNSName = M_ASN1_IA5STRING_new();
			if (!gn->d.dNSName)
				goto errout3;
			ASN1_STRING_set(gn->d.dNSName,
			                (unsigned char *)extraname,
			                strlen(extraname));
			sk_GENERAL_NAME_push(names, gn);
			X509_EXTENSION *ext = X509V3_EXT_i2d(
			                      NID_subject_alt_name, 0, names);
			if (!X509_add_ext(crt, ext, -1)) {
				if (ext) {
					X509_EXTENSION_free(ext);
				}
				goto errout3;
			}
			X509_EXTENSION_free(ext);
			sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
		}
	}
#ifdef DEBUG_CERTIFICATE
	ssl_x509_v3ext_add(&ctx, crt, "nsComment", "Generated by " PNAME);
#endif /* DEBUG_CERTIFICATE */

	const EVP_MD *md;
	switch (EVP_PKEY_type(cakey->type)) {
#ifndef OPENSSL_NO_RSA
		case EVP_PKEY_RSA:
			md = EVP_sha1();
			break;
#endif /* !OPENSSL_NO_RSA */
#ifndef OPENSSL_NO_DSA
		case EVP_PKEY_DSA:
			md = EVP_dss1();
			break;
#endif /* !OPENSSL_NO_DSA */
#ifndef OPENSSL_NO_ECDSA
		case EVP_PKEY_EC:
			md = EVP_ecdsa();
			break;
#endif /* !OPENSSL_NO_ECDSA */
		default:
			goto errout;
	}
	if (!X509_sign(crt, cakey, md))
		goto errout;

	return crt;

errout3:
	GENERAL_NAME_free(gn);
errout2:
	sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
errout:
	X509_free(crt);
	return NULL;
}
Exemple #6
0
static int ssl3_prf(const SSL *ssl, uint8_t *out, size_t out_len,
                    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) {
  EVP_MD_CTX md5;
  EVP_MD_CTX sha1;
  uint8_t buf[16], smd[SHA_DIGEST_LENGTH];
  uint8_t c = 'A';
  size_t i, j, k;

  k = 0;
  EVP_MD_CTX_init(&md5);
  EVP_MD_CTX_init(&sha1);
  for (i = 0; i < out_len; i += MD5_DIGEST_LENGTH) {
    k++;
    if (k > sizeof(buf)) {
      /* bug: 'buf' is too small for this ciphersuite */
      OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
      return 0;
    }

    for (j = 0; j < k; j++) {
      buf[j] = c;
    }
    c++;
    if (!EVP_DigestInit_ex(&sha1, EVP_sha1(), NULL)) {
      OPENSSL_PUT_ERROR(SSL, ERR_LIB_EVP);
      return 0;
    }
    EVP_DigestUpdate(&sha1, buf, k);
    EVP_DigestUpdate(&sha1, secret, secret_len);
    /* |label| is ignored for SSLv3. */
    if (seed1_len) {
      EVP_DigestUpdate(&sha1, seed1, seed1_len);
    }
    if (seed2_len) {
      EVP_DigestUpdate(&sha1, seed2, seed2_len);
    }
    EVP_DigestFinal_ex(&sha1, smd, NULL);

    if (!EVP_DigestInit_ex(&md5, EVP_md5(), NULL)) {
      OPENSSL_PUT_ERROR(SSL, ERR_LIB_EVP);
      return 0;
    }
    EVP_DigestUpdate(&md5, secret, secret_len);
    EVP_DigestUpdate(&md5, smd, SHA_DIGEST_LENGTH);
    if (i + MD5_DIGEST_LENGTH > out_len) {
      EVP_DigestFinal_ex(&md5, smd, NULL);
      memcpy(out, smd, out_len - i);
    } else {
      EVP_DigestFinal_ex(&md5, out, NULL);
    }

    out += MD5_DIGEST_LENGTH;
  }

  OPENSSL_cleanse(smd, SHA_DIGEST_LENGTH);
  EVP_MD_CTX_cleanup(&md5);
  EVP_MD_CTX_cleanup(&sha1);

  return 1;
}
bool PaymentRequestPlus::getMerchant(X509_STORE* certStore, QString& merchant) const
{
    merchant.clear();

    if (!IsInitialized())
        return false;

    // One day we'll support more PKI types, but just
    // x509 for now:
    const EVP_MD* digestAlgorithm = NULL;
    if (paymentRequest.pki_type() == "x509+sha256") {
        digestAlgorithm = EVP_sha256();
    }
    else if (paymentRequest.pki_type() == "x509+sha1") {
        digestAlgorithm = EVP_sha1();
    }
    else if (paymentRequest.pki_type() == "none") {
        qDebug() << "PaymentRequestPlus::getMerchant : Payment request: pki_type == none";
        return false;
    }
    else {
        qDebug() << "PaymentRequestPlus::getMerchant : Payment request: unknown pki_type " << QString::fromStdString(paymentRequest.pki_type());
        return false;
    }

    payments::X509Certificates certChain;
    if (!certChain.ParseFromString(paymentRequest.pki_data())) {
        qDebug() << "PaymentRequestPlus::getMerchant : Payment request: error parsing pki_data";
        return false;
    }

    std::vector<X509*> certs;
    const QDateTime currentTime = QDateTime::currentDateTime();
    for (int i = 0; i < certChain.certificate_size(); i++) {
        QByteArray certData(certChain.certificate(i).data(), certChain.certificate(i).size());
        QSslCertificate qCert(certData, QSsl::Der);
        if (currentTime < qCert.effectiveDate() || currentTime > qCert.expiryDate()) {
            qDebug() << "PaymentRequestPlus::getMerchant : Payment request: certificate expired or not yet active: " << qCert;
            return false;
        }
#if QT_VERSION >= 0x050000
        if (qCert.isBlacklisted()) {
            qDebug() << "PaymentRequestPlus::getMerchant : Payment request: certificate blacklisted: " << qCert;
            return false;
        }
#endif
        const unsigned char *data = (const unsigned char *)certChain.certificate(i).data();
        X509 *cert = d2i_X509(NULL, &data, certChain.certificate(i).size());
        if (cert)
            certs.push_back(cert);
    }
    if (certs.empty()) {
        qDebug() << "PaymentRequestPlus::getMerchant : Payment request: empty certificate chain";
        return false;
    }

    // The first cert is the signing cert, the rest are untrusted certs that chain
    // to a valid root authority. OpenSSL needs them separately.
    STACK_OF(X509) *chain = sk_X509_new_null();
    for (int i = certs.size()-1; i > 0; i--) {
        sk_X509_push(chain, certs[i]);
    }
    X509 *signing_cert = certs[0];

    // Now create a "store context", which is a single use object for checking,
    // load the signing cert into it and verify.
    X509_STORE_CTX *store_ctx = X509_STORE_CTX_new();
    if (!store_ctx) {
        qDebug() << "PaymentRequestPlus::getMerchant : Payment request: error creating X509_STORE_CTX";
        return false;
    }

    char *website = NULL;
    bool fResult = true;
    try
    {
        if (!X509_STORE_CTX_init(store_ctx, certStore, signing_cert, chain))
        {
            int error = X509_STORE_CTX_get_error(store_ctx);
            throw SSLVerifyError(X509_verify_cert_error_string(error));
        }

        // Now do the verification!
        int result = X509_verify_cert(store_ctx);
        if (result != 1) {
            int error = X509_STORE_CTX_get_error(store_ctx);
            throw SSLVerifyError(X509_verify_cert_error_string(error));
        }
        X509_NAME *certname = X509_get_subject_name(signing_cert);

        // Valid cert; check signature:
        payments::PaymentRequest rcopy(paymentRequest); // Copy
        rcopy.set_signature(std::string(""));
        std::string data_to_verify;                     // Everything but the signature
        rcopy.SerializeToString(&data_to_verify);

        EVP_MD_CTX ctx;
        EVP_PKEY *pubkey = X509_get_pubkey(signing_cert);
        EVP_MD_CTX_init(&ctx);
        if (!EVP_VerifyInit_ex(&ctx, digestAlgorithm, NULL) ||
            !EVP_VerifyUpdate(&ctx, data_to_verify.data(), data_to_verify.size()) ||
            !EVP_VerifyFinal(&ctx, (const unsigned char*)paymentRequest.signature().data(), paymentRequest.signature().size(), pubkey)) {

            throw SSLVerifyError("Bad signature, invalid PaymentRequest.");
        }

        // OpenSSL API for getting human printable strings from certs is baroque.
        int textlen = X509_NAME_get_text_by_NID(certname, NID_commonName, NULL, 0);
        website = new char[textlen + 1];
        if (X509_NAME_get_text_by_NID(certname, NID_commonName, website, textlen + 1) == textlen && textlen > 0) {
            merchant = website;
        }
        else {
            throw SSLVerifyError("Bad certificate, missing common name.");
        }
        // TODO: detect EV certificates and set merchant = business name instead of unfriendly NID_commonName ?
    }
    catch (SSLVerifyError& err)
    {
        fResult = false;
        qDebug() << "PaymentRequestPlus::getMerchant : SSL error: " << err.what();
    }

    if (website)
        delete[] website;
    X509_STORE_CTX_free(store_ctx);
    for (unsigned int i = 0; i < certs.size(); i++)
        X509_free(certs[i]);

    return fResult;
}
Exemple #8
0
int main() {

	unsigned char ordinal[4] = { 0x00, 0x00, 0x00, 0x17 };

	HMAC_CTX hmac;

	unsigned char shared_secret[20] = { 0x42, 0xAC ,0xAF, 0xF1, 0xD4 ,0x99, 0x3C, 0xCA, 0xC9, 0x00, 0x3C, 0xCA, 0xC8, 0x00, 0x3C, 0xCA, 0xC8, 0x00, 0x3C, 0xCA };
	unsigned char hashDigest[20] = { 0x6F, 0x02, 0x98, 0x86, 0x25, 0x8C, 0xAF, 0x9F, 0xC2, 0x4A, 0x70, 0x6B, 0xBD, 0x44, 0xBC, 0x5E, 0x57, 0xD8, 0x32, 0xA1 };
	unsigned char even[20] = { 0x76, 0xF4, 0x26, 0x85, 0xF4, 0x8E, 0x33, 0x3B, 0x9B, 0x8B, 0xBA, 0xCF, 0x8D, 0x12, 0x42, 0x39, 0x7F, 0x8A, 0xC3, 0x23 };
	unsigned char odd[20] = { 0xFE, 0x26, 0x68, 0x4C, 0x27, 0xB6, 0x50, 0x2A, 0xEC, 0x90, 0x85, 0xAA, 0xD9, 0x80, 0x38, 0x13, 0x9C, 0xD6, 0xE5, 0xBF };
	//unsigned char h[20] = { 0x6B, 0xB0, 0x85, 0x4C, 0xA0, 0x9C, 0xAF, 0x9C, 0x3C, 0xCC, 0xA5, 0x57, 0x30, 0x85, 0xB9, 0x5F, 0x7B, 0x85, 0xE9, 0xCB };
	unsigned char new_h[20] = { 0x00 };
	unsigned char new_h2[20] = { 0x00 };
	unsigned char xor_key[20] = { 0x00 };
	unsigned char encrypted_secret[20] = { 0x00 };
	unsigned char secret_key[20] = { 0x00 };
	unsigned char shared[20] = { 0x00 };
	unsigned char cont = 0x00;

	unsigned char osapEven[20] = { 0x03 ,0xF0 ,0x02 ,0xB6, 0xA9 ,0x2C ,0x48 ,0xAE, 0x3E ,0x0E ,0xEA ,0xA1, 0x47 ,0x5C ,0x3D ,0x21, 0xE8 ,0x06 ,0x38 ,0xD6 };

	unsigned char osapOdd[20]  = { 0x67, 0x04, 0x00, 0x4E, 0x36, 0x0C, 0x6E, 0x4A, 0xCB, 0xDB, 0xBB, 0xE6, 0xDD, 0xE2, 0xF1, 0x46, 0x2C, 0xF0, 0x77, 0x01 };

	hmac_init(secret_key, 20);
	hmac_update(osapEven, 20);
	hmac_update(osapOdd, 20);
	hmac_final(shared);

	int i;
	printf("ENC AUTH:\n");
	for(i=0;i<20;i++)
		printf("%02X ", shared[i]);

	printf("\n");

	unsigned char pcrInfoSize[4] = { 0x00, 0x00, 0x00, 0x2C };

	unsigned char pcrInfo[44] = { 0x00 };

	unsigned char data[20] = { 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x57, 0x6f, 0x72, 0x6c, 0x64,
							  0x21, 0x54, 0x68, 0x69, 0x73, 0x49, 0x73, 0x4d, 0x65, 0x0A };

	unsigned char data_len[4] = { 0x00, 0x00, 0x00, 0x14 };

	pcrInfo[1] = 0x02;
	pcrInfo[2] = 0x00;

	unsigned int hmac_len = 20;

	hash_init();
	hash_update(even, 20);
	hash_update(shared_secret, 20);
	hash_final(xor_key);

	for(i=0;i<20;i++)
		encrypted_secret[i] = xor_key[i] ^ secret_key[i];

	printf("ENC AUTH:\n");
	for(i=0;i<20;i++)
		printf("%02X ", encrypted_secret[i]);

	printf("\n");

	hash_init();
	hash_update(ordinal, 4);
	hash_update(encrypted_secret, 20);
	hash_update(pcrInfoSize, 4);
	hash_update(pcrInfo, 44);
	hash_update(data_len, 4);
	hash_update(data, 20);
	hash_final(hashDigest);

	printf("HASH DIGEST:\n");
	for(i=0;i<20;i++)
		printf("%02X ", hashDigest[i]);

	printf("\n");

	HMAC_CTX_init(&hmac);
	HMAC_Init(&hmac, shared_secret, 20, EVP_sha1());
	HMAC_Update(&hmac, hashDigest, 20);
	HMAC_Update(&hmac, even, 20);
	HMAC_Update(&hmac, odd, 20);
	HMAC_Update(&hmac, &cont, 1);
	HMAC_Final(&hmac, new_h, &hmac_len);

	printf("OPENSSL HMAC:\n");
	for(i=0;i<20;i++)
		printf("%02X ", new_h[i]);

	printf("\n");

	h_init(shared_secret, 20);
	h_update(hashDigest, 20);
	h_update(even, 20);
	h_update(odd, 20);
	h_update(&cont, 1);
	h_final(new_h2);

	printf("IAIK HMAC:\n");
	i=0;
	for(;i<20;i++)
		printf("%02X ", new_h2[i]);
	printf("\n");

	return 0;
}
Exemple #9
0
int main(int argc, char *argv[])
{
  FILE *in, *out;
  cencrypted_v1_header v1header;
  cencrypted_v2_pwheader v2header;
  char hmacsha1_key_str[20*2+1];
  char aes_key_str[16*2+1];
  uint8_t hmacsha1_key[20];
  uint8_t aes_key[16];
  uint8_t inbuf[CHUNK_SIZE], outbuf[CHUNK_SIZE];
  uint32_t chunk_no;
  int hdr_version;
  
  /* getopts */
  int c;
  int optError;
  char inFile[512] = "";
  char outFile[512] = "";
  char passphrase[512];
  int kflag = 0, iflag = 0, oflag = 0, pflag = 0, mflag = 0;
  int verbose = 0;
  extern char *optarg;
  extern int optind, optopt;

  memset(hmacsha1_key_str, '0', sizeof(hmacsha1_key_str)-1);
  hmacsha1_key_str[sizeof(hmacsha1_key_str)-1] = '\0';

  optError = 0;
  while((c = getopt(argc, argv, "hvi:o::p::k:m:")) != -1){
    switch(c) {
    case 'h':      
      usage("Help is on the way. Stay calm.");
      break;
    case 'v':      
      verbose = verbose + 1;
      break;
    case 'i':
      if(optarg) {
	strncpy(inFile, optarg, sizeof(inFile)-1);
      } 
      iflag = 1;
      break;
    case 'o':
      if (optarg) {
	strncpy(outFile, optarg, sizeof(outFile)-1);
      }
      oflag = 1;
      break;
    case 'p':
      if (optarg) {
	strncpy(passphrase, optarg, sizeof(passphrase)-1);
      }
      pflag = 1;
      break;
    case 'k':
      if (optarg) {
	if (strlen(optarg) == 2*(16+20)) {
	  strncpy(aes_key_str, optarg, sizeof(aes_key_str));
	  aes_key_str[sizeof(aes_key_str)-1] = '\0';
	  strncpy(hmacsha1_key_str, optarg+(2*16), sizeof(hmacsha1_key_str));
	  hmacsha1_key_str[sizeof(hmacsha1_key_str)-1] = '\0';
	  mflag = 1;
	} else if(strlen(optarg) == 2*16) {
	  strncpy(aes_key_str, optarg, sizeof(aes_key_str));
	  aes_key_str[sizeof(aes_key_str)-1] = '\0';
	} else {
	  usage("you should either specify a aeskey||hmacsha1key or simply aeskey");
	  optError++;
	}
      }
      kflag = 1;
      break;
    case 'm':
      if (mflag) {
	usage("hmacsha1 key has already been specified!");
	optError++;
      }
      if (optarg && strlen(optarg) == 2*20) {
	strncpy(hmacsha1_key_str, optarg, sizeof(hmacsha1_key_str));
	hmacsha1_key_str[sizeof(hmacsha1_key_str)-1] = '\0';
      } else {
        usage("Perhaps you'd like to give us 40 hex bytes of the HMACSHA1 key?");
	optError++;
      }
      mflag = 1;
      break;
    case '?':
      fprintf(stderr, "Unknown option: -%c\n", optopt);
      optError++;
      break;
    }
  }

  /* check to see if our user gave incorrect options */
  if (optError) {
    usage("Incorrect arguments.");
  }

  if (strlen(inFile) == 0) {
    in = stdin; 
  } else {
    if ((in = fopen(inFile, "rb")) == NULL) {
      fprintf(stderr, "Error: unable to open %s\n", inFile);
      exit(1);
    }
  }

  if (strlen(outFile) == 0) {
    out = stdout;
  } else {
    if ((out = fopen(outFile, "wb")) == NULL) {
      fprintf(stderr, "Error: unable to open %s\n", outFile);
      exit(1);
    }
  }

  /* Obviously change this if we implement brute force methods inside vfdecrypt */
  if (!kflag && !pflag) {
    fprintf(stderr, "Neither a passphrase nor a valid key/hmac combo were given.\n");
    exit(1);
  }

  if (kflag && !mflag) {
    fprintf(stderr, "Setting HMAC-SHA1 key to all zeros!\n");
  }

  hdr_version = determine_header_version(in);
 
  if (verbose >= 1) {
    if (hdr_version > 0) {
      fprintf(stderr, "v%d header detected.\n", hdr_version);
    } else {
      fprintf(stderr, "unknown format.\n");
      exit(1);
    }
  }

  if (hdr_version == 1) {
    fseek(in, (long) -sizeof(cencrypted_v1_header), SEEK_END);
    if (fread(&v1header, sizeof(cencrypted_v1_header), 1, in) < 1) {
      fprintf(stderr, "header corrupted?\n"), exit(1);
    }
    adjust_v1_header_byteorder(&v1header);
    if(!kflag) unwrap_v1_header(passphrase, &v1header, aes_key, hmacsha1_key);
  }
  
  if (hdr_version == 2) {
    fseek(in, 0L, SEEK_SET);
    if (fread(&v2header, sizeof(cencrypted_v2_pwheader), 1, in) < 1) {
      fprintf(stderr, "header corrupted?\n"), exit(1);
    }
    adjust_v2_header_byteorder(&v2header);
    if (verbose >= 1) {
      dump_v2_header(&v2header);
    }
    if(!kflag) unwrap_v2_header(passphrase, &v2header, aes_key, hmacsha1_key);
    CHUNK_SIZE = v2header.blocksize;
  }

  if (kflag) {
    convert_hex(aes_key_str, aes_key, 16);
    convert_hex(hmacsha1_key_str, hmacsha1_key, 20);
  }
  
  HMAC_CTX_init(&hmacsha1_ctx);
  HMAC_Init_ex(&hmacsha1_ctx, hmacsha1_key, sizeof(hmacsha1_key), EVP_sha1(), NULL);
  AES_set_decrypt_key(aes_key, CIPHER_KEY_LENGTH * 8, &aes_decrypt_key);

  if (verbose >= 1) {
    fprintf(stderr, "aeskey:\n");
    print_hex(stderr, aes_key, 16);
  }
  if (verbose >= 1) {
    fprintf(stderr, "hmacsha1key:\n");
    print_hex(stderr, hmacsha1_key, 20);
  }
  if (hdr_version == 2) {
    if (verbose >= 1) {
      fprintf(stderr, "data offset : %llu\n", v2header.dataoffset);
      fprintf(stderr, "data size   : %llu\n", v2header.datasize);
    }
    fseek(in, v2header.dataoffset, SEEK_SET);
  } else  {
    fseek(in, 0L, SEEK_SET);
  }

  chunk_no = 0;
  while(fread(inbuf, CHUNK_SIZE, 1, in) > 0) {
    decrypt_chunk(inbuf, outbuf, chunk_no);
    chunk_no++;
    // fix for last chunk
    if(hdr_version == 2 && (v2header.datasize-ftell(out)) < CHUNK_SIZE) {
      fwrite(outbuf, v2header.datasize - ftell(out), 1, out);
      break;
    }
    fwrite(outbuf, CHUNK_SIZE, 1, out);
  }
  if (verbose >= 1) {
    fprintf(stderr, "%d chunks written\n", chunk_no);
  }
  fclose(in);
  fclose(out);
  return(0);
}
static int pkey_rsa_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
{
    RSA_PKEY_CTX *rctx = ctx->data;
    switch (type) {
    case EVP_PKEY_CTRL_RSA_PADDING:
        if ((p1 >= RSA_PKCS1_PADDING) && (p1 <= RSA_PKCS1_PSS_PADDING)) {
            if (!check_padding_md(rctx->md, p1))
                return 0;
            if (p1 == RSA_PKCS1_PSS_PADDING) {
                if (!(ctx->operation &
                      (EVP_PKEY_OP_SIGN | EVP_PKEY_OP_VERIFY)))
                    goto bad_pad;
                if (!rctx->md)
                    rctx->md = EVP_sha1();
            }
            if (p1 == RSA_PKCS1_OAEP_PADDING) {
                if (!(ctx->operation & EVP_PKEY_OP_TYPE_CRYPT))
                    goto bad_pad;
                if (!rctx->md)
                    rctx->md = EVP_sha1();
            }
            rctx->pad_mode = p1;
            return 1;
        }
 bad_pad:
        RSAerr(RSA_F_PKEY_RSA_CTRL,
               RSA_R_ILLEGAL_OR_UNSUPPORTED_PADDING_MODE);
        return -2;

    case EVP_PKEY_CTRL_RSA_PSS_SALTLEN:
        if (p1 < -2)
            return -2;
        if (rctx->pad_mode != RSA_PKCS1_PSS_PADDING) {
            RSAerr(RSA_F_PKEY_RSA_CTRL, RSA_R_INVALID_PSS_SALTLEN);
            return -2;
        }
        rctx->saltlen = p1;
        return 1;

    case EVP_PKEY_CTRL_RSA_KEYGEN_BITS:
        if (p1 < 256) {
            RSAerr(RSA_F_PKEY_RSA_CTRL, RSA_R_INVALID_KEYBITS);
            return -2;
        }
        rctx->nbits = p1;
        return 1;

    case EVP_PKEY_CTRL_RSA_KEYGEN_PUBEXP:
        if (!p2)
            return -2;
        rctx->pub_exp = p2;
        return 1;

    case EVP_PKEY_CTRL_MD:
        if (!check_padding_md(p2, rctx->pad_mode))
            return 0;
        rctx->md = p2;
        return 1;

    case EVP_PKEY_CTRL_DIGESTINIT:
    case EVP_PKEY_CTRL_PKCS7_ENCRYPT:
    case EVP_PKEY_CTRL_PKCS7_DECRYPT:
    case EVP_PKEY_CTRL_PKCS7_SIGN:
#ifndef OPENSSL_NO_CMS
    case EVP_PKEY_CTRL_CMS_ENCRYPT:
    case EVP_PKEY_CTRL_CMS_DECRYPT:
    case EVP_PKEY_CTRL_CMS_SIGN:
#endif
        return 1;
    case EVP_PKEY_CTRL_PEER_KEY:
        RSAerr(RSA_F_PKEY_RSA_CTRL,
               RSA_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
        return -2;

    default:
        return -2;

    }
}
Exemple #11
0
int ocsp_main(int argc, char **argv)
{
    BIO *acbio = NULL, *cbio = NULL, *derbio = NULL, *out = NULL;
    const EVP_MD *cert_id_md = NULL, *rsign_md = NULL;
    CA_DB *rdb = NULL;
    EVP_PKEY *key = NULL, *rkey = NULL;
    OCSP_BASICRESP *bs = NULL;
    OCSP_REQUEST *req = NULL;
    OCSP_RESPONSE *resp = NULL;
    STACK_OF(CONF_VALUE) *headers = NULL;
    STACK_OF(OCSP_CERTID) *ids = NULL;
    STACK_OF(OPENSSL_STRING) *reqnames = NULL;
    STACK_OF(X509) *sign_other = NULL, *verify_other = NULL, *rother = NULL;
    STACK_OF(X509) *issuers = NULL;
    X509 *issuer = NULL, *cert = NULL, *rca_cert = NULL;
    X509 *signer = NULL, *rsigner = NULL;
    X509_STORE *store = NULL;
    X509_VERIFY_PARAM *vpm = NULL;
    char *CAfile = NULL, *CApath = NULL, *header, *value;
    char *host = NULL, *port = NULL, *path = "/", *outfile = NULL;
    char *rca_filename = NULL, *reqin = NULL, *respin = NULL;
    char *reqout = NULL, *respout = NULL, *ridx_filename = NULL;
    char *rsignfile = NULL, *rkeyfile = NULL;
    char *sign_certfile = NULL, *verify_certfile = NULL, *rcertfile = NULL;
    char *signfile = NULL, *keyfile = NULL;
    char *thost = NULL, *tport = NULL, *tpath = NULL;
    int noCAfile = 0, noCApath = 0;
    int accept_count = -1, add_nonce = 1, noverify = 0, use_ssl = -1;
    int vpmtouched = 0, badsig = 0, i, ignore_err = 0, nmin = 0, ndays = -1;
    int req_text = 0, resp_text = 0, req_timeout = -1, ret = 1;
    long nsec = MAX_VALIDITY_PERIOD, maxage = -1;
    unsigned long sign_flags = 0, verify_flags = 0, rflags = 0;
    OPTION_CHOICE o;
    char *prog;

    reqnames = sk_OPENSSL_STRING_new_null();
    if (!reqnames)
        goto end;
    ids = sk_OCSP_CERTID_new_null();
    if (!ids)
        goto end;
    if ((vpm = X509_VERIFY_PARAM_new()) == NULL)
        return 1;

    prog = opt_init(argc, argv, ocsp_options);
    while ((o = opt_next()) != OPT_EOF) {
        switch (o) {
        case OPT_EOF:
        case OPT_ERR:
 opthelp:
            BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
            goto end;
        case OPT_HELP:
            ret = 0;
            opt_help(ocsp_options);
            goto end;
        case OPT_OUTFILE:
            outfile = opt_arg();
            break;
        case OPT_TIMEOUT:
            req_timeout = atoi(opt_arg());
            break;
        case OPT_URL:
            OPENSSL_free(thost);
            OPENSSL_free(tport);
            OPENSSL_free(tpath);
            thost = tport = tpath = NULL;
            if (!OCSP_parse_url(opt_arg(), &host, &port, &path, &use_ssl)) {
                BIO_printf(bio_err, "%s Error parsing URL\n", prog);
                goto end;
            }
            thost = host;
            tport = port;
            tpath = path;
            break;
        case OPT_HOST:
            host = opt_arg();
            break;
        case OPT_PORT:
            port = opt_arg();
            break;
        case OPT_IGNORE_ERR:
            ignore_err = 1;
            break;
        case OPT_NOVERIFY:
            noverify = 1;
            break;
        case OPT_NONCE:
            add_nonce = 2;
            break;
        case OPT_NO_NONCE:
            add_nonce = 0;
            break;
        case OPT_RESP_NO_CERTS:
            rflags |= OCSP_NOCERTS;
            break;
        case OPT_RESP_KEY_ID:
            rflags |= OCSP_RESPID_KEY;
            break;
        case OPT_NO_CERTS:
            sign_flags |= OCSP_NOCERTS;
            break;
        case OPT_NO_SIGNATURE_VERIFY:
            verify_flags |= OCSP_NOSIGS;
            break;
        case OPT_NO_CERT_VERIFY:
            verify_flags |= OCSP_NOVERIFY;
            break;
        case OPT_NO_CHAIN:
            verify_flags |= OCSP_NOCHAIN;
            break;
        case OPT_NO_CERT_CHECKS:
            verify_flags |= OCSP_NOCHECKS;
            break;
        case OPT_NO_EXPLICIT:
            verify_flags |= OCSP_NOEXPLICIT;
            break;
        case OPT_TRUST_OTHER:
            verify_flags |= OCSP_TRUSTOTHER;
            break;
        case OPT_NO_INTERN:
            verify_flags |= OCSP_NOINTERN;
            break;
        case OPT_BADSIG:
            badsig = 1;
            break;
        case OPT_TEXT:
            req_text = resp_text = 1;
            break;
        case OPT_REQ_TEXT:
            req_text = 1;
            break;
        case OPT_RESP_TEXT:
            resp_text = 1;
            break;
        case OPT_REQIN:
            reqin = opt_arg();
            break;
        case OPT_RESPIN:
            respin = opt_arg();
            break;
        case OPT_SIGNER:
            signfile = opt_arg();
            break;
        case OPT_VAFILE:
            verify_certfile = opt_arg();
            verify_flags |= OCSP_TRUSTOTHER;
            break;
        case OPT_SIGN_OTHER:
            sign_certfile = opt_arg();
            break;
        case OPT_VERIFY_OTHER:
            verify_certfile = opt_arg();
            break;
        case OPT_CAFILE:
            CAfile = opt_arg();
            break;
        case OPT_CAPATH:
            CApath = opt_arg();
            break;
        case OPT_NOCAFILE:
            noCAfile = 1;
            break;
        case OPT_NOCAPATH:
            noCApath = 1;
            break;
        case OPT_V_CASES:
            if (!opt_verify(o, vpm))
                goto end;
            vpmtouched++;
            break;
        case OPT_VALIDITY_PERIOD:
            opt_long(opt_arg(), &nsec);
            break;
        case OPT_STATUS_AGE:
            opt_long(opt_arg(), &maxage);
            break;
        case OPT_SIGNKEY:
            keyfile = opt_arg();
            break;
        case OPT_REQOUT:
            reqout = opt_arg();
            break;
        case OPT_RESPOUT:
            respout = opt_arg();
            break;
        case OPT_PATH:
            path = opt_arg();
            break;
        case OPT_ISSUER:
            issuer = load_cert(opt_arg(), FORMAT_PEM,
                               NULL, NULL, "issuer certificate");
            if (issuer == NULL)
                goto end;
            if (issuers == NULL) {
                if ((issuers = sk_X509_new_null()) == NULL)
                    goto end;
            }
            sk_X509_push(issuers, issuer);
            break;
        case OPT_CERT:
            X509_free(cert);
            cert = load_cert(opt_arg(), FORMAT_PEM,
                             NULL, NULL, "certificate");
            if (cert == NULL)
                goto end;
            if (cert_id_md == NULL)
                cert_id_md = EVP_sha1();
            if (!add_ocsp_cert(&req, cert, cert_id_md, issuer, ids))
                goto end;
            if (!sk_OPENSSL_STRING_push(reqnames, opt_arg()))
                goto end;
            break;
        case OPT_SERIAL:
            if (cert_id_md == NULL)
                cert_id_md = EVP_sha1();
            if (!add_ocsp_serial(&req, opt_arg(), cert_id_md, issuer, ids))
                goto end;
            if (!sk_OPENSSL_STRING_push(reqnames, opt_arg()))
                goto end;
            break;
        case OPT_INDEX:
            ridx_filename = opt_arg();
            break;
        case OPT_CA:
            rca_filename = opt_arg();
            break;
        case OPT_NMIN:
            opt_int(opt_arg(), &nmin);
            if (ndays == -1)
                ndays = 0;
            break;
        case OPT_REQUEST:
            opt_int(opt_arg(), &accept_count);
            break;
        case OPT_NDAYS:
            ndays = atoi(opt_arg());
            break;
        case OPT_RSIGNER:
            rsignfile = opt_arg();
            break;
        case OPT_RKEY:
            rkeyfile = opt_arg();
            break;
        case OPT_ROTHER:
            rcertfile = opt_arg();
            break;
        case OPT_RMD:
            if (!opt_md(opt_arg(), &rsign_md))
                goto end;
            break;
        case OPT_HEADER:
            header = opt_arg();
            value = strchr(header, '=');
            if (value == NULL) {
                BIO_printf(bio_err, "Missing = in header key=value\n");
                goto opthelp;
            }
            *value++ = '\0';
            if (!X509V3_add_value(header, value, &headers))
                goto end;
            break;
        case OPT_MD:
            if (cert_id_md != NULL) {
                BIO_printf(bio_err,
                           "%s: Digest must be before -cert or -serial\n",
                           prog);
                goto opthelp;
            }
            if (!opt_md(opt_unknown(), &cert_id_md))
                goto opthelp;
            break;
        }
    }
    argc = opt_num_rest();
    argv = opt_rest();

    /* Have we anything to do? */
    if (!req && !reqin && !respin && !(port && ridx_filename))
        goto opthelp;

    out = bio_open_default(outfile, 'w', FORMAT_TEXT);
    if (out == NULL)
        goto end;

    if (!req && (add_nonce != 2))
        add_nonce = 0;

    if (!req && reqin) {
        derbio = bio_open_default(reqin, 'r', FORMAT_ASN1);
        if (derbio == NULL)
            goto end;
        req = d2i_OCSP_REQUEST_bio(derbio, NULL);
        BIO_free(derbio);
        if (!req) {
            BIO_printf(bio_err, "Error reading OCSP request\n");
            goto end;
        }
    }

    if (!req && port) {
        acbio = init_responder(port);
        if (!acbio)
            goto end;
    }

    if (rsignfile) {
        if (!rkeyfile)
            rkeyfile = rsignfile;
        rsigner = load_cert(rsignfile, FORMAT_PEM,
                            NULL, NULL, "responder certificate");
        if (!rsigner) {
            BIO_printf(bio_err, "Error loading responder certificate\n");
            goto end;
        }
        rca_cert = load_cert(rca_filename, FORMAT_PEM,
                             NULL, NULL, "CA certificate");
        if (rcertfile) {
            if (!load_certs(rcertfile, &rother, FORMAT_PEM, NULL, NULL,
                            "responder other certificates"))
                goto end;
        }
        rkey = load_key(rkeyfile, FORMAT_PEM, 0, NULL, NULL,
                        "responder private key");
        if (!rkey)
            goto end;
    }
    if (acbio)
        BIO_printf(bio_err, "Waiting for OCSP client connections...\n");

 redo_accept:

    if (acbio) {
        if (!do_responder(&req, &cbio, acbio, port))
            goto end;
        if (!req) {
            resp =
                OCSP_response_create(OCSP_RESPONSE_STATUS_MALFORMEDREQUEST,
                                     NULL);
            send_ocsp_response(cbio, resp);
            goto done_resp;
        }
    }

    if (!req && (signfile || reqout || host || add_nonce || ridx_filename)) {
        BIO_printf(bio_err, "Need an OCSP request for this operation!\n");
        goto end;
    }

    if (req && add_nonce)
        OCSP_request_add1_nonce(req, NULL, -1);

    if (signfile) {
        if (!keyfile)
            keyfile = signfile;
        signer = load_cert(signfile, FORMAT_PEM,
                           NULL, NULL, "signer certificate");
        if (!signer) {
            BIO_printf(bio_err, "Error loading signer certificate\n");
            goto end;
        }
        if (sign_certfile) {
            if (!load_certs(sign_certfile, &sign_other, FORMAT_PEM, NULL, NULL,
                            "signer certificates"))
                goto end;
        }
        key = load_key(keyfile, FORMAT_PEM, 0, NULL, NULL,
                       "signer private key");
        if (!key)
            goto end;

        if (!OCSP_request_sign
            (req, signer, key, NULL, sign_other, sign_flags)) {
            BIO_printf(bio_err, "Error signing OCSP request\n");
            goto end;
        }
    }

    if (req_text && req)
        OCSP_REQUEST_print(out, req, 0);

    if (reqout) {
        derbio = bio_open_default(reqout, 'w', FORMAT_ASN1);
        if (derbio == NULL)
            goto end;
        i2d_OCSP_REQUEST_bio(derbio, req);
        BIO_free(derbio);
    }

    if (ridx_filename && (!rkey || !rsigner || !rca_cert)) {
        BIO_printf(bio_err,
                   "Need a responder certificate, key and CA for this operation!\n");
        goto end;
    }

    if (ridx_filename && !rdb) {
        rdb = load_index(ridx_filename, NULL);
        if (!rdb)
            goto end;
        if (!index_index(rdb))
            goto end;
    }

    if (rdb) {
        make_ocsp_response(&resp, req, rdb, rca_cert, rsigner, rkey,
                               rsign_md, rother, rflags, nmin, ndays, badsig);
        if (cbio)
            send_ocsp_response(cbio, resp);
    } else if (host) {
# ifndef OPENSSL_NO_SOCK
        resp = process_responder(req, host, path,
                                 port, use_ssl, headers, req_timeout);
        if (!resp)
            goto end;
# else
        BIO_printf(bio_err,
                   "Error creating connect BIO - sockets not supported.\n");
        goto end;
# endif
    } else if (respin) {
        derbio = bio_open_default(respin, 'r', FORMAT_ASN1);
        if (derbio == NULL)
            goto end;
        resp = d2i_OCSP_RESPONSE_bio(derbio, NULL);
        BIO_free(derbio);
        if (!resp) {
            BIO_printf(bio_err, "Error reading OCSP response\n");
            goto end;
        }
    } else {
        ret = 0;
        goto end;
    }

 done_resp:

    if (respout) {
        derbio = bio_open_default(respout, 'w', FORMAT_ASN1);
        if (derbio == NULL)
            goto end;
        i2d_OCSP_RESPONSE_bio(derbio, resp);
        BIO_free(derbio);
    }

    i = OCSP_response_status(resp);
    if (i != OCSP_RESPONSE_STATUS_SUCCESSFUL) {
        BIO_printf(out, "Responder Error: %s (%d)\n",
                   OCSP_response_status_str(i), i);
        if (ignore_err)
            goto redo_accept;
        ret = 0;
        goto end;
    }

    if (resp_text)
        OCSP_RESPONSE_print(out, resp, 0);

    /* If running as responder don't verify our own response */
    if (cbio) {
        /* If not unlimited, see if we took all we should. */
        if (accept_count != -1 && --accept_count <= 0) {
            ret = 0;
            goto end;
        }
        BIO_free_all(cbio);
        cbio = NULL;
        OCSP_REQUEST_free(req);
        req = NULL;
        OCSP_RESPONSE_free(resp);
        resp = NULL;
        goto redo_accept;
    }
    if (ridx_filename) {
        ret = 0;
        goto end;
    }

    if (!store) {
        store = setup_verify(CAfile, CApath, noCAfile, noCApath);
        if (!store)
            goto end;
    }
    if (vpmtouched)
        X509_STORE_set1_param(store, vpm);
    if (verify_certfile) {
        if (!load_certs(verify_certfile, &verify_other, FORMAT_PEM, NULL, NULL,
                        "validator certificate"))
            goto end;
    }

    bs = OCSP_response_get1_basic(resp);
    if (!bs) {
        BIO_printf(bio_err, "Error parsing response\n");
        goto end;
    }

    ret = 0;

    if (!noverify) {
        if (req && ((i = OCSP_check_nonce(req, bs)) <= 0)) {
            if (i == -1)
                BIO_printf(bio_err, "WARNING: no nonce in response\n");
            else {
                BIO_printf(bio_err, "Nonce Verify error\n");
                ret = 1;
                goto end;
            }
        }

        i = OCSP_basic_verify(bs, verify_other, store, verify_flags);
        if (i <= 0 && issuers) {
            i = OCSP_basic_verify(bs, issuers, store, OCSP_TRUSTOTHER);
            if (i > 0)
                ERR_clear_error();
        }
        if (i <= 0) {
            BIO_printf(bio_err, "Response Verify Failure\n");
            ERR_print_errors(bio_err);
            ret = 1;
        } else
            BIO_printf(bio_err, "Response verify OK\n");

    }

    print_ocsp_summary(out, bs, req, reqnames, ids, nsec, maxage);

 end:
    ERR_print_errors(bio_err);
    X509_free(signer);
    X509_STORE_free(store);
    X509_VERIFY_PARAM_free(vpm);
    EVP_PKEY_free(key);
    EVP_PKEY_free(rkey);
    X509_free(cert);
    sk_X509_pop_free(issuers, X509_free);
    X509_free(rsigner);
    X509_free(rca_cert);
    free_index(rdb);
    BIO_free_all(cbio);
    BIO_free_all(acbio);
    BIO_free(out);
    OCSP_REQUEST_free(req);
    OCSP_RESPONSE_free(resp);
    OCSP_BASICRESP_free(bs);
    sk_OPENSSL_STRING_free(reqnames);
    sk_OCSP_CERTID_free(ids);
    sk_X509_pop_free(sign_other, X509_free);
    sk_X509_pop_free(verify_other, X509_free);
    sk_CONF_VALUE_pop_free(headers, X509V3_conf_free);
    OPENSSL_free(thost);
    OPENSSL_free(tport);
    OPENSSL_free(tpath);

    return (ret);
}
Exemple #12
0
void crypto_hmac_sha1_init(CryptoHmac hmac, const BYTE* data, UINT32 length)
{
    HMAC_Init_ex(&hmac->hmac_ctx, data, length, EVP_sha1(), NULL);
}
Exemple #13
0
HmacHash::HmacHash(uint32 len, uint8 *seed)
{
    HMAC_CTX_init(&m_ctx);
    HMAC_Init_ex(&m_ctx, seed, len, EVP_sha1(), NULL);
}
Exemple #14
0
/* Customised RSA item verification routine. This is called
 * when a signature is encountered requiring special handling. We
 * currently only handle PSS.
 */
static int
rsa_item_verify(EVP_MD_CTX *ctx, const ASN1_ITEM *it, void *asn,
    X509_ALGOR *sigalg, ASN1_BIT_STRING *sig, EVP_PKEY *pkey)
{
	int rv = -1;
	int saltlen;
	const EVP_MD *mgf1md = NULL, *md = NULL;
	RSA_PSS_PARAMS *pss;
	X509_ALGOR *maskHash;
	EVP_PKEY_CTX *pkctx;

	/* Sanity check: make sure it is PSS */
	if (OBJ_obj2nid(sigalg->algorithm) != NID_rsassaPss) {
		RSAerr(RSA_F_RSA_ITEM_VERIFY, RSA_R_UNSUPPORTED_SIGNATURE_TYPE);
		return -1;
	}

	/* Decode PSS parameters */
	pss = rsa_pss_decode(sigalg, &maskHash);

	if (pss == NULL) {
		RSAerr(RSA_F_RSA_ITEM_VERIFY, RSA_R_INVALID_PSS_PARAMETERS);
		goto err;
	}
	/* Check mask and lookup mask hash algorithm */
	if (pss->maskGenAlgorithm) {
		if (OBJ_obj2nid(pss->maskGenAlgorithm->algorithm) != NID_mgf1) {
			RSAerr(RSA_F_RSA_ITEM_VERIFY,
			    RSA_R_UNSUPPORTED_MASK_ALGORITHM);
			goto err;
		}
		if (!maskHash) {
			RSAerr(RSA_F_RSA_ITEM_VERIFY,
			    RSA_R_UNSUPPORTED_MASK_PARAMETER);
			goto err;
		}
		mgf1md = EVP_get_digestbyobj(maskHash->algorithm);
		if (mgf1md == NULL) {
			RSAerr(RSA_F_RSA_ITEM_VERIFY,
			    RSA_R_UNKNOWN_MASK_DIGEST);
			goto err;
		}
	} else
		mgf1md = EVP_sha1();

	if (pss->hashAlgorithm) {
		md = EVP_get_digestbyobj(pss->hashAlgorithm->algorithm);
		if (md == NULL) {
			RSAerr(RSA_F_RSA_ITEM_VERIFY, RSA_R_UNKNOWN_PSS_DIGEST);
			goto err;
		}
	} else
		md = EVP_sha1();

	if (pss->saltLength) {
		saltlen = ASN1_INTEGER_get(pss->saltLength);

		/* Could perform more salt length sanity checks but the main
		 * RSA routines will trap other invalid values anyway.
		 */
		if (saltlen < 0) {
			RSAerr(RSA_F_RSA_ITEM_VERIFY,
			    RSA_R_INVALID_SALT_LENGTH);
			goto err;
		}
	} else
		saltlen = 20;

	/* low-level routines support only trailer field 0xbc (value 1)
	 * and PKCS#1 says we should reject any other value anyway.
	 */
	if (pss->trailerField && ASN1_INTEGER_get(pss->trailerField) != 1) {
		RSAerr(RSA_F_RSA_ITEM_VERIFY, RSA_R_INVALID_TRAILER);
		goto err;
	}

	/* We have all parameters now set up context */

	if (!EVP_DigestVerifyInit(ctx, &pkctx, md, NULL, pkey))
		goto err;

	if (EVP_PKEY_CTX_set_rsa_padding(pkctx, RSA_PKCS1_PSS_PADDING) <= 0)
		goto err;

	if (EVP_PKEY_CTX_set_rsa_pss_saltlen(pkctx, saltlen) <= 0)
		goto err;

	if (EVP_PKEY_CTX_set_rsa_mgf1_md(pkctx, mgf1md) <= 0)
		goto err;
	/* Carry on */
	rv = 2;

err:
	RSA_PSS_PARAMS_free(pss);
	if (maskHash)
		X509_ALGOR_free(maskHash);
	return rv;
}
Exemple #15
0
void HmacHash::Initialize()
{
    HMAC_Init_ex(&m_ctx, &m_key, SEED_KEY_SIZE, EVP_sha1(), NULL);
}
Exemple #16
0
static int ecdh_cms_encrypt(CMS_RecipientInfo *ri)
{
    EVP_PKEY_CTX *pctx;
    EVP_PKEY *pkey;
    EVP_CIPHER_CTX *ctx;
    int keylen;
    X509_ALGOR *talg, *wrap_alg = NULL;
    ASN1_OBJECT *aoid;
    ASN1_BIT_STRING *pubkey;
    ASN1_STRING *wrap_str;
    ASN1_OCTET_STRING *ukm;
    unsigned char *penc = NULL;
    int penclen;
    int rv = 0;
    int ecdh_nid, kdf_type, kdf_nid, wrap_nid;
    const EVP_MD *kdf_md;
    pctx = CMS_RecipientInfo_get0_pkey_ctx(ri);
    if (!pctx)
        return 0;
    /* Get ephemeral key */
    pkey = EVP_PKEY_CTX_get0_pkey(pctx);
    if (!CMS_RecipientInfo_kari_get0_orig_id(ri, &talg, &pubkey,
                                             NULL, NULL, NULL))
        goto err;
    X509_ALGOR_get0(&aoid, NULL, NULL, talg);
    /* Is everything uninitialised? */
    if (aoid == OBJ_nid2obj(NID_undef)) {

        EC_KEY *eckey = pkey->pkey.ec;
        /* Set the key */
        unsigned char *p;

        penclen = i2o_ECPublicKey(eckey, NULL);
        if (penclen <= 0)
            goto err;
        penc = OPENSSL_malloc(penclen);
        if (penc == NULL)
            goto err;
        p = penc;
        penclen = i2o_ECPublicKey(eckey, &p);
        if (penclen <= 0)
            goto err;
        ASN1_STRING_set0(pubkey, penc, penclen);
        pubkey->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07);
        pubkey->flags |= ASN1_STRING_FLAG_BITS_LEFT;

        penc = NULL;
        X509_ALGOR_set0(talg, OBJ_nid2obj(NID_X9_62_id_ecPublicKey),
                        V_ASN1_UNDEF, NULL);
    }

    /* See if custom parameters set */
    kdf_type = EVP_PKEY_CTX_get_ecdh_kdf_type(pctx);
    if (kdf_type <= 0)
        goto err;
    if (!EVP_PKEY_CTX_get_ecdh_kdf_md(pctx, &kdf_md))
        goto err;
    ecdh_nid = EVP_PKEY_CTX_get_ecdh_cofactor_mode(pctx);
    if (ecdh_nid < 0)
        goto err;
    else if (ecdh_nid == 0)
        ecdh_nid = NID_dh_std_kdf;
    else if (ecdh_nid == 1)
        ecdh_nid = NID_dh_cofactor_kdf;

    if (kdf_type == EVP_PKEY_ECDH_KDF_NONE) {
        kdf_type = EVP_PKEY_ECDH_KDF_X9_62;
        if (EVP_PKEY_CTX_set_ecdh_kdf_type(pctx, kdf_type) <= 0)
            goto err;
    } else
        /* Unknown KDF */
        goto err;
    if (kdf_md == NULL) {
        /* Fixme later for better MD */
        kdf_md = EVP_sha1();
        if (EVP_PKEY_CTX_set_ecdh_kdf_md(pctx, kdf_md) <= 0)
            goto err;
    }

    if (!CMS_RecipientInfo_kari_get0_alg(ri, &talg, &ukm))
        goto err;

    /* Lookup NID for KDF+cofactor+digest */

    if (!OBJ_find_sigid_by_algs(&kdf_nid, EVP_MD_type(kdf_md), ecdh_nid))
        goto err;
    /* Get wrap NID */
    ctx = CMS_RecipientInfo_kari_get0_ctx(ri);
    wrap_nid = EVP_CIPHER_CTX_type(ctx);
    keylen = EVP_CIPHER_CTX_key_length(ctx);

    /* Package wrap algorithm in an AlgorithmIdentifier */

    wrap_alg = X509_ALGOR_new();
    if (wrap_alg == NULL)
        goto err;
    wrap_alg->algorithm = OBJ_nid2obj(wrap_nid);
    wrap_alg->parameter = ASN1_TYPE_new();
    if (wrap_alg->parameter == NULL)
        goto err;
    if (EVP_CIPHER_param_to_asn1(ctx, wrap_alg->parameter) <= 0)
        goto err;
    if (ASN1_TYPE_get(wrap_alg->parameter) == NID_undef) {
        ASN1_TYPE_free(wrap_alg->parameter);
        wrap_alg->parameter = NULL;
    }

    if (EVP_PKEY_CTX_set_ecdh_kdf_outlen(pctx, keylen) <= 0)
        goto err;

    penclen = CMS_SharedInfo_encode(&penc, wrap_alg, ukm, keylen);

    if (!penclen)
        goto err;

    if (EVP_PKEY_CTX_set0_ecdh_kdf_ukm(pctx, penc, penclen) <= 0)
        goto err;
    penc = NULL;

    /*
     * Now need to wrap encoding of wrap AlgorithmIdentifier into parameter
     * of another AlgorithmIdentifier.
     */
    penclen = i2d_X509_ALGOR(wrap_alg, &penc);
    if (!penc || !penclen)
        goto err;
    wrap_str = ASN1_STRING_new();
    if (wrap_str == NULL)
        goto err;
    ASN1_STRING_set0(wrap_str, penc, penclen);
    penc = NULL;
    X509_ALGOR_set0(talg, OBJ_nid2obj(kdf_nid), V_ASN1_SEQUENCE, wrap_str);

    rv = 1;

 err:
    OPENSSL_free(penc);
    X509_ALGOR_free(wrap_alg);
    return rv;
}
Exemple #17
0
void HMACHash::Initialize(uint32 len, uint8 *seed)
{
	HMAC_CTX_init(&mC);
	HMAC_Init_ex(&mC, seed, len, EVP_sha1(), NULL);
}
Exemple #18
0
extern "C" const EVP_MD* EvpSha1()
{
    return EVP_sha1();
}
Exemple #19
0
ldns_rdf *
ldns_sign_public_buffer(ldns_buffer *sign_buf, ldns_key *current_key)
{
	ldns_rdf *b64rdf = NULL;

	switch(ldns_key_algorithm(current_key)) {
	case LDNS_SIGN_DSA:
	case LDNS_SIGN_DSA_NSEC3:
		b64rdf = ldns_sign_public_evp(
				   sign_buf,
				   ldns_key_evp_key(current_key),
				   EVP_dss1());
		break;
	case LDNS_SIGN_RSASHA1:
	case LDNS_SIGN_RSASHA1_NSEC3:
		b64rdf = ldns_sign_public_evp(
				   sign_buf,
				   ldns_key_evp_key(current_key),
				   EVP_sha1());
		break;
#ifdef USE_SHA2
	case LDNS_SIGN_RSASHA256:
		b64rdf = ldns_sign_public_evp(
				   sign_buf,
				   ldns_key_evp_key(current_key),
				   EVP_sha256());
		break;
	case LDNS_SIGN_RSASHA512:
		b64rdf = ldns_sign_public_evp(
				   sign_buf,
				   ldns_key_evp_key(current_key),
				   EVP_sha512());
		break;
#endif /* USE_SHA2 */
#ifdef USE_GOST
	case LDNS_SIGN_ECC_GOST:
		b64rdf = ldns_sign_public_evp(
				   sign_buf,
				   ldns_key_evp_key(current_key),
				   EVP_get_digestbyname("md_gost94"));
		break;
#endif /* USE_GOST */
#ifdef USE_ECDSA
        case LDNS_SIGN_ECDSAP256SHA256:
       		b64rdf = ldns_sign_public_evp(
				   sign_buf,
				   ldns_key_evp_key(current_key),
				   EVP_sha256());
                break;
        case LDNS_SIGN_ECDSAP384SHA384:
       		b64rdf = ldns_sign_public_evp(
				   sign_buf,
				   ldns_key_evp_key(current_key),
				   EVP_sha384());
                break;
#endif
	case LDNS_SIGN_RSAMD5:
		b64rdf = ldns_sign_public_evp(
				   sign_buf,
				   ldns_key_evp_key(current_key),
				   EVP_md5());
		break;
	default:
		/* do _you_ know this alg? */
		printf("unknown algorithm, ");
		printf("is the one used available on this system?\n");
		break;
	}

	return b64rdf;
}
Exemple #20
0
bool SSLSocket::waitWant(int ret, uint64_t millis) {
#ifdef HEADER_OPENSSLV_H
	int err = SSL_get_error(ssl, ret);
	switch(err) {
	case SSL_ERROR_WANT_READ:
		return wait(millis, Socket::WAIT_READ) == WAIT_READ;
	case SSL_ERROR_WANT_WRITE:
		return wait(millis, Socket::WAIT_WRITE) == WAIT_WRITE;
#else
	int err = ssl->last_error;
	switch(err) {
	case GNUTLS_E_INTERRUPTED:
	case GNUTLS_E_AGAIN: 
	{
		int waitFor = wait(millis, Socket::WAIT_READ | Socket::WAIT_WRITE);
		return (waitFor & Socket::WAIT_READ) || (waitFor & Socket::WAIT_WRITE);
	}
#endif
	// Check if this is a fatal error...
	default: checkSSL(ret);
	}
	dcdebug("SSL: Unexpected fallthrough");
	// There was no error?
	return true;
}

int SSLSocket::read(void* aBuffer, int aBufLen) throw(SocketException) {
	if(!ssl) {
		return -1;
	}
	int len = checkSSL(SSL_read(ssl, aBuffer, aBufLen));

	if(len > 0) {
		stats.totalDown += len;
		//dcdebug("In(s): %.*s\n", len, (char*)aBuffer);
	}
	return len;
}

int SSLSocket::write(const void* aBuffer, int aLen) throw(SocketException) {
	if(!ssl) {
		return -1;
	}
	int ret = checkSSL(SSL_write(ssl, aBuffer, aLen));
	if(ret > 0) {
		stats.totalUp += ret;
		//dcdebug("Out(s): %.*s\n", ret, (char*)aBuffer);
	}
	return ret;
}

int SSLSocket::checkSSL(int ret) throw(SocketException) {
	if(!ssl) {
		return -1;
	}
	if(ret <= 0) {
		int err = SSL_get_error(ssl, ret);
		switch(err) {
			case SSL_ERROR_NONE:		// Fallthrough - YaSSL doesn't for example return an openssl compatible error on recv fail
			case SSL_ERROR_WANT_READ:	// Fallthrough
			case SSL_ERROR_WANT_WRITE:
				return -1;
			case SSL_ERROR_ZERO_RETURN:
#ifndef HEADER_OPENSSLV_H
				if(ssl->last_error == GNUTLS_E_INTERRUPTED || ssl->last_error == GNUTLS_E_AGAIN)
					return -1;
#endif				
				throw SocketException(STRING(CONNECTION_CLOSED));
			default:
				{
					ssl.reset();
					// @todo replace 80 with MAX_ERROR_SZ or whatever's appropriate for yaSSL in some nice way...
					char errbuf[80];

					/* TODO: better message for SSL_ERROR_SYSCALL
					 * If the error queue is empty (i.e. ERR_get_error() returns 0), ret can be used to find out more about the error: 
					 * If ret == 0, an EOF was observed that violates the protocol. If ret == -1, the underlying BIO reported an I/O error 
					 * (for socket I/O on Unix systems, consult errno for details).
					 */
					int error = ERR_get_error();
					sprintf(errbuf, "%s %d: %s", CSTRING(SSL_ERROR), err, (error == 0) ? CSTRING(CONNECTION_CLOSED) : ERR_reason_error_string(error));
					throw SSLSocketException(errbuf);
				}
		}
	}
	return ret;
}

int SSLSocket::wait(uint64_t millis, int waitFor) throw(SocketException) {
#ifdef HEADER_OPENSSLV_H
	if(ssl && (waitFor & Socket::WAIT_READ)) {
		/** @todo Take writing into account as well if reading is possible? */
		char c;
		if(SSL_peek(ssl, &c, 1) > 0)
			return WAIT_READ;
	}
#endif
	return Socket::wait(millis, waitFor);
}

bool SSLSocket::isTrusted() throw() {
	if(!ssl) {
		return false;
	}

#ifdef HEADER_OPENSSLV_H
	if(SSL_get_verify_result(ssl) != X509_V_OK) {
		return false;
	}
#else
	if(gnutls_certificate_verify_peers(((SSL*)ssl)->gnutls_state) != 0) {
		return false;
	}
#endif

	X509* cert = SSL_get_peer_certificate(ssl);
	if(!cert) {
		return false;
	}

	X509_free(cert);

	return true;
}

std::string SSLSocket::getCipherName() throw() {
	if(!ssl)
		return Util::emptyString;
	
	return SSL_get_cipher_name(ssl);
}

std::string SSLSocket::getDigest() const throw() {
#ifdef HEADER_OPENSSLV_H

	if(!ssl)
		return Util::emptyString;
	X509* x509 = SSL_get_peer_certificate(ssl);
	if(!x509)
		return Util::emptyString;
	
	return ssl::X509_digest(x509, EVP_sha1());
#else
	return Util::emptyString;
#endif
}

void SSLSocket::shutdown() throw() {
	if(ssl)
		SSL_shutdown(ssl);
}

void SSLSocket::close() throw() {
	if(ssl) {
		ssl.reset();
	}
	Socket::shutdown();
	Socket::close();
}

} // namespace dcpp
Exemple #21
0
int MAIN(int argc, char **argv)
{
    ENGINE *e = NULL;
    char **args;
    char *host = NULL, *port = NULL, *path = "/";
    char *thost = NULL, *tport = NULL, *tpath = NULL;
    char *reqin = NULL, *respin = NULL;
    char *reqout = NULL, *respout = NULL;
    char *signfile = NULL, *keyfile = NULL;
    char *rsignfile = NULL, *rkeyfile = NULL;
    char *outfile = NULL;
    int add_nonce = 1, noverify = 0, use_ssl = -1;
    STACK_OF(CONF_VALUE) *headers = NULL;
    OCSP_REQUEST *req = NULL;
    OCSP_RESPONSE *resp = NULL;
    OCSP_BASICRESP *bs = NULL;
    X509 *issuer = NULL, *cert = NULL;
    X509 *signer = NULL, *rsigner = NULL;
    EVP_PKEY *key = NULL, *rkey = NULL;
    BIO *acbio = NULL, *cbio = NULL;
    BIO *derbio = NULL;
    BIO *out = NULL;
    int req_timeout = -1;
    int req_text = 0, resp_text = 0;
    long nsec = MAX_VALIDITY_PERIOD, maxage = -1;
    char *CAfile = NULL, *CApath = NULL;
    X509_STORE *store = NULL;
    STACK_OF(X509) *sign_other = NULL, *verify_other = NULL, *rother = NULL;
    char *sign_certfile = NULL, *verify_certfile = NULL, *rcertfile = NULL;
    unsigned long sign_flags = 0, verify_flags = 0, rflags = 0;
    int ret = 1;
    int accept_count = -1;
    int badarg = 0;
    int i;
    int ignore_err = 0;
    STACK_OF(OPENSSL_STRING) *reqnames = NULL;
    STACK_OF(OCSP_CERTID) *ids = NULL;

    X509 *rca_cert = NULL;
    char *ridx_filename = NULL;
    char *rca_filename = NULL;
    CA_DB *rdb = NULL;
    int nmin = 0, ndays = -1;
    const EVP_MD *cert_id_md = NULL;

    if (bio_err == NULL)
        bio_err = BIO_new_fp(stderr, BIO_NOCLOSE);

    if (!load_config(bio_err, NULL))
        goto end;
    SSL_load_error_strings();
    OpenSSL_add_ssl_algorithms();
    args = argv + 1;
    reqnames = sk_OPENSSL_STRING_new_null();
    ids = sk_OCSP_CERTID_new_null();
    while (!badarg && *args && *args[0] == '-') {
        if (!strcmp(*args, "-out")) {
            if (args[1]) {
                args++;
                outfile = *args;
            } else
                badarg = 1;
        } else if (!strcmp(*args, "-timeout")) {
            if (args[1]) {
                args++;
                req_timeout = atol(*args);
                if (req_timeout < 0) {
                    BIO_printf(bio_err, "Illegal timeout value %s\n", *args);
                    badarg = 1;
                }
            } else
                badarg = 1;
        } else if (!strcmp(*args, "-url")) {
            if (thost)
                OPENSSL_free(thost);
            if (tport)
                OPENSSL_free(tport);
            if (tpath)
                OPENSSL_free(tpath);
            if (args[1]) {
                args++;
                if (!OCSP_parse_url(*args, &host, &port, &path, &use_ssl)) {
                    BIO_printf(bio_err, "Error parsing URL\n");
                    badarg = 1;
                }
                thost = host;
                tport = port;
                tpath = path;
            } else
                badarg = 1;
        } else if (!strcmp(*args, "-host")) {
            if (args[1]) {
                args++;
                host = *args;
            } else
                badarg = 1;
        } else if (!strcmp(*args, "-port")) {
            if (args[1]) {
                args++;
                port = BUF_strdup(*args);
            } else
                badarg = 1;
        } else if (!strcmp(*args, "-header")) {
            if (args[1] && args[2]) {
                if (!X509V3_add_value(args[1], args[2], &headers))
                    goto end;
                args += 2;
            } else
                badarg = 1;
        } else if (!strcmp(*args, "-ignore_err"))
            ignore_err = 1;
        else if (!strcmp(*args, "-noverify"))
            noverify = 1;
        else if (!strcmp(*args, "-nonce"))
            add_nonce = 2;
        else if (!strcmp(*args, "-no_nonce"))
            add_nonce = 0;
        else if (!strcmp(*args, "-resp_no_certs"))
            rflags |= OCSP_NOCERTS;
        else if (!strcmp(*args, "-resp_key_id"))
            rflags |= OCSP_RESPID_KEY;
        else if (!strcmp(*args, "-no_certs"))
            sign_flags |= OCSP_NOCERTS;
        else if (!strcmp(*args, "-no_signature_verify"))
            verify_flags |= OCSP_NOSIGS;
        else if (!strcmp(*args, "-no_cert_verify"))
            verify_flags |= OCSP_NOVERIFY;
        else if (!strcmp(*args, "-no_chain"))
            verify_flags |= OCSP_NOCHAIN;
        else if (!strcmp(*args, "-no_cert_checks"))
            verify_flags |= OCSP_NOCHECKS;
        else if (!strcmp(*args, "-no_explicit"))
            verify_flags |= OCSP_NOEXPLICIT;
        else if (!strcmp(*args, "-trust_other"))
            verify_flags |= OCSP_TRUSTOTHER;
        else if (!strcmp(*args, "-no_intern"))
            verify_flags |= OCSP_NOINTERN;
        else if (!strcmp(*args, "-text")) {
            req_text = 1;
            resp_text = 1;
        } else if (!strcmp(*args, "-req_text"))
            req_text = 1;
        else if (!strcmp(*args, "-resp_text"))
            resp_text = 1;
        else if (!strcmp(*args, "-reqin")) {
            if (args[1]) {
                args++;
                reqin = *args;
            } else
                badarg = 1;
        } else if (!strcmp(*args, "-respin")) {
            if (args[1]) {
                args++;
                respin = *args;
            } else
                badarg = 1;
        } else if (!strcmp(*args, "-signer")) {
            if (args[1]) {
                args++;
                signfile = *args;
            } else
                badarg = 1;
        } else if (!strcmp(*args, "-VAfile")) {
            if (args[1]) {
                args++;
                verify_certfile = *args;
                verify_flags |= OCSP_TRUSTOTHER;
            } else
                badarg = 1;
        } else if (!strcmp(*args, "-sign_other")) {
            if (args[1]) {
                args++;
                sign_certfile = *args;
            } else
                badarg = 1;
        } else if (!strcmp(*args, "-verify_other")) {
            if (args[1]) {
                args++;
                verify_certfile = *args;
            } else
                badarg = 1;
        } else if (!strcmp(*args, "-CAfile")) {
            if (args[1]) {
                args++;
                CAfile = *args;
            } else
                badarg = 1;
        } else if (!strcmp(*args, "-CApath")) {
            if (args[1]) {
                args++;
                CApath = *args;
            } else
                badarg = 1;
        } else if (!strcmp(*args, "-validity_period")) {
            if (args[1]) {
                args++;
                nsec = atol(*args);
                if (nsec < 0) {
                    BIO_printf(bio_err,
                               "Illegal validity period %s\n", *args);
                    badarg = 1;
                }
            } else
                badarg = 1;
        } else if (!strcmp(*args, "-status_age")) {
            if (args[1]) {
                args++;
                maxage = atol(*args);
                if (maxage < 0) {
                    BIO_printf(bio_err, "Illegal validity age %s\n", *args);
                    badarg = 1;
                }
            } else
                badarg = 1;
        } else if (!strcmp(*args, "-signkey")) {
            if (args[1]) {
                args++;
                keyfile = *args;
            } else
                badarg = 1;
        } else if (!strcmp(*args, "-reqout")) {
            if (args[1]) {
                args++;
                reqout = *args;
            } else
                badarg = 1;
        } else if (!strcmp(*args, "-respout")) {
            if (args[1]) {
                args++;
                respout = *args;
            } else
                badarg = 1;
        } else if (!strcmp(*args, "-path")) {
            if (args[1]) {
                args++;
                path = *args;
            } else
                badarg = 1;
        } else if (!strcmp(*args, "-issuer")) {
            if (args[1]) {
                args++;
                X509_free(issuer);
                issuer = load_cert(bio_err, *args, FORMAT_PEM,
                                   NULL, e, "issuer certificate");
                if (!issuer)
                    goto end;
            } else
                badarg = 1;
        } else if (!strcmp(*args, "-cert")) {
            if (args[1]) {
                args++;
                X509_free(cert);
                cert = load_cert(bio_err, *args, FORMAT_PEM,
                                 NULL, e, "certificate");
                if (!cert)
                    goto end;
                if (!cert_id_md)
                    cert_id_md = EVP_sha1();
                if (!add_ocsp_cert(&req, cert, cert_id_md, issuer, ids))
                    goto end;
                if (!sk_OPENSSL_STRING_push(reqnames, *args))
                    goto end;
            } else
                badarg = 1;
        } else if (!strcmp(*args, "-serial")) {
            if (args[1]) {
                args++;
                if (!cert_id_md)
                    cert_id_md = EVP_sha1();
                if (!add_ocsp_serial(&req, *args, cert_id_md, issuer, ids))
                    goto end;
                if (!sk_OPENSSL_STRING_push(reqnames, *args))
                    goto end;
            } else
                badarg = 1;
        } else if (!strcmp(*args, "-index")) {
            if (args[1]) {
                args++;
                ridx_filename = *args;
            } else
                badarg = 1;
        } else if (!strcmp(*args, "-CA")) {
            if (args[1]) {
                args++;
                rca_filename = *args;
            } else
                badarg = 1;
        } else if (!strcmp(*args, "-nmin")) {
            if (args[1]) {
                args++;
                nmin = atol(*args);
                if (nmin < 0) {
                    BIO_printf(bio_err, "Illegal update period %s\n", *args);
                    badarg = 1;
                }
            }
            if (ndays == -1)
                ndays = 0;
            else
                badarg = 1;
        } else if (!strcmp(*args, "-nrequest")) {
            if (args[1]) {
                args++;
                accept_count = atol(*args);
                if (accept_count < 0) {
                    BIO_printf(bio_err, "Illegal accept count %s\n", *args);
                    badarg = 1;
                }
            } else
                badarg = 1;
        } else if (!strcmp(*args, "-ndays")) {
            if (args[1]) {
                args++;
                ndays = atol(*args);
                if (ndays < 0) {
                    BIO_printf(bio_err, "Illegal update period %s\n", *args);
                    badarg = 1;
                }
            } else
                badarg = 1;
        } else if (!strcmp(*args, "-rsigner")) {
            if (args[1]) {
                args++;
                rsignfile = *args;
            } else
                badarg = 1;
        } else if (!strcmp(*args, "-rkey")) {
            if (args[1]) {
                args++;
                rkeyfile = *args;
            } else
                badarg = 1;
        } else if (!strcmp(*args, "-rother")) {
            if (args[1]) {
                args++;
                rcertfile = *args;
            } else
                badarg = 1;
        } else if ((cert_id_md = EVP_get_digestbyname((*args) + 1)) == NULL) {
            badarg = 1;
        }
        args++;
    }

    /* Have we anything to do? */
    if (!req && !reqin && !respin && !(port && ridx_filename))
        badarg = 1;

    if (badarg) {
        BIO_printf(bio_err, "OCSP utility\n");
        BIO_printf(bio_err, "Usage ocsp [options]\n");
        BIO_printf(bio_err, "where options are\n");
        BIO_printf(bio_err, "-out file            output filename\n");
        BIO_printf(bio_err, "-issuer file         issuer certificate\n");
        BIO_printf(bio_err, "-cert file           certificate to check\n");
        BIO_printf(bio_err, "-serial n            serial number to check\n");
        BIO_printf(bio_err,
                   "-signer file         certificate to sign OCSP request with\n");
        BIO_printf(bio_err,
                   "-signkey file        private key to sign OCSP request with\n");
        BIO_printf(bio_err,
                   "-sign_other file     additional certificates to include in signed request\n");
        BIO_printf(bio_err,
                   "-no_certs            don't include any certificates in signed request\n");
        BIO_printf(bio_err,
                   "-req_text            print text form of request\n");
        BIO_printf(bio_err,
                   "-resp_text           print text form of response\n");
        BIO_printf(bio_err,
                   "-text                print text form of request and response\n");
        BIO_printf(bio_err,
                   "-reqout file         write DER encoded OCSP request to \"file\"\n");
        BIO_printf(bio_err,
                   "-respout file        write DER encoded OCSP reponse to \"file\"\n");
        BIO_printf(bio_err,
                   "-reqin file          read DER encoded OCSP request from \"file\"\n");
        BIO_printf(bio_err,
                   "-respin file         read DER encoded OCSP reponse from \"file\"\n");
        BIO_printf(bio_err,
                   "-nonce               add OCSP nonce to request\n");
        BIO_printf(bio_err,
                   "-no_nonce            don't add OCSP nonce to request\n");
        BIO_printf(bio_err, "-url URL             OCSP responder URL\n");
        BIO_printf(bio_err,
                   "-host host:n         send OCSP request to host on port n\n");
        BIO_printf(bio_err,
                   "-path                path to use in OCSP request\n");
        BIO_printf(bio_err,
                   "-CApath dir          trusted certificates directory\n");
        BIO_printf(bio_err,
                   "-CAfile file         trusted certificates file\n");
        BIO_printf(bio_err,
                   "-no_alt_chains       only ever use the first certificate chain found\n");
        BIO_printf(bio_err,
                   "-VAfile file         validator certificates file\n");
        BIO_printf(bio_err,
                   "-validity_period n   maximum validity discrepancy in seconds\n");
        BIO_printf(bio_err,
                   "-status_age n        maximum status age in seconds\n");
        BIO_printf(bio_err,
                   "-noverify            don't verify response at all\n");
        BIO_printf(bio_err,
                   "-verify_other file   additional certificates to search for signer\n");
        BIO_printf(bio_err,
                   "-trust_other         don't verify additional certificates\n");
        BIO_printf(bio_err,
                   "-no_intern           don't search certificates contained in response for signer\n");
        BIO_printf(bio_err,
                   "-no_signature_verify don't check signature on response\n");
        BIO_printf(bio_err,
                   "-no_cert_verify      don't check signing certificate\n");
        BIO_printf(bio_err,
                   "-no_chain            don't chain verify response\n");
        BIO_printf(bio_err,
                   "-no_cert_checks      don't do additional checks on signing certificate\n");
        BIO_printf(bio_err,
                   "-port num            port to run responder on\n");
        BIO_printf(bio_err,
                   "-index file          certificate status index file\n");
        BIO_printf(bio_err, "-CA file             CA certificate\n");
        BIO_printf(bio_err,
                   "-rsigner file        responder certificate to sign responses with\n");
        BIO_printf(bio_err,
                   "-rkey file           responder key to sign responses with\n");
        BIO_printf(bio_err,
                   "-rother file         other certificates to include in response\n");
        BIO_printf(bio_err,
                   "-resp_no_certs       don't include any certificates in response\n");
        BIO_printf(bio_err,
                   "-nmin n              number of minutes before next update\n");
        BIO_printf(bio_err,
                   "-ndays n             number of days before next update\n");
        BIO_printf(bio_err,
                   "-resp_key_id         identify reponse by signing certificate key ID\n");
        BIO_printf(bio_err,
                   "-nrequest n          number of requests to accept (default unlimited)\n");
        BIO_printf(bio_err,
                   "-<dgst alg>          use specified digest in the request\n");
        BIO_printf(bio_err,
                   "-timeout n           timeout connection to OCSP responder after n seconds\n");
        goto end;
    }

    if (outfile)
        out = BIO_new_file(outfile, "w");
    else
        out = BIO_new_fp(stdout, BIO_NOCLOSE);

    if (!out) {
        BIO_printf(bio_err, "Error opening output file\n");
        goto end;
    }

    if (!req && (add_nonce != 2))
        add_nonce = 0;

    if (!req && reqin) {
        derbio = BIO_new_file(reqin, "rb");
        if (!derbio) {
            BIO_printf(bio_err, "Error Opening OCSP request file\n");
            goto end;
        }
        req = d2i_OCSP_REQUEST_bio(derbio, NULL);
        BIO_free(derbio);
        if (!req) {
            BIO_printf(bio_err, "Error reading OCSP request\n");
            goto end;
        }
    }

    if (!req && port) {
        acbio = init_responder(port);
        if (!acbio)
            goto end;
    }

    if (rsignfile && !rdb) {
        if (!rkeyfile)
            rkeyfile = rsignfile;
        rsigner = load_cert(bio_err, rsignfile, FORMAT_PEM,
                            NULL, e, "responder certificate");
        if (!rsigner) {
            BIO_printf(bio_err, "Error loading responder certificate\n");
            goto end;
        }
        rca_cert = load_cert(bio_err, rca_filename, FORMAT_PEM,
                             NULL, e, "CA certificate");
        if (rcertfile) {
            rother = load_certs(bio_err, rcertfile, FORMAT_PEM,
                                NULL, e, "responder other certificates");
            if (!rother)
                goto end;
        }
        rkey = load_key(bio_err, rkeyfile, FORMAT_PEM, 0, NULL, NULL,
                        "responder private key");
        if (!rkey)
            goto end;
    }
    if (acbio)
        BIO_printf(bio_err, "Waiting for OCSP client connections...\n");

 redo_accept:

    if (acbio) {
        if (!do_responder(&req, &cbio, acbio, port))
            goto end;
        if (!req) {
            resp =
                OCSP_response_create(OCSP_RESPONSE_STATUS_MALFORMEDREQUEST,
                                     NULL);
            send_ocsp_response(cbio, resp);
            goto done_resp;
        }
    }

    if (!req && (signfile || reqout || host || add_nonce || ridx_filename)) {
        BIO_printf(bio_err, "Need an OCSP request for this operation!\n");
        goto end;
    }

    if (req && add_nonce)
        OCSP_request_add1_nonce(req, NULL, -1);

    if (signfile) {
        if (!keyfile)
            keyfile = signfile;
        signer = load_cert(bio_err, signfile, FORMAT_PEM,
                           NULL, e, "signer certificate");
        if (!signer) {
            BIO_printf(bio_err, "Error loading signer certificate\n");
            goto end;
        }
        if (sign_certfile) {
            sign_other = load_certs(bio_err, sign_certfile, FORMAT_PEM,
                                    NULL, e, "signer certificates");
            if (!sign_other)
                goto end;
        }
        key = load_key(bio_err, keyfile, FORMAT_PEM, 0, NULL, NULL,
                       "signer private key");
        if (!key)
            goto end;

        if (!OCSP_request_sign
            (req, signer, key, NULL, sign_other, sign_flags)) {
            BIO_printf(bio_err, "Error signing OCSP request\n");
            goto end;
        }
    }

    if (req_text && req)
        OCSP_REQUEST_print(out, req, 0);

    if (reqout) {
        derbio = BIO_new_file(reqout, "wb");
        if (!derbio) {
            BIO_printf(bio_err, "Error opening file %s\n", reqout);
            goto end;
        }
        i2d_OCSP_REQUEST_bio(derbio, req);
        BIO_free(derbio);
    }

    if (ridx_filename && (!rkey || !rsigner || !rca_cert)) {
        BIO_printf(bio_err,
                   "Need a responder certificate, key and CA for this operation!\n");
        goto end;
    }

    if (ridx_filename && !rdb) {
        rdb = load_index(ridx_filename, NULL);
        if (!rdb)
            goto end;
        if (!index_index(rdb))
            goto end;
    }

    if (rdb) {
        i = make_ocsp_response(&resp, req, rdb, rca_cert, rsigner, rkey,
                               rother, rflags, nmin, ndays);
        if (cbio)
            send_ocsp_response(cbio, resp);
    } else if (host) {
# ifndef OPENSSL_NO_SOCK
        resp = process_responder(bio_err, req, host, path,
                                 port, use_ssl, headers, req_timeout);
        if (!resp)
            goto end;
# else
        BIO_printf(bio_err,
                   "Error creating connect BIO - sockets not supported.\n");
        goto end;
# endif
    } else if (respin) {
        derbio = BIO_new_file(respin, "rb");
        if (!derbio) {
            BIO_printf(bio_err, "Error Opening OCSP response file\n");
            goto end;
        }
        resp = d2i_OCSP_RESPONSE_bio(derbio, NULL);
        BIO_free(derbio);
        if (!resp) {
            BIO_printf(bio_err, "Error reading OCSP response\n");
            goto end;
        }

    } else {
        ret = 0;
        goto end;
    }

 done_resp:

    if (respout) {
        derbio = BIO_new_file(respout, "wb");
        if (!derbio) {
            BIO_printf(bio_err, "Error opening file %s\n", respout);
            goto end;
        }
        i2d_OCSP_RESPONSE_bio(derbio, resp);
        BIO_free(derbio);
    }

    i = OCSP_response_status(resp);

    if (i != OCSP_RESPONSE_STATUS_SUCCESSFUL) {
        BIO_printf(out, "Responder Error: %s (%d)\n",
                   OCSP_response_status_str(i), i);
        if (ignore_err)
            goto redo_accept;
        ret = 0;
        goto end;
    }

    if (resp_text)
        OCSP_RESPONSE_print(out, resp, 0);

    /* If running as responder don't verify our own response */
    if (cbio) {
        if (accept_count > 0)
            accept_count--;
        /* Redo if more connections needed */
        if (accept_count) {
            BIO_free_all(cbio);
            cbio = NULL;
            OCSP_REQUEST_free(req);
            req = NULL;
            OCSP_RESPONSE_free(resp);
            resp = NULL;
            goto redo_accept;
        }
        goto end;
    }

    if (!store)
        store = setup_verify(bio_err, CAfile, CApath);
    if (!store)
        goto end;
    if (verify_certfile) {
        verify_other = load_certs(bio_err, verify_certfile, FORMAT_PEM,
                                  NULL, e, "validator certificate");
        if (!verify_other)
            goto end;
    }

    bs = OCSP_response_get1_basic(resp);

    if (!bs) {
        BIO_printf(bio_err, "Error parsing response\n");
        goto end;
    }

    if (!noverify) {
        if (req && ((i = OCSP_check_nonce(req, bs)) <= 0)) {
            if (i == -1)
                BIO_printf(bio_err, "WARNING: no nonce in response\n");
            else {
                BIO_printf(bio_err, "Nonce Verify error\n");
                goto end;
            }
        }

        i = OCSP_basic_verify(bs, verify_other, store, verify_flags);
        if (i < 0)
            i = OCSP_basic_verify(bs, NULL, store, 0);

        if (i <= 0) {
            BIO_printf(bio_err, "Response Verify Failure\n");
            ERR_print_errors(bio_err);
        } else
            BIO_printf(bio_err, "Response verify OK\n");

    }

    if (!print_ocsp_summary(out, bs, req, reqnames, ids, nsec, maxage))
        goto end;

    ret = 0;

 end:
    ERR_print_errors(bio_err);
    X509_free(signer);
    X509_STORE_free(store);
    EVP_PKEY_free(key);
    EVP_PKEY_free(rkey);
    X509_free(issuer);
    X509_free(cert);
    X509_free(rsigner);
    X509_free(rca_cert);
    free_index(rdb);
    BIO_free_all(cbio);
    BIO_free_all(acbio);
    BIO_free(out);
    OCSP_REQUEST_free(req);
    OCSP_RESPONSE_free(resp);
    OCSP_BASICRESP_free(bs);
    sk_OPENSSL_STRING_free(reqnames);
    sk_OCSP_CERTID_free(ids);
    sk_X509_pop_free(sign_other, X509_free);
    sk_X509_pop_free(verify_other, X509_free);
    sk_CONF_VALUE_pop_free(headers, X509V3_conf_free);

    if (thost)
        OPENSSL_free(thost);
    if (tport)
        OPENSSL_free(tport);
    if (tpath)
        OPENSSL_free(tpath);

    OPENSSL_EXIT(ret);
}
Exemple #22
0
bool avjackif::async_register_new_user(std::string user_name, boost::asio::yield_context yield_context)
{
	// 先发 client_hello
	if( m_shared_key.empty())
		async_client_hello(yield_context);

	auto digest = EVP_sha1();

	// 先生成 RSA 密钥
	_rsa.reset(RSA_generate_key(2048, 65537, 0, 0), RSA_free);

	// 然后生成 CSR
	boost::shared_ptr<X509_REQ> csr(X509_REQ_new(), X509_REQ_free);

	boost::shared_ptr<EVP_PKEY> pkey(EVP_PKEY_new(), EVP_PKEY_free);
	EVP_PKEY_set1_RSA(pkey.get(), _rsa.get());

	// 添加证书申请信息

	auto subj =X509_REQ_get_subject_name(csr.get());
/*	X509_NAME_add_entry_by_NID(subj, NID_countryName, "CN");
	X509_NAME_add_entry_by_NID(subj, NID_stateOrProvinceName, "Shanghai");
	X509_NAME_add_entry_by_NID(subj, NID_localityName, "Shanghai");
	X509_NAME_add_entry_by_NID(subj, NID_organizationName, "avplayer");
	X509_NAME_add_entry_by_NID(subj, NID_organizationalUnitName, "sales");
*/	X509_NAME_add_entry_by_NID(subj, NID_commonName, user_name);
//	X509_NAME_add_entry_by_NID(subj, NID_pkcs9_emailAddress, "test-client");

	X509_REQ_set_pubkey(csr.get(), pkey.get());

	// 签出 CSR
	X509_REQ_sign(csr.get(), pkey.get(), digest);

	unsigned char * out = NULL;
	auto csr_out_len = i2d_X509_REQ(csr.get(), &out);

	std::string csrout((char*)out, csr_out_len);

	OPENSSL_free(out);
	out = NULL;
	auto rsa_key_out_len = i2d_RSA_PUBKEY(_rsa.get(), &out);

	std::string rsa_key((char*)out, rsa_key_out_len);
	OPENSSL_free(out);

	PEM_write_X509_REQ(stderr, csr.get());

	// 然后发送 注册信息
	proto::user_register user_register;

	user_register.set_user_name(user_name);
	user_register.set_rsa_pubkey(rsa_key);
	user_register.set_csr(csrout);

	boost::asio::async_write(*m_sock, boost::asio::buffer(av_router::encode(user_register)), yield_context);

	// 读取应答
	std::unique_ptr<proto::user_register_result> user_register_result((proto::user_register_result*)async_read_protobuf_message(*m_sock, yield_context));

	return user_register_result->result() == proto::user_register_result::REGISTER_SUCCEED;
}
/*
 *	Generate the keys after the user has been authenticated.
 */
static int wimax_postauth(void *instance, REQUEST *request)
{
	rlm_wimax_t *inst = instance;
	VALUE_PAIR *msk, *emsk, *vp;
	VALUE_PAIR *mn_nai, *ip, *fa_rk;
	HMAC_CTX hmac;
	unsigned int rk1_len, rk2_len, rk_len;
	int rk_lifetime = 3600;	/* ? */
	uint32_t mip_spi;
	uint8_t usage_data[24];
	uint8_t mip_rk_1[EVP_MAX_MD_SIZE], mip_rk_2[EVP_MAX_MD_SIZE];
	uint8_t mip_rk[2 * EVP_MAX_MD_SIZE];

	msk = pairfind(request->reply->vps, 1129, 0);
	emsk = pairfind(request->reply->vps, 1130, 0);
	if (!msk || !emsk) {
		RDEBUG("No EAP-MSK or EAP-EMSK.  Cannot create WiMAX keys.");
		return RLM_MODULE_NOOP;
	}

	/*
	 *	If we delete the MS-MPPE-*-Key attributes, then add in
	 *	the WiMAX-MSK so that the client has a key available.
	 */
	if (inst->delete_mppe_keys) {
		pairdelete(&request->reply->vps, 16, VENDORPEC_MICROSOFT, -1);
		pairdelete(&request->reply->vps, 17, VENDORPEC_MICROSOFT, -1);

		vp = radius_pairmake(request, &request->reply->vps, "WiMAX-MSK", "0x00", T_OP_EQ);
		if (vp) {
			memcpy(vp->vp_octets, msk->vp_octets, msk->length);
			vp->length = msk->length;
		}
	}

	/*
	 *	Initialize usage data.
	 */
	memcpy(usage_data, "*****@*****.**", 21);	/* with trailing \0 */
	usage_data[21] = 0x02;
	usage_data[22] = 0x00;
	usage_data[23] = 0x01;

	/*
	 *	MIP-RK-1 = HMAC-SSHA256(EMSK, usage-data | 0x01)
	 */
	HMAC_CTX_init(&hmac);
	HMAC_Init_ex(&hmac, emsk->vp_octets, emsk->length, EVP_sha256(), NULL);
	
	HMAC_Update(&hmac, &usage_data[0], sizeof(usage_data));
	HMAC_Final(&hmac, &mip_rk_1[0], &rk1_len);

	/*
	 *	MIP-RK-2 = HMAC-SSHA256(EMSK, MIP-RK-1 | usage-data | 0x01)
	 */
	HMAC_Init_ex(&hmac, emsk->vp_octets, emsk->length, EVP_sha256(), NULL);
	
	HMAC_Update(&hmac, (const uint8_t *) &mip_rk_1, rk1_len);
	HMAC_Update(&hmac, &usage_data[0], sizeof(usage_data));
	HMAC_Final(&hmac, &mip_rk_2[0], &rk2_len);

	vp = pairfind(request->reply->vps, PW_SESSION_TIMEOUT, 0);
	if (vp) rk_lifetime = vp->vp_integer;

	memcpy(mip_rk, mip_rk_1, rk1_len);
	memcpy(mip_rk + rk1_len, mip_rk_2, rk2_len);
	rk_len = rk1_len + rk2_len;

	/*
	 *	MIP-SPI = HMAC-SSHA256(MIP-RK, "SPI CMIP PMIP");
	 */
	HMAC_Init_ex(&hmac, mip_rk, rk_len, EVP_sha256(), NULL);
	
	HMAC_Update(&hmac, (const uint8_t *) "SPI CMIP PMIP", 12);
	HMAC_Final(&hmac, &mip_rk_1[0], &rk1_len);

	/*
	 *	Take the 4 most significant octets.
	 *	If less than 256, add 256.
	 */
	mip_spi = ((mip_rk_1[0] << 24) | (mip_rk_1[1] << 16) |
		   (mip_rk_1[2] << 8) | mip_rk_1[3]);
	if (mip_spi < 256) mip_spi += 256;

	if (debug_flag) {
		int len = rk_len;
		char buffer[512];

		if (len > 128) len = 128; /* buffer size */

		fr_bin2hex(mip_rk, buffer, len);
		radlog_request(L_DBG, 0, request, "MIP-RK = 0x%s", buffer);
		radlog_request(L_DBG, 0, request, "MIP-SPI = %08x",
			       ntohl(mip_spi));
	}

	/*
	 *	FIXME: Perform SPI collision prevention
	 */

	/*
	 *	Calculate mobility keys
	 */
	mn_nai = pairfind(request->packet->vps, 1900, 0);
	if (!mn_nai) mn_nai = pairfind(request->reply->vps, 1900, 0);
	if (!mn_nai) {
		RDEBUG("WARNING: WiMAX-MN-NAI was not found in the request or in the reply.");
		RDEBUG("WARNING: We cannot calculate MN-HA keys.");
	}

	/*
	 *	WiMAX-IP-Technology
	 */
	vp = NULL;
	if (mn_nai) vp = pairfind(request->reply->vps, 23, VENDORPEC_WIMAX);
	if (!vp) {
		RDEBUG("WARNING: WiMAX-IP-Technology not found in reply.");
		RDEBUG("WARNING: Not calculating MN-HA keys");
	}

	if (vp) switch (vp->vp_integer) {
	case 2:			/* PMIP4 */
		/*
		 *	Look for WiMAX-hHA-IP-MIP4
		 */
		ip = pairfind(request->reply->vps, 6, VENDORPEC_WIMAX);
		if (!ip) {
			RDEBUG("WARNING: WiMAX-hHA-IP-MIP4 not found.  Cannot calculate MN-HA-PMIP4 key");
			break;
		}

		/*
		 *	MN-HA-PMIP4 =
		 *	   H(MIP-RK, "PMIP4 MN HA" | HA-IPv4 | MN-NAI);
		 */
		HMAC_Init_ex(&hmac, mip_rk, rk_len, EVP_sha1(), NULL);

		HMAC_Update(&hmac, (const uint8_t *) "PMIP4 MN HA", 11);
		HMAC_Update(&hmac, (const uint8_t *) &ip->vp_ipaddr, 4);
		HMAC_Update(&hmac, (const uint8_t *) &mn_nai->vp_strvalue, mn_nai->length);
		HMAC_Final(&hmac, &mip_rk_1[0], &rk1_len);

		/*
		 *	Put MN-HA-PMIP4 into WiMAX-MN-hHA-MIP4-Key
		 */
		vp = pairfind(request->reply->vps, 10, VENDORPEC_WIMAX);
		if (!vp) {
			vp = radius_paircreate(request, &request->reply->vps,
					       10, VENDORPEC_WIMAX, PW_TYPE_OCTETS);
		}
		if (!vp) {
			RDEBUG("WARNING: Failed creating WiMAX-MN-hHA-MIP4-Key");
			break;
		}
		memcpy(vp->vp_octets, &mip_rk_1[0], rk1_len);
		vp->length = rk1_len;

		/*
		 *	Put MN-HA-PMIP4-SPI into WiMAX-MN-hHA-MIP4-SPI
		 */
		vp = pairfind(request->reply->vps, 11, VENDORPEC_WIMAX);
		if (!vp) {
			vp = radius_paircreate(request, &request->reply->vps,
					       11, VENDORPEC_WIMAX, PW_TYPE_INTEGER);
		}
		if (!vp) {
			RDEBUG("WARNING: Failed creating WiMAX-MN-hHA-MIP4-SPI");
			break;
		}
		vp->vp_integer = mip_spi + 1;
		break;

	case 3:			/* CMIP4 */
		/*
		 *	Look for WiMAX-hHA-IP-MIP4
		 */
		ip = pairfind(request->reply->vps, 6, VENDORPEC_WIMAX);
		if (!ip) {
			RDEBUG("WARNING: WiMAX-hHA-IP-MIP4 not found.  Cannot calculate MN-HA-CMIP4 key");
			break;
		}

		/*
		 *	MN-HA-CMIP4 =
		 *	   H(MIP-RK, "CMIP4 MN HA" | HA-IPv4 | MN-NAI);
		 */
		HMAC_Init_ex(&hmac, mip_rk, rk_len, EVP_sha1(), NULL);

		HMAC_Update(&hmac, (const uint8_t *) "CMIP4 MN HA", 11);
		HMAC_Update(&hmac, (const uint8_t *) &ip->vp_ipaddr, 4);
		HMAC_Update(&hmac, (const uint8_t *) &mn_nai->vp_strvalue, mn_nai->length);
		HMAC_Final(&hmac, &mip_rk_1[0], &rk1_len);

		/*
		 *	Put MN-HA-CMIP4 into WiMAX-MN-hHA-MIP4-Key
		 */
		vp = pairfind(request->reply->vps, 10, VENDORPEC_WIMAX);
		if (!vp) {
			vp = radius_paircreate(request, &request->reply->vps,
					       10, VENDORPEC_WIMAX, PW_TYPE_OCTETS);
		}
		if (!vp) {
			RDEBUG("WARNING: Failed creating WiMAX-MN-hHA-MIP4-Key");
			break;
		}
		memcpy(vp->vp_octets, &mip_rk_1[0], rk1_len);
		vp->length = rk1_len;

		/*
		 *	Put MN-HA-CMIP4-SPI into WiMAX-MN-hHA-MIP4-SPI
		 */
		vp = pairfind(request->reply->vps, 11, VENDORPEC_WIMAX);
		if (!vp) {
			vp = radius_paircreate(request, &request->reply->vps,
					       11, VENDORPEC_WIMAX, PW_TYPE_INTEGER);
		}
		if (!vp) {
			RDEBUG("WARNING: Failed creating WiMAX-MN-hHA-MIP4-SPI");
			break;
		}
		vp->vp_integer = mip_spi;
		break;

	case 4:			/* CMIP6 */
		/*
		 *	Look for WiMAX-hHA-IP-MIP6
		 */
		ip = pairfind(request->reply->vps, 7, VENDORPEC_WIMAX);
		if (!ip) {
			RDEBUG("WARNING: WiMAX-hHA-IP-MIP6 not found.  Cannot calculate MN-HA-CMIP6 key");
			break;
		}

		/*
		 *	MN-HA-CMIP6 =
		 *	   H(MIP-RK, "CMIP6 MN HA" | HA-IPv6 | MN-NAI);
		 */
		HMAC_Init_ex(&hmac, mip_rk, rk_len, EVP_sha1(), NULL);

		HMAC_Update(&hmac, (const uint8_t *) "CMIP6 MN HA", 11);
		HMAC_Update(&hmac, (const uint8_t *) &ip->vp_ipv6addr, 16);
		HMAC_Update(&hmac, (const uint8_t *) &mn_nai->vp_strvalue, mn_nai->length);
		HMAC_Final(&hmac, &mip_rk_1[0], &rk1_len);

		/*
		 *	Put MN-HA-CMIP6 into WiMAX-MN-hHA-MIP6-Key
		 */
		vp = pairfind(request->reply->vps, 12, VENDORPEC_WIMAX);
		if (!vp) {
			vp = radius_paircreate(request, &request->reply->vps,
					       12, VENDORPEC_WIMAX, PW_TYPE_OCTETS);
		}
		if (!vp) {
			RDEBUG("WARNING: Failed creating WiMAX-MN-hHA-MIP6-Key");
			break;
		}
		memcpy(vp->vp_octets, &mip_rk_1[0], rk1_len);
		vp->length = rk1_len;

		/*
		 *	Put MN-HA-CMIP6-SPI into WiMAX-MN-hHA-MIP6-SPI
		 */
		vp = pairfind(request->reply->vps, 13, VENDORPEC_WIMAX);
		if (!vp) {
			vp = radius_paircreate(request, &request->reply->vps,
					       13, VENDORPEC_WIMAX, PW_TYPE_INTEGER);
		}
		if (!vp) {
			RDEBUG("WARNING: Failed creating WiMAX-MN-hHA-MIP6-SPI");
			break;
		}
		vp->vp_integer = mip_spi + 2;
		break;

	default:
		break;		/* do nothing */
	}

	/*
	 *	Generate FA-RK, if requested.
	 *
	 *	FA-RK= H(MIP-RK, "FA-RK")
	 */
	fa_rk = pairfind(request->reply->vps, 14, VENDORPEC_WIMAX);
	if (fa_rk && (fa_rk->length <= 1)) {
		HMAC_Init_ex(&hmac, mip_rk, rk_len, EVP_sha1(), NULL);
		
		HMAC_Update(&hmac, (const uint8_t *) "FA-RK", 5);

		HMAC_Final(&hmac, &mip_rk_1[0], &rk1_len);

		memcpy(fa_rk->vp_octets, &mip_rk_1[0], rk1_len);
		fa_rk->length = rk1_len;
	}

	/*
	 *	Create FA-RK-SPI, which is really SPI-CMIP4, which is
	 *	really MIP-SPI.  Clear?  Of course.  This is WiMAX.
	 */
	if (fa_rk) {
		vp = pairfind(request->reply->vps, 61, VENDORPEC_WIMAX);
		if (!vp) {
			vp = radius_paircreate(request, &request->reply->vps,
					       61, VENDORPEC_WIMAX, PW_TYPE_INTEGER);
		}
		if (!vp) {
			RDEBUG("WARNING: Failed creating WiMAX-FA-RK-SPI");
		} else {
			vp->vp_integer = mip_spi;
		}
	}

	/*
	 *	Give additional information about requests && responses
	 *
	 *	WiMAX-RRQ-MN-HA-SPI
	 */
	vp = pairfind(request->packet->vps, 20, VENDORPEC_WIMAX);
	if (vp) {
		RDEBUG("Client requested MN-HA key: Should use SPI to look up key from storage.");
		if (!mn_nai) {
			RDEBUG("WARNING: MN-NAI was not found!");
		}

		/*
		 *	WiMAX-RRQ-HA-IP
		 */
		if (!pairfind(request->packet->vps, 18, VENDORPEC_WIMAX)) {
			RDEBUG("WARNING: HA-IP was not found!");
		}


		/*
		 *	WiMAX-HA-RK-Key-Requested
		 */
		vp = pairfind(request->packet->vps, 58, VENDORPEC_WIMAX);
		if (vp && (vp->vp_integer == 1)) {
			RDEBUG("Client requested HA-RK: Should use IP to look it up from storage.");
		}
	}

	/*
	 *	Wipe the context of all sensitive information.
	 */
	HMAC_CTX_cleanup(&hmac);

	return RLM_MODULE_UPDATED;
}
_SCAPI_NOT_CONFIGURED
#endif                          /*  */
/*******************************************************************-o-******
 * sc_generate_keyed_hash
 *
 * Parameters:
 *	 authtype	Type of authentication transform.
 *	 authtypelen
 *	*key		Pointer to key (Kul) to use in keyed hash.
 *	 keylen		Length of key in bytes.
 *	*message	Pointer to the message to hash.
 *	 msglen		Length of the message.
 *	*MAC		Will be returned with allocated bytes containg hash.
 *	*maclen		Length of the hash buffer in bytes; also indicates
 *				whether the MAC should be truncated.
 *      
 * Returns:
 *	SNMPERR_SUCCESS			Success.
 *	SNMPERR_GENERR			All errs
 *
 *
 * A hash of the first msglen bytes of message using a keyed hash defined
 * by authtype is created and stored in MAC.  MAC is ASSUMED to be a buffer
 * of at least maclen bytes.  If the length of the hash is greater than
 * maclen, it is truncated to fit the buffer.  If the length of the hash is
 * less than maclen, maclen set to the number of hash bytes generated.
 *
 * ASSUMED that the number of hash bits is a multiple of 8.
 */
     int















      
         
         
         
         
         
         
         
         
         
         
         
         
         
         
         sc_generate_keyed_hash(const oid * authtype, size_t authtypelen,
                                u_char * key, u_int keylen,
                                u_char * message, u_int msglen,
                                u_char * MAC, size_t * maclen)
#if  defined(USE_INTERNAL_MD5) || defined(USE_OPENSSL)
{
    int             rval = SNMPERR_SUCCESS;
    int             properlength;

    u_char          buf[SNMP_MAXBUF_SMALL];
#if  defined(USE_OPENSSL)
    int             buf_len = sizeof(buf);
#endif

    DEBUGTRACE;

#ifdef SNMP_TESTING_CODE
    {
        int             i;
        DEBUGMSG(("sc_generate_keyed_hash",
                  "sc_generate_keyed_hash(): key=0x"));
        for (i = 0; i < keylen; i++)
            DEBUGMSG(("sc_generate_keyed_hash", "%02x", key[i] & 0xff));
        DEBUGMSG(("sc_generate_keyed_hash", " (%d)\n", keylen));
    }
#endif                          /* SNMP_TESTING_CODE */

    /*
     * Sanity check.
     */
    if (!authtype || !key || !message || !MAC || !maclen
        || (keylen <= 0) || (msglen <= 0) || (*maclen <= 0)
        || (authtypelen != USM_LENGTH_OID_TRANSFORM)) {
        QUITFUN(SNMPERR_GENERR, sc_generate_keyed_hash_quit);
    }

    properlength = sc_get_properlength(authtype, authtypelen);
    if (properlength == SNMPERR_GENERR)
        return properlength;

    if (((int) keylen < properlength)) {
        QUITFUN(SNMPERR_GENERR, sc_generate_keyed_hash_quit);
    }
#ifdef USE_OPENSSL
    /*
     * Determine transform type.
     */
    if (ISTRANSFORM(authtype, HMACMD5Auth))
        HMAC(EVP_md5(), key, keylen, message, msglen, buf, &buf_len);
    else if (ISTRANSFORM(authtype, HMACSHA1Auth))
        HMAC(EVP_sha1(), key, keylen, message, msglen, buf, &buf_len);
    else {
        QUITFUN(SNMPERR_GENERR, sc_generate_keyed_hash_quit);
    }
    if (buf_len != properlength) {
        QUITFUN(rval, sc_generate_keyed_hash_quit);
    }
    if (*maclen > buf_len)
        *maclen = buf_len;
    memcpy(MAC, buf, *maclen);
#else
    if ((int) *maclen > properlength)
        *maclen = properlength;
    if (MDsign(message, msglen, MAC, *maclen, key, keylen)) {
        rval = SNMPERR_GENERR;
        goto sc_generate_keyed_hash_quit;
    }
#endif                          /* USE_OPENSSL */

#ifdef SNMP_TESTING_CODE
    {
        char           *s;
        int             len = binary_to_hex(MAC, *maclen, &s);

        DEBUGMSGTL(("scapi", "Full v3 message hash: %s\n", s));
        SNMP_ZERO(s, len);
        SNMP_FREE(s);
    }
#endif

  sc_generate_keyed_hash_quit:
    SNMP_ZERO(buf, SNMP_MAXBUF_SMALL);
    return rval;
}                               /* end sc_generate_keyed_hash() */
Exemple #25
0
static int pkey_rsa_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) {
  RSA_PKEY_CTX *rctx = ctx->data;
  switch (type) {
    case EVP_PKEY_CTRL_RSA_PADDING:
      if (!is_known_padding(p1) || !check_padding_md(rctx->md, p1) ||
          (p1 == RSA_PKCS1_PSS_PADDING &&
           0 == (ctx->operation & (EVP_PKEY_OP_SIGN | EVP_PKEY_OP_VERIFY))) ||
          (p1 == RSA_PKCS1_OAEP_PADDING &&
           0 == (ctx->operation & EVP_PKEY_OP_TYPE_CRYPT))) {
        OPENSSL_PUT_ERROR(EVP, pkey_rsa_ctrl,
                          EVP_R_ILLEGAL_OR_UNSUPPORTED_PADDING_MODE);
        return 0;
      }
      if ((p1 == RSA_PKCS1_PSS_PADDING || p1 == RSA_PKCS1_OAEP_PADDING) &&
          rctx->md == NULL) {
        rctx->md = EVP_sha1();
      }
      rctx->pad_mode = p1;
      return 1;

    case EVP_PKEY_CTRL_GET_RSA_PADDING:
      *(int *)p2 = rctx->pad_mode;
      return 1;

    case EVP_PKEY_CTRL_RSA_PSS_SALTLEN:
    case EVP_PKEY_CTRL_GET_RSA_PSS_SALTLEN:
      if (rctx->pad_mode != RSA_PKCS1_PSS_PADDING) {
        OPENSSL_PUT_ERROR(EVP, pkey_rsa_ctrl, EVP_R_INVALID_PSS_SALTLEN);
        return 0;
      }
      if (type == EVP_PKEY_CTRL_GET_RSA_PSS_SALTLEN) {
        *(int *)p2 = rctx->saltlen;
      } else {
        if (p1 < -2) {
          return 0;
        }
        rctx->saltlen = p1;
      }
      return 1;

    case EVP_PKEY_CTRL_RSA_KEYGEN_BITS:
      if (p1 < 256) {
        OPENSSL_PUT_ERROR(EVP, pkey_rsa_ctrl, EVP_R_INVALID_KEYBITS);
        return 0;
      }
      rctx->nbits = p1;
      return 1;

    case EVP_PKEY_CTRL_RSA_KEYGEN_PUBEXP:
      if (!p2) {
        return 0;
      }
      BN_free(rctx->pub_exp);
      rctx->pub_exp = p2;
      return 1;

    case EVP_PKEY_CTRL_RSA_OAEP_MD:
    case EVP_PKEY_CTRL_GET_RSA_OAEP_MD:
      if (rctx->pad_mode != RSA_PKCS1_OAEP_PADDING) {
        OPENSSL_PUT_ERROR(EVP, pkey_rsa_ctrl, EVP_R_INVALID_PADDING_MODE);
        return 0;
      }
      if (type == EVP_PKEY_CTRL_GET_RSA_OAEP_MD) {
        *(const EVP_MD **)p2 = rctx->md;
      } else {
        rctx->md = p2;
      }
      return 1;

    case EVP_PKEY_CTRL_MD:
      if (!check_padding_md(p2, rctx->pad_mode)) {
        return 0;
      }
      rctx->md = p2;
      return 1;

    case EVP_PKEY_CTRL_GET_MD:
      *(const EVP_MD **)p2 = rctx->md;
      return 1;

    case EVP_PKEY_CTRL_RSA_MGF1_MD:
    case EVP_PKEY_CTRL_GET_RSA_MGF1_MD:
      if (rctx->pad_mode != RSA_PKCS1_PSS_PADDING &&
          rctx->pad_mode != RSA_PKCS1_OAEP_PADDING) {
        OPENSSL_PUT_ERROR(EVP, pkey_rsa_ctrl, EVP_R_INVALID_MGF1_MD);
        return 0;
      }
      if (type == EVP_PKEY_CTRL_GET_RSA_MGF1_MD) {
        if (rctx->mgf1md) {
          *(const EVP_MD **)p2 = rctx->mgf1md;
        } else {
          *(const EVP_MD **)p2 = rctx->md;
        }
      } else {
        rctx->mgf1md = p2;
      }
      return 1;

    case EVP_PKEY_CTRL_RSA_OAEP_LABEL:
      if (rctx->pad_mode != RSA_PKCS1_OAEP_PADDING) {
        OPENSSL_PUT_ERROR(EVP, pkey_rsa_ctrl, EVP_R_INVALID_PADDING_MODE);
        return 0;
      }
      if (rctx->oaep_label) {
        OPENSSL_free(rctx->oaep_label);
      }
      if (p2 && p1 > 0) {
        /* TODO(fork): this seems wrong. Shouldn't it take a copy of the
         * buffer? */
        rctx->oaep_label = p2;
        rctx->oaep_labellen = p1;
      } else {
        rctx->oaep_label = NULL;
        rctx->oaep_labellen = 0;
      }
      return 1;

    case EVP_PKEY_CTRL_GET_RSA_OAEP_LABEL:
      if (rctx->pad_mode != RSA_PKCS1_OAEP_PADDING) {
        OPENSSL_PUT_ERROR(EVP, pkey_rsa_ctrl, EVP_R_INVALID_PADDING_MODE);
        return 0;
      }
      CBS_init((CBS *)p2, rctx->oaep_label, rctx->oaep_labellen);
      return 1;

    case EVP_PKEY_CTRL_DIGESTINIT:
      return 1;

    default:
      OPENSSL_PUT_ERROR(EVP, pkey_rsa_ctrl, EVP_R_COMMAND_NOT_SUPPORTED);
      return 0;
  }
}
                _SCAPI_NOT_CONFIGURED
#endif                          /* */
/*
 * sc_hash(): a generic wrapper around whatever hashing package we are using.
 * 
 * IN:
 * hashtype    - oid pointer to a hash type
 * hashtypelen - length of oid pointer
 * buf         - u_char buffer to be hashed
 * buf_len     - integer length of buf data
 * MAC_len     - length of the passed MAC buffer size.
 * 
 * OUT:    
 * MAC         - pre-malloced space to store hash output.
 * MAC_len     - length of MAC output to the MAC buffer.
 * 
 * Returns:
 * SNMPERR_SUCCESS              Success.
 * SNMP_SC_GENERAL_FAILURE      Any error.
 */
     int















      
         
         
         
         
         
         
         
         
         
         
         
         
         
         
         sc_hash(const oid * hashtype, size_t hashtypelen, u_char * buf,
                 size_t buf_len, u_char * MAC, size_t * MAC_len)
#if defined(USE_INTERNAL_MD5) || defined(USE_OPENSSL)
{
    int             rval = SNMPERR_SUCCESS;

#ifdef USE_OPENSSL
    EVP_MD         *hash(void);
    HMAC_CTX       *c = NULL;
#endif

    DEBUGTRACE;

    if (hashtype == NULL || hashtypelen < 0 || buf == NULL ||
        buf_len < 0 || MAC == NULL || MAC_len == NULL ||
        (int) (*MAC_len) < sc_get_properlength(hashtype, hashtypelen))
        return (SNMPERR_GENERR);

#ifdef USE_OPENSSL
    /*
     * Determine transform type.
     */
    c = malloc(sizeof(HMAC_CTX));
    if (c == NULL)
        return (SNMPERR_GENERR);

    if (ISTRANSFORM(hashtype, HMACMD5Auth)) {
        EVP_DigestInit(&c->md_ctx, (const EVP_MD *) EVP_md5());
    } else if (ISTRANSFORM(hashtype, HMACSHA1Auth)) {
        EVP_DigestInit(&c->md_ctx, (const EVP_MD *) EVP_sha1());
    } else {
        return (SNMPERR_GENERR);
    }
    EVP_DigestUpdate(&c->md_ctx, buf, buf_len);
    EVP_DigestFinal(&(c->md_ctx), MAC, MAC_len);
    free(c);
    return (rval);
#else                           /* USE_INTERNAL_MD5 */

    if (MDchecksum(buf, buf_len, MAC, *MAC_len)) {
        return SNMPERR_GENERR;
    }
    if (*MAC_len > 16)
        *MAC_len = 16;
    return SNMPERR_SUCCESS;

#endif                          /* USE_OPENSSL */
}
Exemple #27
0
EVP_PKEY *pki_evp::decryptKey() const
{
	unsigned char *p;
	const unsigned char *p1;
	int outl, decsize;
	unsigned char iv[EVP_MAX_IV_LENGTH];
	unsigned char ckey[EVP_MAX_KEY_LENGTH];

	EVP_PKEY *tmpkey;
	EVP_CIPHER_CTX ctx;
	const EVP_CIPHER *cipher = EVP_des_ede3_cbc();
	char ownPassBuf[MAX_PASS_LENGTH] = "";

	if (isPubKey()) {
		unsigned char *q;
		outl = i2d_PUBKEY(key, NULL);
		p = q = (unsigned char *)OPENSSL_malloc(outl);
		check_oom(q);
		i2d_PUBKEY(key, &p);
		p = q;
		tmpkey = d2i_PUBKEY(NULL, (const unsigned char**)&p, outl);
		OPENSSL_free(q);
		return tmpkey;
	}
	/* This key has its own password */
	if (ownPass == ptPrivate) {
		int ret;
		pass_info pi(XCA_TITLE, qApp->translate("MainWindow",
			"Please enter the password to decrypt the private key: '%1'").arg(getIntName()));
		ret = MainWindow::passRead(ownPassBuf, MAX_PASS_LENGTH, 0, &pi);
		if (ret < 0)
			throw errorEx(tr("Password input aborted"), class_name);
	} else if (ownPass == ptBogus) { // BOGUS pass
		ownPassBuf[0] = '\0';
	} else {
		memcpy(ownPassBuf, passwd, MAX_PASS_LENGTH);
		//printf("Orig password: '******' len:%d\n", passwd, strlen(passwd));
		while (md5passwd(ownPassBuf) != passHash &&
			sha512passwd(ownPassBuf, passHash) != passHash)
		{
			int ret;
			//printf("Passhash= '%s', new hash= '%s', passwd= '%s'\n",
				//CCHAR(passHash), CCHAR(md5passwd(ownPassBuf)), ownPassBuf);
			pass_info p(XCA_TITLE, tr("Please enter the database password for decrypting the key '%1'").arg(getIntName()));
			ret = MainWindow::passRead(ownPassBuf, MAX_PASS_LENGTH, 0, &p);
			if (ret < 0)
				throw errorEx(tr("Password input aborted"), class_name);
		}
	}
	//printf("Using decrypt Pass: %s\n", ownPassBuf);
	p = (unsigned char *)OPENSSL_malloc(encKey.count());
	check_oom(p);
	pki_openssl_error();
	p1 = p;
	memset(iv, 0, EVP_MAX_IV_LENGTH);

	memcpy(iv, encKey.constData(), 8); /* recover the iv */
	/* generate the key */
	EVP_BytesToKey(cipher, EVP_sha1(), iv, (unsigned char *)ownPassBuf,
		strlen(ownPassBuf), 1, ckey,NULL);
	/* we use sha1 as message digest,
	 * because an md5 version of the password is
	 * stored in the database...
	 */
	EVP_CIPHER_CTX_init(&ctx);
	EVP_DecryptInit(&ctx, cipher, ckey, iv);
	EVP_DecryptUpdate(&ctx, p , &outl,
		(const unsigned char*)encKey.constData() +8, encKey.count() -8);

	decsize = outl;
	EVP_DecryptFinal(&ctx, p + decsize , &outl);
	decsize += outl;
	//printf("Decrypt decsize=%d, encKey_len=%d\n", decsize, encKey_len);
	pki_openssl_error();
	tmpkey = d2i_PrivateKey(key->type, NULL, &p1, decsize);
	pki_openssl_error();
	OPENSSL_free(p);
	EVP_CIPHER_CTX_cleanup(&ctx);
	pki_openssl_error();
	if (EVP_PKEY_type(tmpkey->type) == EVP_PKEY_RSA)
		RSA_blinding_on(tmpkey->pkey.rsa, NULL);
	return tmpkey;
}
/*============================================================================
 * OpcUa_P_OpenSSL_X509_SelfSigned_Custom_Create
 *===========================================================================*/
OpcUa_StatusCode OpcUa_P_OpenSSL_X509_SelfSigned_Custom_Create(
    OpcUa_CryptoProvider*       a_pProvider,
    OpcUa_Int32                 a_serialNumber,
    OpcUa_UInt32                a_validToInSec,
    OpcUa_Crypto_NameEntry*     a_pNameEntries,      /* will be used for issuer and subject thus it's selfigned cert */
    OpcUa_UInt                  a_nameEntriesCount,  /* will be used for issuer and subject thus it's selfigned cert */
    OpcUa_Key                   a_pSubjectPublicKey, /* EVP_PKEY* - type defines also public key algorithm */
    OpcUa_Crypto_Extension*     a_pExtensions,
    OpcUa_UInt                  a_extensionsCount,
    OpcUa_UInt                  a_signatureHashAlgorithm, /* EVP_sha1(),... */
    OpcUa_Key                   a_pIssuerPrivateKey, /* EVP_PKEY* - type defines also signature algorithm */
    OpcUa_ByteString*           a_pCertificate)
{
    OpcUa_UInt          i;

    X509_NAME*          pSubj               = OpcUa_Null;
    X509V3_CTX          ctx;
    const EVP_MD*       pDigest             = OpcUa_Null;

    X509*               pCert               = OpcUa_Null;
    EVP_PKEY*           pSubjectPublicKey   = OpcUa_Null;
    EVP_PKEY*           pIssuerPrivateKey   = OpcUa_Null;

    OpcUa_InitializeStatus(OpcUa_Module_P_OpenSSL, "X509_SelfSigned_Custom_Create");

    OpcUa_ReferenceParameter(a_pProvider);

    OpcUa_ReturnErrorIfArgumentNull(a_pNameEntries);
    OpcUa_ReturnErrorIfArgumentNull(a_pExtensions);
    OpcUa_ReturnErrorIfArgumentNull(a_pIssuerPrivateKey.Key.Data);
    OpcUa_ReturnErrorIfArgumentNull(a_pCertificate);

    if(a_pSubjectPublicKey.Type != OpcUa_Crypto_KeyType_Rsa_Public)
    {
        uStatus =  OpcUa_BadInvalidArgument;
        OpcUa_GotoErrorIfBad(uStatus);
    }

    if(a_pIssuerPrivateKey.Type != OpcUa_Crypto_KeyType_Rsa_Private)
    {
        uStatus =  OpcUa_BadInvalidArgument;
        OpcUa_GotoErrorIfBad(uStatus);
    }

    pSubjectPublicKey = d2i_PublicKey(EVP_PKEY_RSA,OpcUa_Null,((const unsigned char**)&(a_pSubjectPublicKey.Key.Data)),a_pSubjectPublicKey.Key.Length);
    if(pSubjectPublicKey == OpcUa_Null)
    {
        uStatus =  OpcUa_Bad;
        OpcUa_GotoErrorIfBad(uStatus);
    }

    pIssuerPrivateKey = d2i_PrivateKey(EVP_PKEY_RSA,OpcUa_Null,((const unsigned char**)&(a_pIssuerPrivateKey.Key.Data)),a_pIssuerPrivateKey.Key.Length);
    if(pIssuerPrivateKey == OpcUa_Null)
    {
        uStatus =  OpcUa_Bad;
        OpcUa_GotoErrorIfBad(uStatus);
    }

    /* create new certificate object */
    pCert = X509_new();
    if(pCert == OpcUa_Null)
    {
        uStatus =  OpcUa_Bad;
        OpcUa_GotoErrorIfBad(uStatus);
    }

    /* set version of certificate (V3 since internal representation starts versioning from 0) */
    if(X509_set_version(pCert, 2L) != 1)
    {
        uStatus =  OpcUa_Bad;
        OpcUa_GotoErrorIfBad(uStatus);
    }

    /* generate a unique number for a serial number if none provided. */
    if(a_serialNumber == 0)
    {
        ASN1_INTEGER* pSerialNumber = X509_get_serialNumber(pCert);

        pSerialNumber->type   = V_ASN1_INTEGER;
        pSerialNumber->data   = OPENSSL_realloc(pSerialNumber->data, 16);
        pSerialNumber->length = 16;

        if(pSerialNumber->data == NULL || OpcUa_P_Guid_Create((OpcUa_Guid*)pSerialNumber->data) == NULL)
        {
            uStatus =  OpcUa_Bad;
            OpcUa_GotoErrorIfBad(uStatus);
        }
    }

    /* use the integer passed in - note the API should not be using a 32-bit integer - must fix sometime */
    else if(ASN1_INTEGER_set(X509_get_serialNumber(pCert), a_serialNumber) == 0)
    {
        uStatus =  OpcUa_Bad;
        OpcUa_GotoErrorIfBad(uStatus);
    }

    /* add key to the request */
    if(X509_set_pubkey(pCert, pSubjectPublicKey) != 1)
    {
        uStatus =  OpcUa_Bad;
        OpcUa_GotoErrorIfBad(uStatus);
    }

    if(pSubjectPublicKey != OpcUa_Null)
    {
        EVP_PKEY_free(pSubjectPublicKey);
        pSubjectPublicKey = OpcUa_Null;
    }

    /* assign the subject name */
    pSubj = X509_NAME_new();
    if(!pSubj)
    {
        uStatus =  OpcUa_Bad;
        OpcUa_GotoErrorIfBad(uStatus);
    }

    /* create and add entries to subject name */
    for(i=0; i<a_nameEntriesCount; i++)
    {
        uStatus = OpcUa_P_OpenSSL_X509_Name_AddEntry(&pSubj, a_pNameEntries + i);
        OpcUa_GotoErrorIfBad(uStatus);
    }

    /* set subject name in request */
    if(X509_set_subject_name(pCert, pSubj) != 1)
    {
        uStatus =  OpcUa_Bad;
        OpcUa_GotoErrorIfBad(uStatus);
    }

    /* set name of issuer (CA) */
    if(X509_set_issuer_name(pCert, pSubj) != 1)
    {
        uStatus =  OpcUa_Bad;
        OpcUa_GotoErrorIfBad(uStatus);
    }

    if(!(X509_gmtime_adj(X509_get_notBefore(pCert), 0)))
    {
        uStatus =  OpcUa_Bad;
        OpcUa_GotoErrorIfBad(uStatus);
    }

    /* set ending time of the certificate */
    if(!(X509_gmtime_adj(X509_get_notAfter(pCert), a_validToInSec)))
    {
        uStatus =  OpcUa_Bad;
        OpcUa_GotoErrorIfBad(uStatus);
    }

    /* add x509v3 extensions */
    X509V3_set_ctx(&ctx, pCert, pCert, OpcUa_Null, OpcUa_Null, 0);

    for(i=0; i<a_extensionsCount; i++)
    {
        uStatus = OpcUa_P_OpenSSL_X509_AddCustomExtension(&pCert, a_pExtensions+i, &ctx);
        OpcUa_GotoErrorIfBad(uStatus);
    }

    /* sign certificate with the CA private key */
    switch(a_signatureHashAlgorithm)
    {
    case OPCUA_P_SHA_160:
        pDigest = EVP_sha1();
        break;
    case OPCUA_P_SHA_224:
        pDigest = EVP_sha224();
        break;
    case OPCUA_P_SHA_256:
        pDigest = EVP_sha256();
        break;
    case OPCUA_P_SHA_384:
        pDigest = EVP_sha384();
        break;
    case OPCUA_P_SHA_512:
        pDigest = EVP_sha512();
        break;
    default:
        uStatus =  OpcUa_BadNotSupported;
        OpcUa_GotoErrorIfBad(uStatus);
    }

    if(!(X509_sign(pCert, pIssuerPrivateKey, pDigest)))
    {
        uStatus =  OpcUa_Bad;
        OpcUa_GotoErrorIfBad(uStatus);
    }

    if(X509_verify(pCert, pIssuerPrivateKey) <= 0)
    {
        uStatus =  OpcUa_Bad;
        OpcUa_GotoErrorIfBad(uStatus);
    }

    if(pIssuerPrivateKey != OpcUa_Null)
    {
        EVP_PKEY_free(pIssuerPrivateKey);
        pIssuerPrivateKey = OpcUa_Null;
    }

    if(pSubj != OpcUa_Null)
    {
        X509_NAME_free(pSubj);
        pSubj = OpcUa_Null;
    }

    /* prepare container */
    memset(a_pCertificate, 0, sizeof(OpcUa_ByteString));

    /* get required length for conversion target buffer */
    a_pCertificate->Length = i2d_X509(pCert, NULL);

    if(a_pCertificate->Length <= 0)
    {
        /* conversion to DER not possible */
        uStatus = OpcUa_Bad;
    }

    /* allocate conversion target buffer */
    a_pCertificate->Data = (OpcUa_Byte*)OpcUa_P_Memory_Alloc(a_pCertificate->Length);
    OpcUa_GotoErrorIfAllocFailed(a_pCertificate->Data);

    /* convert into DER */
    a_pCertificate->Length = i2d_X509(pCert, &(a_pCertificate->Data));
    if(a_pCertificate->Length <= 0)
    {
        /* conversion to DER not possible */
        uStatus = OpcUa_Bad;
    }
    else
    {
        /* correct pointer incrementation by i2d_X509() */
        a_pCertificate->Data -= a_pCertificate->Length;
    }

    X509_free(pCert);

OpcUa_ReturnStatusCode;

OpcUa_BeginErrorHandling;

    X509_free(pCert);

    if(pSubjectPublicKey != OpcUa_Null)
    {
        EVP_PKEY_free(pSubjectPublicKey);
    }

    if(pIssuerPrivateKey != OpcUa_Null)
    {
        EVP_PKEY_free(pIssuerPrivateKey);
    }

    if(pSubj != OpcUa_Null)
    {
        X509_NAME_free(pSubj);
    }

OpcUa_FinishErrorHandling;
}
Exemple #29
0
int x509_main(int argc, char **argv)
{
    ASN1_INTEGER *sno = NULL;
    ASN1_OBJECT *objtmp;
    BIO *out = NULL;
    CONF *extconf = NULL;
    EVP_PKEY *Upkey = NULL, *CApkey = NULL, *fkey = NULL;
    STACK_OF(ASN1_OBJECT) *trust = NULL, *reject = NULL;
    STACK_OF(OPENSSL_STRING) *sigopts = NULL;
    X509 *x = NULL, *xca = NULL;
    X509_REQ *req = NULL, *rq = NULL;
    X509_STORE *ctx = NULL;
    const EVP_MD *digest = NULL;
    char *CAkeyfile = NULL, *CAserial = NULL, *fkeyfile = NULL, *alias = NULL;
    char *checkhost = NULL, *checkemail = NULL, *checkip = NULL;
    char *extsect = NULL, *extfile = NULL, *passin = NULL, *passinarg = NULL;
    char *infile = NULL, *outfile = NULL, *keyfile = NULL, *CAfile = NULL;
    char buf[256], *prog;
    int x509req = 0, days = DEF_DAYS, modulus = 0, pubkey = 0, pprint = 0;
    int C = 0, CAformat = FORMAT_PEM, CAkeyformat = FORMAT_PEM;
    int fingerprint = 0, reqfile = 0, need_rand = 0, checkend = 0;
    int informat = FORMAT_PEM, outformat = FORMAT_PEM, keyformat = FORMAT_PEM;
    int next_serial = 0, subject_hash = 0, issuer_hash = 0, ocspid = 0;
    int noout = 0, sign_flag = 0, CA_flag = 0, CA_createserial = 0, email = 0;
    int ocsp_uri = 0, trustout = 0, clrtrust = 0, clrreject = 0, aliasout = 0;
    int ret = 1, i, num = 0, badsig = 0, clrext = 0, nocert = 0;
    int text = 0, serial = 0, subject = 0, issuer = 0, startdate = 0;
    int enddate = 0;
    time_t checkoffset = 0;
    unsigned long nmflag = 0, certflag = 0;
    char nmflag_set = 0;
    OPTION_CHOICE o;
    ENGINE *e = NULL;
#ifndef OPENSSL_NO_MD5
    int subject_hash_old = 0, issuer_hash_old = 0;
#endif

    ctx = X509_STORE_new();
    if (ctx == NULL)
        goto end;
    X509_STORE_set_verify_cb(ctx, callb);

    prog = opt_init(argc, argv, x509_options);
    while ((o = opt_next()) != OPT_EOF) {
        switch (o) {
        case OPT_EOF:
        case OPT_ERR:
 opthelp:
            BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
            goto end;
        case OPT_HELP:
            opt_help(x509_options);
            ret = 0;
            goto end;
        case OPT_INFORM:
            if (!opt_format(opt_arg(), OPT_FMT_ANY, &informat))
                goto opthelp;
            break;
        case OPT_IN:
            infile = opt_arg();
            break;
        case OPT_OUTFORM:
            if (!opt_format(opt_arg(), OPT_FMT_ANY, &outformat))
                goto opthelp;
            break;
        case OPT_KEYFORM:
            if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &keyformat))
                goto opthelp;
            break;
        case OPT_CAFORM:
            if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &CAformat))
                goto opthelp;
            break;
        case OPT_CAKEYFORM:
            if (!opt_format(opt_arg(), OPT_FMT_ANY, &CAkeyformat))
                goto opthelp;
            break;
        case OPT_OUT:
            outfile = opt_arg();
            break;
        case OPT_REQ:
            reqfile = need_rand = 1;
            break;

        case OPT_SIGOPT:
            if (!sigopts)
                sigopts = sk_OPENSSL_STRING_new_null();
            if (!sigopts || !sk_OPENSSL_STRING_push(sigopts, opt_arg()))
                goto opthelp;
            break;
        case OPT_DAYS:
            days = atoi(opt_arg());
            break;
        case OPT_PASSIN:
            passinarg = opt_arg();
            break;
        case OPT_EXTFILE:
            extfile = opt_arg();
            break;
        case OPT_EXTENSIONS:
            extsect = opt_arg();
            break;
        case OPT_SIGNKEY:
            keyfile = opt_arg();
            sign_flag = ++num;
            need_rand = 1;
            break;
        case OPT_CA:
            CAfile = opt_arg();
            CA_flag = ++num;
            need_rand = 1;
            break;
        case OPT_CAKEY:
            CAkeyfile = opt_arg();
            break;
        case OPT_CASERIAL:
            CAserial = opt_arg();
            break;
        case OPT_SET_SERIAL:
            if ((sno = s2i_ASN1_INTEGER(NULL, opt_arg())) == NULL)
                goto opthelp;
            break;
        case OPT_FORCE_PUBKEY:
            fkeyfile = opt_arg();
            break;
        case OPT_ADDTRUST:
            if ((objtmp = OBJ_txt2obj(opt_arg(), 0)) == NULL) {
                BIO_printf(bio_err,
                           "%s: Invalid trust object value %s\n",
                           prog, opt_arg());
                goto opthelp;
            }
            if (trust == NULL && (trust = sk_ASN1_OBJECT_new_null()) == NULL)
                goto end;
            sk_ASN1_OBJECT_push(trust, objtmp);
            trustout = 1;
            break;
        case OPT_ADDREJECT:
            if ((objtmp = OBJ_txt2obj(opt_arg(), 0)) == NULL) {
                BIO_printf(bio_err,
                           "%s: Invalid reject object value %s\n",
                           prog, opt_arg());
                goto opthelp;
            }
            if (reject == NULL
                && (reject = sk_ASN1_OBJECT_new_null()) == NULL)
                goto end;
            sk_ASN1_OBJECT_push(reject, objtmp);
            trustout = 1;
            break;
        case OPT_SETALIAS:
            alias = opt_arg();
            trustout = 1;
            break;
        case OPT_CERTOPT:
            if (!set_cert_ex(&certflag, opt_arg()))
                goto opthelp;
            break;
        case OPT_NAMEOPT:
            nmflag_set = 1;
            if (!set_name_ex(&nmflag, opt_arg()))
                goto opthelp;
            break;
        case OPT_ENGINE:
            e = setup_engine(opt_arg(), 0);
            break;
        case OPT_C:
            C = ++num;
            break;
        case OPT_EMAIL:
            email = ++num;
            break;
        case OPT_OCSP_URI:
            ocsp_uri = ++num;
            break;
        case OPT_SERIAL:
            serial = ++num;
            break;
        case OPT_NEXT_SERIAL:
            next_serial = ++num;
            break;
        case OPT_MODULUS:
            modulus = ++num;
            break;
        case OPT_PUBKEY:
            pubkey = ++num;
            break;
        case OPT_X509TOREQ:
            x509req = ++num;
            break;
        case OPT_TEXT:
            text = ++num;
            break;
        case OPT_SUBJECT:
            subject = ++num;
            break;
        case OPT_ISSUER:
            issuer = ++num;
            break;
        case OPT_FINGERPRINT:
            fingerprint = ++num;
            break;
        case OPT_HASH:
            subject_hash = ++num;
            break;
        case OPT_ISSUER_HASH:
            issuer_hash = ++num;
            break;
        case OPT_PURPOSE:
            pprint = ++num;
            break;
        case OPT_STARTDATE:
            startdate = ++num;
            break;
        case OPT_ENDDATE:
            enddate = ++num;
            break;
        case OPT_NOOUT:
            noout = ++num;
            break;
        case OPT_NOCERT:
            nocert = 1;
            break;
        case OPT_TRUSTOUT:
            trustout = 1;
            break;
        case OPT_CLRTRUST:
            clrtrust = ++num;
            break;
        case OPT_CLRREJECT:
            clrreject = ++num;
            break;
        case OPT_ALIAS:
            aliasout = ++num;
            break;
        case OPT_CACREATESERIAL:
            CA_createserial = ++num;
            break;
        case OPT_CLREXT:
            clrext = 1;
            break;
        case OPT_OCSPID:
            ocspid = ++num;
            break;
        case OPT_BADSIG:
            badsig = 1;
            break;
#ifndef OPENSSL_NO_MD5
        case OPT_SUBJECT_HASH_OLD:
            subject_hash_old = ++num;
            break;
        case OPT_ISSUER_HASH_OLD:
            issuer_hash_old = ++num;
            break;
#else
        case OPT_SUBJECT_HASH_OLD:
        case OPT_ISSUER_HASH_OLD:
            break;
#endif
        case OPT_DATES:
            startdate = ++num;
            enddate = ++num;
            break;
        case OPT_CHECKEND:
            checkend = 1;
            {
                intmax_t temp = 0;
                if (!opt_imax(opt_arg(), &temp))
                    goto opthelp;
                checkoffset = (time_t)temp;
                if ((intmax_t)checkoffset != temp) {
                    BIO_printf(bio_err, "%s: checkend time out of range %s\n",
                               prog, opt_arg());
                    goto opthelp;
                }
            }
            break;
        case OPT_CHECKHOST:
            checkhost = opt_arg();
            break;
        case OPT_CHECKEMAIL:
            checkemail = opt_arg();
            break;
        case OPT_CHECKIP:
            checkip = opt_arg();
            break;
        case OPT_MD:
            if (!opt_md(opt_unknown(), &digest))
                goto opthelp;
        }
    }
    argc = opt_num_rest();
    argv = opt_rest();
    if (argc != 0) {
        BIO_printf(bio_err, "%s: Unknown parameter %s\n", prog, argv[0]);
        goto opthelp;
    }

    if (!nmflag_set)
        nmflag = XN_FLAG_ONELINE;

    out = bio_open_default(outfile, 'w', outformat);
    if (out == NULL)
        goto end;

    if (need_rand)
        app_RAND_load_file(NULL, 0);

    if (!app_passwd(passinarg, NULL, &passin, NULL)) {
        BIO_printf(bio_err, "Error getting password\n");
        goto end;
    }

    if (!X509_STORE_set_default_paths(ctx)) {
        ERR_print_errors(bio_err);
        goto end;
    }

    if (fkeyfile) {
        fkey = load_pubkey(fkeyfile, keyformat, 0, NULL, e, "Forced key");
        if (fkey == NULL)
            goto end;
    }

    if ((CAkeyfile == NULL) && (CA_flag) && (CAformat == FORMAT_PEM)) {
        CAkeyfile = CAfile;
    } else if ((CA_flag) && (CAkeyfile == NULL)) {
        BIO_printf(bio_err,
                   "need to specify a CAkey if using the CA command\n");
        goto end;
    }

    if (extfile) {
        X509V3_CTX ctx2;
        if ((extconf = app_load_config(extfile)) == NULL)
            goto end;
        if (!extsect) {
            extsect = NCONF_get_string(extconf, "default", "extensions");
            if (!extsect) {
                ERR_clear_error();
                extsect = "default";
            }
        }
        X509V3_set_ctx_test(&ctx2);
        X509V3_set_nconf(&ctx2, extconf);
        if (!X509V3_EXT_add_nconf(extconf, &ctx2, extsect, NULL)) {
            BIO_printf(bio_err,
                       "Error Loading extension section %s\n", extsect);
            ERR_print_errors(bio_err);
            goto end;
        }
    }

    if (reqfile) {
        EVP_PKEY *pkey;
        BIO *in;

        if (!sign_flag && !CA_flag) {
            BIO_printf(bio_err, "We need a private key to sign with\n");
            goto end;
        }
        in = bio_open_default(infile, 'r', informat);
        if (in == NULL)
            goto end;
        req = PEM_read_bio_X509_REQ(in, NULL, NULL, NULL);
        BIO_free(in);

        if (req == NULL) {
            ERR_print_errors(bio_err);
            goto end;
        }

        if ((pkey = X509_REQ_get0_pubkey(req)) == NULL) {
            BIO_printf(bio_err, "error unpacking public key\n");
            goto end;
        }
        i = X509_REQ_verify(req, pkey);
        if (i < 0) {
            BIO_printf(bio_err, "Signature verification error\n");
            ERR_print_errors(bio_err);
            goto end;
        }
        if (i == 0) {
            BIO_printf(bio_err,
                       "Signature did not match the certificate request\n");
            goto end;
        } else
            BIO_printf(bio_err, "Signature ok\n");

        print_name(bio_err, "subject=", X509_REQ_get_subject_name(req),
                   nmflag);

        if ((x = X509_new()) == NULL)
            goto end;

        if (sno == NULL) {
            sno = ASN1_INTEGER_new();
            if (sno == NULL || !rand_serial(NULL, sno))
                goto end;
            if (!X509_set_serialNumber(x, sno))
                goto end;
            ASN1_INTEGER_free(sno);
            sno = NULL;
        } else if (!X509_set_serialNumber(x, sno))
            goto end;

        if (!X509_set_issuer_name(x, X509_REQ_get_subject_name(req)))
            goto end;
        if (!X509_set_subject_name(x, X509_REQ_get_subject_name(req)))
            goto end;

        X509_gmtime_adj(X509_get_notBefore(x), 0);
        X509_time_adj_ex(X509_get_notAfter(x), days, 0, NULL);
        if (fkey)
            X509_set_pubkey(x, fkey);
        else {
            pkey = X509_REQ_get0_pubkey(req);
            X509_set_pubkey(x, pkey);
        }
    } else
        x = load_cert(infile, informat, "Certificate");

    if (x == NULL)
        goto end;
    if (CA_flag) {
        xca = load_cert(CAfile, CAformat, "CA Certificate");
        if (xca == NULL)
            goto end;
    }

    if (!noout || text || next_serial) {
        OBJ_create("2.99999.3", "SET.ex3", "SET x509v3 extension 3");

    }

    if (alias)
        X509_alias_set1(x, (unsigned char *)alias, -1);

    if (clrtrust)
        X509_trust_clear(x);
    if (clrreject)
        X509_reject_clear(x);

    if (trust) {
        for (i = 0; i < sk_ASN1_OBJECT_num(trust); i++) {
            objtmp = sk_ASN1_OBJECT_value(trust, i);
            X509_add1_trust_object(x, objtmp);
        }
    }

    if (reject) {
        for (i = 0; i < sk_ASN1_OBJECT_num(reject); i++) {
            objtmp = sk_ASN1_OBJECT_value(reject, i);
            X509_add1_reject_object(x, objtmp);
        }
    }

    if (num) {
        for (i = 1; i <= num; i++) {
            if (issuer == i) {
                print_name(out, "issuer= ", X509_get_issuer_name(x), nmflag);
            } else if (subject == i) {
                print_name(out, "subject= ",
                           X509_get_subject_name(x), nmflag);
            } else if (serial == i) {
                BIO_printf(out, "serial=");
                i2a_ASN1_INTEGER(out, X509_get_serialNumber(x));
                BIO_printf(out, "\n");
            } else if (next_serial == i) {
                BIGNUM *bnser;
                ASN1_INTEGER *ser;
                ser = X509_get_serialNumber(x);
                bnser = ASN1_INTEGER_to_BN(ser, NULL);
                if (!bnser)
                    goto end;
                if (!BN_add_word(bnser, 1))
                    goto end;
                ser = BN_to_ASN1_INTEGER(bnser, NULL);
                if (!ser)
                    goto end;
                BN_free(bnser);
                i2a_ASN1_INTEGER(out, ser);
                ASN1_INTEGER_free(ser);
                BIO_puts(out, "\n");
            } else if ((email == i) || (ocsp_uri == i)) {
                int j;
                STACK_OF(OPENSSL_STRING) *emlst;
                if (email == i)
                    emlst = X509_get1_email(x);
                else
                    emlst = X509_get1_ocsp(x);
                for (j = 0; j < sk_OPENSSL_STRING_num(emlst); j++)
                    BIO_printf(out, "%s\n",
                               sk_OPENSSL_STRING_value(emlst, j));
                X509_email_free(emlst);
            } else if (aliasout == i) {
                unsigned char *alstr;
                alstr = X509_alias_get0(x, NULL);
                if (alstr)
                    BIO_printf(out, "%s\n", alstr);
                else
                    BIO_puts(out, "<No Alias>\n");
            } else if (subject_hash == i) {
                BIO_printf(out, "%08lx\n", X509_subject_name_hash(x));
            }
#ifndef OPENSSL_NO_MD5
            else if (subject_hash_old == i) {
                BIO_printf(out, "%08lx\n", X509_subject_name_hash_old(x));
            }
#endif
            else if (issuer_hash == i) {
                BIO_printf(out, "%08lx\n", X509_issuer_name_hash(x));
            }
#ifndef OPENSSL_NO_MD5
            else if (issuer_hash_old == i) {
                BIO_printf(out, "%08lx\n", X509_issuer_name_hash_old(x));
            }
#endif
            else if (pprint == i) {
                X509_PURPOSE *ptmp;
                int j;
                BIO_printf(out, "Certificate purposes:\n");
                for (j = 0; j < X509_PURPOSE_get_count(); j++) {
                    ptmp = X509_PURPOSE_get0(j);
                    purpose_print(out, x, ptmp);
                }
            } else if (modulus == i) {
                EVP_PKEY *pkey;

                pkey = X509_get0_pubkey(x);
                if (pkey == NULL) {
                    BIO_printf(bio_err, "Modulus=unavailable\n");
                    ERR_print_errors(bio_err);
                    goto end;
                }
                BIO_printf(out, "Modulus=");
#ifndef OPENSSL_NO_RSA
                if (EVP_PKEY_id(pkey) == EVP_PKEY_RSA) {
                    BIGNUM *n;
                    RSA_get0_key(EVP_PKEY_get0_RSA(pkey), &n, NULL, NULL);
                    BN_print(out, n);
                } else
#endif
#ifndef OPENSSL_NO_DSA
                if (EVP_PKEY_id(pkey) == EVP_PKEY_DSA) {
                    BIGNUM *dsapub = NULL;
                    DSA_get0_key(EVP_PKEY_get0_DSA(pkey), &dsapub, NULL);
                    BN_print(out, dsapub);
                } else
#endif
                {
                    BIO_printf(out, "Wrong Algorithm type");
                }
                BIO_printf(out, "\n");
            } else if (pubkey == i) {
                EVP_PKEY *pkey;

                pkey = X509_get0_pubkey(x);
                if (pkey == NULL) {
                    BIO_printf(bio_err, "Error getting public key\n");
                    ERR_print_errors(bio_err);
                    goto end;
                }
                PEM_write_bio_PUBKEY(out, pkey);
            } else if (C == i) {
                unsigned char *d;
                char *m;
                int len;

                X509_NAME_oneline(X509_get_subject_name(x), buf, sizeof buf);
                BIO_printf(out, "/*\n"
                                " * Subject: %s\n", buf);

                X509_NAME_oneline(X509_get_issuer_name(x), buf, sizeof buf);
                BIO_printf(out, " * Issuer:  %s\n"
                                " */\n", buf);

                len = i2d_X509(x, NULL);
                m = app_malloc(len, "x509 name buffer");
                d = (unsigned char *)m;
                len = i2d_X509_NAME(X509_get_subject_name(x), &d);
                print_array(out, "the_subject_name", len, (unsigned char *)m);
                d = (unsigned char *)m;
                len = i2d_X509_PUBKEY(X509_get_X509_PUBKEY(x), &d);
                print_array(out, "the_public_key", len, (unsigned char *)m);
                d = (unsigned char *)m;
                len = i2d_X509(x, &d);
                print_array(out, "the_certificate", len, (unsigned char *)m);
                OPENSSL_free(m);
            } else if (text == i) {
                X509_print_ex(out, x, nmflag, certflag);
            } else if (startdate == i) {
                BIO_puts(out, "notBefore=");
                ASN1_TIME_print(out, X509_get_notBefore(x));
                BIO_puts(out, "\n");
            } else if (enddate == i) {
                BIO_puts(out, "notAfter=");
                ASN1_TIME_print(out, X509_get_notAfter(x));
                BIO_puts(out, "\n");
            } else if (fingerprint == i) {
                int j;
                unsigned int n;
                unsigned char md[EVP_MAX_MD_SIZE];
                const EVP_MD *fdig = digest;

                if (!fdig)
                    fdig = EVP_sha1();

                if (!X509_digest(x, fdig, md, &n)) {
                    BIO_printf(bio_err, "out of memory\n");
                    goto end;
                }
                BIO_printf(out, "%s Fingerprint=",
                           OBJ_nid2sn(EVP_MD_type(fdig)));
                for (j = 0; j < (int)n; j++) {
                    BIO_printf(out, "%02X%c", md[j], (j + 1 == (int)n)
                               ? '\n' : ':');
                }
            }

            /* should be in the library */
            else if ((sign_flag == i) && (x509req == 0)) {
                BIO_printf(bio_err, "Getting Private key\n");
                if (Upkey == NULL) {
                    Upkey = load_key(keyfile, keyformat, 0,
                                     passin, e, "Private key");
                    if (Upkey == NULL)
                        goto end;
                }

                assert(need_rand);
                if (!sign(x, Upkey, days, clrext, digest, extconf, extsect))
                    goto end;
            } else if (CA_flag == i) {
                BIO_printf(bio_err, "Getting CA Private Key\n");
                if (CAkeyfile != NULL) {
                    CApkey = load_key(CAkeyfile, CAkeyformat,
                                      0, passin, e, "CA Private Key");
                    if (CApkey == NULL)
                        goto end;
                }

                assert(need_rand);
                if (!x509_certify(ctx, CAfile, digest, x, xca,
                                  CApkey, sigopts,
                                  CAserial, CA_createserial, days, clrext,
                                  extconf, extsect, sno, reqfile))
                    goto end;
            } else if (x509req == i) {
                EVP_PKEY *pk;

                BIO_printf(bio_err, "Getting request Private Key\n");
                if (keyfile == NULL) {
                    BIO_printf(bio_err, "no request key file specified\n");
                    goto end;
                } else {
                    pk = load_key(keyfile, keyformat, 0,
                                  passin, e, "request key");
                    if (pk == NULL)
                        goto end;
                }

                BIO_printf(bio_err, "Generating certificate request\n");

                rq = X509_to_X509_REQ(x, pk, digest);
                EVP_PKEY_free(pk);
                if (rq == NULL) {
                    ERR_print_errors(bio_err);
                    goto end;
                }
                if (!noout) {
                    X509_REQ_print(out, rq);
                    PEM_write_bio_X509_REQ(out, rq);
                }
                noout = 1;
            } else if (ocspid == i) {
                X509_ocspid_print(out, x);
            }
        }
    }

    if (checkend) {
        time_t tcheck = time(NULL) + checkoffset;

        if (X509_cmp_time(X509_get_notAfter(x), &tcheck) < 0) {
            BIO_printf(out, "Certificate will expire\n");
            ret = 1;
        } else {
            BIO_printf(out, "Certificate will not expire\n");
            ret = 0;
        }
        goto end;
    }

    print_cert_checks(out, x, checkhost, checkemail, checkip);

    if (noout || nocert) {
        ret = 0;
        goto end;
    }

    if (badsig) {
        ASN1_BIT_STRING *signature;
        unsigned char *s;
        X509_get0_signature(&signature, NULL, x);
        s = ASN1_STRING_data(signature);
        s[ASN1_STRING_length(signature) - 1] ^= 0x1;
    }

    if (outformat == FORMAT_ASN1)
        i = i2d_X509_bio(out, x);
    else if (outformat == FORMAT_PEM) {
        if (trustout)
            i = PEM_write_bio_X509_AUX(out, x);
        else
            i = PEM_write_bio_X509(out, x);
    } else {
        BIO_printf(bio_err, "bad output format specified for outfile\n");
        goto end;
    }
    if (!i) {
        BIO_printf(bio_err, "unable to write certificate\n");
        ERR_print_errors(bio_err);
        goto end;
    }
    ret = 0;
 end:
    if (need_rand)
        app_RAND_write_file(NULL);
    NCONF_free(extconf);
    BIO_free_all(out);
    X509_STORE_free(ctx);
    X509_REQ_free(req);
    X509_free(x);
    X509_free(xca);
    EVP_PKEY_free(Upkey);
    EVP_PKEY_free(CApkey);
    EVP_PKEY_free(fkey);
    sk_OPENSSL_STRING_free(sigopts);
    X509_REQ_free(rq);
    ASN1_INTEGER_free(sno);
    sk_ASN1_OBJECT_pop_free(trust, ASN1_OBJECT_free);
    sk_ASN1_OBJECT_pop_free(reject, ASN1_OBJECT_free);
    OPENSSL_free(passin);
    return (ret);
}
Exemple #30
0
int MS_CALLBACK verify_cookie_callback(SSL *ssl, unsigned char *cookie, unsigned int cookie_len)
	{
	unsigned char *buffer, result[EVP_MAX_MD_SIZE];
	unsigned int length, resultlength;
	union {
		struct TINYCLR_SSL_SOCKADDR sa;
		struct TINYCLR_SSL_SOCKADDR_IN s4;
#if OPENSSL_USE_IPV6
		struct sockaddr_in6 s6;
#endif
	} peer;

	/* If secret isn't initialized yet, the cookie can't be valid */
	if (!cookie_initialized)
		return 0;

	/* Read peer information */
	(void)BIO_dgram_get_peer(SSL_get_rbio(ssl), &peer);

	/* Create buffer with peer's address and port */
	length = 0;
	switch (peer.sa.sa_family)
		{
	case AF_INET:
		length += sizeof(struct in_addr);
		length += sizeof(peer.s4.sin_port);
		break;
#if OPENSSL_USE_IPV6
	case AF_INET6:
		length += sizeof(struct in6_addr);
		length += sizeof(peer.s6.sin6_port);
		break;
#endif
	default:
		TINYCLR_SSL_ASSERT(0);
		break;
		}
	buffer = (unsigned char*)OPENSSL_malloc(length);
	
	if (buffer == NULL)
		{
		BIO_printf(bio_err,"out of memory\n");
		return 0;
		}

	switch (peer.sa.sa_family)
		{
	case AF_INET:
		TINYCLR_SSL_MEMCPY(buffer,
		       &peer.s4.sin_port,
		       sizeof(peer.s4.sin_port));
		TINYCLR_SSL_MEMCPY(buffer + sizeof(peer.s4.sin_port),
		       &peer.s4.sin_addr,
		       sizeof(struct in_addr));
		break;
#if OPENSSL_USE_IPV6
	case AF_INET6:
		TINYCLR_SSL_MEMCPY(buffer,
		       &peer.s6.sin6_port,
		       sizeof(peer.s6.sin6_port));
		TINYCLR_SSL_MEMCPY(buffer + sizeof(peer.s6.sin6_port),
		       &peer.s6.sin6_addr,
		       sizeof(struct in6_addr));
		break;
#endif
	default:
		TINYCLR_SSL_ASSERT(0);
		break;
		}

	/* Calculate HMAC of buffer using the secret */
	HMAC(EVP_sha1(), cookie_secret, COOKIE_SECRET_LENGTH,
	     buffer, length, result, &resultlength);
	OPENSSL_free(buffer);

	if (cookie_len == resultlength && TINYCLR_SSL_MEMCMP(result, cookie, resultlength) == 0)
		return 1;

	return 0;
	}