Beispiel #1
0
static
int digest_ticket(const gnutls_datum_t * key, struct ticket_st *ticket,
	      uint8_t * digest)
{
	mac_hd_st digest_hd;
	uint16_t length16;
	int ret;

	ret = _gnutls_mac_init(&digest_hd, mac_to_entry(TICKET_MAC_ALGO),
			      key->data, key->size);
	if (ret < 0) {
		gnutls_assert();
		return ret;
	}

	_gnutls_mac(&digest_hd, ticket->key_name, TICKET_KEY_NAME_SIZE);
	_gnutls_mac(&digest_hd, ticket->IV, TICKET_IV_SIZE);
	length16 = _gnutls_conv_uint16(ticket->encrypted_state_len);
	_gnutls_mac(&digest_hd, &length16, 2);
	_gnutls_mac(&digest_hd, ticket->encrypted_state,
		   ticket->encrypted_state_len);
	_gnutls_mac_deinit(&digest_hd, digest);

	return 0;
}
Beispiel #2
0
/* Randomizes the given password entry. It actually sets the verifier
 * to random data and sets the salt based on fake_salt_seed and
 * username. Returns 0 on success.
 */
static int _randomize_pwd_entry(SRP_PWD_ENTRY * entry,
				gnutls_srp_server_credentials_t sc,
				const char * username)
{
	int ret;
	const mac_entry_st *me = mac_to_entry(SRP_FAKE_SALT_MAC);
	mac_hd_st ctx;
	size_t username_len = strlen(username);

	if (entry->g.size == 0 || entry->n.size == 0) {
		gnutls_assert();
		return GNUTLS_E_INTERNAL_ERROR;
	}

	entry->v.data = gnutls_malloc(20);
	entry->v.size = 20;
	if (entry->v.data == NULL) {
		gnutls_assert();
		return GNUTLS_E_MEMORY_ERROR;
	}

	ret = _gnutls_rnd(GNUTLS_RND_RANDOM, entry->v.data, 20);
	if (ret < 0) {
		gnutls_assert();
		return ret;
	}

	/* Always allocate and work with the output size of the MAC,
	 * even if they don't need salts that long, for convenience.
	 *
	 * In case an error occurs 'entry' (and the salt inside)
	 * is deallocated by our caller: _gnutls_srp_pwd_read_entry().
	 */
	entry->salt.data = gnutls_malloc(me->output_size);
	if (entry->salt.data == NULL) {
		gnutls_assert();
		return GNUTLS_E_MEMORY_ERROR;
	}

	ret = _gnutls_mac_init(&ctx, me, sc->fake_salt_seed.data,
			sc->fake_salt_seed.size);

	if (ret < 0) {
		gnutls_assert();
		return ret;
	}

	_gnutls_mac(&ctx, "salt", 4);
	_gnutls_mac(&ctx, username, username_len);
	_gnutls_mac_deinit(&ctx, entry->salt.data);

	/* Set length to the actual number of bytes they asked for.
	 * This is always less than or equal to the output size of
	 * the MAC, enforced by gnutls_srp_set_server_fake_salt_seed().
	 */
	entry->salt.size = sc->fake_salt_length;

	return 0;
}
Beispiel #3
0
/**
 * gnutls_pkcs12_generate_mac2:
 * @pkcs12: A pkcs12 type
 * @mac: the MAC algorithm to use
 * @pass: The password for the MAC
 *
 * This function will generate a MAC for the PKCS12 structure.
 *
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
 *   negative error value.
 **/
