Example #1
0
mpi_read(IOBUF inp, unsigned *ret_nread, int secure)
#endif
{
    int c, i, j;
    unsigned nbits, nbytes, nlimbs, nread=0;
    mpi_limb_t a;
    MPI val = MPI_NULL;

    if( (c = iobuf_get(inp)) == -1 )
	goto leave;
    nbits = c << 8;
    if( (c = iobuf_get(inp)) == -1 )
	goto leave;
    nbits |= c;
    if( nbits > MAX_EXTERN_MPI_BITS ) {
	log_error("mpi too large (%u bits)\n", nbits);
	goto leave;
    }
    nread = 2;

    nbytes = (nbits+7) / 8;
    nlimbs = (nbytes+BYTES_PER_MPI_LIMB-1) / BYTES_PER_MPI_LIMB;
  #ifdef M_DEBUG
    val = secure? mpi_debug_alloc_secure( nlimbs, info )
		: mpi_debug_alloc( nlimbs, info );
  #else
    val = secure? mpi_alloc_secure( nlimbs )
		: mpi_alloc( nlimbs );
  #endif
    i = BYTES_PER_MPI_LIMB - nbytes % BYTES_PER_MPI_LIMB;
    i %= BYTES_PER_MPI_LIMB;
    val->nbits = nbits;
    j= val->nlimbs = nlimbs;
    val->sign = 0;
    for( ; j > 0; j-- ) {
	a = 0;
	for(; i < BYTES_PER_MPI_LIMB; i++ ) {
	    a <<= 8;
	    a |= iobuf_get(inp) & 0xff; nread++;
	}
	i = 0;
	val->d[j-1] = a;
    }

  leave:
    if( nread > *ret_nread )
	log_bug("mpi crosses packet border\n");
    else
	*ret_nread = nread;
    return val;
}
int32_t ida_buffer_add_buffer(ida_local_t * local, ida_buffer_t * buffers, uint32_t size)
{
    struct iobuf * buffer;

    buffer = iobuf_get(local->xl->ctx->iobuf_pool);
    if (unlikely(buffer == NULL))
    {
        goto failed;
    }
    if (unlikely(iobuf_pagesize(buffer) < size))
    {
        gf_log(local->xl->name, GF_LOG_ERROR, "Insufficient space in buffer");

        goto failed_buffer;
    }
    if (iobref_add(buffers->buffers, buffer) != 0)
    {
        goto failed_buffer;
    }

    return 0;

failed_buffer:
    iobuf_unref(buffer);
failed:
    return ENOMEM;
}
Example #3
0
int
acl3svc_submit_reply (rpcsvc_request_t *req, void *arg, acl3_serializer sfunc)
{
        struct iovec            outmsg = {0, };
        struct iobuf            *iob = NULL;
        struct nfs3_state       *nfs3 = NULL;
        int                     ret = -1;
        struct iobref           *iobref = NULL;

        if (!req)
                return -1;

        nfs3 = (struct nfs3_state *)rpcsvc_request_program_private (req);
        if (!nfs3) {
                gf_log (GF_ACL, GF_LOG_ERROR, "mount state not found");
                goto ret;
        }

        /* First, get the io buffer into which the reply in arg will
         * be serialized.
         */
        iob = iobuf_get (nfs3->iobpool);
        if (!iob) {
                gf_log (GF_ACL, GF_LOG_ERROR, "Failed to get iobuf");
                goto ret;
        }

        iobuf_to_iovec (iob, &outmsg);
        /* Use the given serializer to translate the give C structure in arg
         * to XDR format which will be written into the buffer in outmsg.
         */
        outmsg.iov_len = sfunc (outmsg, arg);

        iobref = iobref_new ();
        if (iobref == NULL) {
                gf_log (GF_ACL, GF_LOG_ERROR, "Failed to get iobref");
                goto ret;
        }

        iobref_add (iobref, iob);

        /* Then, submit the message for transmission. */
        ret = rpcsvc_submit_message (req, &outmsg, 1, NULL, 0, iobref);
        if (ret == -1) {
                gf_log (GF_ACL, GF_LOG_ERROR, "Reply submission failed");
                goto ret;
        }

        ret = 0;
ret:
        if (iob)
                iobuf_unref (iob);
        if (iobref)
                iobref_unref (iobref);

        return ret;
}
Example #4
0
int term_writepoll() {
    char c;

    if( iobuf_empty( &oterm )  ) return 1;
    if( (*TERM_FLAG & (TXFF_MASK | TXBUSY_MASK)) ) return 2;
    if( iobuf_get( &oterm, &c ) ) return 3;
    *TERM_DATA = c;

	return 0;
}
Example #5
0
int train_writepoll() {
    char c;

    if( iobuf_empty( &otrain ) ) return 1;
    if( (*TRAIN_FLAG & (TXFF_MASK | TXBUSY_MASK)) || !(*TRAIN_FLAG & CTS_MASK) ) return 2;
    if( iobuf_get( &otrain, &c ) ) {
        return 3;
    }
    *TRAIN_DATA = c;
    
    return 0;
}
Example #6
0
/****************
 * Take file and write it out with armor
 */
