Ejemplo n.º 1
0
/**
 * cdk_pk_get_fingerprint:
 * @pk: the public key
 * @fpr: the buffer to hold the fingerprint
 * 
 * Return the fingerprint of the given public key.
 * The buffer must be at least 20 octets.
 * This function should be considered deprecated and
 * the new cdk_pk_to_fingerprint() should be used whenever
 * possible to avoid overflows.
 **/
cdk_error_t cdk_pk_get_fingerprint(cdk_pubkey_t pk, byte * fpr)
{
	digest_hd_st hd;
	int md_algo;
	int dlen = 0;
	int err;
	const mac_entry_st *me;

	if (!pk || !fpr)
		return CDK_Inv_Value;

	if (pk->version < 4 && is_RSA(pk->pubkey_algo))
		md_algo = GNUTLS_DIG_MD5;	/* special */
	else
		md_algo = GNUTLS_DIG_SHA1;

	me = mac_to_entry(md_algo);

	dlen = _gnutls_hash_get_algo_len(me);
	err = _gnutls_hash_init(&hd, me);
	if (err < 0) {
		gnutls_assert();
		return map_gnutls_error(err);
	}
	_cdk_hash_pubkey(pk, &hd, 1);
	_gnutls_hash_deinit(&hd, fpr);
	if (dlen == 16)
		memset(fpr + 16, 0, 4);
	return 0;
}
Ejemplo n.º 2
0
/* generate x = SHA(s | SHA(U | ":" | p))
 * The output is exactly 20 bytes
 */
static int
_gnutls_calc_srp_sha(const char *username, const char *password,
		     uint8_t * salt, int salt_size, size_t * size,
		     void *digest)
{
	digest_hd_st td;
	uint8_t res[MAX_HASH_SIZE];
	int ret;
	const mac_entry_st *me = mac_to_entry(GNUTLS_MAC_SHA1);

	*size = 20;

	ret = _gnutls_hash_init(&td, me);
	if (ret < 0) {
		return GNUTLS_E_MEMORY_ERROR;
	}
	_gnutls_hash(&td, username, strlen(username));
	_gnutls_hash(&td, ":", 1);
	_gnutls_hash(&td, password, strlen(password));

	_gnutls_hash_deinit(&td, res);

	ret = _gnutls_hash_init(&td, me);
	if (ret < 0) {
		return GNUTLS_E_MEMORY_ERROR;
	}

	_gnutls_hash(&td, salt, salt_size);
	_gnutls_hash(&td, res, 20);	/* 20 bytes is the output of sha1 */

	_gnutls_hash_deinit(&td, digest);

	return 0;
}
Ejemplo n.º 3
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;
}
Ejemplo n.º 4
0
static int
ssl3_sha(int i, uint8_t * secret, int secret_len,
	 uint8_t * rnd, int rnd_len, void *digest)
{
	int j, ret;
	uint8_t text1[26];

	digest_hd_st td;

	for (j = 0; j < i + 1; j++) {
		text1[j] = 65 + i;	/* A==65 */
	}

	ret = _gnutls_hash_init(&td, mac_to_entry(GNUTLS_MAC_SHA1));
	if (ret < 0) {
		gnutls_assert();
		return ret;
	}

	_gnutls_hash(&td, text1, i + 1);
	_gnutls_hash(&td, secret, secret_len);
	_gnutls_hash(&td, rnd, rnd_len);

	_gnutls_hash_deinit(&td, digest);
	return 0;
}
Ejemplo n.º 5
0
static int
ssl3_md5(int i, uint8_t * secret, int secret_len,
	 uint8_t * rnd, int rnd_len, void *digest)
{
	uint8_t tmp[MAX_HASH_SIZE];
	digest_hd_st td;
	int ret;

	ret = _gnutls_hash_init(&td, mac_to_entry(GNUTLS_MAC_MD5));
	if (ret < 0) {
		gnutls_assert();
		return ret;
	}

	_gnutls_hash(&td, secret, secret_len);

	ret = ssl3_sha(i, secret, secret_len, rnd, rnd_len, tmp);
	if (ret < 0) {
		gnutls_assert();
		_gnutls_hash_deinit(&td, digest);
		return ret;
	}

	_gnutls_hash(&td, tmp, SHA1_DIGEST_OUTPUT);

	_gnutls_hash_deinit(&td, digest);
	return 0;
}
Ejemplo n.º 6
0
int
_gnutls_ssl3_hash_md5(const void *first, int first_len,
		      const void *second, int second_len,
		      int ret_len, uint8_t * ret)
{
	uint8_t digest[MAX_HASH_SIZE];
	digest_hd_st td;
	int block = MD5_DIGEST_OUTPUT;
	int rc;

	rc = _gnutls_hash_init(&td, mac_to_entry(GNUTLS_MAC_MD5));
	if (rc < 0) {
		gnutls_assert();
		return rc;
	}

	_gnutls_hash(&td, first, first_len);
	_gnutls_hash(&td, second, second_len);

	_gnutls_hash_deinit(&td, digest);

	if (ret_len > block) {
		gnutls_assert();
		return GNUTLS_E_INTERNAL_ERROR;
	}

	memcpy(ret, digest, ret_len);

	return 0;

}
Ejemplo n.º 7
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;
}
Ejemplo n.º 8
0
const mac_entry_st *_gnutls_cipher_suite_get_mac_algo(const uint8_t
						      suite[2])
{				/* In bytes */
	int ret = 0;
	CIPHER_SUITE_ALG_LOOP(ret = p->mac_algorithm);
	return mac_to_entry(ret);

}
Ejemplo n.º 9
0
/**
 * gnutls_sign_is_secure:
 * @algorithm: is a sign algorithm
 *
 * Returns: Non-zero if the provided signature algorithm is considered to be secure.
 **/