int gnutls_pkcs12_generate_mac2(gnutls_pkcs12_t pkcs12, gnutls_mac_algorithm_t mac, const char *pass)
{
	uint8_t salt[8], key[MAX_HASH_SIZE];
	int result;
	const int iter = 10*1024;
	mac_hd_st td1;
	gnutls_datum_t tmp = { NULL, 0 };
	unsigned mac_size, key_len;
	uint8_t mac_out[MAX_HASH_SIZE];
	const mac_entry_st *me = mac_to_entry(mac);

	if (pkcs12 == NULL || me == NULL)
		return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);

	if (me->oid == NULL)
		return gnutls_assert_val(GNUTLS_E_UNIMPLEMENTED_FEATURE);

	mac_size = _gnutls_mac_get_algo_len(me);
	key_len = mac_size;

	/* Generate the salt.
	 */
	result = gnutls_rnd(GNUTLS_RND_NONCE, salt, sizeof(salt));
	if (result < 0) {
		gnutls_assert();
		return result;
	}

	/* Write the salt into the structure.
	 */
	result =
	    asn1_write_value(pkcs12->pkcs12, "macData.macSalt", salt,
			     sizeof(salt));
	if (result != ASN1_SUCCESS) {
		gnutls_assert();
		result = _gnutls_asn2err(result);
		goto cleanup;
	}

	/* write the iterations
	 */

	if (iter > 1) {
		result =
		    _gnutls_x509_write_uint32(pkcs12->pkcs12,
					      "macData.iterations", iter);
		if (result < 0) {
			gnutls_assert();
			goto cleanup;
		}
	}

	/* Generate the key.
	 */
#if ENABLE_GOST
	if (me->id == GNUTLS_MAC_GOSTR_94 ||
	    me->id == GNUTLS_MAC_STREEBOG_256 ||
	    me->id == GNUTLS_MAC_STREEBOG_512) {
		key_len = 32;
		result = _gnutls_pkcs12_gost_string_to_key(me->id,
							   salt,
							   sizeof(salt),
							   iter,
							   pass,
							   mac_size,
							   key);
	} else
#endif
		result = _gnutls_pkcs12_string_to_key(me, 3 /*MAC*/,
						      salt, sizeof(salt),
						      iter, pass,
						      mac_size, key);
	if (result < 0) {
		gnutls_assert();
		goto cleanup;
	}

	/* Get the data to be MACed
	 */
	result = _decode_pkcs12_auth_safe(pkcs12->pkcs12, NULL, &tmp);
	if (result < 0) {
		gnutls_assert();
		goto cleanup;
	}

	/* MAC the data
	 */
	result = _gnutls_mac_init(&td1, me,
				  key, key_len);
	if (result < 0) {
		gnutls_assert();
		goto cleanup;
	}

	_gnutls_mac(&td1, tmp.data, tmp.size);
	_gnutls_free_datum(&tmp);

	_gnutls_mac_deinit(&td1, mac_out);


	result =
	    asn1_write_value(pkcs12->pkcs12, "macData.mac.digest", mac_out,
			     mac_size);
	if (result != ASN1_SUCCESS) {
		gnutls_assert();
		result = _gnutls_asn2err(result);
		goto cleanup;
	}

	result =
	    asn1_write_value(pkcs12->pkcs12,
			     "macData.mac.digestAlgorithm.parameters",
			     NULL, 0);
	if (result != ASN1_SUCCESS && result != ASN1_ELEMENT_NOT_FOUND) {
		gnutls_assert();
		result = _gnutls_asn2err(result);
		goto cleanup;
	}

	result =
	    asn1_write_value(pkcs12->pkcs12,
			     "macData.mac.digestAlgorithm.algorithm",
			     me->oid, 1);
	if (result != ASN1_SUCCESS) {
		gnutls_assert();
		result = _gnutls_asn2err(result);
		goto cleanup;
	}

	return 0;

      cleanup:
	_gnutls_free_datum(&tmp);
	return result;
}
Beispiel #4
0
/**
 * gnutls_pkcs12_verify_mac:
 * @pkcs12: should contain a gnutls_pkcs12_t type
 * @pass: The password for the MAC
 *
 * This function will verify the MAC for the PKCS12 structure.
 *
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
 *   negative error value.
 **/
