db-d2/primevul-codebert-embeddings huggingface dataset:
Commit message: sctp: fix random memory dereference with SCTP_HMAC_IDENT option.

The number of identifiers needs to be checked against the option
length.  Also, the identifier index provided needs to be verified
to make sure that it doesn't exceed the bounds of the array.

Signed-off-by: Vlad Yasevich <vladislav.yasevich@hp.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
CVE: CVE-2008-4445
CWE: CWE-200
Vulnerability description: The sctp_auth_ep_set_hmacs function in net/sctp/auth.c in the Stream Control Transmission Protocol (sctp) implementation in the Linux kernel before 2.6.26.4, when the SCTP-AUTH extension is enabled, does not verify that the identifier index is within the bounds established by SCTP_AUTH_HMAC_ID_MAX, which allows local users to obtain sensitive information via a crafted SCTP_HMAC_IDENT IOCTL request involving the sctp_getsockopt function, a different vulnerability than CVE-2008-4113.

Project: linux-2.6

static int sctp_setsockopt_hmac_ident(struct sock *sk,
				    char __user *optval,
				    int optlen)
{
	struct sctp_hmacalgo *hmacs;
	u32 idents;
	int err;

	if (!sctp_auth_enable)
		return -EACCES;

	if (optlen < sizeof(struct sctp_hmacalgo))
		return -EINVAL;

	hmacs = kmalloc(optlen, GFP_KERNEL);
	if (!hmacs)
		return -ENOMEM;

	if (copy_from_user(hmacs, optval, optlen)) {
		err = -EFAULT;
		goto out;
	}

	idents = hmacs->shmac_num_idents;
	if (idents == 0 || idents > SCTP_AUTH_NUM_HMACS ||
	    (idents * sizeof(u16)) > (optlen - sizeof(struct sctp_hmacalgo))) {
		err = -EINVAL;
		goto out;
	}

	err = sctp_auth_ep_set_hmacs(sctp_sk(sk)->ep, hmacs);
out:
	kfree(hmacs);
	return err;
}

Project: linux-2.6

int sctp_auth_ep_set_hmacs(struct sctp_endpoint *ep,
			   struct sctp_hmacalgo *hmacs)
{
	int has_sha1 = 0;
	__u16 id;
	int i;

	/* Scan the list looking for unsupported id.  Also make sure that
	 * SHA1 is specified.
	 */
	for (i = 0; i < hmacs->shmac_num_idents; i++) {
		id = hmacs->shmac_idents[i];

		if (id > SCTP_AUTH_HMAC_ID_MAX)
			return -EOPNOTSUPP;

		if (SCTP_AUTH_HMAC_ID_SHA1 == id)
			has_sha1 = 1;

		if (!sctp_hmac_list[id].hmac_name)
			return -EOPNOTSUPP;
	}

	if (!has_sha1)
		return -EINVAL;

	memcpy(ep->auth_hmacs_list->hmac_ids, &hmacs->shmac_idents[0],
		hmacs->shmac_num_idents * sizeof(__u16));
	ep->auth_hmacs_list->param_hdr.length = htons(sizeof(sctp_paramhdr_t) +
				hmacs->shmac_num_idents * sizeof(__u16));
	return 0;
}
Commit message: [NETLINK]: Clear padding in netlink messages

Signed-off-by: Patrick McHardy <kaber@trash.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
CVE: CVE-2005-4881
CWE: CWE-200
Vulnerability description: The netlink subsystem in the Linux kernel 2.4.x before 2.4.37.6 and 2.6.x before 2.6.13-rc1 does not initialize certain padding fields in structures, which might allow local users to obtain sensitive information from kernel memory via unspecified vectors, related to the (1) tc_fill_qdisc, (2) tcf_fill_node, (3) neightbl_fill_info, (4) neightbl_fill_param_info, (5) neigh_fill_info, (6) rtnetlink_fill_ifinfo, (7) rtnetlink_fill_iwinfo, (8) vif_delete, (9) ipmr_destroy_unres, (10) ipmr_cache_alloc_unres, (11) ipmr_cache_resolve, (12) inet6_fill_ifinfo, (13) tca_get_fill, (14) tca_action_flush, (15) tcf_add_notify, (16) tc_dump_action, (17) cbq_dump_police, (18) __nlmsg_put, (19) __rta_fill, (20) __rta_reserve, (21) inet6_fill_prefix, (22) rsvp_dump, and (23) cbq_dump_ovl functions.