int 
gnutls_sign_is_secure (gnutls_sign_algorithm_t algorithm)
{
  gnutls_sign_algorithm_t sign = algorithm;
  gnutls_digest_algorithm_t dig = GNUTLS_DIG_UNKNOWN;

  /* avoid prefix */
  GNUTLS_SIGN_ALG_LOOP (dig = p->mac);
  
  if (dig != GNUTLS_DIG_UNKNOWN)
    return _gnutls_digest_is_secure(mac_to_entry(dig));

  return 0;
}
Ejemplo n.º 10
0
static int
openssl_hash_password(const char *pass, gnutls_datum_t * key,
		      gnutls_datum_t * salt)
{
	unsigned char md5[16];
	digest_hd_st hd;
	unsigned int count = 0;
	int err;

	while (count < key->size) {
		err = _gnutls_hash_init(&hd, mac_to_entry(GNUTLS_MAC_MD5));
		if (err) {
			gnutls_assert();
			return err;
		}
		if (count) {
			err = _gnutls_hash(&hd, md5, sizeof(md5));
			if (err) {
			      hash_err:
				_gnutls_hash_deinit(&hd, NULL);
				gnutls_assert();
				return err;
			}
		}
		if (pass) {
			err = _gnutls_hash(&hd, pass, strlen(pass));
			if (err) {
				gnutls_assert();
				goto hash_err;
			}
		}
		err = _gnutls_hash(&hd, salt->data, 8);
		if (err) {
			gnutls_assert();
			goto hash_err;
		}

		_gnutls_hash_deinit(&hd, md5);

		if (key->size - count <= sizeof(md5)) {
			memcpy(&key->data[count], md5, key->size - count);
			break;
		}

		memcpy(&key->data[count], md5, sizeof(md5));
		count += sizeof(md5);
	}

	return 0;
}
Ejemplo n.º 11
0
/**
 * gnutls_srp_set_server_fake_salt_seed:
 * @cred: is a #gnutls_srp_server_credentials_t type
 * @seed: is the seed data, only needs to be valid until the function
 * returns; size of the seed must be greater than zero
 * @salt_length: is the length of the generated fake salts
 *
 * This function sets the seed that is used to generate salts for
 * invalid (non-existent) usernames.
 *
 * In order to prevent attackers from guessing valid usernames,
 * when a user does not exist gnutls generates a salt and a verifier
 * and proceeds with the protocol as usual.
 * The authentication will ultimately fail, but the client cannot tell
 * whether the username is valid (exists) or invalid.
 *
 * If an attacker learns the seed, given a salt (which is part of the
 * handshake) which was generated when the seed was in use, it can tell
 * whether or not the authentication failed because of an unknown username.
 * This seed cannot be used to reveal application data or passwords.
 *
 * @salt_length should represent the salt length your application uses.
 * Generating fake salts longer than 20 bytes is not supported.
 *
 * By default the seed is a random value, different each time a
 * #gnutls_srp_server_credentials_t is allocated and fake salts are
 * 16 bytes long.
 *
 * Since: 3.3.0
 **/
void
gnutls_srp_set_server_fake_salt_seed(gnutls_srp_server_credentials_t cred,
				     const gnutls_datum_t * seed,
				     unsigned int salt_length)
{
	_gnutls_free_datum(&cred->fake_salt_seed);
	_gnutls_set_datum(&cred->fake_salt_seed, seed->data, seed->size);

	/* Cap the salt length at the output size of the MAC algorithm
	 * we are using to generate the fake salts.
	 */
	const mac_entry_st * me = mac_to_entry(SRP_FAKE_SALT_MAC);
	const size_t mac_len = me->output_size;

	cred->fake_salt_length = (salt_length < mac_len ? salt_length : mac_len);
}
Ejemplo n.º 12
0
void
_gnutls_epoch_set_null_algos(gnutls_session_t session,
			     record_parameters_st * params)
{
	/* This is only called on startup. We are extra paranoid about this
	   because it may cause unencrypted application data to go out on
	   the wire. */
	if (params->initialized || params->epoch != 0) {
		gnutls_assert();
		return;
	}

	params->cipher = cipher_to_entry(GNUTLS_CIPHER_NULL);
	params->mac = mac_to_entry(GNUTLS_MAC_NULL);
	params->compression_algorithm = GNUTLS_COMP_NULL;
	params->initialized = 1;
}
Ejemplo n.º 13
0
/**
 * gnutls_privkey_sign_hash:
 * @signer: Holds the signer's key
 * @hash_algo: The hash algorithm used
 * @flags: Zero or one of %gnutls_privkey_flags_t
 * @hash_data: holds the data to be signed
 * @signature: will contain newly allocated signature
 *
 * This function will sign the given hashed data using a signature algorithm
 * supported by the private key. Signature algorithms are always used
 * together with a hash functions.  Different hash functions may be
 * used for the RSA algorithm, but only SHA-XXX for the DSA keys.
 *
 * You may use gnutls_pubkey_get_preferred_hash_algorithm() to determine
 * the hash algorithm.
 *
 * Note that if %GNUTLS_PRIVKEY_SIGN_FLAG_TLS1_RSA flag is specified this function
 * will ignore @hash_algo and perform a raw PKCS1 signature.
 *
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
 *   negative error value.
 *
 * Since: 2.12.0
 **/
