Exemple #1
0
int
ssh_ecdsa_sign(const Key *key, u_char **sigp, u_int *lenp,
    const u_char *data, u_int datalen)
{
	ECDSA_SIG *sig;
	int hash_alg;
	u_char digest[SSH_DIGEST_MAX_LENGTH];
	u_int len, dlen;
	Buffer b, bb;

	if (key == NULL || key_type_plain(key->type) != KEY_ECDSA ||
	    key->ecdsa == NULL) {
		error("%s: no ECDSA key", __func__);
		return -1;
	}

	hash_alg = key_ec_nid_to_hash_alg(key->ecdsa_nid);
	if ((dlen = ssh_digest_bytes(hash_alg)) == 0) {
		error("%s: bad hash algorithm %d", __func__, hash_alg);
		return -1;
	}
	if (ssh_digest_memory(hash_alg, data, datalen,
	    digest, sizeof(digest)) != 0) {
		error("%s: digest_memory failed", __func__);
		return -1;
	}

	sig = ECDSA_do_sign(digest, dlen, key->ecdsa);
	explicit_bzero(digest, sizeof(digest));

	if (sig == NULL) {
		error("%s: sign failed", __func__);
		return -1;
	}

	buffer_init(&bb);
	buffer_put_bignum2(&bb, sig->r);
	buffer_put_bignum2(&bb, sig->s);
	ECDSA_SIG_free(sig);

	buffer_init(&b);
	buffer_put_cstring(&b, key_ssh_name_plain(key));
	buffer_put_string(&b, buffer_ptr(&bb), buffer_len(&bb));
	buffer_free(&bb);
	len = buffer_len(&b);
	if (lenp != NULL)
		*lenp = len;
	if (sigp != NULL) {
		*sigp = xmalloc(len);
		memcpy(*sigp, buffer_ptr(&b), len);
	}
	buffer_free(&b);

	return 0;
}
Exemple #2
0
int
ssh_ecdsa_sign(const Key *key, u_char **sigp, u_int *lenp,
    const u_char *data, u_int datalen)
{
	ECDSA_SIG *sig;
	const EVP_MD *evp_md;
	EVP_MD_CTX md;
	u_char digest[EVP_MAX_MD_SIZE];
	u_int len, dlen;
	Buffer b, bb;

	if (key == NULL || key->ecdsa == NULL ||
	    (key->type != KEY_ECDSA && key->type != KEY_ECDSA_CERT)) {
		error("%s: no ECDSA key", __func__);
		return -1;
	}
	evp_md = key_ec_nid_to_evpmd(key->ecdsa_nid);
	EVP_DigestInit(&md, evp_md);
	EVP_DigestUpdate(&md, data, datalen);
	EVP_DigestFinal(&md, digest, &dlen);

	sig = ECDSA_do_sign(digest, dlen, key->ecdsa);
	memset(digest, 'd', sizeof(digest));

	if (sig == NULL) {
		error("%s: sign failed", __func__);
		return -1;
	}

	buffer_init(&bb);
	buffer_put_bignum2(&bb, sig->r);
	buffer_put_bignum2(&bb, sig->s);
	ECDSA_SIG_free(sig);

	buffer_init(&b);
	buffer_put_cstring(&b, key_ssh_name_plain(key));
	buffer_put_string(&b, buffer_ptr(&bb), buffer_len(&bb));
	buffer_free(&bb);
	len = buffer_len(&b);
	if (lenp != NULL)
		*lenp = len;
	if (sigp != NULL) {
		*sigp = xmalloc(len);
		memcpy(*sigp, buffer_ptr(&b), len);
	}
	buffer_free(&b);

	return 0;
}
Exemple #3
0
int
ssh_ecdsa_verify(const Key *key, const u_char *signature, u_int signaturelen,
    const u_char *data, u_int datalen)
{
	ECDSA_SIG *sig;
	int hash_alg;
	u_char digest[SSH_DIGEST_MAX_LENGTH], *sigblob;
	u_int len, dlen;
	int rlen, ret;
	Buffer b, bb;
	char *ktype;

	if (key == NULL || key_type_plain(key->type) != KEY_ECDSA ||
	    key->ecdsa == NULL) {
		error("%s: no ECDSA key", __func__);
		return -1;
	}

	/* fetch signature */
	buffer_init(&b);
	buffer_append(&b, signature, signaturelen);
	ktype = buffer_get_string(&b, NULL);
	if (strcmp(key_ssh_name_plain(key), ktype) != 0) {
		error("%s: cannot handle type %s", __func__, ktype);
		buffer_free(&b);
		free(ktype);
		return -1;
	}
	free(ktype);
	sigblob = buffer_get_string(&b, &len);
	rlen = buffer_len(&b);
	buffer_free(&b);
	if (rlen != 0) {
		error("%s: remaining bytes in signature %d", __func__, rlen);
		free(sigblob);
		return -1;
	}

	/* parse signature */
	if ((sig = ECDSA_SIG_new()) == NULL)
		fatal("%s: ECDSA_SIG_new failed", __func__);

	buffer_init(&bb);
	buffer_append(&bb, sigblob, len);
	buffer_get_bignum2(&bb, sig->r);
	buffer_get_bignum2(&bb, sig->s);
	if (buffer_len(&bb) != 0)
		fatal("%s: remaining bytes in inner sigblob", __func__);
	buffer_free(&bb);

	/* clean up */
	explicit_bzero(sigblob, len);
	free(sigblob);

	/* hash the data */
	hash_alg = key_ec_nid_to_hash_alg(key->ecdsa_nid);
	if ((dlen = ssh_digest_bytes(hash_alg)) == 0) {
		error("%s: bad hash algorithm %d", __func__, hash_alg);
		return -1;
	}
	if (ssh_digest_memory(hash_alg, data, datalen,
	    digest, sizeof(digest)) != 0) {
		error("%s: digest_memory failed", __func__);
		return -1;
	}

	ret = ECDSA_do_verify(digest, dlen, sig, key->ecdsa);
	explicit_bzero(digest, sizeof(digest));

	ECDSA_SIG_free(sig);

	debug("%s: signature %s", __func__,
	    ret == 1 ? "correct" : ret == 0 ? "incorrect" : "error");
	return ret;
}
Exemple #4
0
int
ssh_ecdsa_verify(const Key *key, const u_char *signature, u_int signaturelen,
    const u_char *data, u_int datalen)
{
	ECDSA_SIG *sig;
	const EVP_MD *evp_md;
	EVP_MD_CTX md;
	u_char digest[EVP_MAX_MD_SIZE], *sigblob;
	u_int len, dlen;
	int rlen, ret;
	Buffer b, bb;
	char *ktype;

	if (key == NULL || key->ecdsa == NULL ||
	    (key->type != KEY_ECDSA && key->type != KEY_ECDSA_CERT)) {
		error("%s: no ECDSA key", __func__);
		return -1;
	}
	evp_md = key_ec_nid_to_evpmd(key->ecdsa_nid);

	/* fetch signature */
	buffer_init(&b);
	buffer_append(&b, signature, signaturelen);
	ktype = buffer_get_string(&b, NULL);
	if (strcmp(key_ssh_name_plain(key), ktype) != 0) {
		error("%s: cannot handle type %s", __func__, ktype);
		buffer_free(&b);
		free(ktype);
		return -1;
	}
	free(ktype);
	sigblob = buffer_get_string(&b, &len);
	rlen = buffer_len(&b);
	buffer_free(&b);
	if (rlen != 0) {
		error("%s: remaining bytes in signature %d", __func__, rlen);
		free(sigblob);
		return -1;
	}

	/* parse signature */
	if ((sig = ECDSA_SIG_new()) == NULL)
		fatal("%s: ECDSA_SIG_new failed", __func__);
	if ((sig->r = BN_new()) == NULL ||
	    (sig->s = BN_new()) == NULL)
		fatal("%s: BN_new failed", __func__);

	buffer_init(&bb);
	buffer_append(&bb, sigblob, len);
	buffer_get_bignum2(&bb, sig->r);
	buffer_get_bignum2(&bb, sig->s);
	if (buffer_len(&bb) != 0)
		fatal("%s: remaining bytes in inner sigblob", __func__);
	buffer_free(&bb);

	/* clean up */
	memset(sigblob, 0, len);
	free(sigblob);

	/* hash the data */
	EVP_DigestInit(&md, evp_md);
	EVP_DigestUpdate(&md, data, datalen);
	EVP_DigestFinal(&md, digest, &dlen);

	ret = ECDSA_do_verify(digest, dlen, sig, key->ecdsa);
	memset(digest, 'd', sizeof(digest));

	ECDSA_SIG_free(sig);

	debug("%s: signature %s", __func__,
	    ret == 1 ? "correct" : ret == 0 ? "incorrect" : "error");
	return ret;
}