Project: linux-2.6

static __inline__ int rtattr_strcmp(const struct rtattr *rta, const char *str)
{
	int len = strlen(str) + 1;
	return len > rta->rta_len || memcmp(RTA_DATA(rta), str, len);
}

Project: linux-2.6

__nlmsg_put(struct sk_buff *skb, u32 pid, u32 seq, int type, int len, int flags)
{
	struct nlmsghdr *nlh;
	int size = NLMSG_LENGTH(len);

	nlh = (struct nlmsghdr*)skb_put(skb, NLMSG_ALIGN(size));
	nlh->nlmsg_type = type;
	nlh->nlmsg_len = size;
	nlh->nlmsg_flags = flags;
	nlh->nlmsg_pid = pid;
	nlh->nlmsg_seq = seq;
	memset(NLMSG_DATA(nlh) + len, 0, NLMSG_ALIGN(size) - size);
	return nlh;
}

Project: linux-2.6

__rta_reserve(struct sk_buff *skb, int attrtype, int attrlen)
{
	struct rtattr *rta;
	int size = RTA_LENGTH(attrlen);

	rta = (struct rtattr*)skb_put(skb, RTA_ALIGN(size));
	rta->rta_type = attrtype;
	rta->rta_len = size;
	memset(RTA_DATA(rta) + attrlen, 0, RTA_ALIGN(size) - size);
	return rta;
}
Commit message: proc: fix mount -t proc -o AAA

The proc_parse_options() call from proc_mount() runs only once at boot
time.  So on any later mount attempt, any mount options are ignored
because ->s_root is already initialized.

As a consequence, "mount -o <options>" will ignore the options.  The
only way to change mount options is "mount -o remount,<options>".

To fix this, parse the mount options unconditionally.

Signed-off-by: Vasiliy Kulikov <segoon@openwall.com>
Reported-by: Arkadiusz Miskiewicz <a.miskiewicz@gmail.com>
Tested-by: Arkadiusz Miskiewicz <a.miskiewicz@gmail.com>
Cc: Alexey Dobriyan <adobriyan@gmail.com>
Cc: Al Viro <viro@zeniv.linux.org.uk>
Cc: Valdis Kletnieks <Valdis.Kletnieks@vt.edu>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
CVE: None
Vulnerability description: None

Project: linux-2.6

static struct dentry *proc_mount(struct file_system_type *fs_type,
	int flags, const char *dev_name, void *data)
{
	int err;
	struct super_block *sb;
	struct pid_namespace *ns;
	struct proc_inode *ei;
	char *options;

	if (flags & MS_KERNMOUNT) {
		ns = (struct pid_namespace *)data;
		options = NULL;
	} else {
		ns = current->nsproxy->pid_ns;
		options = data;
	}

	sb = sget(fs_type, proc_test_super, proc_set_super, ns);
	if (IS_ERR(sb))
		return ERR_CAST(sb);

	if (!proc_parse_options(options, ns)) {
		deactivate_locked_super(sb);
		return ERR_PTR(-EINVAL);
	}

	if (!sb->s_root) {
		sb->s_flags = flags;
		err = proc_fill_super(sb);
		if (err) {
			deactivate_locked_super(sb);
			return ERR_PTR(err);
		}

		sb->s_flags |= MS_ACTIVE;
	}

	ei = PROC_I(sb->s_root->d_inode);
	if (!ei->pid) {
		rcu_read_lock();
		ei->pid = get_pid(find_pid_ns(1, ns));
		rcu_read_unlock();
	}

	return dget(sb->s_root);
}
Commit message: core: Validate SSL certificates for all connections

This prevents MitM attacks which use spoofed SSL certificates.