int
gnutls_privkey_sign_hash(gnutls_privkey_t signer,
			 gnutls_digest_algorithm_t hash_algo,
			 unsigned int flags,
			 const gnutls_datum_t * hash_data,
			 gnutls_datum_t * signature)
{
	int ret;
	gnutls_datum_t digest;

	if (flags & GNUTLS_PRIVKEY_SIGN_FLAG_TLS1_RSA)
		return gnutls_privkey_sign_raw_data(signer, flags,
						    hash_data, signature);

	digest.data = gnutls_malloc(hash_data->size);
	if (digest.data == NULL) {
		gnutls_assert();
		return GNUTLS_E_MEMORY_ERROR;
	}
	digest.size = hash_data->size;
	memcpy(digest.data, hash_data->data, digest.size);

	ret =
	    pk_prepare_hash(signer->pk_algorithm, mac_to_entry(hash_algo),
			    &digest);
	if (ret < 0) {
		gnutls_assert();
		goto cleanup;
	}

	ret =
	    gnutls_privkey_sign_raw_data(signer, flags, &digest,
					 signature);
	if (ret < 0) {
		gnutls_assert();
		goto cleanup;
	}

	ret = 0;

      cleanup:
	_gnutls_free_datum(&digest);
	return ret;
}
Ejemplo n.º 14
0
/**
 * gnutls_privkey_sign_data:
 * @signer: Holds the key
 * @hash: should be a digest algorithm
 * @flags: Zero or one of %gnutls_privkey_flags_t
 * @data: holds the data to be signed
 * @signature: will contain the signature allocate with gnutls_malloc()
 *
 * This function will sign the given data using a signature algorithm
 * supported by the private key. Signature algorithms are always used
 * together with a hash functions.  Different hash functions may be
 * used for the RSA algorithm, but only the SHA family for the DSA keys.
 *
 * You may use gnutls_pubkey_get_preferred_hash_algorithm() to determine
 * the hash algorithm.
 *
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
 * negative error value.
 *
 * Since: 2.12.0
 **/
int
gnutls_privkey_sign_data(gnutls_privkey_t signer,
			 gnutls_digest_algorithm_t hash,
			 unsigned int flags,
			 const gnutls_datum_t * data,
			 gnutls_datum_t * signature)
{
	int ret;
	gnutls_datum_t digest;
	const mac_entry_st *me = mac_to_entry(hash);

	if (flags & GNUTLS_PRIVKEY_SIGN_FLAG_TLS1_RSA)
		return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);

	ret = pk_hash_data(signer->pk_algorithm, me, NULL, data, &digest);
	if (ret < 0) {
		gnutls_assert();
		return ret;
	}

	ret = pk_prepare_hash(signer->pk_algorithm, me, &digest);
	if (ret < 0) {
		gnutls_assert();
		goto cleanup;
	}

	ret =
	    gnutls_privkey_sign_raw_data(signer, flags, &digest,
					 signature);
	_gnutls_free_datum(&digest);

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

	return 0;

      cleanup:
	_gnutls_free_datum(&digest);
	return ret;
}
Ejemplo n.º 15
0
int
_gnutls_epoch_set_cipher_suite(gnutls_session_t session,
			       int epoch_rel, const uint8_t suite[2])
{
	const cipher_entry_st *cipher_algo;
	const mac_entry_st *mac_algo;
	record_parameters_st *params;
	const gnutls_cipher_suite_entry_st *cs;
	int ret;

	ret = _gnutls_epoch_get(session, epoch_rel, &params);
	if (ret < 0)
		return gnutls_assert_val(ret);

	if (params->initialized
	    || params->cipher != NULL || params->mac != NULL)
		return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);

	cs = ciphersuite_to_entry(suite);
	if (cs == NULL)
		return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);

	cipher_algo = cipher_to_entry(cs->block_algorithm);
	mac_algo = mac_to_entry(cs->mac_algorithm);

	if (_gnutls_cipher_is_ok(cipher_algo) == 0
	    || _gnutls_mac_is_ok(mac_algo) == 0)
		return gnutls_assert_val(GNUTLS_E_UNWANTED_ALGORITHM);

	if (_gnutls_cipher_priority(session, cipher_algo->id) < 0)
		return gnutls_assert_val(GNUTLS_E_UNWANTED_ALGORITHM);

	if (_gnutls_mac_priority(session, mac_algo->id) < 0)
		return gnutls_assert_val(GNUTLS_E_UNWANTED_ALGORITHM);

	params->cipher = cipher_algo;
	params->mac = mac_algo;

	return 0;
}
Ejemplo n.º 16
0
/* 
 * Verifies the given certificate against a certificate list of
 * trusted CAs.
 *
 * Returns only 0 or 1. If 1 it means that the certificate 
 * was successfuly verified.
 *
 * 'flags': an OR of the gnutls_certificate_verify_flags enumeration.
 *
 * Output will hold some extra information about the verification
 * procedure.
 */