int
enarmor_file( const char *fname )
{
    armor_filter_context_t *afx;
    IOBUF inp = NULL, out = NULL;
    int rc = 0;
    int c;

    afx = new_armor_context ();

    /* prepare iobufs */
    inp = iobuf_open(fname);
    if (inp && is_secured_file (iobuf_get_fd (inp)))
      {
        iobuf_close (inp);
        inp = NULL;
        errno = EPERM;
      }
    if (!inp) {
        rc = gpg_error_from_syserror ();
	log_error(_("can't open `%s': %s\n"), fname? fname: "[stdin]",
                  strerror(errno) );
	goto leave;
    }


    if( (rc = open_outfile( fname, 1, &out )) )
	goto leave;

    afx->what = 4;
    afx->hdrlines = "Comment: Use \"gpg --dearmor\" for unpacking\n";
    push_armor_filter ( afx, out );

    while( (c = iobuf_get(inp)) != -1 )
	iobuf_put( out, c );


  leave:
    if( rc )
	iobuf_cancel(out);
    else
	iobuf_close(out);
    iobuf_close(inp);
    release_armor_context (afx);
    return rc;
}
int32_t ida_buffer_new(ida_local_t * local, ida_buffer_t * dst, uint32_t size)
{
    struct iobuf * buffer;

    dst->buffers = iobref_new();
    if (unlikely(dst->buffers == NULL))
    {
        goto failed;
    }
    buffer = iobuf_get(local->xl->ctx->iobuf_pool);
    if (unlikely(buffer == NULL))
    {
        goto failed_iobref;
    }
    if (unlikely(iobuf_pagesize(buffer) < size))
    {
        gf_log(local->xl->name, GF_LOG_ERROR, "Insufficient space in buffer");

        goto failed_buffer;
    }
    if (iobref_add(dst->buffers, buffer) != 0)
    {
        goto failed_buffer;
    }
    dst->vectors = IDA_ALLOC_OR_GOTO(local->xl->name, sizeof(struct iovec), gf_common_mt_iovec, failed_buffer);
    dst->vectors->iov_base = buffer->ptr;
    dst->vectors->iov_len = size;
    dst->count = 1;

    iobuf_unref(buffer);

    return 0;

failed_buffer:
    iobuf_unref(buffer);
failed_iobref:
    iobref_unref(dst->buffers);
    dst->buffers = NULL;
failed:
    return ENOMEM;
}
Example #8
0
/****************
 * Decrypt the data, specified by ED with the key DEK.
 */