Closes: https://bugzilla.gnome.org/show_bug.cgi?id=671535
CVE: CVE-2012-1177
CWE: CWE-20
Vulnerability description: libgdata before 0.10.2 and 0.11.x before 0.11.1 does not validate SSL certificates, which allows remote attackers to obtain user names and passwords via a man-in-the-middle (MITM) attack with a spoofed certificate.

Project: libgdata

_gdata_service_build_session (void)
{
	SoupSession *session = soup_session_sync_new_with_options (SOUP_SESSION_SSL_CA_FILE, CA_CERTS, NULL);

#ifdef HAVE_GNOME
	soup_session_add_feature_by_type (session, SOUP_TYPE_GNOME_FEATURES_2_26);
#endif /* HAVE_GNOME */

	/* Log all libsoup traffic if debugging's turned on */
	if (_gdata_service_get_log_level () > GDATA_LOG_MESSAGES) {
		SoupLoggerLogLevel level;
		SoupLogger *logger;

		switch (_gdata_service_get_log_level ()) {
			case GDATA_LOG_FULL:
				level = SOUP_LOGGER_LOG_BODY;
				break;
			case GDATA_LOG_HEADERS:
				level = SOUP_LOGGER_LOG_HEADERS;
				break;
			case GDATA_LOG_MESSAGES:
			case GDATA_LOG_NONE:
			default:
				g_assert_not_reached ();
		}

		logger = soup_logger_new (level, -1);
		soup_logger_set_printer (logger, (SoupLoggerPrinter) soup_log_printer, NULL, NULL);

		soup_session_add_feature (session, SOUP_SESSION_FEATURE (logger));

		g_object_unref (logger);
	}

	return session;
}

Project: libgdata

soup_log_printer (SoupLogger *logger, SoupLoggerLogLevel level, char direction, const char *data, gpointer user_data)
{
	g_debug ("%c %s", direction, data);
}

Project: libgdata

_gdata_service_get_log_level (void)
{
	static int level = -1;

	if (level < 0) {
		const gchar *envvar = g_getenv ("LIBGDATA_DEBUG");
		if (envvar != NULL)
			level = atoi (envvar);
		level = MIN (MAX (level, 0), GDATA_LOG_FULL);
	}

	return level;
}
Commit message: Reject new clients if in the deferred state

As mentioned in bug 641811, Vino can get stuck trying to process the
same data in an infinite loop if an authentication request is received
from a client while that client is in the deferred state.

Avoid this situation by closing new connections from the same client
when it is in the deferred state.
CVE: CVE-2013-5745
CWE: CWE-20
Vulnerability description: The vino_server_client_data_pending function in vino-server.c in GNOME Vino 2.26.1, 2.32.1, 3.7.3, and earlier, and 3.8 when encryption is disabled, does not properly clear client data when an error causes the connection to close during authentication, which allows remote attackers to cause a denial of service (infinite loop, CPU and disk consumption) via multiple crafted requests during authentication.

Project: vino

rfbProcessClientMessage(rfbClientPtr cl)
{
    switch (cl->state) {
    case RFB_PROTOCOL_VERSION:
        rfbProcessClientProtocolVersion(cl);
        return;
    case RFB_SECURITY_TYPE:
	rfbAuthProcessSecurityTypeMessage(cl);
	return;
#ifdef VINO_HAVE_GNUTLS
    case RFB_TLS_HANDSHAKE:
	rfbAuthProcessTLSHandshake(cl);
	return;
#endif
    case RFB_AUTH_TYPE:
	rfbAuthProcessAuthTypeMessage(cl);
	return;
    case RFB_AUTHENTICATION:
        rfbAuthProcessClientMessage(cl);
        return;
    case RFB_AUTH_DEFERRED:
	rfbLog("Authentication deferred for this client - closing connection\n");
	rfbCloseClient(cl);
	return;
    case RFB_INITIALISATION:
        rfbProcessClientInitMessage(cl);
        return;
    default:
        rfbProcessClientNormalMessage(cl);
        return;
    }
}
Commit message: Fix typo
CVE: None
Vulnerability description: None

Project: cpio