static unsigned
verify_crt(gnutls_x509_crt_t cert,
			    const gnutls_x509_crt_t * trusted_cas,
			    int tcas_size, unsigned int flags,
			    unsigned int *output,
			    verify_state_st *vparams,
			    unsigned end_cert)
{
	gnutls_datum_t cert_signed_data = { NULL, 0 };
	gnutls_datum_t cert_signature = { NULL, 0 };
	gnutls_x509_crt_t issuer = NULL;
	int issuer_version, hash_algo;
	unsigned result = 1;
	const mac_entry_st * me;
	unsigned int out = 0, usage;
	int sigalg, ret;

	if (output)
		*output = 0;

	if (vparams->max_path == 0) {
		MARK_INVALID(GNUTLS_CERT_SIGNER_CONSTRAINTS_FAILURE);
		/* bail immediately, to avoid inconistency  */
		goto cleanup;
	}
	vparams->max_path--;

	if (tcas_size >= 1)
		issuer = find_issuer(cert, trusted_cas, tcas_size);

	ret =
	    _gnutls_x509_get_signed_data(cert->cert, &cert->der, "tbsCertificate",
					 &cert_signed_data);
	if (ret < 0) {
		MARK_INVALID(0);
		cert_signed_data.data = NULL;
	}

	ret =
	    _gnutls_x509_get_signature(cert->cert, "signature",
				       &cert_signature);
	if (ret < 0) {
		MARK_INVALID(0);
		cert_signature.data = NULL;
	}

	ret =
	    _gnutls_x509_get_signature_algorithm(cert->cert,
						 "signatureAlgorithm.algorithm");
	if (ret < 0) {
		MARK_INVALID(0);
	}
	sigalg = ret;

	/* issuer is not in trusted certificate
	 * authorities.
	 */
	if (issuer == NULL) {
		MARK_INVALID(GNUTLS_CERT_SIGNER_NOT_FOUND);
	} else {
		if (vparams->nc != NULL) {
			/* append the issuer's constraints */
			ret = gnutls_x509_crt_get_name_constraints(issuer, vparams->nc, 
				GNUTLS_NAME_CONSTRAINTS_FLAG_APPEND, NULL);
			if (ret < 0 && ret != GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
				MARK_INVALID(GNUTLS_CERT_SIGNER_CONSTRAINTS_FAILURE);
				goto nc_done;
			}

			/* only check name constraints in server certificates, not CAs */
			if (end_cert != 0) {
				ret = gnutls_x509_name_constraints_check_crt(vparams->nc, GNUTLS_SAN_DNSNAME, cert);
				if (ret == 0) {
					MARK_INVALID(GNUTLS_CERT_SIGNER_CONSTRAINTS_FAILURE);
					goto nc_done;
				}

				ret = gnutls_x509_name_constraints_check_crt(vparams->nc, GNUTLS_SAN_RFC822NAME, cert);
				if (ret == 0) {
					MARK_INVALID(GNUTLS_CERT_SIGNER_CONSTRAINTS_FAILURE);
					goto nc_done;
				}

				ret = gnutls_x509_name_constraints_check_crt(vparams->nc, GNUTLS_SAN_DN, cert);
				if (ret == 0) {
					MARK_INVALID(GNUTLS_CERT_SIGNER_CONSTRAINTS_FAILURE);
					goto nc_done;
				}

				ret = gnutls_x509_name_constraints_check_crt(vparams->nc, GNUTLS_SAN_URI, cert);
				if (ret == 0) {
					MARK_INVALID(GNUTLS_CERT_SIGNER_CONSTRAINTS_FAILURE);
					goto nc_done;
				}

				ret = gnutls_x509_name_constraints_check_crt(vparams->nc, GNUTLS_SAN_IPADDRESS, cert);
				if (ret == 0) {
					MARK_INVALID(GNUTLS_CERT_SIGNER_CONSTRAINTS_FAILURE);
					goto nc_done;
				}
			}
		}

 nc_done:
		if (vparams->tls_feat != NULL) {
			/* append the issuer's constraints */
			ret = gnutls_x509_crt_get_tlsfeatures(issuer, vparams->tls_feat, GNUTLS_EXT_FLAG_APPEND, NULL);
			if (ret < 0 && ret != GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
				MARK_INVALID(GNUTLS_CERT_SIGNER_CONSTRAINTS_FAILURE);
				goto feat_done;
			}

			ret = gnutls_x509_tlsfeatures_check_crt(vparams->tls_feat, cert);
			if (ret == 0) {
				MARK_INVALID(GNUTLS_CERT_SIGNER_CONSTRAINTS_FAILURE);
				goto feat_done;
			}
		}

 feat_done:
		issuer_version = gnutls_x509_crt_get_version(issuer);

		if (issuer_version < 0) {
			MARK_INVALID(0);
		} else if (!(flags & GNUTLS_VERIFY_DISABLE_CA_SIGN) &&
			   ((flags & GNUTLS_VERIFY_DO_NOT_ALLOW_X509_V1_CA_CRT)
			    || issuer_version != 1)) {
			if (check_if_ca(cert, issuer, &vparams->max_path, flags) != 1) {
				MARK_INVALID(GNUTLS_CERT_SIGNER_NOT_CA);
			}

			ret =
			    gnutls_x509_crt_get_key_usage(issuer, &usage, NULL);
			if (ret != GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
				if (ret < 0) {
					MARK_INVALID(0);
				} else if (!(usage & GNUTLS_KEY_KEY_CERT_SIGN)) {
					MARK_INVALID(GNUTLS_CERT_SIGNER_CONSTRAINTS_FAILURE);
				}
			}
		}

		if (sigalg >= 0) {
			hash_algo = gnutls_sign_get_hash_algorithm(sigalg);
			me = mac_to_entry(hash_algo);
		} else {
			me = NULL;
		}

		if (me == NULL) {
			MARK_INVALID(0);
		} else if (cert_signed_data.data != NULL &&
			   cert_signature.data != NULL) {
			ret =
			    _gnutls_x509_verify_data(me,
						     &cert_signed_data,
						     &cert_signature,
						     issuer);
			if (ret == GNUTLS_E_PK_SIG_VERIFY_FAILED) {
				MARK_INVALID(GNUTLS_CERT_SIGNATURE_FAILURE);
			} else if (ret < 0) {
				MARK_INVALID(0);
			}
		}
	}

	/* we always check the issuer for unsupported critical extensions */
	if (issuer && check_for_unknown_exts(issuer) != 0) {
		if (!(flags & GNUTLS_VERIFY_IGNORE_UNKNOWN_CRIT_EXTENSIONS)) {
			MARK_INVALID(GNUTLS_CERT_UNKNOWN_CRIT_EXTENSIONS);
		}
	}

	/* we only check the end-certificate for critical extensions; that
	 * way do not perform this check twice on the certificates when
	 * verifying a large list */
	if (end_cert && check_for_unknown_exts(cert) != 0) {
		if (!(flags & GNUTLS_VERIFY_IGNORE_UNKNOWN_CRIT_EXTENSIONS)) {
			MARK_INVALID(GNUTLS_CERT_UNKNOWN_CRIT_EXTENSIONS);
		}
	}

	if (sigalg >= 0) {
		if (is_level_acceptable(cert, issuer, sigalg, flags) == 0) {
			MARK_INVALID(GNUTLS_CERT_INSECURE_ALGORITHM);
		}

		/* If the certificate is not self signed check if the algorithms
		 * used are secure. If the certificate is self signed it doesn't
		 * really matter.
		 */
		if (gnutls_sign_is_secure(sigalg) == 0 &&
		    _gnutls_is_broken_sig_allowed(sigalg, flags) == 0 &&
		    is_issuer(cert, cert) == 0) {
			MARK_INVALID(GNUTLS_CERT_INSECURE_ALGORITHM);
		}
	}

	/* Check activation/expiration times
	 */
	if (!(flags & GNUTLS_VERIFY_DISABLE_TIME_CHECKS)) {
		/* check the time of the issuer first */
		if (issuer != NULL &&
		    !(flags & GNUTLS_VERIFY_DISABLE_TRUSTED_TIME_CHECKS)) {
			out |= check_time_status(issuer, vparams->now);
			if (out != 0) {
				gnutls_assert();
				result = 0;
			}
		}

		out |= check_time_status(cert, vparams->now);
		if (out != 0) {
			gnutls_assert();
			result = 0;
		}
	}

      cleanup:
	if (output)
		*output |= out;

	if (vparams->func) {
		if (result == 0) {
			out |= GNUTLS_CERT_INVALID;
		}
		vparams->func(cert, issuer, NULL, out);
	}
	_gnutls_free_datum(&cert_signed_data);
	_gnutls_free_datum(&cert_signature);

	return result;
}
Ejemplo n.º 17
0
/**
 * gnutls_x509_crl_verify:
 * @crl: is the crl to be verified
 * @trusted_cas: is a certificate list that is considered to be trusted one
 * @tcas_size: holds the number of CA certificates in CA_list
 * @flags: Flags that may be used to change the verification algorithm. Use OR of the gnutls_certificate_verify_flags enumerations.
 * @verify: will hold the crl verification output.
 *
 * This function will try to verify the given crl and return its verification status.
 * See gnutls_x509_crt_list_verify() for a detailed description of
 * return values. Note that since GnuTLS 3.1.4 this function includes
 * the time checks.
 *
 * Note that value in @verify is set only when the return value of this 
 * function is success (i.e, failure to trust a CRL a certificate does not imply 
 * a negative return value).
 *
 * Before GnuTLS 3.5.7 this function would return zero or a positive
 * number on success.
 *
 * Returns: On success, %GNUTLS_E_SUCCESS (0), otherwise a
 *   negative error value.
 **/
