Treat writes as new when holes span across page boundaries

When a hole spans across page boundaries, the next write forces
a read of the block. This could end up reading existing garbage
data from the disk in ocfs2_map_page_blocks. This leads to
non-zero holes. In order to avoid this, mark the writes as new
when the holes span across page boundaries.

Signed-off-by: Goldwyn Rodrigues <rgoldwyn@suse.de>
Signed-off-by: jlbec <jlbec@evilplan.org>

static int ocfs2_prepare_page_for_write(struct inode *inode, u64 *p_blkno,
					struct ocfs2_write_ctxt *wc,
					struct page *page, u32 cpos,
					loff_t user_pos, unsigned user_len,
					int new)
{
	int ret;
	unsigned int map_from = 0, map_to = 0;
	unsigned int cluster_start, cluster_end;
	unsigned int user_data_from = 0, user_data_to = 0;

	ocfs2_figure_cluster_boundaries(OCFS2_SB(inode->i_sb), cpos,
					&cluster_start, &cluster_end);

	if (page == wc->w_target_page) {
		map_from = user_pos & (PAGE_CACHE_SIZE - 1);
		map_to = map_from + user_len;

		if (new)
			ret = ocfs2_map_page_blocks(page, p_blkno, inode,
						    cluster_start, cluster_end,
						    new);
		else
			ret = ocfs2_map_page_blocks(page, p_blkno, inode,
						    map_from, map_to, new);
		if (ret) {
			mlog_errno(ret);
			goto out;
		}

		user_data_from = map_from;
		user_data_to = map_to;
		if (new) {
			map_from = cluster_start;
			map_to = cluster_end;
		}
	} else {
		/*
		 * If we haven't allocated the new page yet, we
		 * shouldn't be writing it out without copying user
		 * data. This is likely a math error from the caller.
		 */
		BUG_ON(!new);

		map_from = cluster_start;
		map_to = cluster_end;

		ret = ocfs2_map_page_blocks(page, p_blkno, inode,
					    cluster_start, cluster_end, new);
		if (ret) {
			mlog_errno(ret);
			goto out;
		}
	}

	/*
	 * Parts of newly allocated pages need to be zero'd.
	 *
	 * Above, we have also rewritten 'to' and 'from' - as far as
	 * the rest of the function is concerned, the entire cluster
	 * range inside of a page needs to be written.
	 *
	 * We can skip this if the page is up to date - it's already
	 * been zero'd from being read in as a hole.
	 */
	if (new && !PageUptodate(page))
		ocfs2_clear_page_regions(page, OCFS2_SB(inode->i_sb),
					 cpos, user_data_from, user_data_to);

	flush_dcache_page(page);

out:
	return ret;
}

The ocfs2_prepare_page_for_write function in fs/ocfs2/aops.c in the Oracle Cluster File System 2 (OCFS2) subsystem in the Linux kernel before 2.6.39-rc1 does not properly handle holes that cross page boundaries, which allows local users to obtain potentially sensitive information from uninitialized disk locations by reading a file.


static int ocfs2_prepare_page_for_write(struct inode *inode, u64 *p_blkno,
					struct ocfs2_write_ctxt *wc,
					struct page *page, u32 cpos,
					loff_t user_pos, unsigned user_len,
					int new)
{
	int ret;
	unsigned int map_from = 0, map_to = 0;
	unsigned int cluster_start, cluster_end;
	unsigned int user_data_from = 0, user_data_to = 0;

	ocfs2_figure_cluster_boundaries(OCFS2_SB(inode->i_sb), cpos,
					&cluster_start, &cluster_end);

	/* treat the write as new if the a hole/lseek spanned across
	 * the page boundary.
	 */
	new = new | ((i_size_read(inode) <= page_offset(page)) &&
			(page_offset(page) <= user_pos));

	if (page == wc->w_target_page) {
		map_from = user_pos & (PAGE_CACHE_SIZE - 1);
		map_to = map_from + user_len;

		if (new)
			ret = ocfs2_map_page_blocks(page, p_blkno, inode,
						    cluster_start, cluster_end,
						    new);
		else
			ret = ocfs2_map_page_blocks(page, p_blkno, inode,
						    map_from, map_to, new);
		if (ret) {
			mlog_errno(ret);
			goto out;
		}

		user_data_from = map_from;
		user_data_to = map_to;
		if (new) {
			map_from = cluster_start;
			map_to = cluster_end;
		}
	} else {
		/*
		 * If we haven't allocated the new page yet, we
		 * shouldn't be writing it out without copying user
		 * data. This is likely a math error from the caller.
		 */
		BUG_ON(!new);

		map_from = cluster_start;
		map_to = cluster_end;

		ret = ocfs2_map_page_blocks(page, p_blkno, inode,
					    cluster_start, cluster_end, new);
		if (ret) {
			mlog_errno(ret);
			goto out;
		}
	}

	/*
	 * Parts of newly allocated pages need to be zero'd.
	 *
	 * Above, we have also rewritten 'to' and 'from' - as far as
	 * the rest of the function is concerned, the entire cluster
	 * range inside of a page needs to be written.
	 *
	 * We can skip this if the page is up to date - it's already
	 * been zero'd from being read in as a hole.
	 */
	if (new && !PageUptodate(page))
		ocfs2_clear_page_regions(page, OCFS2_SB(inode->i_sb),
					 cpos, user_data_from, user_data_to);

	flush_dcache_page(page);

out:
	return ret;
}


Fix memory leak in read_header

Bug reported in https://savannah.gnu.org/bugs/?59897

* src/list.c (read_header): Don't return directly from the loop.
Instead set the status and break.  Return the status.  Free
next_long_name and next_long_link before returning.

read_header (union block **return_block, struct tar_stat_info *info,
	     enum read_header_mode mode)
{
  union block *header;
  union block *header_copy;
  char *bp;
  union block *data_block;
  size_t size, written;
  union block *next_long_name = 0;
  union block *next_long_link = 0;
  size_t next_long_name_blocks = 0;
  size_t next_long_link_blocks = 0;

  while (1)
    {
      enum read_header status;

      header = find_next_block ();
      *return_block = header;
      if (!header)
	return HEADER_END_OF_FILE;

      if ((status = tar_checksum (header, false)) != HEADER_SUCCESS)
	return status;

      /* Good block.  Decode file size and return.  */

      if (header->header.typeflag == LNKTYPE)
	info->stat.st_size = 0;	/* links 0 size on tape */
      else
	{
	  info->stat.st_size = OFF_FROM_HEADER (header->header.size);
	  if (info->stat.st_size < 0)
	    return HEADER_FAILURE;
	}

      if (header->header.typeflag == GNUTYPE_LONGNAME
	  || header->header.typeflag == GNUTYPE_LONGLINK
	  || header->header.typeflag == XHDTYPE
	  || header->header.typeflag == XGLTYPE
	  || header->header.typeflag == SOLARIS_XHDTYPE)
	{
	  if (mode == read_header_x_raw)
	    return HEADER_SUCCESS_EXTENDED;
	  else if (header->header.typeflag == GNUTYPE_LONGNAME
		   || header->header.typeflag == GNUTYPE_LONGLINK)
	    {
	      size_t name_size = info->stat.st_size;
	      size_t n = name_size % BLOCKSIZE;
	      size = name_size + BLOCKSIZE;
	      if (n)
		size += BLOCKSIZE - n;

	      if (name_size != info->stat.st_size || size < name_size)
		xalloc_die ();

	      header_copy = xmalloc (size + 1);

	      if (header->header.typeflag == GNUTYPE_LONGNAME)
		{
		  free (next_long_name);
		  next_long_name = header_copy;
		  next_long_name_blocks = size / BLOCKSIZE;
		}
	      else
		{
		  free (next_long_link);
		  next_long_link = header_copy;
		  next_long_link_blocks = size / BLOCKSIZE;
		}

	      set_next_block_after (header);
	      *header_copy = *header;
	      bp = header_copy->buffer + BLOCKSIZE;

	      for (size -= BLOCKSIZE; size > 0; size -= written)
		{
		  data_block = find_next_block ();
		  if (! data_block)
		    {
		      ERROR ((0, 0, _("Unexpected EOF in archive")));
		      break;
		    }
		  written = available_space_after (data_block);
		  if (written > size)
		    written = size;

		  memcpy (bp, data_block->buffer, written);
		  bp += written;
		  set_next_block_after ((union block *)
					(data_block->buffer + written - 1));
		}

	      *bp = '\0';
	    }
	  else if (header->header.typeflag == XHDTYPE
		   || header->header.typeflag == SOLARIS_XHDTYPE)
	    xheader_read (&info->xhdr, header,
			  OFF_FROM_HEADER (header->header.size));
	  else if (header->header.typeflag == XGLTYPE)
	    {
	      struct xheader xhdr;

	      if (!recent_global_header)
		recent_global_header = xmalloc (sizeof *recent_global_header);
	      memcpy (recent_global_header, header,
		      sizeof *recent_global_header);
	      memset (&xhdr, 0, sizeof xhdr);
	      xheader_read (&xhdr, header,
			    OFF_FROM_HEADER (header->header.size));
	      xheader_decode_global (&xhdr);
	      xheader_destroy (&xhdr);
	      if (mode == read_header_x_global)
		return HEADER_SUCCESS_EXTENDED;
	    }

	  /* Loop!  */

	}
      else
	{
	  char const *name;
	  struct posix_header const *h = &header->header;
	  char namebuf[sizeof h->prefix + 1 + NAME_FIELD_SIZE + 1];

	  free (recent_long_name);

	  if (next_long_name)
	    {
	      name = next_long_name->buffer + BLOCKSIZE;
	      recent_long_name = next_long_name;
	      recent_long_name_blocks = next_long_name_blocks;
	    }
	  else
	    {
	      /* Accept file names as specified by POSIX.1-1996
                 section 10.1.1.  */
	      char *np = namebuf;

	      if (h->prefix[0] && strcmp (h->magic, TMAGIC) == 0)
		{
		  memcpy (np, h->prefix, sizeof h->prefix);
		  np[sizeof h->prefix] = '\0';
		  np += strlen (np);
		  *np++ = '/';
		}
	      memcpy (np, h->name, sizeof h->name);
	      np[sizeof h->name] = '\0';
	      name = namebuf;
	      recent_long_name = 0;
	      recent_long_name_blocks = 0;
	    }
	  assign_string (&info->orig_file_name, name);
	  assign_string (&info->file_name, name);
	  info->had_trailing_slash = strip_trailing_slashes (info->file_name);

	  free (recent_long_link);

	  if (next_long_link)
	    {
	      name = next_long_link->buffer + BLOCKSIZE;
	      recent_long_link = next_long_link;
	      recent_long_link_blocks = next_long_link_blocks;
	    }
	  else
	    {
	      memcpy (namebuf, h->linkname, sizeof h->linkname);
	      namebuf[sizeof h->linkname] = '\0';
	      name = namebuf;
	      recent_long_link = 0;
	      recent_long_link_blocks = 0;
	    }
	  assign_string (&info->link_name, name);

	  return HEADER_SUCCESS;
	}
    }
}

A flaw was found in the src/list.c of tar 1.33 and earlier. This flaw allows an attacker who can submit a crafted input file to tar to cause uncontrolled consumption of memory. The highest threat from this vulnerability is to system availability.


read_header (union block **return_block, struct tar_stat_info *info,
	     enum read_header_mode mode)
{
  union block *header;
  char *bp;
  union block *data_block;
  size_t size, written;
  union block *next_long_name = NULL;
  union block *next_long_link = NULL;
  size_t next_long_name_blocks = 0;
  size_t next_long_link_blocks = 0;
  enum read_header status = HEADER_SUCCESS;