get_link_name (struct cpio_file_stat *file_hdr, int in_file_des)
{
  char *link_name;
  
  if (file_hdr->c_filesize < 0 || file_hdr->c_filesize > SIZE_MAX-1)
    {
      error (0, 0, _("%s: stored filename length is out of range"),
	     file_hdr->c_name);
      link_name = NULL;
    }
  else
    {
      link_name = xmalloc (file_hdr->c_filesize + 1);
      tape_buffered_read (link_name, in_file_des, file_hdr->c_filesize);
      link_name[file_hdr->c_filesize] = '\0';
      tape_skip_padding (in_file_des, file_hdr->c_filesize);
    }
  return link_name;
}
Commit message: wrestool: Make check_offset more stringent
CVE: CVE-2017-5208
CWE: CWE-190
Vulnerability description: Integer overflow in the wrestool program in icoutils before 0.31.1 allows remote attackers to cause a denial of service (memory corruption) via a crafted executable, which triggers a denial of service (application crash) or the possibility of execution of arbitrary code.

Project: icoutils

check_offset(char *memory, int total_size, char *name, void *offset, int size)
{
	char* memory_end = memory + total_size;
	char* block = (char*)offset;
	char* block_end = offset + size;

	/*debug("check_offset: size=%x vs %x offset=%x size=%x\n",
		need_size, total_size, (char *) offset - memory, size);*/

	if (((memory <= memory_end) && (block <= block_end))
		&& ((block < memory) || (block >= memory_end) || (block_end > memory_end))) {
		warn(_("%s: premature end"), name);
		return false;
	}

	return true;
}
Commit message: clone: fix directory traversal

This was introduced in the initial version of this code, way back when
in 2008.

$ curl http://127.0.0.1/cgit/repo/objects/?path=../../../../../../../../../etc/passwd
root:x:0:0:root:/root:/bin/sh
...

Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
Reported-by: Jann Horn <jannh@google.com>
CVE: None
Vulnerability description: None

Project: cgit

static void print_pack_info(void)
{
	struct packed_git *pack;
	char *offset;

	ctx.page.mimetype = "text/plain";
	ctx.page.filename = "objects/info/packs";
	cgit_print_http_headers();
	reprepare_packed_git(the_repository);
	for (pack = get_packed_git(the_repository); pack; pack = pack->next) {
		if (pack->pack_local) {
			offset = strrchr(pack->pack_name, '/');
			if (offset && offset[1] != '\0')
				++offset;
			else
				offset = pack->pack_name;
			htmlf("P %s\n", offset);
		}
	}
}

Project: cgit

void cgit_clone_head(void)
{
	send_file(git_path("%s", "HEAD"));
}

Project: cgit

void cgit_clone_info(void)
{
	if (!ctx.qry.path || strcmp(ctx.qry.path, "refs")) {
		cgit_print_error_page(400, "Bad request", "Bad request");
		return;
	}

	ctx.page.mimetype = "text/plain";
	ctx.page.filename = "info/refs";
	cgit_print_http_headers();
	for_each_ref(print_ref_info, NULL);
}

Project: cgit

static void send_file(const char *path)
{
	struct stat st;

	if (stat(path, &st)) {
		switch (errno) {
		case ENOENT:
			cgit_print_error_page(404, "Not found", "Not found");
			break;
		case EACCES:
			cgit_print_error_page(403, "Forbidden", "Forbidden");
			break;
		default:
			cgit_print_error_page(400, "Bad request", "Bad request");
		}
		return;
	}
	ctx.page.mimetype = "application/octet-stream";
	ctx.page.filename = path;
	skip_prefix(path, ctx.repo->path, &ctx.page.filename);
	skip_prefix(ctx.page.filename, "/", &ctx.page.filename);
	cgit_print_http_headers();
	html_include(path);
}

Project: cgit

static int print_ref_info(const char *refname, const struct object_id *oid,
                          int flags, void *cb_data)
{
	struct object *obj;

	if (!(obj = parse_object(oid)))
		return 0;

	htmlf("%s\t%s\n", oid_to_hex(oid), refname);
	if (obj->type == OBJ_TAG) {
		if (!(obj = deref_tag(obj, refname, 0)))
			return 0;
		htmlf("%s\t%s^{}\n", oid_to_hex(&obj->oid), refname);
	}
	return 0;
}