int
gnutls_x509_crl_verify(gnutls_x509_crl_t crl,
		       const gnutls_x509_crt_t * trusted_cas,
		       unsigned tcas_size, unsigned int flags,
		       unsigned int *verify)
{
/* CRL is ignored for now */
	gnutls_datum_t crl_signed_data = { NULL, 0 };
	gnutls_datum_t crl_signature = { NULL, 0 };
	gnutls_x509_crt_t issuer = NULL;
	int result, hash_algo;
	time_t now = gnutls_time(0);
	unsigned int usage;

	if (verify)
		*verify = 0;

	if (tcas_size >= 1)
		issuer = find_crl_issuer(crl, trusted_cas, tcas_size);

	result =
	    _gnutls_x509_get_signed_data(crl->crl, &crl->der, "tbsCertList",
					 &crl_signed_data);
	if (result < 0) {
		gnutls_assert();
		if (verify)
			*verify |= GNUTLS_CERT_INVALID;
		goto cleanup;
	}

	result =
	    _gnutls_x509_get_signature(crl->crl, "signature",
				       &crl_signature);
	if (result < 0) {
		gnutls_assert();
		if (verify)
			*verify |= GNUTLS_CERT_INVALID;
		goto cleanup;
	}

	result =
	    _gnutls_x509_get_signature_algorithm(crl->crl,
						 "signatureAlgorithm.algorithm");
	if (result < 0) {
		gnutls_assert();
		if (verify)
			*verify |= GNUTLS_CERT_INVALID;
		goto cleanup;
	}

	hash_algo = gnutls_sign_get_hash_algorithm(result);

	/* issuer is not in trusted certificate
	 * authorities.
	 */
	if (issuer == NULL) {
		gnutls_assert();
		if (verify)
			*verify |=
			    GNUTLS_CERT_SIGNER_NOT_FOUND |
			    GNUTLS_CERT_INVALID;
	} else {
		if (!(flags & GNUTLS_VERIFY_DISABLE_CA_SIGN)) {
			if (gnutls_x509_crt_get_ca_status(issuer, NULL) != 1) {
				gnutls_assert();
				if (verify)
					*verify |=
					    GNUTLS_CERT_SIGNER_NOT_CA |
					    GNUTLS_CERT_INVALID;
			}

			result =
			    gnutls_x509_crt_get_key_usage(issuer, &usage, NULL);
			if (result != GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
				if (result < 0) {
					gnutls_assert();
					if (verify)
						*verify |= GNUTLS_CERT_INVALID;
				} else if (!(usage & GNUTLS_KEY_CRL_SIGN)) {
					gnutls_assert();
					if (verify)
						*verify |=
						    GNUTLS_CERT_SIGNER_CONSTRAINTS_FAILURE
						    | GNUTLS_CERT_INVALID;
				}
			}
		}

		result =
		    _gnutls_x509_verify_data(mac_to_entry(hash_algo),
					     &crl_signed_data, &crl_signature,
					     issuer);
		if (result == GNUTLS_E_PK_SIG_VERIFY_FAILED) {
			gnutls_assert();
			/* error. ignore it */
			if (verify)
				*verify |= GNUTLS_CERT_SIGNATURE_FAILURE;
			result = 0;
		} else if (result < 0) {
			gnutls_assert();
			if (verify)
				*verify |= GNUTLS_CERT_INVALID;
			goto cleanup;
		} else if (result >= 0) {
			result = 0; /* everything ok */
		}
	}

	{
		int sigalg;

		sigalg = gnutls_x509_crl_get_signature_algorithm(crl);

		if (((sigalg == GNUTLS_SIGN_RSA_MD2) &&
		     !(flags & GNUTLS_VERIFY_ALLOW_SIGN_RSA_MD2)) ||
		    ((sigalg == GNUTLS_SIGN_RSA_MD5) &&
		     !(flags & GNUTLS_VERIFY_ALLOW_SIGN_RSA_MD5))) {
			if (verify)
				*verify |= GNUTLS_CERT_INSECURE_ALGORITHM;
			result = 0;
		}
	}

	if (gnutls_x509_crl_get_this_update(crl) > now && verify)
		*verify |= GNUTLS_CERT_REVOCATION_DATA_ISSUED_IN_FUTURE;

	if (gnutls_x509_crl_get_next_update(crl) < now && verify)
		*verify |= GNUTLS_CERT_REVOCATION_DATA_SUPERSEDED;


      cleanup:
	if (verify && *verify != 0)
		*verify |= GNUTLS_CERT_INVALID;

	_gnutls_free_datum(&crl_signed_data);
	_gnutls_free_datum(&crl_signature);

	return result;
}
Ejemplo n.º 18
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;
}
Ejemplo n.º 19
0
/**
 * gnutls_pkcs12_mac_info:
 * @pkcs12: A pkcs12 type
 * @mac: the MAC algorithm used as %gnutls_mac_algorithm_t
 * @salt: the salt used for string to key (if non-NULL then @salt_size initially holds its size)
 * @salt_size: string to key salt size
 * @iter_count: string to key iteration count
 * @oid: if non-NULL it will contain an allocated null-terminated variable with the OID
 *
 * This function will provide information on the MAC algorithm used
 * in a PKCS #12 structure. If the structure algorithms
 * are unknown the code %GNUTLS_E_UNKNOWN_HASH_ALGORITHM will be returned,
 * and only @oid, will be set. That is, @oid will be set on structures
 * with a MAC whether supported or not. It must be deinitialized using gnutls_free().
 * The other variables are only set on supported structures.
 *
 * Returns: %GNUTLS_E_INVALID_REQUEST if the provided structure doesn't contain a MAC,
 *  %GNUTLS_E_UNKNOWN_HASH_ALGORITHM if the structure's MAC isn't supported, or
 *  another negative error code in case of a failure. Zero on success.
 **/