int gnutls_pkcs12_verify_mac(gnutls_pkcs12_t pkcs12, const char *pass)
{
	uint8_t key[MAX_HASH_SIZE];
	char oid[MAX_OID_SIZE];
	int result;
	unsigned int iter;
	int len;
	mac_hd_st td1;
	gnutls_datum_t tmp = { NULL, 0 }, salt = {
	NULL, 0};
	uint8_t mac_output[MAX_HASH_SIZE];
	uint8_t mac_output_orig[MAX_HASH_SIZE];
	gnutls_mac_algorithm_t algo;
	unsigned mac_len, key_len;
	const mac_entry_st *entry;
#if ENABLE_GOST
	int gost_retry = 0;
#endif

	if (pkcs12 == NULL) {
		gnutls_assert();
		return GNUTLS_E_INVALID_REQUEST;
	}

	/* read the iterations
	 */
	result =
	    _gnutls_x509_read_uint(pkcs12->pkcs12, "macData.iterations",
				   &iter);
	if (result < 0) {
		iter = 1;	/* the default */
	}

	len = sizeof(oid);
	result =
	    asn1_read_value(pkcs12->pkcs12, "macData.mac.digestAlgorithm.algorithm",
			    oid, &len);
	if (result != ASN1_SUCCESS) {
		gnutls_assert();
		return _gnutls_asn2err(result);
	}

	algo = gnutls_oid_to_digest(oid);
	if (algo == GNUTLS_MAC_UNKNOWN) {
 unknown_mac:
		gnutls_assert();
		return GNUTLS_E_UNKNOWN_HASH_ALGORITHM;
	}

	entry = mac_to_entry(algo);
	if (entry == NULL)
		goto unknown_mac;

	mac_len = _gnutls_mac_get_algo_len(entry);
	key_len = mac_len;

	/* Read the salt from the structure.
	 */
	result =
	    _gnutls_x509_read_null_value(pkcs12->pkcs12, "macData.macSalt",
				    &salt);
	if (result < 0) {
		gnutls_assert();
		goto cleanup;
	}

	/* Generate the key.
	 */
	result = _gnutls_pkcs12_string_to_key(entry, 3 /*MAC*/,
					      salt.data, salt.size,
					      iter, pass,
					      key_len, key);
	if (result < 0) {
		gnutls_assert();
		goto cleanup;
	}

	/* Get the data to be MACed
	 */
	result = _decode_pkcs12_auth_safe(pkcs12->pkcs12, NULL, &tmp);
	if (result < 0) {
		gnutls_assert();
		goto cleanup;
	}

#if ENABLE_GOST
	/* GOST PKCS#12 files use either PKCS#12 scheme or proprietary
	 * HMAC-based scheme to generate MAC key. */
pkcs12_try_gost:
#endif

	/* MAC the data
	 */
	result = _gnutls_mac_init(&td1, entry, key, key_len);
	if (result < 0) {
		gnutls_assert();
		goto cleanup;
	}

	_gnutls_mac(&td1, tmp.data, tmp.size);

	_gnutls_mac_deinit(&td1, mac_output);

	len = sizeof(mac_output_orig);
	result =
	    asn1_read_value(pkcs12->pkcs12, "macData.mac.digest",
			    mac_output_orig, &len);
	if (result != ASN1_SUCCESS) {
		gnutls_assert();
		result = _gnutls_asn2err(result);
		goto cleanup;
	}

	if ((unsigned)len != mac_len ||
	    memcmp(mac_output_orig, mac_output, len) != 0) {

#if ENABLE_GOST
		/* It is possible that GOST files use proprietary
		 * key generation scheme */
		if (!gost_retry &&
		    (algo == GNUTLS_MAC_GOSTR_94 ||
		     algo == GNUTLS_MAC_STREEBOG_256 ||
		     algo == GNUTLS_MAC_STREEBOG_512)) {
			gost_retry = 1;
			key_len = 32;
			result = _gnutls_pkcs12_gost_string_to_key(algo,
								   salt.data,
								   salt.size,
								   iter,
								   pass,
								   key_len,
								   key);
			if (result < 0) {
				gnutls_assert();
				goto cleanup;
			}

			goto pkcs12_try_gost;
		}
#endif

		gnutls_assert();
		result = GNUTLS_E_MAC_VERIFY_FAILED;
		goto cleanup;
	}

	result = 0;
 cleanup:
	_gnutls_free_datum(&tmp);
	_gnutls_free_datum(&salt);
	return result;
}
Beispiel #5
0
/* Auth_cipher API 
 */
