Example #1
0
File: kex.c Project: OpenKod/src
static u_char *
derive_key(Kex *kex, int id, u_int need, u_char *hash, u_int hashlen,
    const u_char *shared_secret, u_int slen)
{
	Buffer b;
	struct ssh_digest_ctx *hashctx;
	char c = id;
	u_int have;
	size_t mdsz;
	u_char *digest;

	if ((mdsz = ssh_digest_bytes(kex->hash_alg)) == 0)
		fatal("bad kex md size %zu", mdsz);
	digest = xmalloc(roundup(need, mdsz));

	buffer_init(&b);
	buffer_append(&b, shared_secret, slen);

	/* K1 = HASH(K || H || "A" || session_id) */
	if ((hashctx = ssh_digest_start(kex->hash_alg)) == NULL)
		fatal("%s: ssh_digest_start failed", __func__);
	if (ssh_digest_update_buffer(hashctx, &b) != 0 ||
	    ssh_digest_update(hashctx, hash, hashlen) != 0 ||
	    ssh_digest_update(hashctx, &c, 1) != 0 ||
	    ssh_digest_update(hashctx, kex->session_id,
	    kex->session_id_len) != 0)
		fatal("%s: ssh_digest_update failed", __func__);
	if (ssh_digest_final(hashctx, digest, mdsz) != 0)
		fatal("%s: ssh_digest_final failed", __func__);
	ssh_digest_free(hashctx);

	/*
	 * expand key:
	 * Kn = HASH(K || H || K1 || K2 || ... || Kn-1)
	 * Key = K1 || K2 || ... || Kn
	 */
	for (have = mdsz; need > have; have += mdsz) {
		if ((hashctx = ssh_digest_start(kex->hash_alg)) == NULL)
			fatal("%s: ssh_digest_start failed", __func__);
		if (ssh_digest_update_buffer(hashctx, &b) != 0 ||
		    ssh_digest_update(hashctx, hash, hashlen) != 0 ||
		    ssh_digest_update(hashctx, digest, have) != 0)
			fatal("%s: ssh_digest_update failed", __func__);
		if (ssh_digest_final(hashctx, digest + have, mdsz) != 0)
			fatal("%s: ssh_digest_final failed", __func__);
		ssh_digest_free(hashctx);
	}
	buffer_free(&b);
#ifdef DEBUG_KEX
	fprintf(stderr, "key '%c'== ", c);
	dump_digest("key", digest, need);
#endif
	return digest;
}
Example #2
0
static int
derive_key(struct ssh *ssh, int id, u_int need, u_char *hash, u_int hashlen,
    const u_char *shared_secret, u_int slen, u_char **keyp)
{
	struct kex *kex = ssh->kex;
	struct sshbuf *b = NULL;
	struct ssh_digest_ctx *hashctx = NULL;
	char c = id;
	u_int have;
	size_t mdsz;
	u_char *digest;
	int r;

	if ((mdsz = ssh_digest_bytes(kex->hash_alg)) == 0)
		return SSH_ERR_INVALID_ARGUMENT;
	if ((digest = calloc(1, roundup(need, mdsz))) == NULL ||
	    (b = sshbuf_new()) == NULL) {
		r = SSH_ERR_ALLOC_FAIL;
		goto out;
	}
	if ((r = sshbuf_put(b, shared_secret, slen)) < 0)
		goto out;

	/* K1 = HASH(K || H || "A" || session_id) */
	if ((hashctx = ssh_digest_start(kex->hash_alg)) == NULL ||
	    ssh_digest_update_buffer(hashctx, b) != 0 ||
	    ssh_digest_update(hashctx, hash, hashlen) != 0 ||
	    ssh_digest_update(hashctx, &c, 1) != 0 ||
	    ssh_digest_update(hashctx, kex->session_id,
	    kex->session_id_len) != 0 ||
	    ssh_digest_final(hashctx, digest, mdsz) != 0) {
		r = SSH_ERR_LIBCRYPTO_ERROR;
		goto out;
	}
	ssh_digest_free(hashctx);
	hashctx = NULL;

	/*
	 * expand key:
	 * Kn = HASH(K || H || K1 || K2 || ... || Kn-1)
	 * Key = K1 || K2 || ... || Kn
	 */
	for (have = mdsz; need > have; have += mdsz) {
		if ((hashctx = ssh_digest_start(kex->hash_alg)) == NULL ||
		    ssh_digest_update_buffer(hashctx, b) != 0 ||
		    ssh_digest_update(hashctx, hash, hashlen) != 0 ||
		    ssh_digest_update(hashctx, digest, have) != 0 ||
		    ssh_digest_final(hashctx, digest + have, mdsz) != 0) {
			r = SSH_ERR_LIBCRYPTO_ERROR;
			goto out;
		}
		ssh_digest_free(hashctx);
		hashctx = NULL;
	}
#ifdef DEBUG_KEX
	fprintf(stderr, "key '%c'== ", c);
	dump_digest("key", digest, need);
#endif
	*keyp = digest;
	digest = NULL;
	r = 0;
 out:
	if (digest)
		free(digest);
	if (b)
		sshbuf_free(b);
	ssh_digest_free(hashctx);
	return r;
}
Example #3
0
int
ssh_hmac_update_buffer(struct ssh_hmac_ctx *ctx, const struct sshbuf *b)
{
	return ssh_digest_update_buffer(ctx->digest, b);
}