int
gnutls_pkcs12_mac_info(gnutls_pkcs12_t pkcs12, unsigned int *mac,
	void *salt, unsigned int *salt_size, unsigned int *iter_count, char **oid)
{
	int ret;
	gnutls_datum_t tmp = { NULL, 0 }, dsalt = {
	NULL, 0};
	gnutls_mac_algorithm_t algo;

	if (oid)
		*oid = NULL;

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

	ret =
	    _gnutls_x509_read_value(pkcs12->pkcs12, "macData.mac.digestAlgorithm.algorithm",
				    &tmp);
	if (ret < 0) {
		gnutls_assert();
		return GNUTLS_E_INVALID_REQUEST;
	}

	if (oid) {
		*oid = (char*)tmp.data;
	}

	algo = gnutls_oid_to_digest((char*)tmp.data);
	if (algo == GNUTLS_MAC_UNKNOWN || mac_to_entry(algo) == NULL) {
		gnutls_assert();
		return GNUTLS_E_UNKNOWN_HASH_ALGORITHM;
	}

	if (oid) {
		tmp.data = NULL;
	}

	if (mac) {
		*mac = algo;
	}

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

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

		if (*salt_size >= (unsigned)dsalt.size) {
			*salt_size = dsalt.size;
			if (dsalt.size > 0)
				memcpy(salt, dsalt.data, dsalt.size);
		} else {
			*salt_size = dsalt.size;
			ret = gnutls_assert_val(GNUTLS_E_SHORT_MEMORY_BUFFER);
			goto cleanup;
		}
	}

	ret = 0;
 cleanup:
	_gnutls_free_datum(&tmp);
	_gnutls_free_datum(&dsalt);
	return ret;

}
Ejemplo n.º 20
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;
}
Ejemplo n.º 21
0
/**
 * cdk_pk_verify:
 * @pk: the public key
 * @sig: signature
 * @md: the message digest
 *
 * Verify the signature in @sig and compare it with the message digest in @md.
 **/