  while (1)
    {
      header = find_next_block ();
      *return_block = header;
      if (!header)
	{
	  status = HEADER_END_OF_FILE;
	  break;
	}

      if ((status = tar_checksum (header, false)) != HEADER_SUCCESS)
	break;

      /* Good block.  Decode file size and return.  */

      if (header->header.typeflag == LNKTYPE)
	info->stat.st_size = 0;	/* links 0 size on tape */
      else
	{
	  info->stat.st_size = OFF_FROM_HEADER (header->header.size);
	  if (info->stat.st_size < 0)
	    {
	      status = HEADER_FAILURE;
	      break;
	    }
	}

      if (header->header.typeflag == GNUTYPE_LONGNAME
	  || header->header.typeflag == GNUTYPE_LONGLINK
	  || header->header.typeflag == XHDTYPE
	  || header->header.typeflag == XGLTYPE
	  || header->header.typeflag == SOLARIS_XHDTYPE)
	{
	  if (mode == read_header_x_raw)
	    {
	      status = HEADER_SUCCESS_EXTENDED;
	      break;
	    }
	  else if (header->header.typeflag == GNUTYPE_LONGNAME
		   || header->header.typeflag == GNUTYPE_LONGLINK)
	    {
	      union block *header_copy;
	      size_t name_size = info->stat.st_size;
	      size_t n = name_size % BLOCKSIZE;
	      size = name_size + BLOCKSIZE;
	      if (n)
		size += BLOCKSIZE - n;

	      if (name_size != info->stat.st_size || size < name_size)
		xalloc_die ();

	      header_copy = xmalloc (size + 1);

	      if (header->header.typeflag == GNUTYPE_LONGNAME)
		{
		  free (next_long_name);
		  next_long_name = header_copy;
		  next_long_name_blocks = size / BLOCKSIZE;
		}
	      else
		{
		  free (next_long_link);
		  next_long_link = header_copy;
		  next_long_link_blocks = size / BLOCKSIZE;
		}

	      set_next_block_after (header);
	      *header_copy = *header;
	      bp = header_copy->buffer + BLOCKSIZE;

	      for (size -= BLOCKSIZE; size > 0; size -= written)
		{
		  data_block = find_next_block ();
		  if (! data_block)
		    {
		      ERROR ((0, 0, _("Unexpected EOF in archive")));
		      break;
		    }
		  written = available_space_after (data_block);
		  if (written > size)
		    written = size;

		  memcpy (bp, data_block->buffer, written);
		  bp += written;
		  set_next_block_after ((union block *)
					(data_block->buffer + written - 1));
		}

	      *bp = '\0';
	    }
	  else if (header->header.typeflag == XHDTYPE
		   || header->header.typeflag == SOLARIS_XHDTYPE)
	    xheader_read (&info->xhdr, header,
			  OFF_FROM_HEADER (header->header.size));
	  else if (header->header.typeflag == XGLTYPE)
	    {
	      struct xheader xhdr;

	      if (!recent_global_header)
		recent_global_header = xmalloc (sizeof *recent_global_header);
	      memcpy (recent_global_header, header,
		      sizeof *recent_global_header);
	      memset (&xhdr, 0, sizeof xhdr);
	      xheader_read (&xhdr, header,
			    OFF_FROM_HEADER (header->header.size));
	      xheader_decode_global (&xhdr);
	      xheader_destroy (&xhdr);
	      if (mode == read_header_x_global)
		{
		  status = HEADER_SUCCESS_EXTENDED;
		  break;
		}
	    }

	  /* Loop!  */

	}
      else
	{
	  char const *name;
	  struct posix_header const *h = &header->header;
	  char namebuf[sizeof h->prefix + 1 + NAME_FIELD_SIZE + 1];

	  free (recent_long_name);

	  if (next_long_name)
	    {
	      name = next_long_name->buffer + BLOCKSIZE;
	      recent_long_name = next_long_name;
	      recent_long_name_blocks = next_long_name_blocks;
	      next_long_name = NULL;
	    }
	  else
	    {
	      /* Accept file names as specified by POSIX.1-1996
                 section 10.1.1.  */
	      char *np = namebuf;

	      if (h->prefix[0] && strcmp (h->magic, TMAGIC) == 0)
		{
		  memcpy (np, h->prefix, sizeof h->prefix);
		  np[sizeof h->prefix] = '\0';
		  np += strlen (np);
		  *np++ = '/';
		}
	      memcpy (np, h->name, sizeof h->name);
	      np[sizeof h->name] = '\0';
	      name = namebuf;
	      recent_long_name = 0;
	      recent_long_name_blocks = 0;
	    }
	  assign_string (&info->orig_file_name, name);
	  assign_string (&info->file_name, name);
	  info->had_trailing_slash = strip_trailing_slashes (info->file_name);

	  free (recent_long_link);

	  if (next_long_link)
	    {
	      name = next_long_link->buffer + BLOCKSIZE;
	      recent_long_link = next_long_link;
	      recent_long_link_blocks = next_long_link_blocks;
	      next_long_link = NULL;
	    }
	  else
	    {
	      memcpy (namebuf, h->linkname, sizeof h->linkname);
	      namebuf[sizeof h->linkname] = '\0';
	      name = namebuf;
	      recent_long_link = 0;
	      recent_long_link_blocks = 0;
	    }
	  assign_string (&info->link_name, name);

	  break;
	}
    }
  free (next_long_name);
  free (next_long_link);
  return status;
}


post_process_urlencoded (struct MHD_PostProcessor *pp,
                         const char *post_data,
                         size_t post_data_len)
{
  char *kbuf = (char *) &pp[1];
  size_t poff;
  const char *start_key = NULL;
  const char *end_key = NULL;
  const char *start_value = NULL;
  const char *end_value = NULL;
  const char *last_escape = NULL;

  poff = 0;
  while ( ( (poff < post_data_len) ||
            (pp->state == PP_Callback) ) &&
          (pp->state != PP_Error) )
  {
    switch (pp->state)
    {
    case PP_Error:
      /* clearly impossible as per while loop invariant */
      abort ();
      break;
    case PP_Init:
      /* key phase */
      if (NULL == start_key)
        start_key = &post_data[poff];
      pp->must_ikvi = true;
      switch (post_data[poff])
      {
      case '=':
        /* Case: 'key=' */
        end_key = &post_data[poff];
        poff++;
        pp->state = PP_ProcessValue;
        break;
      case '&':
        /* Case: 'key&' */
        end_key = &post_data[poff];
        mhd_assert (NULL == start_value);
        mhd_assert (NULL == end_value);
        poff++;
        pp->state = PP_Callback;
        break;
      case '\n':
      case '\r':
        /* Case: 'key\n' or 'key\r' */
        end_key = &post_data[poff];
        poff++;
        pp->state = PP_Done;
        break;
      default:
        /* normal character, advance! */
        poff++;
        continue;
      }
      break; /* end PP_Init */
    case PP_ProcessValue:
      if (NULL == start_value)
        start_value = &post_data[poff];
      switch (post_data[poff])
      {
      case '=':
        /* case 'key==' */
        pp->state = PP_Error;
        continue;
      case '&':
        /* case 'value&' */
        end_value = &post_data[poff];
        poff++;
        if (pp->must_ikvi ||
            (start_value != end_value) )
        {
          pp->state = PP_Callback;
        }
        else
        {
          pp->buffer_pos = 0;
          pp->value_offset = 0;
          pp->state = PP_Init;
          start_value = NULL;
        }
        continue;
      case '\n':
      case '\r':
        /* Case: 'value\n' or 'value\r' */
        end_value = &post_data[poff];
        poff++;
        if (pp->must_ikvi)
          pp->state = PP_Callback;
        else
          pp->state = PP_Done;
        break;
      case '%':
        last_escape = &post_data[poff];
        poff++;
        break;
      case '0':
      case '1':
      case '2':
      case '3':
      case '4':
      case '5':
      case '6':
      case '7':
      case '8':
      case '9':
        /* character, may be part of escaping */
        poff++;
        continue;
      default:
        /* normal character, no more escaping! */
        last_escape = NULL;
        poff++;
        continue;
      }
      break; /* end PP_ProcessValue */
    case PP_Done:
      switch (post_data[poff])
      {
      case '\n':
      case '\r':
        poff++;
        continue;
      }
      /* unexpected data at the end, fail! */
      pp->state = PP_Error;
      break;
    case PP_Callback:
      if ( (pp->buffer_pos + (end_key - start_key) >
            pp->buffer_size) ||
           (pp->buffer_pos + (end_key - start_key) <
            pp->buffer_pos) )
      {
        /* key too long, cannot parse! */
        pp->state = PP_Error;
        continue;
      }
      /* compute key, if we have not already */
      if (NULL != start_key)
      {
        memcpy (&kbuf[pp->buffer_pos],
                start_key,
                end_key - start_key);
        pp->buffer_pos += end_key - start_key;
        start_key = NULL;
        end_key = NULL;
        pp->must_unescape_key = true;
      }
      if (pp->must_unescape_key)
      {
        kbuf[pp->buffer_pos] = '\0'; /* 0-terminate key */
        MHD_unescape_plus (kbuf);
        MHD_http_unescape (kbuf);
        pp->must_unescape_key = false;
      }
      process_value (pp,
                     start_value,
                     end_value,
                     NULL);
      pp->value_offset = 0;
      start_value = NULL;
      end_value = NULL;
      pp->buffer_pos = 0;
      pp->state = PP_Init;
      break;
    default:
      mhd_panic (mhd_panic_cls,
                 __FILE__,
                 __LINE__,
                 NULL);              /* should never happen! */
    }
  }

  /* save remaining data for next iteration */
  if (NULL != start_key)
  {
    if (NULL == end_key)
      end_key = &post_data[poff];
    memcpy (&kbuf[pp->buffer_pos],
            start_key,
            end_key - start_key);
    pp->buffer_pos += end_key - start_key;
    pp->must_unescape_key = true;
    start_key = NULL;
    end_key = NULL;
  }
  if ( (NULL != start_value) &&
       (PP_ProcessValue == pp->state) )
  {
    /* compute key, if we have not already */
    if (pp->must_unescape_key)
    {
      kbuf[pp->buffer_pos] = '\0'; /* 0-terminate key */
      MHD_unescape_plus (kbuf);
      MHD_http_unescape (kbuf);
      pp->must_unescape_key = false;
    }
    if (NULL == end_value)
      end_value = &post_data[poff];
    process_value (pp,
                   start_value,
                   end_value,
                   last_escape);
    pp->must_ikvi = false;
  }
  return MHD_YES;
}

A flaw was found in libmicrohttpd. A missing bounds check in the post_process_urlencoded function leads to a buffer overflow, allowing a remote attacker to write arbitrary data in an application that uses libmicrohttpd. The highest threat from this vulnerability is to data confidentiality and integrity as well as system availability. Only version 0.9.70 is vulnerable.


post_process_urlencoded (struct MHD_PostProcessor *pp,
                         const char *post_data,
                         size_t post_data_len)
{
  char *kbuf = (char *) &pp[1];
  size_t poff;
  const char *start_key = NULL;
  const char *end_key = NULL;
  const char *start_value = NULL;
  const char *end_value = NULL;
  const char *last_escape = NULL;

  poff = 0;
  while ( ( (poff < post_data_len) ||
            (pp->state == PP_Callback) ) &&
          (pp->state != PP_Error) )
  {
    switch (pp->state)
    {
    case PP_Error:
      /* clearly impossible as per while loop invariant */
      abort ();
      break;
    case PP_Init:
      /* key phase */
      if (NULL == start_key)
        start_key = &post_data[poff];
      pp->must_ikvi = true;
      switch (post_data[poff])
      {
      case '=':
        /* Case: 'key=' */
        end_key = &post_data[poff];
        poff++;
        pp->state = PP_ProcessValue;
        break;
      case '&':
        /* Case: 'key&' */
        end_key = &post_data[poff];
        mhd_assert (NULL == start_value);
        mhd_assert (NULL == end_value);
        poff++;
        pp->state = PP_Callback;
        break;
      case '\n':
      case '\r':
        /* Case: 'key\n' or 'key\r' */
        end_key = &post_data[poff];
        poff++;
        pp->state = PP_Done;
        break;
      default:
        /* normal character, advance! */
        poff++;
        continue;
      }
      break; /* end PP_Init */
    case PP_ProcessValue:
      if (NULL == start_value)
        start_value = &post_data[poff];
      switch (post_data[poff])
      {
      case '=':
        /* case 'key==' */
        pp->state = PP_Error;
        continue;
      case '&':
        /* case 'value&' */
        end_value = &post_data[poff];
        poff++;
        if (pp->must_ikvi ||
            (start_value != end_value) )
        {
          pp->state = PP_Callback;
        }
        else
        {
          pp->buffer_pos = 0;
          pp->value_offset = 0;
          pp->state = PP_Init;
          start_value = NULL;
        }
        continue;
      case '\n':
      case '\r':
        /* Case: 'value\n' or 'value\r' */
        end_value = &post_data[poff];
        poff++;
        if (pp->must_ikvi)
          pp->state = PP_Callback;
        else
          pp->state = PP_Done;
        break;
      case '%':
        last_escape = &post_data[poff];
        poff++;
        break;
      case '0':
      case '1':
      case '2':
      case '3':
      case '4':
      case '5':
      case '6':
      case '7':
      case '8':
      case '9':
        /* character, may be part of escaping */
        poff++;
        continue;
      default:
        /* normal character, no more escaping! */
        last_escape = NULL;
        poff++;
        continue;
      }
      break; /* end PP_ProcessValue */
    case PP_Done:
      switch (post_data[poff])
      {
      case '\n':
      case '\r':
        poff++;
        continue;
      }
      /* unexpected data at the end, fail! */
      pp->state = PP_Error;
      break;
    case PP_Callback:
      if ( (pp->buffer_pos + (end_key - start_key) >=
            pp->buffer_size) ||
           (pp->buffer_pos + (end_key - start_key) <
            pp->buffer_pos) )
      {
        /* key too long, cannot parse! */
        pp->state = PP_Error;
        continue;
      }
      /* compute key, if we have not already */
      if (NULL != start_key)
      {
        memcpy (&kbuf[pp->buffer_pos],
                start_key,
                end_key - start_key);
        pp->buffer_pos += end_key - start_key;
        start_key = NULL;
        end_key = NULL;
        pp->must_unescape_key = true;
      }
      if (pp->must_unescape_key)
      {
        kbuf[pp->buffer_pos] = '\0'; /* 0-terminate key */
        MHD_unescape_plus (kbuf);
        MHD_http_unescape (kbuf);
        pp->must_unescape_key = false;
      }
      process_value (pp,
                     start_value,
                     end_value,
                     NULL);
      pp->value_offset = 0;
      start_value = NULL;
      end_value = NULL;
      pp->buffer_pos = 0;
      pp->state = PP_Init;
      break;
    default:
      mhd_panic (mhd_panic_cls,
                 __FILE__,
                 __LINE__,
                 NULL);              /* should never happen! */
    }
  }

  /* save remaining data for next iteration */
  if (NULL != start_key)
  {
    if (NULL == end_key)
      end_key = &post_data[poff];
    if (pp->buffer_pos + (end_key - start_key) >= pp->buffer_size)
    {
      pp->state = PP_Error;
      return MHD_NO;
    }
    memcpy (&kbuf[pp->buffer_pos],
            start_key,
            end_key - start_key);
    pp->buffer_pos += end_key - start_key;
    pp->must_unescape_key = true;
    start_key = NULL;
    end_key = NULL;
  }
  if ( (NULL != start_value) &&
       (PP_ProcessValue == pp->state) )
  {
    /* compute key, if we have not already */
    if (pp->must_unescape_key)
    {
      kbuf[pp->buffer_pos] = '\0'; /* 0-terminate key */
      MHD_unescape_plus (kbuf);
      MHD_http_unescape (kbuf);
      pp->must_unescape_key = false;
    }
    if (NULL == end_value)
      end_value = &post_data[poff];
    process_value (pp,
                   start_value,
                   end_value,
                   last_escape);
    pp->must_ikvi = false;
  }
  if (PP_Error == pp->state)
  {
    /* State in error, returning failure */
    return MHD_NO;
  }
  return MHD_YES;
}