int _gnutls_auth_cipher_init(auth_cipher_hd_st * handle,
			     const cipher_entry_st * e,
			     const gnutls_datum_t * cipher_key,
			     const gnutls_datum_t * iv,
			     const mac_entry_st * me,
			     const gnutls_datum_t * mac_key,
			     unsigned etm,
			     unsigned ssl_hmac, int enc)
{
	int ret;

	if (unlikely(e == NULL))
		return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);

        FAIL_IF_LIB_ERROR;

	memset(handle, 0, sizeof(*handle));
	handle->etm = etm;

	if (e->id != GNUTLS_CIPHER_NULL) {
		handle->non_null = 1;
		ret =
		    _gnutls_cipher_init(&handle->cipher, e, cipher_key, iv,
					enc);
		if (ret < 0)
			return gnutls_assert_val(ret);
	} else
		handle->non_null = 0;

	if (me->id != GNUTLS_MAC_AEAD) {
		handle->is_mac = 1;
		handle->ssl_hmac = ssl_hmac;

		if (ssl_hmac)
			ret =
			    _gnutls_mac_init_ssl3(&handle->mac.dig, me,
						  mac_key->data,
						  mac_key->size);
		else
			ret =
			    _gnutls_mac_init(&handle->mac.mac, me,
					     mac_key->data, mac_key->size);
		if (ret < 0) {
			gnutls_assert();
			goto cleanup;
		}

		handle->tag_size = _gnutls_mac_get_algo_len(me);
	} else if (_gnutls_cipher_algo_is_aead(e)) {
		handle->tag_size = _gnutls_cipher_get_tag_size(e);
	} else {
		gnutls_assert();
		ret = GNUTLS_E_INVALID_REQUEST;
		goto cleanup;
	}

	return 0;
      cleanup:
	if (handle->non_null != 0)
		_gnutls_cipher_deinit(&handle->cipher);
	return ret;

}
Beispiel #6
0
/**
 * gnutls_pkcs12_verify_mac:
 * @pkcs12: should contain a gnutls_pkcs12_t structure
 * @pass: The password for the MAC
 *
 * This function will verify the MAC for the PKCS12 structure.
 *
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
 *   negative error value.
 **/
int gnutls_pkcs12_verify_mac(gnutls_pkcs12_t pkcs12, const char *pass)
{
	uint8_t key[20];
	int result;
	unsigned int iter;
	int len;
	mac_hd_st td1;
	gnutls_datum_t tmp = { NULL, 0 }, salt = {
	NULL, 0};
	uint8_t sha_mac[20];
	uint8_t sha_mac_orig[20];

	if (pkcs12 == NULL) {
		gnutls_assert();
		return GNUTLS_E_INVALID_REQUEST;
	}

	/* read the iterations
	 */

	result =
	    _gnutls_x509_read_uint(pkcs12->pkcs12, "macData.iterations",
				   &iter);
	if (result < 0) {
		iter = 1;	/* the default */
	}


	/* Read the salt from the structure.
	 */
	result =
	    _gnutls_x509_read_value(pkcs12->pkcs12, "macData.macSalt",
				    &salt);
	if (result != ASN1_SUCCESS) {
		gnutls_assert();
		result = _gnutls_asn2err(result);
		goto cleanup;
	}

	/* Generate the key.
	 */
	result =
	    _gnutls_pkcs12_string_to_key(3 /*MAC*/, salt.data, salt.size,
					 iter, pass, sizeof(key), key);
	if (result < 0) {
		gnutls_assert();
		goto cleanup;
	}

	_gnutls_free_datum(&salt);

	/* Get the data to be MACed
	 */
	result = _decode_pkcs12_auth_safe(pkcs12->pkcs12, NULL, &tmp);
	if (result < 0) {
		gnutls_assert();
		goto cleanup;
	}

	/* MAC the data
	 */
	result = _gnutls_mac_init(&td1, mac_to_entry(GNUTLS_MAC_SHA1),
				  key, sizeof(key));
	if (result < 0) {
		gnutls_assert();
		goto cleanup;
	}

	_gnutls_mac(&td1, tmp.data, tmp.size);
	_gnutls_free_datum(&tmp);

	_gnutls_mac_deinit(&td1, sha_mac);

	len = sizeof(sha_mac_orig);
	result =
	    asn1_read_value(pkcs12->pkcs12, "macData.mac.digest",
			    sha_mac_orig, &len);
	if (result != ASN1_SUCCESS) {
		gnutls_assert();
		result = _gnutls_asn2err(result);
		goto cleanup;
	}

	if (memcmp(sha_mac_orig, sha_mac, sizeof(sha_mac)) != 0) {
		gnutls_assert();
		return GNUTLS_E_MAC_VERIFY_FAILED;
	}

	return 0;

      cleanup:
	_gnutls_free_datum(&tmp);
	_gnutls_free_datum(&salt);
	return result;
}
Beispiel #7
0
/**
 * gnutls_pkcs12_generate_mac:
 * @pkcs12: should contain a gnutls_pkcs12_t structure
 * @pass: The password for the MAC
 *
 * This function will generate a MAC for the PKCS12 structure.
 *
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
 *   negative error value.
 **/