Project: cgit

void cgit_clone_objects(void)
{
	char *p;

	if (!ctx.qry.path)
		goto err;

	if (!strcmp(ctx.qry.path, "info/packs")) {
		print_pack_info();
		return;
	}

	/* Avoid directory traversal by forbidding "..", but also work around
	 * other funny business by just specifying a fairly strict format. For
	 * example, now we don't have to stress out about the Cygwin port.
	 */
	for (p = ctx.qry.path; *p; ++p) {
		if (*p == '.' && *(p + 1) == '.')
			goto err;
		if (!isalnum(*p) && *p != '/' && *p != '.' && *p != '-')
			goto err;
	}

	send_file(git_path("objects/%s", ctx.qry.path));
	return;

err:
	cgit_print_error_page(400, "Bad request", "Bad request");
}
Commit message: x509name: fix OpenSSL::X509::Name#{cmp,<=>}

Fix wrong use of X509_NAME_cmp() return value. OpenSSL::X509::Name#<=>
could return 0 when the two objects aren't identical.

Reported by Tyler Eckstein. CVE-2018-16395.

Reference: https://hackerone.com/reports/387250
CVE: CVE-2018-16395
CWE: NVD-CWE-noinfo
Vulnerability description: An issue was discovered in the OpenSSL library in Ruby before 2.3.8, 2.4.x before 2.4.5, 2.5.x before 2.5.2, and 2.6.x before 2.6.0-preview3. When two OpenSSL::X509::Name objects are compared using ==, depending on the ordering, non-equal objects may return true. When the first argument is one character longer than the second, or the second argument contains a character that is one less than a character in the same position of the first argument, the result of == will be true. This could be leveraged to create an illegitimate certificate that may be accepted as legitimate and then used in signing or encryption operations.

Project: openssl

ossl_x509name_eql(VALUE self, VALUE other)
{
    if (!rb_obj_is_kind_of(other, cX509Name))
	return Qfalse;

    return ossl_x509name_cmp0(self, other) == 0 ? Qtrue : Qfalse;
}

Project: openssl

ossl_x509name_cmp(VALUE self, VALUE other)
{
    int result;

    result = ossl_x509name_cmp0(self, other);
    if (result < 0) return INT2FIX(-1);
    if (result > 0) return INT2FIX(1);

    return INT2FIX(0);
}
Commit message: * src/iri.c (do_conversion): Remove unneeded debug lines
CVE: CVE-2019-5953
CWE: CWE-787
Vulnerability description: Buffer overflow in GNU Wget 1.20.1 and earlier allows remote attackers to cause a denial-of-service (DoS) or may execute an arbitrary code via unspecified vectors.

Project: wget