Use ecc_mod_mul_canonical for point comparison.

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

(cherry picked from commit 5b7608fde3a6d2ab82bffb35db1e4e330927c906)

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 (p, t0, x1, z2, t0);
  if (mpn_cmp (t0, p->m, p->size) >= 0)
    mpn_sub_n (t0, t0, p->m, p->size);

  ecc_mod_mul (p, t1, x2, z1, t1);
  if (mpn_cmp (t1, p->m, p->size) >= 0)
    mpn_sub_n (t1, t1, p->m, p->size);

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

#undef t0
#undef t1
}

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.


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
}


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)

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 (&ecc->q, tp, hp, kinv, tp);

  mpn_copyi (sp, tp, ecc->p.size);
#undef P
#undef hp
#undef kinv
#undef tp
}


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
}


Analogous fix to ecc_gostdsa_verify.

* ecc-gostdsa-verify.c (ecc_gostdsa_verify): Use ecc_mod_mul_canonical
to compute the scalars used for ecc multiplication.

(cherry picked from commit fbaefb64b90cb45b7075a0ed72a92f2a1fbcd2ab)

ecc_gostdsa_verify (const struct ecc_curve *ecc,
		  const mp_limb_t *pp, /* Public key */
		  size_t length, const uint8_t *digest,
		  const mp_limb_t *rp, const mp_limb_t *sp,
		  mp_limb_t *scratch)
{
  /* Procedure, according to GOST R 34.10. q denotes the group
     order.

     1. Check 0 < r, s < q.

     2. v <-- h^{-1}  (mod q)

     3. z1  <-- s * v (mod q)

     4. z2  <-- -r * v (mod q)

     5. R = u1 G + u2 Y

     6. Signature is valid if R_x = r (mod q).
  */

#define hp (scratch)
#define vp (scratch + ecc->p.size)
#define z1 (scratch + 3*ecc->p.size)
#define z2 (scratch + 4*ecc->p.size)

#define P1 (scratch + 4*ecc->p.size)
#define P2 (scratch)

  if (! (ecdsa_in_range (ecc, rp)
	 && ecdsa_in_range (ecc, sp)))
    return 0;

  gost_hash (&ecc->q, hp, length, digest);

  if (mpn_zero_p (hp, ecc->p.size))
    mpn_add_1 (hp, hp, ecc->p.size, 1);

  /* Compute v */
  ecc->q.invert (&ecc->q, vp, hp, vp + ecc->p.size);

  /* z1 = s / h, P1 = z1 * G */
  ecc_mod_mul (&ecc->q, z1, sp, vp, z1);

  /* z2 = - r / h, P2 = z2 * Y */
  ecc_mod_mul (&ecc->q, z2, rp, vp, z2);
  mpn_sub_n (z2, ecc->q.m, z2, ecc->p.size);

   /* Total storage: 5*ecc->p.size + ecc->mul_itch */
  ecc->mul (ecc, P2, z2, pp, z2 + ecc->p.size);

  /* Total storage: 7*ecc->p.size + ecc->mul_g_itch (ecc->p.size) */
  ecc->mul_g (ecc, P1, z1, P1 + 3*ecc->p.size);

  /* Total storage: 6*ecc->p.size + ecc->add_hhh_itch */
  ecc->add_hhh (ecc, P1, P1, P2, P1 + 3*ecc->p.size);

  /* x coordinate only, modulo q */
  ecc->h_to_a (ecc, 2, P2, P1, P1 + 3*ecc->p.size);

  return (mpn_cmp (rp, P2, ecc->p.size) == 0);
#undef P2
#undef P1
#undef z2
#undef z1
#undef hp
#undef vp
}


ecc_gostdsa_verify (const struct ecc_curve *ecc,
		  const mp_limb_t *pp, /* Public key */
		  size_t length, const uint8_t *digest,
		  const mp_limb_t *rp, const mp_limb_t *sp,
		  mp_limb_t *scratch)
{
  /* Procedure, according to GOST R 34.10. q denotes the group
     order.

     1. Check 0 < r, s < q.

     2. v <-- h^{-1}  (mod q)

     3. z1  <-- s * v (mod q)

     4. z2  <-- -r * v (mod q)

     5. R = u1 G + u2 Y

     6. Signature is valid if R_x = r (mod q).
  */

#define hp (scratch)
#define vp (scratch + ecc->p.size)
#define z1 (scratch + 3*ecc->p.size)
#define z2 (scratch + 4*ecc->p.size)

#define P1 (scratch + 4*ecc->p.size)
#define P2 (scratch)

  if (! (ecdsa_in_range (ecc, rp)
	 && ecdsa_in_range (ecc, sp)))
    return 0;

  gost_hash (&ecc->q, hp, length, digest);

  if (mpn_zero_p (hp, ecc->p.size))
    mpn_add_1 (hp, hp, ecc->p.size, 1);

  /* Compute v */
  ecc->q.invert (&ecc->q, vp, hp, vp + ecc->p.size);

  /* z1 = s / h, P1 = z1 * G */
  ecc_mod_mul_canonical (&ecc->q, z1, sp, vp, z1);

  /* z2 = - r / h, P2 = z2 * Y */
  mpn_sub_n (hp, ecc->q.m, rp, ecc->p.size);
  ecc_mod_mul_canonical (&ecc->q, z2, hp, vp, z2);

   /* Total storage: 5*ecc->p.size + ecc->mul_itch */
  ecc->mul (ecc, P2, z2, pp, z2 + ecc->p.size);

  /* Total storage: 7*ecc->p.size + ecc->mul_g_itch (ecc->p.size) */
  ecc->mul_g (ecc, P1, z1, P1 + 3*ecc->p.size);

  /* Total storage: 6*ecc->p.size + ecc->add_hhh_itch */
  ecc->add_hhh (ecc, P1, P1, P2, P1 + 3*ecc->p.size);

  /* x coordinate only, modulo q */
  ecc->h_to_a (ecc, 2, P2, P1, P1 + 3*ecc->p.size);

  return (mpn_cmp (rp, P2, ecc->p.size) == 0);
#undef P2
#undef P1
#undef z2
#undef z1
#undef hp
#undef vp
}


Fix canonical reduction in gostdsa_vko.

* gostdsa-vko.c (gostdsa_vko): Use ecc_mod_mul_canonical to
compute the scalar used for ecc multiplication.

(cherry picked from commit b30e0ca6d2b41579a5b6a010fc54065d790e8d55)

gostdsa_vko (const struct ecc_scalar *priv,
		const struct ecc_point *pub,
		size_t ukm_length, const uint8_t *ukm,
		uint8_t *out)
{
  const struct ecc_curve *ecc = priv->ecc;
  unsigned bsize = (ecc_bit_size (ecc) + 7) / 8;
  mp_size_t size = ecc->p.size;
  mp_size_t itch = 4*size + ecc->mul_itch;
  mp_limb_t *scratch;

  if (itch < 5*size + ecc->h_to_a_itch)
      itch = 5*size + ecc->h_to_a_itch;

  assert (pub->ecc == ecc);
  assert (priv->ecc == ecc);
  assert (ukm_length <= bsize);

  scratch = gmp_alloc_limbs (itch);

#define UKM scratch
#define TEMP (scratch + 3*size)
#define XYZ scratch
#define TEMP_Y (scratch + 4*size)

  mpn_set_base256_le (UKM, size, ukm, ukm_length);

  /* If ukm is 0, set it to 1, otherwise the result will be allways equal to 0,
   * no matter what private and public keys are. See RFC 4357 referencing GOST
   * R 34.10-2001 (RFC 5832) Section 6.1 step 2. */
  if (mpn_zero_p (UKM, size))
    UKM[0] = 1;

  ecc_mod_mul (&ecc->q, TEMP, priv->p, UKM, TEMP); /* TEMP = UKM * priv */
  ecc->mul (ecc, XYZ, TEMP, pub->p, scratch + 4*size); /* XYZ = UKM * priv * pub */
  ecc->h_to_a (ecc, 0, TEMP, XYZ, scratch + 5*size); /* TEMP = XYZ */
  mpn_get_base256_le (out, bsize, TEMP, size);
  mpn_get_base256_le (out+bsize, bsize, TEMP_Y, size);
  gmp_free_limbs (scratch, itch);
}


gostdsa_vko (const struct ecc_scalar *priv,
		const struct ecc_point *pub,
		size_t ukm_length, const uint8_t *ukm,
		uint8_t *out)
{
  const struct ecc_curve *ecc = priv->ecc;
  unsigned bsize = (ecc_bit_size (ecc) + 7) / 8;
  mp_size_t size = ecc->p.size;
  mp_size_t itch = 4*size + ecc->mul_itch;
  mp_limb_t *scratch;

  if (itch < 5*size + ecc->h_to_a_itch)
      itch = 5*size + ecc->h_to_a_itch;

  assert (pub->ecc == ecc);
  assert (priv->ecc == ecc);
  assert (ukm_length <= bsize);

  scratch = gmp_alloc_limbs (itch);

#define UKM scratch
#define TEMP (scratch + 3*size)
#define XYZ scratch
#define TEMP_Y (scratch + 4*size)

  mpn_set_base256_le (UKM, size, ukm, ukm_length);

  /* If ukm is 0, set it to 1, otherwise the result will be allways equal to 0,
   * no matter what private and public keys are. See RFC 4357 referencing GOST
   * R 34.10-2001 (RFC 5832) Section 6.1 step 2. */
  if (mpn_zero_p (UKM, size))
    UKM[0] = 1;

  ecc_mod_mul_canonical (&ecc->q, TEMP, priv->p, UKM, TEMP); /* TEMP = UKM * priv */
  ecc->mul (ecc, XYZ, TEMP, pub->p, scratch + 4*size); /* XYZ = UKM * priv * pub */
  ecc->h_to_a (ecc, 0, TEMP, XYZ, scratch + 5*size); /* TEMP = XYZ */
  mpn_get_base256_le (out, bsize, TEMP, size);
  mpn_get_base256_le (out+bsize, bsize, TEMP_Y, size);
  gmp_free_limbs (scratch, itch);
}


[PATCH] Fix for minix crash

Mounting a (corrupt) minix filesystem with zero s_zmap_blocks
gives a spectacular crash on my 2.6.17.8 system, no doubt
because minix/inode.c does an unconditional
	minix_set_bit(0,sbi->s_zmap[0]->b_data);