int gnutls_pkcs12_generate_mac(gnutls_pkcs12_t pkcs12, const char *pass)
{
	uint8_t salt[8], key[20];
	int result;
	const int iter = 1;
	mac_hd_st td1;
	gnutls_datum_t tmp = { NULL, 0 };
	uint8_t sha_mac[20];

	if (pkcs12 == NULL) {
		gnutls_assert();
		return GNUTLS_E_INVALID_REQUEST;
	}

	/* Generate the salt.
	 */
	result = _gnutls_rnd(GNUTLS_RND_NONCE, salt, sizeof(salt));
	if (result < 0) {
		gnutls_assert();
		return result;
	}

	/* Write the salt into the structure.
	 */
	result =
	    asn1_write_value(pkcs12->pkcs12, "macData.macSalt", salt,
			     sizeof(salt));
	if (result != ASN1_SUCCESS) {
		gnutls_assert();
		result = _gnutls_asn2err(result);
		goto cleanup;
	}

	/* write the iterations
	 */

	if (iter > 1) {
		result =
		    _gnutls_x509_write_uint32(pkcs12->pkcs12,
					      "macData.iterations", iter);
		if (result < 0) {
			gnutls_assert();
			goto cleanup;
		}
	}

	/* Generate the key.
	 */
	result =
	    _gnutls_pkcs12_string_to_key(3 /*MAC*/, salt, sizeof(salt),
					 iter, pass, sizeof(key), key);
	if (result < 0) {
		gnutls_assert();
		goto cleanup;
	}

	/* Get the data to be MACed
	 */
	result = _decode_pkcs12_auth_safe(pkcs12->pkcs12, NULL, &tmp);
	if (result < 0) {
		gnutls_assert();
		goto cleanup;
	}

	/* MAC the data
	 */
	result = _gnutls_mac_init(&td1, mac_to_entry(GNUTLS_MAC_SHA1),
				  key, sizeof(key));
	if (result < 0) {
		gnutls_assert();
		goto cleanup;
	}

	_gnutls_mac(&td1, tmp.data, tmp.size);
	_gnutls_free_datum(&tmp);

	_gnutls_mac_deinit(&td1, sha_mac);


	result =
	    asn1_write_value(pkcs12->pkcs12, "macData.mac.digest", sha_mac,
			     sizeof(sha_mac));
	if (result != ASN1_SUCCESS) {
		gnutls_assert();
		result = _gnutls_asn2err(result);
		goto cleanup;
	}

	result =
	    asn1_write_value(pkcs12->pkcs12,
			     "macData.mac.digestAlgorithm.parameters",
			     NULL, 0);
	if (result != ASN1_SUCCESS) {
		gnutls_assert();
		result = _gnutls_asn2err(result);
		goto cleanup;
	}

	result =
	    asn1_write_value(pkcs12->pkcs12,
			     "macData.mac.digestAlgorithm.algorithm",
			     HASH_OID_SHA1, 1);
	if (result != ASN1_SUCCESS) {
		gnutls_assert();
		result = _gnutls_asn2err(result);
		goto cleanup;
	}

	return 0;

      cleanup:
	_gnutls_free_datum(&tmp);
	return result;
}