do_conversion (const char *tocode, const char *fromcode, char const *in_org, size_t inlen, char **out)
{
  iconv_t cd;
  /* sXXXav : hummm hard to guess... */
  size_t len, done, outlen;
  int invalid = 0, tooshort = 0;
  char *s, *in, *in_save;

  cd = iconv_open (tocode, fromcode);
  if (cd == (iconv_t)(-1))
    {
      logprintf (LOG_VERBOSE, _("Conversion from %s to %s isn't supported\n"),
                 quote (fromcode), quote (tocode));
      *out = NULL;
      return false;
    }

  /* iconv() has to work on an unescaped string */
  in_save = in = xstrndup (in_org, inlen);
  url_unescape_except_reserved (in);
  inlen = strlen(in);

  len = outlen = inlen * 2;
  *out = s = xmalloc (outlen + 1);
  done = 0;

  for (;;)
    {
      if (iconv (cd, (ICONV_CONST char **) &in, &inlen, out, &outlen) != (size_t)(-1) &&
          iconv (cd, NULL, NULL, out, &outlen) != (size_t)(-1))
        {
          *out = s;
          *(s + len - outlen - done) = '\0';
          xfree(in_save);
          iconv_close(cd);
          IF_DEBUG
          {
            /* not not print out embedded passwords, in_org might be an URL */
            if (!strchr(in_org, '@') && !strchr(*out, '@'))
              debug_logprintf ("converted '%s' (%s) -> '%s' (%s)\n", in_org, fromcode, *out, tocode);
            else
              debug_logprintf ("logging suppressed, strings may contain password\n");
          }
          return true;
        }

      /* Incomplete or invalid multibyte sequence */
      if (errno == EINVAL || errno == EILSEQ)
        {
          if (!invalid)
            logprintf (LOG_VERBOSE,
                      _("Incomplete or invalid multibyte sequence encountered\n"));

          invalid++;
          **out = *in;
          in++;
          inlen--;
          (*out)++;
          outlen--;
        }
      else if (errno == E2BIG) /* Output buffer full */
        {
          tooshort++;
          done = len;
          len = done + inlen * 2;
          s = xrealloc (s, len + 1);
          *out = s + done - outlen;
          outlen += inlen * 2;
        }
      else /* Weird, we got an unspecified error */
        {
          logprintf (LOG_VERBOSE, _("Unhandled errno %d\n"), errno);
          break;
        }
    }

    xfree(in_save);
    iconv_close(cd);
    IF_DEBUG
    {
      /* not not print out embedded passwords, in_org might be an URL */
      if (!strchr(in_org, '@') && !strchr(*out, '@'))
        debug_logprintf ("converted '%s' (%s) -> '%s' (%s)\n", in_org, fromcode, *out, tocode);
      else
        debug_logprintf ("logging suppressed, strings may contain password\n");
    }
    return false;
}
Commit message: Use ecc_mod_mul_canonical for point comparison.

* eddsa-verify.c (equal_h): Use ecc_mod_mul_canonical.

(cherry picked from commit 5b7608fde3a6d2ab82bffb35db1e4e330927c906)
CVE: CVE-2021-20305
CWE: CWE-787
Vulnerability description: A flaw was found in Nettle in versions before 3.7.2, where several Nettle signature verification functions (GOST DSA, EDDSA & ECDSA) result in the Elliptic Curve Cryptography point (ECC) multiply function being called with out-of-range scalers, possibly resulting in incorrect results. This flaw allows an attacker to force an invalid signature, causing an assertion failure or possible validation. The highest threat to this vulnerability is to confidentiality, integrity, as well as system availability.

Project: nettle

equal_h (const struct ecc_modulo *p,
	 const mp_limb_t *x1, const mp_limb_t *z1,
	 const mp_limb_t *x2, const mp_limb_t *z2,
	 mp_limb_t *scratch)
{
#define t0 scratch
#define t1 (scratch + p->size)

  ecc_mod_mul_canonical (p, t0, x1, z2, t0);
  ecc_mod_mul_canonical (p, t1, x2, z1, t1);

  return mpn_cmp (t0, t1, p->size) == 0;

#undef t0
#undef t1
}

Project: nettle

_eddsa_verify_itch (const struct ecc_curve *ecc)
{
  assert (_eddsa_decompress_itch (ecc) <= ecc->mul_itch);
  return 8*ecc->p.size + ecc->mul_itch;
}

Project: nettle