int
decrypt_data( void *procctx, PKT_encrypted *ed, DEK *dek )
{
  decode_filter_ctx_t dfx;
  byte *p;
  int rc=0, c, i;
  byte temp[32];
  unsigned blocksize;
  unsigned nprefix;
  
  dfx = xtrycalloc (1, sizeof *dfx);
  if (!dfx)
    return gpg_error_from_syserror ();
  dfx->refcount = 1;

  if ( opt.verbose && !dek->algo_info_printed )
    {
      if (!openpgp_cipher_test_algo (dek->algo))
        log_info (_("%s encrypted data\n"), 
                  openpgp_cipher_algo_name (dek->algo));
      else
        log_info (_("encrypted with unknown algorithm %d\n"), dek->algo );
      dek->algo_info_printed = 1;
    }
  rc = openpgp_cipher_test_algo (dek->algo);
  if (rc)
    goto leave;
  blocksize = openpgp_cipher_get_algo_blklen (dek->algo);
  if ( !blocksize || blocksize > 16 )
    log_fatal ("unsupported blocksize %u\n", blocksize );
  nprefix = blocksize;
  if ( ed->len && ed->len < (nprefix+2) )
    BUG();

  if ( ed->mdc_method ) 
    {
      if (gcry_md_open (&dfx->mdc_hash, ed->mdc_method, 0 ))
        BUG ();
      if ( DBG_HASHING )
        gcry_md_start_debug (dfx->mdc_hash, "checkmdc");
    }

  rc = openpgp_cipher_open (&dfx->cipher_hd, dek->algo,
			    GCRY_CIPHER_MODE_CFB,
			    (GCRY_CIPHER_SECURE
			     | ((ed->mdc_method || dek->algo >= 100)?
				0 : GCRY_CIPHER_ENABLE_SYNC)));
  if (rc)
    {
      /* We should never get an error here cause we already checked
       * that the algorithm is available.  */
      BUG();
    }


  /* log_hexdump( "thekey", dek->key, dek->keylen );*/
  rc = gcry_cipher_setkey (dfx->cipher_hd, dek->key, dek->keylen);
  if ( gpg_err_code (rc) == GPG_ERR_WEAK_KEY )
    {
      log_info(_("WARNING: message was encrypted with"
                 " a weak key in the symmetric cipher.\n"));
      rc=0;
    }
  else if( rc )
    {
      log_error("key setup failed: %s\n", g10_errstr(rc) );
      goto leave;
    }

  if (!ed->buf) 
    {
      log_error(_("problem handling encrypted packet\n"));
      goto leave;
    }

  gcry_cipher_setiv (dfx->cipher_hd, NULL, 0);

  if ( ed->len )
    {
      for (i=0; i < (nprefix+2) && ed->len; i++, ed->len-- ) 
        {
          if ( (c=iobuf_get(ed->buf)) == -1 )
            break;
          else
            temp[i] = c;
        }
    }
  else 
    {
      for (i=0; i < (nprefix+2); i++ )
        if ( (c=iobuf_get(ed->buf)) == -1 )
          break;
        else
          temp[i] = c;
    }
  
  gcry_cipher_decrypt (dfx->cipher_hd, temp, nprefix+2, NULL, 0);
  gcry_cipher_sync (dfx->cipher_hd);
  p = temp;
  /* log_hexdump( "prefix", temp, nprefix+2 ); */
  if (dek->symmetric
      && (p[nprefix-2] != p[nprefix] || p[nprefix-1] != p[nprefix+1]) )
    {
      rc = gpg_error (GPG_ERR_BAD_KEY);
      goto leave;
    }
  
  if ( dfx->mdc_hash )
    gcry_md_write (dfx->mdc_hash, temp, nprefix+2);

  dfx->refcount++;
  if ( ed->mdc_method )
    iobuf_push_filter ( ed->buf, mdc_decode_filter, dfx );
  else
    iobuf_push_filter ( ed->buf, decode_filter, dfx );

  proc_packets ( procctx, ed->buf );
  ed->buf = NULL;
  if ( ed->mdc_method && dfx->eof_seen == 2 )
    rc = gpg_error (GPG_ERR_INV_PACKET);
  else if ( ed->mdc_method )
    { 
      /* We used to let parse-packet.c handle the MDC packet but this
         turned out to be a problem with compressed packets: With old
         style packets there is no length information available and
         the decompressor uses an implicit end.  However we can't know
         this implicit end beforehand (:-) and thus may feed the
         decompressor with more bytes than actually needed.  It would
         be possible to unread the extra bytes but due to our weird
         iobuf system any unread is non reliable due to filters
         already popped off.  The easy and sane solution is to care
         about the MDC packet only here and never pass it to the
         packet parser.  Fortunatley the OpenPGP spec requires a
         strict format for the MDC packet so that we know that 22
         bytes are appended.  */
      int datalen = gcry_md_get_algo_dlen (ed->mdc_method);

      assert (dfx->cipher_hd);
      assert (dfx->mdc_hash);
      gcry_cipher_decrypt (dfx->cipher_hd, dfx->defer, 22, NULL, 0);
      gcry_md_write (dfx->mdc_hash, dfx->defer, 2);
      gcry_md_final (dfx->mdc_hash);

      if (dfx->defer[0] != '\xd3' || dfx->defer[1] != '\x14' )
        {
          log_error("mdc_packet with invalid encoding\n");
          rc = gpg_error (GPG_ERR_INV_PACKET);
        }
      else if (datalen != 20
               || memcmp (gcry_md_read (dfx->mdc_hash, 0),
                          dfx->defer+2,datalen ))
        rc = gpg_error (GPG_ERR_BAD_SIGNATURE);
      /* log_printhex("MDC message:", dfx->defer, 22); */
      /* log_printhex("MDC calc:", gcry_md_read (dfx->mdc_hash,0), datalen); */
    }
  
  
 leave:
  release_dfx_context (dfx);
  return rc;
}
Example #9
0
/* I think we should merge this with cipher_filter */
static int
mdc_decode_filter (void *opaque, int control, IOBUF a,
                   byte *buf, size_t *ret_len)
{
  decode_filter_ctx_t dfx = opaque;
  size_t n, size = *ret_len;
  int rc = 0;
  int c;
  
  if ( control == IOBUFCTRL_UNDERFLOW && dfx->eof_seen )
    {
      *ret_len = 0;
      rc = -1;
    }
  else if( control == IOBUFCTRL_UNDERFLOW )
    {
      assert (a);
      assert ( size > 44 );
      
      /* Get at least 22 bytes and put it somewhere ahead in the buffer. */
      for (n=22; n < 44 ; n++ )
        {
          if( (c = iobuf_get(a)) == -1 )
            break;
          buf[n] = c;
	}
      if ( n == 44 ) 
        {
          /* We have enough stuff - flush the deferred stuff.  */
          /* (we asserted that the buffer is large enough) */
          if ( !dfx->defer_filled )  /* First time. */
            {
              memcpy (buf, buf+22, 22 );
              n = 22;
	    }
          else
            {
              memcpy (buf, dfx->defer, 22 );
	    }
          /* Now fill up. */
          for (; n < size; n++ ) 
            {
              if ( (c = iobuf_get(a)) == -1 )
                break;
              buf[n] = c;
	    }
          /* Move the last 22 bytes back to the defer buffer. */
	  /* (right, we are wasting 22 bytes of the supplied buffer.) */
          n -= 22;
          memcpy (dfx->defer, buf+n, 22 );
          dfx->defer_filled = 1;
	}
      else if ( !dfx->defer_filled )  /* EOF seen but empty defer buffer. */
        {
          /* This is bad because it means an incomplete hash. */
          n -= 22;
          memcpy (buf, buf+22, n );
          dfx->eof_seen = 2; /* EOF with incomplete hash.  */
	}
      else  /* EOF seen (i.e. read less than 22 bytes). */
        {
          memcpy (buf, dfx->defer, 22 );
          n -= 22;
          memcpy (dfx->defer, buf+n, 22 );
          dfx->eof_seen = 1; /* Normal EOF. */
	}

      if ( n )
        {
          if ( dfx->cipher_hd )
            gcry_cipher_decrypt (dfx->cipher_hd, buf, n, NULL, 0);
          if ( dfx->mdc_hash )
            gcry_md_write (dfx->mdc_hash, buf, n);
	}
      else
        {
          assert ( dfx->eof_seen );
          rc = -1; /* eof */
	}
      *ret_len = n;
    }
  else if ( control == IOBUFCTRL_FREE ) 
    {
      release_dfx_context (dfx);
    }
  else if ( control == IOBUFCTRL_DESC ) 
    {
      *(char**)buf = "mdc_decode_filter";
    }
  return rc;
}
Example #10
0
int
acl3svc_submit_reply (rpcsvc_request_t *req, void *arg, acl3_serializer sfunc)
{
        struct iovec            outmsg  = {0, };
        struct iobuf            *iob    = NULL;
        struct nfs3_state       *nfs3   = NULL;
        int                     ret     = -1;
        ssize_t                 msglen  = 0;
        struct iobref           *iobref = NULL;

        if (!req)
                return -1;

        nfs3 = (struct nfs3_state *)rpcsvc_request_program_private (req);
        if (!nfs3) {
                gf_msg (GF_ACL, GF_LOG_ERROR, EINVAL,
                        NFS_MSG_MNT_STATE_NOT_FOUND, "mount state not found");
                goto ret;
        }

        /* First, get the io buffer into which the reply in arg will
         * be serialized.
         */
        iob = iobuf_get (nfs3->iobpool);
        if (!iob) {
                gf_msg (GF_ACL, GF_LOG_ERROR, ENOMEM, NFS_MSG_NO_MEMORY,
                        "Failed to get iobuf");
                goto ret;
        }

        iobuf_to_iovec (iob, &outmsg);
        /* Use the given serializer to translate the give C structure in arg
         * to XDR format which will be written into the buffer in outmsg.
         */
        msglen = sfunc (outmsg, arg);
        if (msglen < 0) {
                gf_msg (GF_ACL, GF_LOG_ERROR, errno, NFS_MSG_ENCODE_MSG_FAIL,
                        "Failed to encode message");
                goto ret;
        }
        outmsg.iov_len = msglen;

        iobref = iobref_new ();
        if (iobref == NULL) {
                gf_msg (GF_ACL, GF_LOG_ERROR, ENOMEM, NFS_MSG_NO_MEMORY,
                        "Failed to get iobref");
                goto ret;
        }

        ret = iobref_add (iobref, iob);
        if (ret) {
                gf_msg (GF_ACL, GF_LOG_ERROR, ENOMEM, NFS_MSG_NO_MEMORY,
                        "Failed to add iob to iobref");
                goto ret;
        }

        /* Then, submit the message for transmission. */
        ret = rpcsvc_submit_message (req, &outmsg, 1, NULL, 0, iobref);
        if (ret == -1) {
                gf_msg (GF_ACL, GF_LOG_ERROR, errno, NFS_MSG_REP_SUBMIT_FAIL,
                        "Reply submission failed");
                goto ret;
        }

        ret = 0;
ret:
        if (iob)
                iobuf_unref (iob);
        if (iobref)
                iobref_unref (iobref);

        return ret;
}
Example #11
0
cli_submit_request (void *req, call_frame_t *frame,
                    rpc_clnt_prog_t *prog,
                    int procnum, struct iobref *iobref,
                    cli_serialize_t sfunc, xlator_t *this,
                    fop_cbk_fn_t cbkfn)
{
    int                     ret         = -1;
    int                     count      = 0;
    char                    start_ping = 0;
    struct iovec            iov         = {0, };
    struct iobuf            *iobuf = NULL;
    char                    new_iobref = 0;

    GF_ASSERT (this);

    iobuf = iobuf_get (this->ctx->iobuf_pool);
    if (!iobuf) {
        goto out;
    };

    if (!iobref) {
        iobref = iobref_new ();
        if (!iobref) {
            goto out;
        }

        new_iobref = 1;
    }

    iobref_add (iobref, iobuf);
Example #12
0
/****************
 * Decrypt the data, specified by ED with the key DEK.
 */
int
decrypt_data (ctrl_t ctrl, void *procctx, PKT_encrypted *ed, DEK *dek)
{
  decode_filter_ctx_t dfx;
  byte *p;
  int rc=0, c, i;
  byte temp[32];
  unsigned blocksize;
  unsigned nprefix;

  dfx = xtrycalloc (1, sizeof *dfx);
  if (!dfx)
    return gpg_error_from_syserror ();
  dfx->refcount = 1;

  if ( opt.verbose && !dek->algo_info_printed )
    {
      if (!openpgp_cipher_test_algo (dek->algo))
        log_info (_("%s encrypted data\n"),
                  openpgp_cipher_algo_name (dek->algo));
      else
        log_info (_("encrypted with unknown algorithm %d\n"), dek->algo );
      dek->algo_info_printed = 1;
    }

  {
    char buf[20];

    snprintf (buf, sizeof buf, "%d %d", ed->mdc_method, dek->algo);
    write_status_text (STATUS_DECRYPTION_INFO, buf);
  }

  if (opt.show_session_key)
    {
      char numbuf[25];
      char *hexbuf;

      snprintf (numbuf, sizeof numbuf, "%d:", dek->algo);
      hexbuf = bin2hex (dek->key, dek->keylen, NULL);
      if (!hexbuf)
        {
          rc = gpg_error_from_syserror ();
          goto leave;
        }
      log_info ("session key: '%s%s'\n", numbuf, hexbuf);
      write_status_strings (STATUS_SESSION_KEY, numbuf, hexbuf, NULL);
      xfree (hexbuf);
    }

  rc = openpgp_cipher_test_algo (dek->algo);
  if (rc)
    goto leave;
  blocksize = openpgp_cipher_get_algo_blklen (dek->algo);
  if ( !blocksize || blocksize > 16 )
    log_fatal ("unsupported blocksize %u\n", blocksize );
  nprefix = blocksize;
  if ( ed->len && ed->len < (nprefix+2) )
    {
       /* An invalid message.  We can't check that during parsing
          because we may not know the used cipher then.  */
      rc = gpg_error (GPG_ERR_INV_PACKET);
      goto leave;
    }

  if ( ed->mdc_method )
    {
      if (gcry_md_open (&dfx->mdc_hash, ed->mdc_method, 0 ))
        BUG ();
      if ( DBG_HASHING )
        gcry_md_debug (dfx->mdc_hash, "checkmdc");
    }

  rc = openpgp_cipher_open (&dfx->cipher_hd, dek->algo,
			    GCRY_CIPHER_MODE_CFB,
			    (GCRY_CIPHER_SECURE
			     | ((ed->mdc_method || dek->algo >= 100)?
				0 : GCRY_CIPHER_ENABLE_SYNC)));
  if (rc)
    {
      /* We should never get an error here cause we already checked
       * that the algorithm is available.  */
      BUG();
    }


  /* log_hexdump( "thekey", dek->key, dek->keylen );*/
  rc = gcry_cipher_setkey (dfx->cipher_hd, dek->key, dek->keylen);
  if ( gpg_err_code (rc) == GPG_ERR_WEAK_KEY )
    {
      log_info(_("WARNING: message was encrypted with"
                 " a weak key in the symmetric cipher.\n"));
      rc=0;
    }
  else if( rc )
    {
      log_error("key setup failed: %s\n", gpg_strerror (rc) );
      goto leave;
    }

  if (!ed->buf)
    {
      log_error(_("problem handling encrypted packet\n"));
      goto leave;
    }

  gcry_cipher_setiv (dfx->cipher_hd, NULL, 0);

  if ( ed->len )
    {
      for (i=0; i < (nprefix+2) && ed->len; i++, ed->len-- )
        {
          if ( (c=iobuf_get(ed->buf)) == -1 )
            break;
          else
            temp[i] = c;
        }
    }
  else
    {
      for (i=0; i < (nprefix+2); i++ )
        if ( (c=iobuf_get(ed->buf)) == -1 )
          break;
        else
          temp[i] = c;
    }

  gcry_cipher_decrypt (dfx->cipher_hd, temp, nprefix+2, NULL, 0);
  gcry_cipher_sync (dfx->cipher_hd);
  p = temp;
  /* log_hexdump( "prefix", temp, nprefix+2 ); */
  if (dek->symmetric
      && (p[nprefix-2] != p[nprefix] || p[nprefix-1] != p[nprefix+1]) )
    {
      rc = gpg_error (GPG_ERR_BAD_KEY);
      goto leave;
    }

  if ( dfx->mdc_hash )
    gcry_md_write (dfx->mdc_hash, temp, nprefix+2);

  dfx->refcount++;
  dfx->partial = ed->is_partial;
  dfx->length = ed->len;
  if ( ed->mdc_method )
    iobuf_push_filter ( ed->buf, mdc_decode_filter, dfx );
  else
    iobuf_push_filter ( ed->buf, decode_filter, dfx );

  if (opt.unwrap_encryption)
    {
      char *filename;
      estream_t fp;
      rc = get_output_file ("", 0, ed->buf, &filename, &fp);
      if (! rc)
        {
          iobuf_t output = iobuf_esopen (fp, "w", 0);
          armor_filter_context_t *afx = NULL;

          if (opt.armor)
            {
              afx = new_armor_context ();
              push_armor_filter (afx, output);
            }

          iobuf_copy (output, ed->buf);
          if ((rc = iobuf_error (ed->buf)))
            log_error (_("error reading '%s': %s\n"),
                       filename, gpg_strerror (rc));
          else if ((rc = iobuf_error (output)))
            log_error (_("error writing '%s': %s\n"),
                       filename, gpg_strerror (rc));

          iobuf_close (output);
          if (afx)
            release_armor_context (afx);
        }
    }
  else
    proc_packets (ctrl, procctx, ed->buf );

  ed->buf = NULL;
  if (dfx->eof_seen > 1 )
    rc = gpg_error (GPG_ERR_INV_PACKET);
  else if ( ed->mdc_method )
    {
      /* We used to let parse-packet.c handle the MDC packet but this
         turned out to be a problem with compressed packets: With old
         style packets there is no length information available and
         the decompressor uses an implicit end.  However we can't know
         this implicit end beforehand (:-) and thus may feed the
         decompressor with more bytes than actually needed.  It would
         be possible to unread the extra bytes but due to our weird
         iobuf system any unread is non reliable due to filters
         already popped off.  The easy and sane solution is to care
         about the MDC packet only here and never pass it to the
         packet parser.  Fortunatley the OpenPGP spec requires a
         strict format for the MDC packet so that we know that 22
         bytes are appended.  */
      int datalen = gcry_md_get_algo_dlen (ed->mdc_method);

      log_assert (dfx->cipher_hd);
      log_assert (dfx->mdc_hash);
      gcry_cipher_decrypt (dfx->cipher_hd, dfx->defer, 22, NULL, 0);
      gcry_md_write (dfx->mdc_hash, dfx->defer, 2);
      gcry_md_final (dfx->mdc_hash);

      if (   dfx->defer[0] != '\xd3'
          || dfx->defer[1] != '\x14'
          || datalen != 20
          || memcmp (gcry_md_read (dfx->mdc_hash, 0), dfx->defer+2, datalen))
        rc = gpg_error (GPG_ERR_BAD_SIGNATURE);
      /* log_printhex("MDC message:", dfx->defer, 22); */
      /* log_printhex("MDC calc:", gcry_md_read (dfx->mdc_hash,0), datalen); */
    }


 leave:
  release_dfx_context (dfx);
  return rc;
}
Example #13
0
static int
decode_filter( void *opaque, int control, IOBUF a, byte *buf, size_t *ret_len)
{
  decode_filter_ctx_t fc = opaque;
  size_t size = *ret_len;
  size_t n;
  int c, rc = 0;


  if ( control == IOBUFCTRL_UNDERFLOW && fc->eof_seen )
    {
      *ret_len = 0;
      rc = -1;
    }
  else if ( control == IOBUFCTRL_UNDERFLOW )
    {
      log_assert (a);

      if (fc->partial)
        {
          for (n=0; n < size; n++ )
            {
              c = iobuf_get(a);
              if (c == -1)
                {
                  fc->eof_seen = 1; /* Normal EOF. */
                  break;
                }
              buf[n] = c;
            }
        }
      else
        {
          for (n=0; n < size && fc->length; n++, fc->length--)
            {
              c = iobuf_get(a);
              if (c == -1)
                {
                  fc->eof_seen = 3; /* Premature EOF. */
                  break;
                }
              buf[n] = c;
            }
          if (!fc->length)
            fc->eof_seen = 1; /* Normal EOF.  */
        }
      if (n)
        {
          if (fc->cipher_hd)
            gcry_cipher_decrypt (fc->cipher_hd, buf, n, NULL, 0);
        }
      else
        {
          if (!fc->eof_seen)
            fc->eof_seen = 1;
          rc = -1; /* Return EOF. */
        }
      *ret_len = n;
    }
  else if ( control == IOBUFCTRL_FREE )
    {
      release_dfx_context (fc);
    }
  else if ( control == IOBUFCTRL_DESC )
    {
      mem2str (buf, "decode_filter", *ret_len);
    }
  return rc;
}
Example #14
0
static int
mdc_decode_filter (void *opaque, int control, IOBUF a,
                   byte *buf, size_t *ret_len)
{
  decode_filter_ctx_t dfx = opaque;
  size_t n, size = *ret_len;
  int rc = 0;
  int c;

  /* Note: We need to distinguish between a partial and a fixed length
     packet.  The first is the usual case as created by GPG.  However
     for short messages the format degrades to a fixed length packet
     and other implementations might use fixed length as well.  Only
     looking for the EOF on fixed data works only if the encrypted
     packet is not followed by other data.  This used to be a long
     standing bug which was fixed on 2009-10-02.  */

  if ( control == IOBUFCTRL_UNDERFLOW && dfx->eof_seen )
    {
      *ret_len = 0;
      rc = -1;
    }
  else if( control == IOBUFCTRL_UNDERFLOW )
    {
      log_assert (a);
      log_assert (size > 44); /* Our code requires at least this size.  */

      /* Get at least 22 bytes and put it ahead in the buffer.  */
      if (dfx->partial)
        {
          for (n=22; n < 44; n++)
            {
              if ( (c = iobuf_get(a)) == -1 )
                break;
              buf[n] = c;
            }
        }
      else
        {
          for (n=22; n < 44 && dfx->length; n++, dfx->length--)
            {
              c = iobuf_get (a);
              if (c == -1)
                break; /* Premature EOF.  */
              buf[n] = c;
            }
        }
      if (n == 44)
        {
          /* We have enough stuff - flush the deferred stuff.  */
          if ( !dfx->defer_filled )  /* First time. */
            {
              memcpy (buf, buf+22, 22);
              n = 22;
	    }
          else
            {
              memcpy (buf, dfx->defer, 22);
	    }
          /* Fill up the buffer. */
          if (dfx->partial)
            {
              for (; n < size; n++ )
                {
                  if ( (c = iobuf_get(a)) == -1 )
                    {
                      dfx->eof_seen = 1; /* Normal EOF. */
                      break;
                    }
                  buf[n] = c;
                }
            }
          else
            {
              for (; n < size && dfx->length; n++, dfx->length--)
                {
                  c = iobuf_get(a);
                  if (c == -1)
                    {
                      dfx->eof_seen = 3; /* Premature EOF. */
                      break;
                    }
                  buf[n] = c;
                }
              if (!dfx->length)
                dfx->eof_seen = 1; /* Normal EOF.  */
            }

          /* Move the trailing 22 bytes back to the defer buffer.  We
             have at least 44 bytes thus a memmove is not needed.  */
          n -= 22;
          memcpy (dfx->defer, buf+n, 22 );
          dfx->defer_filled = 1;
	}
      else if ( !dfx->defer_filled )  /* EOF seen but empty defer buffer. */
        {
          /* This is bad because it means an incomplete hash. */
          n -= 22;
          memcpy (buf, buf+22, n );
          dfx->eof_seen = 2; /* EOF with incomplete hash.  */
	}
      else  /* EOF seen (i.e. read less than 22 bytes). */
        {
          memcpy (buf, dfx->defer, 22 );
          n -= 22;
          memcpy (dfx->defer, buf+n, 22 );
          dfx->eof_seen = 1; /* Normal EOF. */
	}

      if ( n )
        {
          if ( dfx->cipher_hd )
            gcry_cipher_decrypt (dfx->cipher_hd, buf, n, NULL, 0);
          if ( dfx->mdc_hash )
            gcry_md_write (dfx->mdc_hash, buf, n);
	}
      else
        {
          log_assert ( dfx->eof_seen );
          rc = -1; /* Return EOF.  */
	}
      *ret_len = n;
    }
  else if ( control == IOBUFCTRL_FREE )
    {
      release_dfx_context (dfx);
    }
  else if ( control == IOBUFCTRL_DESC )
    {
      mem2str (buf, "mdc_decode_filter", *ret_len);
    }
  return rc;
}
Example #15
0
mpi_read(IOBUF inp, unsigned *ret_nread, int secure)
#endif
{
    int c, i, j;
    unsigned int nmax = *ret_nread;
    unsigned nbits, nbytes, nlimbs, nread=0;
    mpi_limb_t a;
    MPI val = NULL;

    if (nread == nmax)
        goto overflow;
    if( (c = iobuf_get(inp)) == -1 )
	goto leave;
    nread++;
    nbits = c << 8;

    if (nread == nmax)
        goto overflow;
    if( (c = iobuf_get(inp)) == -1 )
	goto leave;
    nread++;
    nbits |= c;

    if( nbits > MAX_EXTERN_MPI_BITS ) {
	log_error("mpi too large for this implementation (%u bits)\n", nbits);
	goto leave;
    }

    nbytes = (nbits+7) / 8;
    nlimbs = (nbytes+BYTES_PER_MPI_LIMB-1) / BYTES_PER_MPI_LIMB;
#ifdef M_DEBUG
    val = secure? mpi_debug_alloc_secure( nlimbs, info )
		: mpi_debug_alloc( nlimbs, info );
#else
    val = secure? mpi_alloc_secure( nlimbs )
		: mpi_alloc( nlimbs );
#endif
    i = BYTES_PER_MPI_LIMB - nbytes % BYTES_PER_MPI_LIMB;
    i %= BYTES_PER_MPI_LIMB;
    val->nbits = nbits;
    j= val->nlimbs = nlimbs;
    val->sign = 0;
    for( ; j > 0; j-- ) {
	a = 0;
	for(; i < BYTES_PER_MPI_LIMB; i++ ) {
            if (nread == nmax) {
#ifdef M_DEBUG
                mpi_debug_free (val);
#else
                mpi_free (val);
#endif
                val = NULL;
                goto overflow;
            }
	    a <<= 8;
	    a |= iobuf_get(inp) & 0xff; nread++;
	}
	i = 0;
	val->d[j-1] = a;
    }

  leave:
    *ret_nread = nread;
    return val;
  overflow:
    log_error ("mpi larger than indicated length (%u bytes)\n", nmax);
    *ret_nread = nread;
    return val;
}
static int
pipemode_filter( void *opaque, int control,
	         IOBUF a, byte *buf, size_t *ret_len)
{ 
    size_t size = *ret_len;
    struct pipemode_context_s *stx = opaque;
    int rc=0;
    size_t n = 0;
    int esc = 0;

    if( control == IOBUFCTRL_UNDERFLOW ) {
        *ret_len = 0;
        /* reserve some space for one control packet */
        if ( size <= CONTROL_PACKET_SPACE+FAKED_LITERAL_PACKET_SPACE )
            BUG();
        size -= CONTROL_PACKET_SPACE+FAKED_LITERAL_PACKET_SPACE;

        if ( stx->block_mode ) {
            /* reserve 2 bytes for the block length */
            buf[n++] = 0;
            buf[n++] = 0;
        }
            

        while ( n < size ) {
            /* FIXME: we have to make sure that we have a large enough
             * buffer for a control packet even after we already read 
             * something. The easest way to do this is probably by ungetting
             * the control sequence and returning the buffer we have
             * already assembled */
            int c = iobuf_get (a);
            if (c == -1) {
                if ( stx->state != STX_init ) {
                    log_error ("EOF encountered at wrong state\n");
                    stx->stop = 1;
                    return -1;
                }
                break;
            }
            if ( esc ) {
                switch (c) {
                  case '@':  
                    if ( stx->state == STX_text ) {
                        buf[n++] = c;
                        break;
                    }
                    else if ( stx->state == STX_detached_signature ) {
                        esc = 0;
                        goto do_unarmor; /* not a very elegant solution */
                    }
                    else if ( stx->state == STX_detached_signature_wait_text) {
                        esc = 0;
                        break; /* just ignore it in this state */
                    }
                    log_error ("@@ not allowed in current state\n");
                    return -1;
                  case '<': /* begin of stream part */
                    if ( stx->state != STX_init ) {
                        log_error ("nested begin of stream\n");
                        stx->stop = 1;
                        return -1;
                    }
                    stx->state = STX_wait_operation;
                    stx->block_mode = 0;
                    unarmor_pump_release (stx->unarmor_ctx);
                    stx->unarmor_ctx = NULL;
                    break;
                   case '>': /* end of stream part */
                     if ( stx->state != STX_wait_init ) {
                        log_error ("invalid state for @>\n");
                        stx->stop = 1;
                        return -1;
                    }
                    stx->state = STX_init;
                    break;
                  case 'V': /* operation = verify */
                  case 'E': /* operation = encrypt */
                  case 'S': /* operation = sign */
                  case 'B': /* operation = detach sign */
                  case 'C': /* operation = clearsign */
                  case 'D': /* operation = decrypt */
                    if ( stx->state != STX_wait_operation ) {
                        log_error ("invalid state for operation code\n");
                        stx->stop = 1;
                        return -1;
                    }
                    stx->operation = c;
                    if ( stx->operation == 'B') {
                        stx->state = STX_detached_signature;
                        if ( !opt.no_armor )
                            stx->unarmor_ctx = unarmor_pump_new ();
                    }
                    else
                        stx->state = STX_begin;
                    n += make_control ( buf+n, 1, stx->operation );
                    /* must leave after a control packet */
                    goto leave;

                  case 't': /* plaintext text follows */
                    if ( stx->state == STX_detached_signature_wait_text ) 
                        stx->state = STX_detached_signature;
                    if ( stx->state == STX_detached_signature ) {
                        if ( stx->operation != 'B' ) {
                            log_error ("invalid operation for this state\n");
                            stx->stop = 1;
                            return -1;
                        }
                        stx->state = STX_signed_data;
                        n += make_control ( buf+n, 2, 'B' );
                        /* and now we fake a literal data packet much the same
                         * as in armor.c */
                        buf[n++] = 0xaf; /* old packet format, type 11,
                                            var length */
                        buf[n++] = 0;	 /* set the length header */
                        buf[n++] = 6;
                        buf[n++] = 'b';  /* we ignore it anyway */
                        buf[n++] = 0;	 /* namelength */
                        memset(buf+n, 0, 4); /* timestamp */
                        n += 4;
                        /* and return now so that we are sure to have
                         * more space in the bufer for the next control
                         * packet */
                        stx->block_mode = 1;
                        goto leave2;
                    }
                    else {
                        log_error ("invalid state for @t\n");
                        stx->stop = 1;
                        return -1;
                    }
                    break;

                  case '.': /* ready */
                    if ( stx->state == STX_signed_data ) { 
                        if (stx->block_mode) {
                            buf[0] = (n-2) >> 8;
                            buf[1] = (n-2);
                            if ( buf[0] || buf[1] ) {
                                /* end of blocks marker */
                                buf[n++] = 0;
                                buf[n++] = 0;
                            }
                            stx->block_mode = 0;
                        }
                        n += make_control ( buf+n, 3, 'B' );
                    }
                    else {
                        log_error ("invalid state for @.\n");
                        stx->stop = 1;
                        return -1;
                    }
                    stx->state = STX_wait_init;
                    goto leave;

                 default:      
                    log_error ("invalid escape sequence 0x%02x in stream\n",
                               c);
                    stx->stop = 1;
                    return -1;
                }
                esc = 0;
            }
Example #17
0
int
main (int argc, char *argv[])
{
  (void) argc;
  (void) argv;

  /* A simple test to make sure filters work.  We use a static buffer
     and then add a filter in front of it that returns every other
     character.  */
  {
    char *content = "0123456789abcdefghijklm";
    iobuf_t iobuf;
    int c;
    int n;
    int rc;

    iobuf = iobuf_temp_with_content (content, strlen (content));
    rc = iobuf_push_filter (iobuf, every_other_filter, NULL);
    assert (rc == 0);

    n = 0;
    while ((c = iobuf_readbyte (iobuf)) != -1)
      {
	/* printf ("%d: %c\n", n + 1, (char) c); */
	assert (content[2 * n + 1] == c);
	n ++;
      }
    /* printf ("Got EOF after reading %d bytes (content: %d)\n", */
    /*         n, strlen (content)); */
    assert (n == strlen (content) / 2);

    iobuf_close (iobuf);
  }

  /* A simple test to check buffering.  Make sure that when we add a
     filter to a pipeline, any buffered data gets processed by the */
  {
    char *content = "0123456789abcdefghijklm";
    iobuf_t iobuf;
    int c;
    int n;
    int rc;
    int i;

    iobuf = iobuf_temp_with_content (content, strlen (content));

    n = 0;
    for (i = 0; i < 10; i ++)
      {
	c = iobuf_readbyte (iobuf);
	assert (content[i] == c);
	n ++;
      }

    rc = iobuf_push_filter (iobuf, every_other_filter, NULL);
    assert (rc == 0);

    while ((c = iobuf_readbyte (iobuf)) != -1)
      {
	/* printf ("%d: %c\n", n + 1, (char) c); */
	assert (content[2 * (n - 5) + 1] == c);
	n ++;
      }
    assert (n == 10 + (strlen (content) - 10) / 2);

    iobuf_close (iobuf);
  }


  /* A simple test to check that iobuf_read_line works.  */
  {
    /* - 3 characters plus new line
       - 4 characters plus new line
       - 5 characters plus new line
       - 5 characters, no new line
     */
    char *content = "abc\ndefg\nhijkl\nmnopq";
    iobuf_t iobuf;
    byte *buffer;
    unsigned size;
    unsigned max_len;
    int n;

    iobuf = iobuf_temp_with_content (content, strlen(content));

    /* We read a line with 3 characters plus a newline.  If we
       allocate a buffer that is 5 bytes long, then no reallocation
       should be required.  */
    size = 5;
    buffer = malloc (size);
    assert (buffer);
    max_len = 100;
    n = iobuf_read_line (iobuf, &buffer, &size, &max_len);
    assert (n == 4);
    assert (strcmp (buffer, "abc\n") == 0);
    assert (size == 5);
    assert (max_len == 100);
    free (buffer);

    /* We now read a line with 4 characters plus a newline.  This
       requires 6 bytes of storage.  We pass a buffer that is 5 bytes
       large and we allow the buffer to be grown.  */
    size = 5;
    buffer = malloc (size);
    max_len = 100;
    n = iobuf_read_line (iobuf, &buffer, &size, &max_len);
    assert (n == 5);
    assert (strcmp (buffer, "defg\n") == 0);
    assert (size >= 6);
    /* The string shouldn't have been truncated (max_len == 0).  */
    assert (max_len == 100);
    free (buffer);

    /* We now read a line with 5 characters plus a newline.  This
       requires 7 bytes of storage.  We pass a buffer that is 5 bytes
       large and we don't allow the buffer to be grown.  */
    size = 5;
    buffer = malloc (size);
    max_len = 5;
    n = iobuf_read_line (iobuf, &buffer, &size, &max_len);
    assert (n == 4);
    /* Note: the string should still have a trailing \n.  */
    assert (strcmp (buffer, "hij\n") == 0);
    assert (size == 5);
    /* The string should have been truncated (max_len == 0).  */
    assert (max_len == 0);
    free (buffer);

    /* We now read a line with 6 characters without a newline.  This
       requires 7 bytes of storage.  We pass a NULL buffer and we
       don't allow the buffer to be grown larger than 5 bytes.  */
    size = 5;
    buffer = NULL;
    max_len = 5;
    n = iobuf_read_line (iobuf, &buffer, &size, &max_len);
    assert (n == 4);
    /* Note: the string should still have a trailing \n.  */
    assert (strcmp (buffer, "mno\n") == 0);
    assert (size == 5);
    /* The string should have been truncated (max_len == 0).  */
    assert (max_len == 0);
    free (buffer);

    iobuf_close (iobuf);
  }

  {
    /* - 10 characters, EOF
       - 17 characters, EOF
     */
    char *content = "abcdefghijklmnopq";
    char *content2 = "0123456789";
    iobuf_t iobuf;
    int rc;
    int c;
    int n;
    int lastc = 0;
    struct content_filter_state *state;

    iobuf = iobuf_temp_with_content (content, strlen(content));
    rc = iobuf_push_filter (iobuf,
			    content_filter,
                            state=content_filter_new (content2));
    assert (rc == 0);

    n = 0;
    while (1)
      {
	c = iobuf_readbyte (iobuf);
	if (c == -1 && lastc == -1)
	  {
	    /* printf("Two EOFs in a row.  Done.\n");  */
	    assert (n == 27);
	    break;
	  }

	lastc = c;

	if (c == -1)
	  {
	    /* printf("After %d bytes, got EOF.\n", n); */
	    assert (n == 10 || n == 27);
	  }
	else
	  {
	    n ++;
	    /* printf ("%d: '%c' (%d)\n", n, c, c); */
	  }
      }

    iobuf_close (iobuf);
    free (state);
  }

  /* Write some data to a temporary filter.  Push a new filter.  The
     already written data should not be processed by the new
     filter.  */
  {
    iobuf_t iobuf;
    int rc;
    char *content = "0123456789";
    char *content2 = "abc";
    char buffer[4096];
    int n;

    iobuf = iobuf_temp ();
    assert (iobuf);

    rc = iobuf_write (iobuf, content, strlen (content));
    assert (rc == 0);

    rc = iobuf_push_filter (iobuf, double_filter, NULL);
    assert (rc == 0);

    /* Include a NUL.  */
    rc = iobuf_write (iobuf, content2, strlen (content2) + 1);
    assert (rc == 0);

    n = iobuf_temp_to_buffer (iobuf, buffer, sizeof (buffer));
#if 0
    printf ("Got %d bytes\n", n);
    printf ("buffer: `");
    fwrite (buffer, n, 1, stdout);
    fputc ('\'', stdout);
    fputc ('\n', stdout);
#endif

    assert (n == strlen (content) + 2 * (strlen (content2) + 1));
    assert (strcmp (buffer, "0123456789aabbcc") == 0);

    iobuf_close (iobuf);
  }

  {
    iobuf_t iobuf;
    int rc;
    char *content = "0123456789";
    int n;
    int c;
    char buffer[strlen (content)];

    iobuf = iobuf_temp_with_content (content, strlen (content));
    assert (iobuf);

    rc = iobuf_push_filter (iobuf, every_other_filter, NULL);
    assert (rc == 0);
    rc = iobuf_push_filter (iobuf, every_other_filter, NULL);
    assert (rc == 0);

    for (n = 0; (c = iobuf_get (iobuf)) != -1; n ++)
      {
	/* printf ("%d: `%c'\n", n, c);  */
	buffer[n] = c;
      }

    assert (n == 2);
    assert (buffer[0] == '3');
    assert (buffer[1] == '7');

    iobuf_close (iobuf);
  }

  return 0;
}