cdk_error_t
cdk_pk_verify(cdk_pubkey_t pk, cdk_pkt_signature_t sig, const byte * md)
{
	gnutls_datum_t s_sig = { NULL, 0 }, di = {
	NULL, 0};
	byte *encmd = NULL;
	cdk_error_t rc;
	int ret, algo;
	unsigned int i;
	gnutls_pk_params_st params;
	const mac_entry_st *me;

	if (!pk || !sig || !md) {
		gnutls_assert();
		return CDK_Inv_Value;
	}

	if (is_DSA(pk->pubkey_algo))
		algo = GNUTLS_PK_DSA;
	else if (is_RSA(pk->pubkey_algo))
		algo = GNUTLS_PK_RSA;
	else {
		gnutls_assert();
		return CDK_Inv_Value;
	}

	rc = sig_to_datum(&s_sig, sig);
	if (rc) {
		gnutls_assert();
		goto leave;
	}

	me = mac_to_entry(sig->digest_algo);
	rc = _gnutls_set_datum(&di, md, _gnutls_hash_get_algo_len(me));
	if (rc < 0) {
		rc = gnutls_assert_val(CDK_Out_Of_Core);
		goto leave;
	}

	rc = pk_prepare_hash(algo, me, &di);
	if (rc < 0) {
		rc = gnutls_assert_val(CDK_General_Error);
		goto leave;
	}

	params.params_nr = cdk_pk_get_npkey(pk->pubkey_algo);
	for (i = 0; i < params.params_nr; i++)
		params.params[i] = pk->mpi[i];
	params.flags = 0;
	ret = _gnutls_pk_verify(algo, &di, &s_sig, &params);

	if (ret < 0) {
		gnutls_assert();
		rc = map_gnutls_error(ret);
		goto leave;
	}

	rc = 0;

      leave:
	_gnutls_free_datum(&s_sig);
	_gnutls_free_datum(&di);
	cdk_free(encmd);
	return rc;
}
Ejemplo n.º 22
0
/* Given a signature and parameters, it should return
 * the hash algorithm used in the signature. This is a kludge
 * but until we deprecate gnutls_pubkey_get_verify_algorithm()
 * we depend on it.
 */