[akpm@osdl.org: make labels conistent while we're there]

Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>

static int minix_fill_super(struct super_block *s, void *data, int silent)
{
	struct buffer_head *bh;
	struct buffer_head **map;
	struct minix_super_block *ms;
	int i, block;
	struct inode *root_inode;
	struct minix_sb_info *sbi;

	sbi = kmalloc(sizeof(struct minix_sb_info), GFP_KERNEL);
	if (!sbi)
		return -ENOMEM;
	s->s_fs_info = sbi;
	memset(sbi, 0, sizeof(struct minix_sb_info));

	/* N.B. These should be compile-time tests.
	   Unfortunately that is impossible. */
	if (32 != sizeof (struct minix_inode))
		panic("bad V1 i-node size");
	if (64 != sizeof(struct minix2_inode))
		panic("bad V2 i-node size");

	if (!sb_set_blocksize(s, BLOCK_SIZE))
		goto out_bad_hblock;

	if (!(bh = sb_bread(s, 1)))
		goto out_bad_sb;

	ms = (struct minix_super_block *) bh->b_data;
	sbi->s_ms = ms;
	sbi->s_sbh = bh;
	sbi->s_mount_state = ms->s_state;
	sbi->s_ninodes = ms->s_ninodes;
	sbi->s_nzones = ms->s_nzones;
	sbi->s_imap_blocks = ms->s_imap_blocks;
	sbi->s_zmap_blocks = ms->s_zmap_blocks;
	sbi->s_firstdatazone = ms->s_firstdatazone;
	sbi->s_log_zone_size = ms->s_log_zone_size;
	sbi->s_max_size = ms->s_max_size;
	s->s_magic = ms->s_magic;
	if (s->s_magic == MINIX_SUPER_MAGIC) {
		sbi->s_version = MINIX_V1;
		sbi->s_dirsize = 16;
		sbi->s_namelen = 14;
		sbi->s_link_max = MINIX_LINK_MAX;
	} else if (s->s_magic == MINIX_SUPER_MAGIC2) {
		sbi->s_version = MINIX_V1;
		sbi->s_dirsize = 32;
		sbi->s_namelen = 30;
		sbi->s_link_max = MINIX_LINK_MAX;
	} else if (s->s_magic == MINIX2_SUPER_MAGIC) {
		sbi->s_version = MINIX_V2;
		sbi->s_nzones = ms->s_zones;
		sbi->s_dirsize = 16;
		sbi->s_namelen = 14;
		sbi->s_link_max = MINIX2_LINK_MAX;
	} else if (s->s_magic == MINIX2_SUPER_MAGIC2) {
		sbi->s_version = MINIX_V2;
		sbi->s_nzones = ms->s_zones;
		sbi->s_dirsize = 32;
		sbi->s_namelen = 30;
		sbi->s_link_max = MINIX2_LINK_MAX;
	} else
		goto out_no_fs;

	/*
	 * Allocate the buffer map to keep the superblock small.
	 */
	i = (sbi->s_imap_blocks + sbi->s_zmap_blocks) * sizeof(bh);
	map = kmalloc(i, GFP_KERNEL);
	if (!map)
		goto out_no_map;
	memset(map, 0, i);
	sbi->s_imap = &map[0];
	sbi->s_zmap = &map[sbi->s_imap_blocks];

	block=2;
	for (i=0 ; i < sbi->s_imap_blocks ; i++) {
		if (!(sbi->s_imap[i]=sb_bread(s, block)))
			goto out_no_bitmap;
		block++;
	}
	for (i=0 ; i < sbi->s_zmap_blocks ; i++) {
		if (!(sbi->s_zmap[i]=sb_bread(s, block)))
			goto out_no_bitmap;
		block++;
	}

	minix_set_bit(0,sbi->s_imap[0]->b_data);
	minix_set_bit(0,sbi->s_zmap[0]->b_data);

	/* set up enough so that it can read an inode */
	s->s_op = &minix_sops;
	root_inode = iget(s, MINIX_ROOT_INO);
	if (!root_inode || is_bad_inode(root_inode))
		goto out_no_root;

	s->s_root = d_alloc_root(root_inode);
	if (!s->s_root)
		goto out_iput;

	if (!NO_TRUNCATE)
		s->s_root->d_op = &minix_dentry_operations;

	if (!(s->s_flags & MS_RDONLY)) {
		ms->s_state &= ~MINIX_VALID_FS;
		mark_buffer_dirty(bh);
	}
	if (!(sbi->s_mount_state & MINIX_VALID_FS))
		printk("MINIX-fs: mounting unchecked file system, "
			"running fsck is recommended\n");
 	else if (sbi->s_mount_state & MINIX_ERROR_FS)
		printk("MINIX-fs: mounting file system with errors, "
			"running fsck is recommended\n");
	return 0;

out_iput:
	iput(root_inode);
	goto out_freemap;

out_no_root:
	if (!silent)
		printk("MINIX-fs: get root inode failed\n");
	goto out_freemap;

out_no_bitmap:
	printk("MINIX-fs: bad superblock or unable to read bitmaps\n");
    out_freemap:
	for (i = 0; i < sbi->s_imap_blocks; i++)
		brelse(sbi->s_imap[i]);
	for (i = 0; i < sbi->s_zmap_blocks; i++)
		brelse(sbi->s_zmap[i]);
	kfree(sbi->s_imap);
	goto out_release;

out_no_map:
	if (!silent)
		printk("MINIX-fs: can't allocate map\n");
	goto out_release;

out_no_fs:
	if (!silent)
		printk("VFS: Can't find a Minix or Minix V2 filesystem "
			"on device %s\n", s->s_id);
    out_release:
	brelse(bh);
	goto out;

out_bad_hblock:
	printk("MINIX-fs: blocksize too small for device\n");
	goto out;

out_bad_sb:
	printk("MINIX-fs: unable to read superblock\n");
 out:
	s->s_fs_info = NULL;
	kfree(sbi);
	return -EINVAL;
}

The minix filesystem code in Linux kernel 2.6.x before 2.6.24, including 2.6.18, allows local users to cause a denial of service (hang) via a malformed minix file stream that triggers an infinite loop in the minix_bmap function.  NOTE: this issue might be due to an integer overflow or signedness error.


static int minix_fill_super(struct super_block *s, void *data, int silent)
{
	struct buffer_head *bh;
	struct buffer_head **map;
	struct minix_super_block *ms;
	int i, block;
	struct inode *root_inode;
	struct minix_sb_info *sbi;

	sbi = kmalloc(sizeof(struct minix_sb_info), GFP_KERNEL);
	if (!sbi)
		return -ENOMEM;
	s->s_fs_info = sbi;
	memset(sbi, 0, sizeof(struct minix_sb_info));

	/* N.B. These should be compile-time tests.
	   Unfortunately that is impossible. */
	if (32 != sizeof (struct minix_inode))
		panic("bad V1 i-node size");
	if (64 != sizeof(struct minix2_inode))
		panic("bad V2 i-node size");

	if (!sb_set_blocksize(s, BLOCK_SIZE))
		goto out_bad_hblock;

	if (!(bh = sb_bread(s, 1)))
		goto out_bad_sb;

	ms = (struct minix_super_block *) bh->b_data;
	sbi->s_ms = ms;
	sbi->s_sbh = bh;
	sbi->s_mount_state = ms->s_state;
	sbi->s_ninodes = ms->s_ninodes;
	sbi->s_nzones = ms->s_nzones;
	sbi->s_imap_blocks = ms->s_imap_blocks;
	sbi->s_zmap_blocks = ms->s_zmap_blocks;
	sbi->s_firstdatazone = ms->s_firstdatazone;
	sbi->s_log_zone_size = ms->s_log_zone_size;
	sbi->s_max_size = ms->s_max_size;
	s->s_magic = ms->s_magic;
	if (s->s_magic == MINIX_SUPER_MAGIC) {
		sbi->s_version = MINIX_V1;
		sbi->s_dirsize = 16;
		sbi->s_namelen = 14;
		sbi->s_link_max = MINIX_LINK_MAX;
	} else if (s->s_magic == MINIX_SUPER_MAGIC2) {
		sbi->s_version = MINIX_V1;
		sbi->s_dirsize = 32;
		sbi->s_namelen = 30;
		sbi->s_link_max = MINIX_LINK_MAX;
	} else if (s->s_magic == MINIX2_SUPER_MAGIC) {
		sbi->s_version = MINIX_V2;
		sbi->s_nzones = ms->s_zones;
		sbi->s_dirsize = 16;
		sbi->s_namelen = 14;
		sbi->s_link_max = MINIX2_LINK_MAX;
	} else if (s->s_magic == MINIX2_SUPER_MAGIC2) {
		sbi->s_version = MINIX_V2;
		sbi->s_nzones = ms->s_zones;
		sbi->s_dirsize = 32;
		sbi->s_namelen = 30;
		sbi->s_link_max = MINIX2_LINK_MAX;
	} else
		goto out_no_fs;

	/*
	 * Allocate the buffer map to keep the superblock small.
	 */
	if (sbi->s_imap_blocks == 0 || sbi->s_zmap_blocks == 0)
		goto out_illegal_sb;
	i = (sbi->s_imap_blocks + sbi->s_zmap_blocks) * sizeof(bh);
	map = kmalloc(i, GFP_KERNEL);
	if (!map)
		goto out_no_map;
	memset(map, 0, i);
	sbi->s_imap = &map[0];
	sbi->s_zmap = &map[sbi->s_imap_blocks];

	block=2;
	for (i=0 ; i < sbi->s_imap_blocks ; i++) {
		if (!(sbi->s_imap[i]=sb_bread(s, block)))
			goto out_no_bitmap;
		block++;
	}
	for (i=0 ; i < sbi->s_zmap_blocks ; i++) {
		if (!(sbi->s_zmap[i]=sb_bread(s, block)))
			goto out_no_bitmap;
		block++;
	}

	minix_set_bit(0,sbi->s_imap[0]->b_data);
	minix_set_bit(0,sbi->s_zmap[0]->b_data);

	/* set up enough so that it can read an inode */
	s->s_op = &minix_sops;
	root_inode = iget(s, MINIX_ROOT_INO);
	if (!root_inode || is_bad_inode(root_inode))
		goto out_no_root;

	s->s_root = d_alloc_root(root_inode);
	if (!s->s_root)
		goto out_iput;

	if (!NO_TRUNCATE)
		s->s_root->d_op = &minix_dentry_operations;

	if (!(s->s_flags & MS_RDONLY)) {
		ms->s_state &= ~MINIX_VALID_FS;
		mark_buffer_dirty(bh);
	}
	if (!(sbi->s_mount_state & MINIX_VALID_FS))
		printk("MINIX-fs: mounting unchecked file system, "
			"running fsck is recommended\n");
 	else if (sbi->s_mount_state & MINIX_ERROR_FS)
		printk("MINIX-fs: mounting file system with errors, "
			"running fsck is recommended\n");
	return 0;

out_iput:
	iput(root_inode);
	goto out_freemap;

out_no_root:
	if (!silent)
		printk("MINIX-fs: get root inode failed\n");
	goto out_freemap;

out_no_bitmap:
	printk("MINIX-fs: bad superblock or unable to read bitmaps\n");
out_freemap:
	for (i = 0; i < sbi->s_imap_blocks; i++)
		brelse(sbi->s_imap[i]);
	for (i = 0; i < sbi->s_zmap_blocks; i++)
		brelse(sbi->s_zmap[i]);
	kfree(sbi->s_imap);
	goto out_release;

out_no_map:
	if (!silent)
		printk("MINIX-fs: can't allocate map\n");
	goto out_release;

out_illegal_sb:
	if (!silent)
		printk("MINIX-fs: bad superblock\n");
	goto out_release;

out_no_fs:
	if (!silent)
		printk("VFS: Can't find a Minix or Minix V2 filesystem "
			"on device %s\n", s->s_id);
out_release:
	brelse(bh);
	goto out;

out_bad_hblock:
	printk("MINIX-fs: blocksize too small for device\n");
	goto out;

out_bad_sb:
	printk("MINIX-fs: unable to read superblock\n");
out:
	s->s_fs_info = NULL;
	kfree(sbi);
	return -EINVAL;
}


backport from 1.9 (rev #9980)
fixed temporary GRUU bug that lead to infinite loop
Credits to Tolga Tarhan

git-svn-id: svn+ssh://svn.code.sf.net/p/opensips/svn/trunk@9982 689a6050-402a-0410-94f2-e92a70836424

int lookup(struct sip_msg* _m, char* _t, char* _f, char* _s)
{
	unsigned int flags;
	urecord_t* r;
	str aor, uri;
	ucontact_t* ptr,*it;
	int res;
	int ret;
	str path_dst;
	str flags_s;
	pv_value_t val;
	int_str istr;
	str sip_instance = {0,0},call_id = {0,0};

	flags = 0;
	if (_f && _f[0]!=0) {
		if (fixup_get_svalue( _m, (gparam_p)_f, &flags_s)!=0) {
			LM_ERR("invalid owner uri parameter");
			return -1;
		}
		for( res=0 ; res< flags_s.len ; res++ ) {
			switch (flags_s.s[res]) {
				case 'm': flags |= REG_LOOKUP_METHODFILTER_FLAG; break;
				case 'b': flags |= REG_LOOKUP_NOBRANCH_FLAG; break;
				default: LM_WARN("unsuported flag %c \n",flags_s.s[res]);
			}
		}
	}

	if (_s) {
		if (pv_get_spec_value( _m, (pv_spec_p)_s, &val)!=0) {
			LM_ERR("failed to get PV value\n");
			return -1;
		}
		if ( (val.flags&PV_VAL_STR)==0 ) {
			LM_ERR("PV vals is not string\n");
			return -1;
		}
		uri = val.rs;
	} else {
		if (_m->new_uri.s) uri = _m->new_uri;
		else uri = _m->first_line.u.request.uri;
	}

	if (extract_aor(&uri, &aor,&sip_instance,&call_id) < 0) {
		LM_ERR("failed to extract address of record\n");
		return -3;
	}

	get_act_time();

	ul.lock_udomain((udomain_t*)_t, &aor);
	res = ul.get_urecord((udomain_t*)_t, &aor, &r);
	if (res > 0) {
		LM_DBG("'%.*s' Not found in usrloc\n", aor.len, ZSW(aor.s));
		ul.unlock_udomain((udomain_t*)_t, &aor);
		return -1;
	}

	ptr = r->contacts;
	ret = -1;
	/* look first for an un-expired and suported contact */
search_valid_contact:
	while ( (ptr) &&
	!(VALID_CONTACT(ptr,act_time) && (ret=-2) && allowed_method(_m,ptr,flags)))
		ptr = ptr->next;
	if (ptr==0) {
		/* nothing found */
		LM_DBG("nothing found !\n");
		goto done;
	}

	if (sip_instance.len && sip_instance.s) {
		LM_DBG("ruri has gruu in lookup\n");
		/* uri has GRUU */
		if (ptr->instance.len-2 != sip_instance.len ||
				memcmp(ptr->instance.s+1,sip_instance.s,sip_instance.len)) {
			LM_DBG("no match to sip instace - [%.*s] - [%.*s]\n",ptr->instance.len-2,ptr->instance.s+1,
					sip_instance.len,sip_instance.s);
			/* not the targeted instance, search some more */
			ptr = ptr->next;
			goto search_valid_contact;
		}

		LM_DBG("matched sip instace\n");
	}

	if (call_id.len && call_id.s) {
		/* decide whether GRUU is expired or not
		 *
		 * first - match call-id */
		if (ptr->callid.len != call_id.len ||
				memcmp(ptr->callid.s,call_id.s,call_id.len)) {
			LM_DBG("no match to call id - [%.*s] - [%.*s]\n",ptr->callid.len,ptr->callid.s,
					call_id.len,call_id.s);
			ptr = ptr->next;
			goto search_valid_contact;
		}

		/* matched call-id, check if there are newer contacts with
		 * same sip instace bup newer last_modified */

		it = ptr->next;
		while ( it ) {
			if (VALID_CONTACT(it,act_time)) {
				if (it->instance.len-2 == sip_instance.len &&
						memcmp(it->instance.s+1,sip_instance.s,sip_instance.len) == 0)
					if (it->last_modified > ptr->last_modified) {
						/* same instance id, but newer modified -> expired GRUU, no match at all */
						break;
					}
			}
		}

		if (it != NULL) {
			ret = -1;
			goto done;
		}
	}

	LM_DBG("found a complete match\n");

	ret = 1;
	if (ptr) {
		LM_DBG("setting as ruri <%.*s>\n",ptr->c.len,ptr->c.s);
		if (set_ruri(_m, &ptr->c) < 0) {
			LM_ERR("unable to rewrite Request-URI\n");
			ret = -3;
			goto done;
		}

		/* If a Path is present, use first path-uri in favour of
		 * received-uri because in that case the last hop towards the uac
		 * has to handle NAT. - agranig */
		if (ptr->path.s && ptr->path.len) {
			if (get_path_dst_uri(&ptr->path, &path_dst) < 0) {
				LM_ERR("failed to get dst_uri for Path\n");
				ret = -3;
				goto done;
			}
			if (set_path_vector(_m, &ptr->path) < 0) {
				LM_ERR("failed to set path vector\n");
				ret = -3;
				goto done;
			}
			if (set_dst_uri(_m, &path_dst) < 0) {
				LM_ERR("failed to set dst_uri of Path\n");
				ret = -3;
				goto done;
			}
		} else if (ptr->received.s && ptr->received.len) {
			if (set_dst_uri(_m, &ptr->received) < 0) {
				ret = -3;
				goto done;
			}
		}

		set_ruri_q(ptr->q);

		setbflag( 0, ptr->cflags);

		if (ptr->sock)
			_m->force_send_socket = ptr->sock;

		/* populate the 'attributes' avp */
		if (attr_avp_name != -1) {
			istr.s = ptr->attr;
			if (add_avp_last(AVP_VAL_STR, attr_avp_name, istr) != 0) {
				LM_ERR("Failed to populate attr avp!\n");
			}
		}

		ptr = ptr->next;
	}

	/* Append branches if enabled */
	/* If we got to this point and the URI had a ;gr parameter and it was matched
	 * to a contact. No point in branching */
	if ( flags&REG_LOOKUP_NOBRANCH_FLAG || (sip_instance.len && sip_instance.s) ) goto done;
	LM_DBG("looking for branches\n");

	for( ; ptr ; ptr = ptr->next ) {
		if (VALID_CONTACT(ptr, act_time) && allowed_method(_m,ptr,flags)) {
			path_dst.len = 0;
			if(ptr->path.s && ptr->path.len
			&& get_path_dst_uri(&ptr->path, &path_dst) < 0) {
				LM_ERR("failed to get dst_uri for Path\n");
				continue;
			}

			/* The same as for the first contact applies for branches
			 * regarding path vs. received. */
			LM_DBG("setting branch <%.*s>\n",ptr->c.len,ptr->c.s);
			if (append_branch(_m,&ptr->c,path_dst.len?&path_dst:&ptr->received,
			&ptr->path, ptr->q, ptr->cflags, ptr->sock) == -1) {
				LM_ERR("failed to append a branch\n");
				/* Also give a chance to the next branches*/
				continue;
			}

			/* populate the 'attributes' avp */
			if (attr_avp_name != -1) {
				istr.s = ptr->attr;
				if (add_avp_last(AVP_VAL_STR, attr_avp_name, istr) != 0) {
					LM_ERR("Failed to populate attr avp!\n");
				}
			}
		}
	}

done:
	ul.release_urecord(r);
	ul.unlock_udomain((udomain_t*)_t, &aor);
	return ret;
}

A Denial of Service (infinite loop) exists in OpenSIPS before 1.10 in lookup.c.


int lookup(struct sip_msg* _m, char* _t, char* _f, char* _s)
{
	unsigned int flags;
	urecord_t* r;
	str aor, uri;
	ucontact_t* ptr,*it;
	int res;
	int ret;
	str path_dst;
	str flags_s;
	pv_value_t val;
	int_str istr;
	str sip_instance = {0,0},call_id = {0,0};

	flags = 0;
	if (_f && _f[0]!=0) {
		if (fixup_get_svalue( _m, (gparam_p)_f, &flags_s)!=0) {
			LM_ERR("invalid owner uri parameter");
			return -1;
		}
		for( res=0 ; res< flags_s.len ; res++ ) {
			switch (flags_s.s[res]) {
				case 'm': flags |= REG_LOOKUP_METHODFILTER_FLAG; break;
				case 'b': flags |= REG_LOOKUP_NOBRANCH_FLAG; break;
				default: LM_WARN("unsuported flag %c \n",flags_s.s[res]);
			}
		}
	}

	if (_s) {
		if (pv_get_spec_value( _m, (pv_spec_p)_s, &val)!=0) {
			LM_ERR("failed to get PV value\n");
			return -1;
		}
		if ( (val.flags&PV_VAL_STR)==0 ) {
			LM_ERR("PV vals is not string\n");
			return -1;
		}
		uri = val.rs;
	} else {
		if (_m->new_uri.s) uri = _m->new_uri;
		else uri = _m->first_line.u.request.uri;
	}

	if (extract_aor(&uri, &aor,&sip_instance,&call_id) < 0) {
		LM_ERR("failed to extract address of record\n");
		return -3;
	}

	get_act_time();

	ul.lock_udomain((udomain_t*)_t, &aor);
	res = ul.get_urecord((udomain_t*)_t, &aor, &r);
	if (res > 0) {
		LM_DBG("'%.*s' Not found in usrloc\n", aor.len, ZSW(aor.s));
		ul.unlock_udomain((udomain_t*)_t, &aor);
		return -1;
	}

	ptr = r->contacts;
	ret = -1;
	/* look first for an un-expired and suported contact */
search_valid_contact:
	while ( (ptr) &&
	!(VALID_CONTACT(ptr,act_time) && (ret=-2) && allowed_method(_m,ptr,flags)))
		ptr = ptr->next;
	if (ptr==0) {
		/* nothing found */
		LM_DBG("nothing found !\n");
		goto done;
	}

	if (sip_instance.len && sip_instance.s) {
		LM_DBG("ruri has gruu in lookup\n");
		/* uri has GRUU */
		if (ptr->instance.len-2 != sip_instance.len ||
				memcmp(ptr->instance.s+1,sip_instance.s,sip_instance.len)) {
			LM_DBG("no match to sip instace - [%.*s] - [%.*s]\n",ptr->instance.len-2,ptr->instance.s+1,
					sip_instance.len,sip_instance.s);
			/* not the targeted instance, search some more */
			ptr = ptr->next;
			goto search_valid_contact;
		}

		LM_DBG("matched sip instace\n");
	}

	if (call_id.len && call_id.s) {
		/* decide whether GRUU is expired or not
		 *
		 * first - match call-id */
		if (ptr->callid.len != call_id.len ||
				memcmp(ptr->callid.s,call_id.s,call_id.len)) {
			LM_DBG("no match to call id - [%.*s] - [%.*s]\n",ptr->callid.len,ptr->callid.s,
					call_id.len,call_id.s);
			ptr = ptr->next;
			goto search_valid_contact;
		}

		/* matched call-id, check if there are newer contacts with
		 * same sip instace bup newer last_modified */

		it = ptr->next;
		while ( it ) {
			if (VALID_CONTACT(it,act_time)) {
				if (it->instance.len-2 == sip_instance.len &&
						memcmp(it->instance.s+1,sip_instance.s,sip_instance.len) == 0)
					if (it->last_modified > ptr->last_modified) {
						/* same instance id, but newer modified -> expired GRUU, no match at all */
						break;
					}
			}
			it=it->next;
		}

		if (it != NULL) {
			ret = -1;
			goto done;
		}
	}

	LM_DBG("found a complete match\n");

	ret = 1;
	if (ptr) {
		LM_DBG("setting as ruri <%.*s>\n",ptr->c.len,ptr->c.s);
		if (set_ruri(_m, &ptr->c) < 0) {
			LM_ERR("unable to rewrite Request-URI\n");
			ret = -3;
			goto done;
		}

		/* If a Path is present, use first path-uri in favour of
		 * received-uri because in that case the last hop towards the uac
		 * has to handle NAT. - agranig */
		if (ptr->path.s && ptr->path.len) {
			if (get_path_dst_uri(&ptr->path, &path_dst) < 0) {
				LM_ERR("failed to get dst_uri for Path\n");
				ret = -3;
				goto done;
			}
			if (set_path_vector(_m, &ptr->path) < 0) {
				LM_ERR("failed to set path vector\n");
				ret = -3;
				goto done;
			}
			if (set_dst_uri(_m, &path_dst) < 0) {
				LM_ERR("failed to set dst_uri of Path\n");
				ret = -3;
				goto done;
			}
		} else if (ptr->received.s && ptr->received.len) {
			if (set_dst_uri(_m, &ptr->received) < 0) {
				ret = -3;
				goto done;
			}
		}

		set_ruri_q(ptr->q);

		setbflag( 0, ptr->cflags);

		if (ptr->sock)
			_m->force_send_socket = ptr->sock;

		/* populate the 'attributes' avp */
		if (attr_avp_name != -1) {
			istr.s = ptr->attr;
			if (add_avp_last(AVP_VAL_STR, attr_avp_name, istr) != 0) {
				LM_ERR("Failed to populate attr avp!\n");
			}
		}

		ptr = ptr->next;
	}

	/* Append branches if enabled */
	/* If we got to this point and the URI had a ;gr parameter and it was matched
	 * to a contact. No point in branching */
	if ( flags&REG_LOOKUP_NOBRANCH_FLAG || (sip_instance.len && sip_instance.s) ) goto done;
	LM_DBG("looking for branches\n");

	for( ; ptr ; ptr = ptr->next ) {
		if (VALID_CONTACT(ptr, act_time) && allowed_method(_m,ptr,flags)) {
			path_dst.len = 0;
			if(ptr->path.s && ptr->path.len
			&& get_path_dst_uri(&ptr->path, &path_dst) < 0) {
				LM_ERR("failed to get dst_uri for Path\n");
				continue;
			}

			/* The same as for the first contact applies for branches
			 * regarding path vs. received. */
			LM_DBG("setting branch <%.*s>\n",ptr->c.len,ptr->c.s);
			if (append_branch(_m,&ptr->c,path_dst.len?&path_dst:&ptr->received,
			&ptr->path, ptr->q, ptr->cflags, ptr->sock) == -1) {
				LM_ERR("failed to append a branch\n");
				/* Also give a chance to the next branches*/
				continue;
			}

			/* populate the 'attributes' avp */
			if (attr_avp_name != -1) {
				istr.s = ptr->attr;
				if (add_avp_last(AVP_VAL_STR, attr_avp_name, istr) != 0) {
					LM_ERR("Failed to populate attr avp!\n");
				}
			}
		}
	}

done:
	ul.release_urecord(r);
	ul.unlock_udomain((udomain_t*)_t, &aor);
	return ret;
}


s3/s3_cbc.c: allow for compilations with NO_SHA256|512.
(cherry picked from commit d5371324d978e4096bf99b9d0fe71b2cb65d9dc8)

void ssl3_cbc_digest_record(
	const EVP_MD_CTX *ctx,
	unsigned char* md_out,
	size_t* md_out_size,
	const unsigned char header[13],
	const unsigned char *data,
	size_t data_plus_mac_size,
	size_t data_plus_mac_plus_padding_size,
	const unsigned char *mac_secret,
	unsigned mac_secret_length,
	char is_sslv3)
	{
	union {	double align;
		unsigned char c[sizeof(SHA512_CTX)]; } md_state;
	void (*md_final_raw)(void *ctx, unsigned char *md_out);
	void (*md_transform)(void *ctx, const unsigned char *block);
	unsigned md_size, md_block_size = 64;
	unsigned sslv3_pad_length = 40, header_length, variance_blocks,
		 len, max_mac_bytes, num_blocks,
		 num_starting_blocks, k, mac_end_offset, c, index_a, index_b;
	unsigned int bits;	/* at most 18 bits */
	unsigned char length_bytes[MAX_HASH_BIT_COUNT_BYTES];
	/* hmac_pad is the masked HMAC key. */
	unsigned char hmac_pad[MAX_HASH_BLOCK_SIZE];
	unsigned char first_block[MAX_HASH_BLOCK_SIZE];
	unsigned char mac_out[EVP_MAX_MD_SIZE];
	unsigned i, j, md_out_size_u;
	EVP_MD_CTX md_ctx;
	/* mdLengthSize is the number of bytes in the length field that terminates
	* the hash. */
	unsigned md_length_size = 8;

	/* This is a, hopefully redundant, check that allows us to forget about
	 * many possible overflows later in this function. */
	OPENSSL_assert(data_plus_mac_plus_padding_size < 1024*1024);

	switch (ctx->digest->type)
		{
		case NID_md5:
			MD5_Init((MD5_CTX*)md_state.c);
			md_final_raw = tls1_md5_final_raw;
			md_transform = (void(*)(void *ctx, const unsigned char *block)) MD5_Transform;
			md_size = 16;
			sslv3_pad_length = 48;
			break;
		case NID_sha1:
			SHA1_Init((SHA_CTX*)md_state.c);
			md_final_raw = tls1_sha1_final_raw;
			md_transform = (void(*)(void *ctx, const unsigned char *block)) SHA1_Transform;
			md_size = 20;
			break;
		case NID_sha224:
			SHA224_Init((SHA256_CTX*)md_state.c);
			md_final_raw = tls1_sha256_final_raw;
			md_transform = (void(*)(void *ctx, const unsigned char *block)) SHA256_Transform;
			md_size = 224/8;
			break;
		case NID_sha256:
			SHA256_Init((SHA256_CTX*)md_state.c);
			md_final_raw = tls1_sha256_final_raw;
			md_transform = (void(*)(void *ctx, const unsigned char *block)) SHA256_Transform;
			md_size = 32;
			break;
		case NID_sha384:
			SHA384_Init((SHA512_CTX*)md_state.c);
			md_final_raw = tls1_sha512_final_raw;
			md_transform = (void(*)(void *ctx, const unsigned char *block)) SHA512_Transform;
			md_size = 384/8;
			md_block_size = 128;
			md_length_size = 16;
			break;
		case NID_sha512:
			SHA512_Init((SHA512_CTX*)md_state.c);
			md_final_raw = tls1_sha512_final_raw;
			md_transform = (void(*)(void *ctx, const unsigned char *block)) SHA512_Transform;
			md_size = 64;
			md_block_size = 128;
			md_length_size = 16;
			break;
		default:
			/* ssl3_cbc_record_digest_supported should have been
			 * called first to check that the hash function is
			 * supported. */
			OPENSSL_assert(0);
			if (md_out_size)
				*md_out_size = -1;
			return;
		}

	OPENSSL_assert(md_length_size <= MAX_HASH_BIT_COUNT_BYTES);
	OPENSSL_assert(md_block_size <= MAX_HASH_BLOCK_SIZE);
	OPENSSL_assert(md_size <= EVP_MAX_MD_SIZE);

	header_length = 13;
	if (is_sslv3)
		{
		header_length =
			mac_secret_length +
			sslv3_pad_length +
			8 /* sequence number */ +
			1 /* record type */ +
			2 /* record length */;
		}

	/* variance_blocks is the number of blocks of the hash that we have to
	 * calculate in constant time because they could be altered by the
	 * padding value.
	 *
	 * In SSLv3, the padding must be minimal so the end of the plaintext
	 * varies by, at most, 15+20 = 35 bytes. (We conservatively assume that
	 * the MAC size varies from 0..20 bytes.) In case the 9 bytes of hash
	 * termination (0x80 + 64-bit length) don't fit in the final block, we
	 * say that the final two blocks can vary based on the padding.
	 *
	 * TLSv1 has MACs up to 48 bytes long (SHA-384) and the padding is not
	 * required to be minimal. Therefore we say that the final six blocks
	 * can vary based on the padding.
	 *
	 * Later in the function, if the message is short and there obviously
	 * cannot be this many blocks then variance_blocks can be reduced. */
	variance_blocks = is_sslv3 ? 2 : 6;
	/* From now on we're dealing with the MAC, which conceptually has 13
	 * bytes of `header' before the start of the data (TLS) or 71/75 bytes
	 * (SSLv3) */
	len = data_plus_mac_plus_padding_size + header_length;
	/* max_mac_bytes contains the maximum bytes of bytes in the MAC, including
	* |header|, assuming that there's no padding. */
	max_mac_bytes = len - md_size - 1;
	/* num_blocks is the maximum number of hash blocks. */
	num_blocks = (max_mac_bytes + 1 + md_length_size + md_block_size - 1) / md_block_size;
	/* In order to calculate the MAC in constant time we have to handle
	 * the final blocks specially because the padding value could cause the
	 * end to appear somewhere in the final |variance_blocks| blocks and we
	 * can't leak where. However, |num_starting_blocks| worth of data can
	 * be hashed right away because no padding value can affect whether
	 * they are plaintext. */
	num_starting_blocks = 0;
	/* k is the starting byte offset into the conceptual header||data where
	 * we start processing. */
	k = 0;
	/* mac_end_offset is the index just past the end of the data to be
	 * MACed. */
	mac_end_offset = data_plus_mac_size + header_length - md_size;
	/* c is the index of the 0x80 byte in the final hash block that
	 * contains application data. */
	c = mac_end_offset % md_block_size;
	/* index_a is the hash block number that contains the 0x80 terminating
	 * value. */
	index_a = mac_end_offset / md_block_size;
	/* index_b is the hash block number that contains the 64-bit hash
	 * length, in bits. */
	index_b = (mac_end_offset + md_length_size) / md_block_size;
	/* bits is the hash-length in bits. It includes the additional hash
	 * block for the masked HMAC key, or whole of |header| in the case of
	 * SSLv3. */

	/* For SSLv3, if we're going to have any starting blocks then we need
	 * at least two because the header is larger than a single block. */
	if (num_blocks > variance_blocks + (is_sslv3 ? 1 : 0))
		{
		num_starting_blocks = num_blocks - variance_blocks;
		k = md_block_size*num_starting_blocks;
		}

	bits = 8*mac_end_offset;
	if (!is_sslv3)
		{
		/* Compute the initial HMAC block. For SSLv3, the padding and
		 * secret bytes are included in |header| because they take more
		 * than a single block. */
		bits += 8*md_block_size;
		memset(hmac_pad, 0, md_block_size);
		OPENSSL_assert(mac_secret_length <= sizeof(hmac_pad));
		memcpy(hmac_pad, mac_secret, mac_secret_length);
		for (i = 0; i < md_block_size; i++)
			hmac_pad[i] ^= 0x36;

		md_transform(md_state.c, hmac_pad);
		}

	memset(length_bytes,0,md_length_size-4);
	length_bytes[md_length_size-4] = (unsigned char)(bits>>24);
	length_bytes[md_length_size-3] = (unsigned char)(bits>>16);
	length_bytes[md_length_size-2] = (unsigned char)(bits>>8);
	length_bytes[md_length_size-1] = (unsigned char)bits;

	if (k > 0)
		{
		if (is_sslv3)
			{
			/* The SSLv3 header is larger than a single block.
			 * overhang is the number of bytes beyond a single
			 * block that the header consumes: either 7 bytes
			 * (SHA1) or 11 bytes (MD5). */
			unsigned overhang = header_length-md_block_size;
			md_transform(md_state.c, header);
			memcpy(first_block, header + md_block_size, overhang);
			memcpy(first_block + overhang, data, md_block_size-overhang);
			md_transform(md_state.c, first_block);
			for (i = 1; i < k/md_block_size - 1; i++)
				md_transform(md_state.c, data + md_block_size*i - overhang);
			}
		else
			{
			/* k is a multiple of md_block_size. */
			memcpy(first_block, header, 13);
			memcpy(first_block+13, data, md_block_size-13);
			md_transform(md_state.c, first_block);
			for (i = 1; i < k/md_block_size; i++)
				md_transform(md_state.c, data + md_block_size*i - 13);
			}
		}

	memset(mac_out, 0, sizeof(mac_out));

	/* We now process the final hash blocks. For each block, we construct
	 * it in constant time. If the |i==index_a| then we'll include the 0x80
	 * bytes and zero pad etc. For each block we selectively copy it, in
	 * constant time, to |mac_out|. */
	for (i = num_starting_blocks; i <= num_starting_blocks+variance_blocks; i++)
		{
		unsigned char block[MAX_HASH_BLOCK_SIZE];
		unsigned char is_block_a = constant_time_eq_8(i, index_a);
		unsigned char is_block_b = constant_time_eq_8(i, index_b);
		for (j = 0; j < md_block_size; j++)
			{
			unsigned char b = 0, is_past_c, is_past_cp1;
			if (k < header_length)
				b = header[k];
			else if (k < data_plus_mac_plus_padding_size + header_length)
				b = data[k-header_length];
			k++;

			is_past_c = is_block_a & constant_time_ge(j, c);
			is_past_cp1 = is_block_a & constant_time_ge(j, c+1);
			/* If this is the block containing the end of the
			 * application data, and we are at the offset for the
			 * 0x80 value, then overwrite b with 0x80. */
			b = (b&~is_past_c) | (0x80&is_past_c);
			/* If this the the block containing the end of the
			 * application data and we're past the 0x80 value then
			 * just write zero. */
			b = b&~is_past_cp1;
			/* If this is index_b (the final block), but not
			 * index_a (the end of the data), then the 64-bit
			 * length didn't fit into index_a and we're having to
			 * add an extra block of zeros. */
			b &= ~is_block_b | is_block_a;

			/* The final bytes of one of the blocks contains the
			 * length. */
			if (j >= md_block_size - md_length_size)
				{
				/* If this is index_b, write a length byte. */
				b = (b&~is_block_b) | (is_block_b&length_bytes[j-(md_block_size-md_length_size)]);
				}
			block[j] = b;
			}

		md_transform(md_state.c, block);
		md_final_raw(md_state.c, block);
		/* If this is index_b, copy the hash value to |mac_out|. */
		for (j = 0; j < md_size; j++)
			mac_out[j] |= block[j]&is_block_b;
		}

	EVP_MD_CTX_init(&md_ctx);
	EVP_DigestInit_ex(&md_ctx, ctx->digest, NULL /* engine */);
	if (is_sslv3)
		{
		/* We repurpose |hmac_pad| to contain the SSLv3 pad2 block. */
		memset(hmac_pad, 0x5c, sslv3_pad_length);

		EVP_DigestUpdate(&md_ctx, mac_secret, mac_secret_length);
		EVP_DigestUpdate(&md_ctx, hmac_pad, sslv3_pad_length);
		EVP_DigestUpdate(&md_ctx, mac_out, md_size);
		}
	else
		{
		/* Complete the HMAC in the standard manner. */
		for (i = 0; i < md_block_size; i++)
			hmac_pad[i] ^= 0x6a;

		EVP_DigestUpdate(&md_ctx, hmac_pad, md_block_size);
		EVP_DigestUpdate(&md_ctx, mac_out, md_size);
		}
	EVP_DigestFinal(&md_ctx, md_out, &md_out_size_u);
	if (md_out_size)
		*md_out_size = md_out_size_u;
	EVP_MD_CTX_cleanup(&md_ctx);
	}

The TLS protocol 1.1 and 1.2 and the DTLS protocol 1.0 and 1.2, as used in OpenSSL, OpenJDK, PolarSSL, and other products, do not properly consider timing side-channel attacks on a MAC check requirement during the processing of malformed CBC padding, which allows remote attackers to conduct distinguishing attacks and plaintext-recovery attacks via statistical analysis of timing data for crafted packets, aka the "Lucky Thirteen" issue.


void ssl3_cbc_digest_record(
	const EVP_MD_CTX *ctx,
	unsigned char* md_out,
	size_t* md_out_size,
	const unsigned char header[13],
	const unsigned char *data,
	size_t data_plus_mac_size,
	size_t data_plus_mac_plus_padding_size,
	const unsigned char *mac_secret,
	unsigned mac_secret_length,
	char is_sslv3)
	{
	union {	double align;
		unsigned char c[sizeof(LARGEST_DIGEST_CTX)]; } md_state;
	void (*md_final_raw)(void *ctx, unsigned char *md_out);
	void (*md_transform)(void *ctx, const unsigned char *block);
	unsigned md_size, md_block_size = 64;
	unsigned sslv3_pad_length = 40, header_length, variance_blocks,
		 len, max_mac_bytes, num_blocks,
		 num_starting_blocks, k, mac_end_offset, c, index_a, index_b;
	unsigned int bits;	/* at most 18 bits */
	unsigned char length_bytes[MAX_HASH_BIT_COUNT_BYTES];
	/* hmac_pad is the masked HMAC key. */
	unsigned char hmac_pad[MAX_HASH_BLOCK_SIZE];
	unsigned char first_block[MAX_HASH_BLOCK_SIZE];
	unsigned char mac_out[EVP_MAX_MD_SIZE];
	unsigned i, j, md_out_size_u;
	EVP_MD_CTX md_ctx;
	/* mdLengthSize is the number of bytes in the length field that terminates
	* the hash. */
	unsigned md_length_size = 8;

	/* This is a, hopefully redundant, check that allows us to forget about
	 * many possible overflows later in this function. */
	OPENSSL_assert(data_plus_mac_plus_padding_size < 1024*1024);

	switch (ctx->digest->type)
		{
		case NID_md5:
			MD5_Init((MD5_CTX*)md_state.c);
			md_final_raw = tls1_md5_final_raw;
			md_transform = (void(*)(void *ctx, const unsigned char *block)) MD5_Transform;
			md_size = 16;
			sslv3_pad_length = 48;
			break;
		case NID_sha1:
			SHA1_Init((SHA_CTX*)md_state.c);
			md_final_raw = tls1_sha1_final_raw;
			md_transform = (void(*)(void *ctx, const unsigned char *block)) SHA1_Transform;
			md_size = 20;
			break;
#ifndef OPENSSL_NO_SHA256
		case NID_sha224:
			SHA224_Init((SHA256_CTX*)md_state.c);
			md_final_raw = tls1_sha256_final_raw;
			md_transform = (void(*)(void *ctx, const unsigned char *block)) SHA256_Transform;
			md_size = 224/8;
			break;
		case NID_sha256:
			SHA256_Init((SHA256_CTX*)md_state.c);
			md_final_raw = tls1_sha256_final_raw;
			md_transform = (void(*)(void *ctx, const unsigned char *block)) SHA256_Transform;
			md_size = 32;
			break;
#endif
#ifndef OPENSSL_NO_SHA512
		case NID_sha384:
			SHA384_Init((SHA512_CTX*)md_state.c);
			md_final_raw = tls1_sha512_final_raw;
			md_transform = (void(*)(void *ctx, const unsigned char *block)) SHA512_Transform;
			md_size = 384/8;
			md_block_size = 128;
			md_length_size = 16;
			break;
		case NID_sha512:
			SHA512_Init((SHA512_CTX*)md_state.c);
			md_final_raw = tls1_sha512_final_raw;
			md_transform = (void(*)(void *ctx, const unsigned char *block)) SHA512_Transform;
			md_size = 64;
			md_block_size = 128;
			md_length_size = 16;
			break;
#endif
		default:
			/* ssl3_cbc_record_digest_supported should have been
			 * called first to check that the hash function is
			 * supported. */
			OPENSSL_assert(0);
			if (md_out_size)
				*md_out_size = -1;
			return;
		}

	OPENSSL_assert(md_length_size <= MAX_HASH_BIT_COUNT_BYTES);
	OPENSSL_assert(md_block_size <= MAX_HASH_BLOCK_SIZE);
	OPENSSL_assert(md_size <= EVP_MAX_MD_SIZE);

	header_length = 13;
	if (is_sslv3)
		{
		header_length =
			mac_secret_length +
			sslv3_pad_length +
			8 /* sequence number */ +
			1 /* record type */ +
			2 /* record length */;
		}

	/* variance_blocks is the number of blocks of the hash that we have to
	 * calculate in constant time because they could be altered by the
	 * padding value.
	 *
	 * In SSLv3, the padding must be minimal so the end of the plaintext
	 * varies by, at most, 15+20 = 35 bytes. (We conservatively assume that
	 * the MAC size varies from 0..20 bytes.) In case the 9 bytes of hash
	 * termination (0x80 + 64-bit length) don't fit in the final block, we
	 * say that the final two blocks can vary based on the padding.
	 *
	 * TLSv1 has MACs up to 48 bytes long (SHA-384) and the padding is not
	 * required to be minimal. Therefore we say that the final six blocks
	 * can vary based on the padding.
	 *
	 * Later in the function, if the message is short and there obviously
	 * cannot be this many blocks then variance_blocks can be reduced. */
	variance_blocks = is_sslv3 ? 2 : 6;
	/* From now on we're dealing with the MAC, which conceptually has 13
	 * bytes of `header' before the start of the data (TLS) or 71/75 bytes
	 * (SSLv3) */
	len = data_plus_mac_plus_padding_size + header_length;
	/* max_mac_bytes contains the maximum bytes of bytes in the MAC, including
	* |header|, assuming that there's no padding. */
	max_mac_bytes = len - md_size - 1;
	/* num_blocks is the maximum number of hash blocks. */
	num_blocks = (max_mac_bytes + 1 + md_length_size + md_block_size - 1) / md_block_size;
	/* In order to calculate the MAC in constant time we have to handle
	 * the final blocks specially because the padding value could cause the
	 * end to appear somewhere in the final |variance_blocks| blocks and we
	 * can't leak where. However, |num_starting_blocks| worth of data can
	 * be hashed right away because no padding value can affect whether
	 * they are plaintext. */
	num_starting_blocks = 0;
	/* k is the starting byte offset into the conceptual header||data where
	 * we start processing. */
	k = 0;
	/* mac_end_offset is the index just past the end of the data to be
	 * MACed. */
	mac_end_offset = data_plus_mac_size + header_length - md_size;
	/* c is the index of the 0x80 byte in the final hash block that
	 * contains application data. */
	c = mac_end_offset % md_block_size;
	/* index_a is the hash block number that contains the 0x80 terminating
	 * value. */
	index_a = mac_end_offset / md_block_size;
	/* index_b is the hash block number that contains the 64-bit hash
	 * length, in bits. */
	index_b = (mac_end_offset + md_length_size) / md_block_size;
	/* bits is the hash-length in bits. It includes the additional hash
	 * block for the masked HMAC key, or whole of |header| in the case of
	 * SSLv3. */

	/* For SSLv3, if we're going to have any starting blocks then we need
	 * at least two because the header is larger than a single block. */
	if (num_blocks > variance_blocks + (is_sslv3 ? 1 : 0))
		{
		num_starting_blocks = num_blocks - variance_blocks;
		k = md_block_size*num_starting_blocks;
		}

	bits = 8*mac_end_offset;
	if (!is_sslv3)
		{
		/* Compute the initial HMAC block. For SSLv3, the padding and
		 * secret bytes are included in |header| because they take more
		 * than a single block. */
		bits += 8*md_block_size;
		memset(hmac_pad, 0, md_block_size);
		OPENSSL_assert(mac_secret_length <= sizeof(hmac_pad));
		memcpy(hmac_pad, mac_secret, mac_secret_length);
		for (i = 0; i < md_block_size; i++)
			hmac_pad[i] ^= 0x36;

		md_transform(md_state.c, hmac_pad);
		}

	memset(length_bytes,0,md_length_size-4);
	length_bytes[md_length_size-4] = (unsigned char)(bits>>24);
	length_bytes[md_length_size-3] = (unsigned char)(bits>>16);
	length_bytes[md_length_size-2] = (unsigned char)(bits>>8);
	length_bytes[md_length_size-1] = (unsigned char)bits;

	if (k > 0)
		{
		if (is_sslv3)
			{
			/* The SSLv3 header is larger than a single block.
			 * overhang is the number of bytes beyond a single
			 * block that the header consumes: either 7 bytes
			 * (SHA1) or 11 bytes (MD5). */
			unsigned overhang = header_length-md_block_size;
			md_transform(md_state.c, header);
			memcpy(first_block, header + md_block_size, overhang);
			memcpy(first_block + overhang, data, md_block_size-overhang);
			md_transform(md_state.c, first_block);
			for (i = 1; i < k/md_block_size - 1; i++)
				md_transform(md_state.c, data + md_block_size*i - overhang);
			}
		else
			{
			/* k is a multiple of md_block_size. */
			memcpy(first_block, header, 13);
			memcpy(first_block+13, data, md_block_size-13);
			md_transform(md_state.c, first_block);
			for (i = 1; i < k/md_block_size; i++)
				md_transform(md_state.c, data + md_block_size*i - 13);
			}
		}

	memset(mac_out, 0, sizeof(mac_out));

	/* We now process the final hash blocks. For each block, we construct
	 * it in constant time. If the |i==index_a| then we'll include the 0x80
	 * bytes and zero pad etc. For each block we selectively copy it, in
	 * constant time, to |mac_out|. */
	for (i = num_starting_blocks; i <= num_starting_blocks+variance_blocks; i++)
		{
		unsigned char block[MAX_HASH_BLOCK_SIZE];
		unsigned char is_block_a = constant_time_eq_8(i, index_a);
		unsigned char is_block_b = constant_time_eq_8(i, index_b);
		for (j = 0; j < md_block_size; j++)
			{
			unsigned char b = 0, is_past_c, is_past_cp1;
			if (k < header_length)
				b = header[k];
			else if (k < data_plus_mac_plus_padding_size + header_length)
				b = data[k-header_length];
			k++;

			is_past_c = is_block_a & constant_time_ge(j, c);
			is_past_cp1 = is_block_a & constant_time_ge(j, c+1);
			/* If this is the block containing the end of the
			 * application data, and we are at the offset for the
			 * 0x80 value, then overwrite b with 0x80. */
			b = (b&~is_past_c) | (0x80&is_past_c);
			/* If this the the block containing the end of the
			 * application data and we're past the 0x80 value then
			 * just write zero. */
			b = b&~is_past_cp1;
			/* If this is index_b (the final block), but not
			 * index_a (the end of the data), then the 64-bit
			 * length didn't fit into index_a and we're having to
			 * add an extra block of zeros. */
			b &= ~is_block_b | is_block_a;

			/* The final bytes of one of the blocks contains the
			 * length. */
			if (j >= md_block_size - md_length_size)
				{
				/* If this is index_b, write a length byte. */
				b = (b&~is_block_b) | (is_block_b&length_bytes[j-(md_block_size-md_length_size)]);
				}
			block[j] = b;
			}

		md_transform(md_state.c, block);
		md_final_raw(md_state.c, block);
		/* If this is index_b, copy the hash value to |mac_out|. */
		for (j = 0; j < md_size; j++)
			mac_out[j] |= block[j]&is_block_b;
		}

	EVP_MD_CTX_init(&md_ctx);
	EVP_DigestInit_ex(&md_ctx, ctx->digest, NULL /* engine */);
	if (is_sslv3)
		{
		/* We repurpose |hmac_pad| to contain the SSLv3 pad2 block. */
		memset(hmac_pad, 0x5c, sslv3_pad_length);

		EVP_DigestUpdate(&md_ctx, mac_secret, mac_secret_length);
		EVP_DigestUpdate(&md_ctx, hmac_pad, sslv3_pad_length);
		EVP_DigestUpdate(&md_ctx, mac_out, md_size);
		}
	else
		{
		/* Complete the HMAC in the standard manner. */
		for (i = 0; i < md_block_size; i++)
			hmac_pad[i] ^= 0x6a;

		EVP_DigestUpdate(&md_ctx, hmac_pad, md_block_size);
		EVP_DigestUpdate(&md_ctx, mac_out, md_size);
		}
	EVP_DigestFinal(&md_ctx, md_out, &md_out_size_u);
	if (md_out_size)
		*md_out_size = md_out_size_u;
	EVP_MD_CTX_cleanup(&md_ctx);
	}


Fix IV check and padding removal.

Fix the calculation that checks there is enough room in a record
after removing padding and optional explicit IV. (by Steve)

For AEAD remove the correct number of padding bytes (by Andy)

int tls1_cbc_remove_padding(const SSL* s,
			    SSL3_RECORD *rec,
			    unsigned block_size,
			    unsigned mac_size)
	{
	unsigned padding_length, good, to_check, i;
	const char has_explicit_iv =
		s->version >= TLS1_1_VERSION || s->version == DTLS1_VERSION;
	const unsigned overhead = 1 /* padding length byte */ +
				  mac_size +
				  (has_explicit_iv ? block_size : 0);

	/* These lengths are all public so we can test them in non-constant
	 * time. */
	if (overhead > rec->length)
		return 0;

	/* We can always safely skip the explicit IV. We check at the beginning
	 * of this function that the record has at least enough space for the
	 * IV, MAC and padding length byte. (These can be checked in
	 * non-constant time because it's all public information.) So, if the
	 * padding was invalid, then we didn't change |rec->length| and this is
	 * safe. If the padding was valid then we know that we have at least
	 * overhead+padding_length bytes of space and so this is still safe
	 * because overhead accounts for the explicit IV. */
	if (has_explicit_iv)
		{
		rec->data += block_size;
		rec->input += block_size;
		rec->length -= block_size;
		}

	padding_length = rec->data[rec->length-1];

	/* NB: if compression is in operation the first packet may not be of
	 * even length so the padding bug check cannot be performed. This bug
	 * workaround has been around since SSLeay so hopefully it is either
	 * fixed now or no buggy implementation supports compression [steve]
	 */
	if ( (s->options&SSL_OP_TLS_BLOCK_PADDING_BUG) && !s->expand)
		{
		/* First packet is even in size, so check */
		if ((memcmp(s->s3->read_sequence, "\0\0\0\0\0\0\0\0",8) == 0) &&
		    !(padding_length & 1))
			{
			s->s3->flags|=TLS1_FLAGS_TLS_PADDING_BUG;
			}
		if ((s->s3->flags & TLS1_FLAGS_TLS_PADDING_BUG) &&
		    padding_length > 0)
			{
			padding_length--;
			}
		}

	if (EVP_CIPHER_flags(s->enc_read_ctx->cipher)&EVP_CIPH_FLAG_AEAD_CIPHER)
		{
		/* padding is already verified */
		rec->length -= padding_length;
		return 1;
		}

	good = constant_time_ge(rec->length, overhead+padding_length);
	/* The padding consists of a length byte at the end of the record and
	 * then that many bytes of padding, all with the same value as the
	 * length byte. Thus, with the length byte included, there are i+1
	 * bytes of padding.
	 *
	 * We can't check just |padding_length+1| bytes because that leaks
	 * decrypted information. Therefore we always have to check the maximum
	 * amount of padding possible. (Again, the length of the record is
	 * public information so we can use it.) */
	to_check = 255; /* maximum amount of padding. */
	if (to_check > rec->length-1)
		to_check = rec->length-1;

	for (i = 0; i < to_check; i++)
		{
		unsigned char mask = constant_time_ge(padding_length, i);
		unsigned char b = rec->data[rec->length-1-i];
		/* The final |padding_length+1| bytes should all have the value
		 * |padding_length|. Therefore the XOR should be zero. */
		good &= ~(mask&(padding_length ^ b));
		}

	/* If any of the final |padding_length+1| bytes had the wrong value,
	 * one or more of the lower eight bits of |good| will be cleared. We
	 * AND the bottom 8 bits together and duplicate the result to all the
	 * bits. */
	good &= good >> 4;
	good &= good >> 2;
	good &= good >> 1;
	good <<= sizeof(good)*8-1;
	good = DUPLICATE_MSB_TO_ALL(good);

	padding_length = good & (padding_length+1);
	rec->length -= padding_length;
	rec->type |= padding_length<<8;	/* kludge: pass padding length */

	return (int)((good & 1) | (~good & -1));
	}


int tls1_cbc_remove_padding(const SSL* s,
			    SSL3_RECORD *rec,
			    unsigned block_size,
			    unsigned mac_size)
	{
	unsigned padding_length, good, to_check, i;
	const unsigned overhead = 1 /* padding length byte */ + mac_size;
	/* Check if version requires explicit IV */
	if (s->version >= TLS1_1_VERSION || s->version == DTLS1_VERSION)
		{
		/* These lengths are all public so we can test them in
		 * non-constant time.
		 */
		if (overhead + block_size > rec->length)
			return 0;
		/* We can now safely skip explicit IV */
		rec->data += block_size;
		rec->input += block_size;
		rec->length -= block_size;
		}
	else if (overhead > rec->length)
		return 0;

	padding_length = rec->data[rec->length-1];

	/* NB: if compression is in operation the first packet may not be of
	 * even length so the padding bug check cannot be performed. This bug
	 * workaround has been around since SSLeay so hopefully it is either
	 * fixed now or no buggy implementation supports compression [steve]
	 */
	if ( (s->options&SSL_OP_TLS_BLOCK_PADDING_BUG) && !s->expand)
		{
		/* First packet is even in size, so check */
		if ((memcmp(s->s3->read_sequence, "\0\0\0\0\0\0\0\0",8) == 0) &&
		    !(padding_length & 1))
			{
			s->s3->flags|=TLS1_FLAGS_TLS_PADDING_BUG;
			}
		if ((s->s3->flags & TLS1_FLAGS_TLS_PADDING_BUG) &&
		    padding_length > 0)
			{
			padding_length--;
			}
		}

	if (EVP_CIPHER_flags(s->enc_read_ctx->cipher)&EVP_CIPH_FLAG_AEAD_CIPHER)
		{
		/* padding is already verified */
		rec->length -= padding_length + 1;
		return 1;
		}

	good = constant_time_ge(rec->length, overhead+padding_length);
	/* The padding consists of a length byte at the end of the record and
	 * then that many bytes of padding, all with the same value as the
	 * length byte. Thus, with the length byte included, there are i+1
	 * bytes of padding.
	 *
	 * We can't check just |padding_length+1| bytes because that leaks
	 * decrypted information. Therefore we always have to check the maximum
	 * amount of padding possible. (Again, the length of the record is
	 * public information so we can use it.) */
	to_check = 255; /* maximum amount of padding. */
	if (to_check > rec->length-1)
		to_check = rec->length-1;

	for (i = 0; i < to_check; i++)
		{
		unsigned char mask = constant_time_ge(padding_length, i);
		unsigned char b = rec->data[rec->length-1-i];
		/* The final |padding_length+1| bytes should all have the value
		 * |padding_length|. Therefore the XOR should be zero. */
		good &= ~(mask&(padding_length ^ b));
		}

	/* If any of the final |padding_length+1| bytes had the wrong value,
	 * one or more of the lower eight bits of |good| will be cleared. We
	 * AND the bottom 8 bits together and duplicate the result to all the
	 * bits. */
	good &= good >> 4;
	good &= good >> 2;
	good &= good >> 1;
	good <<= sizeof(good)*8-1;
	good = DUPLICATE_MSB_TO_ALL(good);

	padding_length = good & (padding_length+1);
	rec->length -= padding_length;
	rec->type |= padding_length<<8;	/* kludge: pass padding length */

	return (int)((good & 1) | (~good & -1));
	}


e_aes_cbc_hmac_sha1.c: align calculated MAC at cache line.

static int aesni_cbc_hmac_sha1_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
		      const unsigned char *in, size_t len)
	{
	EVP_AES_HMAC_SHA1 *key = data(ctx);
	unsigned int l;
	size_t	plen = key->payload_length,
		iv = 0,		/* explicit IV in TLS 1.1 and later */
		sha_off = 0;
#if defined(STITCHED_CALL)
	size_t	aes_off = 0,
		blocks;

	sha_off = SHA_CBLOCK-key->md.num;
#endif

	key->payload_length = NO_PAYLOAD_LENGTH;

	if (len%AES_BLOCK_SIZE) return 0;

	if (ctx->encrypt) {
		if (plen==NO_PAYLOAD_LENGTH)
			plen = len;
		else if (len!=((plen+SHA_DIGEST_LENGTH+AES_BLOCK_SIZE)&-AES_BLOCK_SIZE))
			return 0;
		else if (key->aux.tls_ver >= TLS1_1_VERSION)
			iv = AES_BLOCK_SIZE;

#if defined(STITCHED_CALL)
		if (plen>(sha_off+iv) && (blocks=(plen-(sha_off+iv))/SHA_CBLOCK)) {
			SHA1_Update(&key->md,in+iv,sha_off);

			aesni_cbc_sha1_enc(in,out,blocks,&key->ks,
				ctx->iv,&key->md,in+iv+sha_off);
			blocks *= SHA_CBLOCK;
			aes_off += blocks;
			sha_off += blocks;
			key->md.Nh += blocks>>29;
			key->md.Nl += blocks<<=3;
			if (key->md.Nl<(unsigned int)blocks) key->md.Nh++;
		} else {
			sha_off = 0;
		}
#endif
		sha_off += iv;
		SHA1_Update(&key->md,in+sha_off,plen-sha_off);

		if (plen!=len)	{	/* "TLS" mode of operation */
			if (in!=out)
				memcpy(out+aes_off,in+aes_off,plen-aes_off);

			/* calculate HMAC and append it to payload */
			SHA1_Final(out+plen,&key->md);
			key->md = key->tail;
			SHA1_Update(&key->md,out+plen,SHA_DIGEST_LENGTH);
			SHA1_Final(out+plen,&key->md);

			/* pad the payload|hmac */
			plen += SHA_DIGEST_LENGTH;
			for (l=len-plen-1;plen<len;plen++) out[plen]=l;
			/* encrypt HMAC|padding at once */
			aesni_cbc_encrypt(out+aes_off,out+aes_off,len-aes_off,
					&key->ks,ctx->iv,1);
		} else {
			aesni_cbc_encrypt(in+aes_off,out+aes_off,len-aes_off,
					&key->ks,ctx->iv,1);
		}
	} else {
		union { unsigned int  u[SHA_DIGEST_LENGTH/sizeof(unsigned int)];
			unsigned char c[SHA_DIGEST_LENGTH]; } mac;

		/* decrypt HMAC|padding at once */
		aesni_cbc_encrypt(in,out,len,
				&key->ks,ctx->iv,0);

		if (plen) {	/* "TLS" mode of operation */
			size_t inp_len, mask, j, i;
			unsigned int res, maxpad, pad, bitlen;
			int ret = 1;
			union {	unsigned int  u[SHA_LBLOCK];
				unsigned char c[SHA_CBLOCK]; }
				*data = (void *)key->md.data;

			if ((key->aux.tls_aad[plen-4]<<8|key->aux.tls_aad[plen-3])
			    >= TLS1_1_VERSION)
				iv = AES_BLOCK_SIZE;

			if (len<(iv+SHA_DIGEST_LENGTH+1))
				return 0;

			/* omit explicit iv */
			out += iv;
			len -= iv;

			/* figure out payload length */
			pad = out[len-1];
			maxpad = len-(SHA_DIGEST_LENGTH+1);
			maxpad |= (255-maxpad)>>(sizeof(maxpad)*8-8);
			maxpad &= 255;

			inp_len = len - (SHA_DIGEST_LENGTH+pad+1);
			mask = (0-((inp_len-len)>>(sizeof(inp_len)*8-1)));
			inp_len &= mask;
			ret &= (int)mask;

			key->aux.tls_aad[plen-2] = inp_len>>8;
			key->aux.tls_aad[plen-1] = inp_len;

			/* calculate HMAC */
			key->md = key->head;
			SHA1_Update(&key->md,key->aux.tls_aad,plen);

#if 1
			len -= SHA_DIGEST_LENGTH;		/* amend mac */
			if (len>=(256+SHA_CBLOCK)) {
				j = (len-(256+SHA_CBLOCK))&(0-SHA_CBLOCK);
				j += SHA_CBLOCK-key->md.num;
				SHA1_Update(&key->md,out,j);
				out += j;
				len -= j;
				inp_len -= j;
			}

			/* but pretend as if we hashed padded payload */
			bitlen = key->md.Nl+(inp_len<<3);	/* at most 18 bits */
			mac.c[0] = 0;
			mac.c[1] = (unsigned char)(bitlen>>16);
			mac.c[2] = (unsigned char)(bitlen>>8);
			mac.c[3] = (unsigned char)bitlen;
			bitlen = mac.u[0];

			mac.u[0]=0;
			mac.u[1]=0;
			mac.u[2]=0;
			mac.u[3]=0;
			mac.u[4]=0;

			for (res=key->md.num, j=0;j<len;j++) {
				size_t c = out[j];
				mask = (j-inp_len)>>(sizeof(j)*8-8);
				c &= mask;
				c |= 0x80&~mask&~((inp_len-j)>>(sizeof(j)*8-8));
				data->c[res++]=(unsigned char)c;

				if (res!=SHA_CBLOCK) continue;

				mask = 0-((inp_len+8-j)>>(sizeof(j)*8-1));
				data->u[SHA_LBLOCK-1] |= bitlen&mask;
				sha1_block_data_order(&key->md,data,1);
				mask &= 0-((j-inp_len-73)>>(sizeof(j)*8-1));
				mac.u[0] |= key->md.h0 & mask;
				mac.u[1] |= key->md.h1 & mask;
				mac.u[2] |= key->md.h2 & mask;
				mac.u[3] |= key->md.h3 & mask;
				mac.u[4] |= key->md.h4 & mask;
				res=0;
			}

			for(i=res;i<SHA_CBLOCK;i++,j++) data->c[i]=0;

			if (res>SHA_CBLOCK-8) {
				mask = 0-((inp_len+8-j)>>(sizeof(j)*8-1));
				data->u[SHA_LBLOCK-1] |= bitlen&mask;
				sha1_block_data_order(&key->md,data,1);
				mask &= 0-((j-inp_len-73)>>(sizeof(j)*8-1));
				mac.u[0] |= key->md.h0 & mask;
				mac.u[1] |= key->md.h1 & mask;
				mac.u[2] |= key->md.h2 & mask;
				mac.u[3] |= key->md.h3 & mask;
				mac.u[4] |= key->md.h4 & mask;

				memset(data,0,SHA_CBLOCK);
				j+=64;
			}
			data->u[SHA_LBLOCK-1] = bitlen;
			sha1_block_data_order(&key->md,data,1);
			mask = 0-((j-inp_len-73)>>(sizeof(j)*8-1));
			mac.u[0] |= key->md.h0 & mask;
			mac.u[1] |= key->md.h1 & mask;
			mac.u[2] |= key->md.h2 & mask;
			mac.u[3] |= key->md.h3 & mask;
			mac.u[4] |= key->md.h4 & mask;

#ifdef BSWAP
			mac.u[0] = BSWAP(mac.u[0]);
			mac.u[1] = BSWAP(mac.u[1]);
			mac.u[2] = BSWAP(mac.u[2]);
			mac.u[3] = BSWAP(mac.u[3]);
			mac.u[4] = BSWAP(mac.u[4]);
#else
			for (i=0;i<5;i++) {
				res = mac.u[i];
				mac.c[4*i+0]=(unsigned char)(res>>24);
				mac.c[4*i+1]=(unsigned char)(res>>16);
				mac.c[4*i+2]=(unsigned char)(res>>8);
				mac.c[4*i+3]=(unsigned char)res;
			}
#endif
			len += SHA_DIGEST_LENGTH;
#else
			SHA1_Update(&key->md,out,inp_len);
			res = key->md.num;
			SHA1_Final(mac.c,&key->md);

			{
			unsigned int inp_blocks, pad_blocks;

			/* but pretend as if we hashed padded payload */
			inp_blocks = 1+((SHA_CBLOCK-9-res)>>(sizeof(res)*8-1));
			res += (unsigned int)(len-inp_len);
			pad_blocks = res / SHA_CBLOCK;
			res %= SHA_CBLOCK;
			pad_blocks += 1+((SHA_CBLOCK-9-res)>>(sizeof(res)*8-1));
			for (;inp_blocks<pad_blocks;inp_blocks++)
				sha1_block_data_order(&key->md,data,1);
			}
#endif
			key->md = key->tail;
			SHA1_Update(&key->md,mac.c,SHA_DIGEST_LENGTH);
			SHA1_Final(mac.c,&key->md);

			/* verify HMAC */
			out += inp_len;
			len -= inp_len;
#if 1
			{
			unsigned char *p = out+len-1-maxpad-SHA_DIGEST_LENGTH;
			size_t off = out-p;
			unsigned int c, cmask;

			maxpad += SHA_DIGEST_LENGTH;
			for (res=0,i=0,j=0;j<maxpad;j++) {
				c = p[j];
				cmask = ((int)(j-off-SHA_DIGEST_LENGTH))>>(sizeof(int)*8-1);
				res |= (c^pad)&~cmask;	/* ... and padding */
				cmask &= ((int)(off-1-j))>>(sizeof(int)*8-1);
				res |= (c^mac.c[i])&cmask;
				i += 1&cmask;
			}
			maxpad -= SHA_DIGEST_LENGTH;

			res = 0-((0-res)>>(sizeof(res)*8-1));
			ret &= (int)~res;
			}
#else
			for (res=0,i=0;i<SHA_DIGEST_LENGTH;i++)
				res |= out[i]^mac.c[i];
			res = 0-((0-res)>>(sizeof(res)*8-1));
			ret &= (int)~res;

			/* verify padding */
			pad = (pad&~res) | (maxpad&res);
			out = out+len-1-pad;
			for (res=0,i=0;i<pad;i++)
				res |= out[i]^pad;

			res = (0-res)>>(sizeof(res)*8-1);
			ret &= (int)~res;
#endif
			return ret;
		} else {
			SHA1_Update(&key->md,out,len);
		}
	}

	return 1;
	}