_eddsa_verify (const struct ecc_curve *ecc,
	       const struct ecc_eddsa *eddsa,
	       const uint8_t *pub,
	       const mp_limb_t *A,
	       void *ctx,
	       size_t length,
	       const uint8_t *msg,
	       const uint8_t *signature,
	       mp_limb_t *scratch)
{
  size_t nbytes;
#define R scratch
#define sp (scratch + 2*ecc->p.size)
#define hp (scratch + 3*ecc->p.size)
#define P (scratch + 5*ecc->p.size)
#define scratch_out (scratch + 8*ecc->p.size)
#define S R
#define hash ((uint8_t *) P)

  nbytes = 1 + ecc->p.bit_size / 8;

  /* Could maybe save some storage by delaying the R and S operations,
     but it makes sense to check them for validity up front. */
  if (!_eddsa_decompress (ecc, R, signature, R+2*ecc->p.size))
    return 0;

  mpn_set_base256_le (sp, ecc->q.size, signature + nbytes, nbytes);
  /* Check that s < q */
  if (mpn_cmp (sp, ecc->q.m, ecc->q.size) >= 0)
    return 0;

  eddsa->dom (ctx);
  eddsa->update (ctx, nbytes, signature);
  eddsa->update (ctx, nbytes, pub);
  eddsa->update (ctx, length, msg);
  eddsa->digest (ctx, 2*nbytes, hash);
  _eddsa_hash (&ecc->q, hp, 2*nbytes, hash);

  /* Compute h A + R - s G, which should be the neutral point */
  ecc->mul (ecc, P, hp, A, scratch_out);
  ecc->add_hh (ecc, P, P, R, scratch_out);
  /* Move out of the way. */
  mpn_copyi (hp, sp, ecc->q.size);
  ecc->mul_g (ecc, S, hp, scratch_out);

  return equal_h (&ecc->p,
		   P, P + 2*ecc->p.size,
		   S, S + 2*ecc->p.size, scratch_out)
    && equal_h (&ecc->p,
		P + ecc->p.size, P + 2*ecc->p.size,
		S + ecc->p.size, S + 2*ecc->p.size, scratch_out);

#undef R
#undef sp
#undef hp
#undef P
#undef S
}
Commit message: Ensure ecdsa_sign output is canonically reduced.

* ecc-ecdsa-sign.c (ecc_ecdsa_sign): Ensure s output is reduced to
canonical range.

(cherry picked from commit c24b36160dc5303f7541dd9da1429c4046f27398)
CVE: CVE-2021-20305
CWE: CWE-787
Vulnerability description: A flaw was found in Nettle in versions before 3.7.2, where several Nettle signature verification functions (GOST DSA, EDDSA & ECDSA) result in the Elliptic Curve Cryptography point (ECC) multiply function being called with out-of-range scalers, possibly resulting in incorrect results. This flaw allows an attacker to force an invalid signature, causing an assertion failure or possible validation. The highest threat to this vulnerability is to confidentiality, integrity, as well as system availability.

Project: nettle

ecc_ecdsa_sign (const struct ecc_curve *ecc,
		const mp_limb_t *zp,
		/* Random nonce, must be invertible mod ecc group
		   order. */
		const mp_limb_t *kp,
		size_t length, const uint8_t *digest,
		mp_limb_t *rp, mp_limb_t *sp,
		mp_limb_t *scratch)
{
#define P	    scratch
#define kinv	    scratch
#define hp	    (scratch  + ecc->p.size) /* NOTE: ecc->p.size + 1 limbs! */
#define tp	    (scratch + 2*ecc->p.size)
  /* Procedure, according to RFC 6090, "KT-I". q denotes the group
     order.

     1. k <-- uniformly random, 0 < k < q

     2. R <-- (r_x, r_y) = k g

     3. s1 <-- r_x mod q

     4. s2 <-- (h + z*s1)/k mod q.
  */

  ecc->mul_g (ecc, P, kp, P + 3*ecc->p.size);
  /* x coordinate only, modulo q */
  ecc->h_to_a (ecc, 2, rp, P, P + 3*ecc->p.size);

  /* Invert k, uses up to 7 * ecc->p.size including scratch (for secp384). */
  ecc->q.invert (&ecc->q, kinv, kp, tp);
  
  /* Process hash digest */
  ecc_hash (&ecc->q, hp, length, digest);

  ecc_mod_mul (&ecc->q, tp, zp, rp, tp);
  ecc_mod_add (&ecc->q, hp, hp, tp);
  ecc_mod_mul_canonical (&ecc->q, sp, hp, kinv, tp);

#undef P
#undef hp
#undef kinv
#undef tp
}

Project: nettle

ecc_ecdsa_sign_itch (const struct ecc_curve *ecc)
{
  /* Needs 3*ecc->p.size + scratch for ecc->mul_g. Currently same for
     ecc_mul_g. */
  assert (ecc->p.size + ecc->p.invert_itch <= 3*ecc->p.size + ecc->mul_g_itch);
  return ECC_ECDSA_SIGN_ITCH (ecc->p.size);
}