static int wrap_nettle_hash_algorithm(gnutls_pk_algorithm_t pk,
				      const gnutls_datum_t * sig,
				      gnutls_pk_params_st * issuer_params,
				      gnutls_digest_algorithm_t *
				      hash_algo)
{
	uint8_t digest[MAX_HASH_SIZE];
	uint8_t *rdi = NULL;
	gnutls_datum_t di;
	unsigned digest_size;
	mpz_t s;
	struct rsa_public_key pub;
	const mac_entry_st *me;
	int ret;

	mpz_init(s);

	switch (pk) {
	case GNUTLS_PK_DSA:
	case GNUTLS_PK_EC:

		me = _gnutls_dsa_q_to_hash(pk, issuer_params, NULL);
		if (hash_algo)
			*hash_algo = me->id;

		ret = 0;
		break;
	case GNUTLS_PK_RSA:
		if (sig == NULL) {	/* return a sensible algorithm */
			if (hash_algo)
				*hash_algo = GNUTLS_DIG_SHA256;
			return 0;
		}

		_rsa_params_to_pubkey(issuer_params, &pub);

		digest_size = sizeof(digest);

		nettle_mpz_set_str_256_u(s, sig->size, sig->data);

		ret = extract_digest_info(&pub, &di, &rdi, s);
		if (ret == 0) {
			ret = GNUTLS_E_PK_SIG_VERIFY_FAILED;
			gnutls_assert();
			goto cleanup;
		}

		digest_size = sizeof(digest);
		if ((ret =
		     decode_ber_digest_info(&di, hash_algo, digest,
					    &digest_size)) < 0) {
			gnutls_assert();
			goto cleanup;
		}

		if (digest_size !=
		    _gnutls_hash_get_algo_len(mac_to_entry(*hash_algo))) {
			gnutls_assert();
			ret = GNUTLS_E_PK_SIG_VERIFY_FAILED;
			goto cleanup;
		}

		ret = 0;
		break;

	default:
		gnutls_assert();
		ret = GNUTLS_E_INTERNAL_ERROR;
	}

      cleanup:
	mpz_clear(s);
	gnutls_free(rdi);
	return ret;

}
Ejemplo n.º 23
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;
}
Ejemplo n.º 24
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;
}
Ejemplo n.º 25
0
static int
wrap_padlock_hmac_fast(gnutls_mac_algorithm_t algo,
		       const void *nonce, size_t nonce_size,
		       const void *key, size_t key_size, const void *text,
		       size_t text_size, void *digest)
{
	if (algo == GNUTLS_MAC_SHA1 || algo == GNUTLS_MAC_SHA256) {
		unsigned char *pad;
		unsigned char pad2[SHA1_DATA_SIZE + MAX_SHA_DIGEST_SIZE];
		unsigned char hkey[MAX_SHA_DIGEST_SIZE];
		unsigned int digest_size =
		    _gnutls_mac_get_algo_len(mac_to_entry(algo));

		if (key_size > SHA1_DATA_SIZE) {
			wrap_padlock_hash_fast((gnutls_digest_algorithm_t)
					       algo, key, key_size, hkey);
			key = hkey;
			key_size = digest_size;
		}

		pad = gnutls_malloc(text_size + SHA1_DATA_SIZE);
		if (pad == NULL)
			return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);

		memset(pad, IPAD, SHA1_DATA_SIZE);
		memxor(pad, key, key_size);

		memcpy(&pad[SHA1_DATA_SIZE], text, text_size);

		wrap_padlock_hash_fast((gnutls_digest_algorithm_t) algo,
				       pad, text_size + SHA1_DATA_SIZE,
				       &pad2[SHA1_DATA_SIZE]);

		gnutls_free(pad);

		memset(pad2, OPAD, SHA1_DATA_SIZE);
		memxor(pad2, key, key_size);

		wrap_padlock_hash_fast((gnutls_digest_algorithm_t) algo,
				       pad2, digest_size + SHA1_DATA_SIZE,
				       digest);

	} else {
		struct padlock_hmac_ctx ctx;
		int ret;

		ret = _hmac_ctx_init(algo, &ctx);
		if (ret < 0)
			return gnutls_assert_val(ret);
		ctx.algo = algo;

		wrap_padlock_hmac_setkey(&ctx, key, key_size);

		wrap_padlock_hmac_update(&ctx, text, text_size);

		wrap_padlock_hmac_output(&ctx, digest, ctx.length);
		wrap_padlock_hmac_deinit(&ctx);
	}

	return 0;
}
Ejemplo n.º 26
0
static int parse_commitment_line(char *line,
				 const char *host, size_t host_len,
				 const char *service, size_t service_len,
				 time_t now, const gnutls_datum_t * skey)
{
	char *p, *kp;
	char *savep = NULL;
	size_t kp_len, phash_size;
	time_t expiration;
	int ret;
	const mac_entry_st *hash_algo;
	uint8_t phash[MAX_HASH_SIZE];
	uint8_t hphash[MAX_HASH_SIZE * 2 + 1];

	/* read host */
	p = strtok_r(line, "|", &savep);
	if (p == NULL)
		return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);

	if (p[0] != '*' && host != NULL && strcmp(p, host) != 0)
		return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);

	/* read service */
	p = strtok_r(NULL, "|", &savep);
	if (p == NULL)
		return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);

	if (p[0] != '*' && service != NULL && strcmp(p, service) != 0)
		return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);

	/* read expiration */
	p = strtok_r(NULL, "|", &savep);
	if (p == NULL)
		return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);

	expiration = (time_t) atol(p);
	if (expiration > 0 && now > expiration)
		return gnutls_assert_val(GNUTLS_E_EXPIRED);

	/* read hash algorithm */
	p = strtok_r(NULL, "|", &savep);
	if (p == NULL)
		return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);

	hash_algo = mac_to_entry(atol(p));
	if (_gnutls_digest_get_name(hash_algo) == NULL)
		return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);

	/* read hash */
	kp = strtok_r(NULL, "|", &savep);
	if (kp == NULL)
		return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);

	p = strpbrk(kp, "\n \r\t|");
	if (p != NULL)
		*p = 0;

	/* hash and hex encode */
	ret =
	    _gnutls_hash_fast((gnutls_digest_algorithm_t)hash_algo->id, 
	    			skey->data, skey->size, phash);
	if (ret < 0)
		return gnutls_assert_val(ret);

	phash_size = _gnutls_hash_get_algo_len(hash_algo);

	p = _gnutls_bin2hex(phash, phash_size, (void *) hphash,
			    sizeof(hphash), NULL);
	if (p == NULL)
		return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);

	kp_len = strlen(kp);
	if (kp_len != phash_size * 2)
		return
		    gnutls_assert_val(GNUTLS_E_CERTIFICATE_KEY_MISMATCH);

	if (memcmp(kp, hphash, kp_len) != 0)
		return
		    gnutls_assert_val(GNUTLS_E_CERTIFICATE_KEY_MISMATCH);

	/* key found and matches */
	return 0;
}