예제 #1
0
파일: sexputil.c 프로젝트: hsaito/gnupg
/* Same as make_canon_sexp but pad the buffer to multiple of 64
   bits.  If SECURE is set, secure memory will be allocated.  */
gpg_error_t
make_canon_sexp_pad (gcry_sexp_t sexp, int secure,
                     unsigned char **r_buffer, size_t *r_buflen)
{
    size_t len;
    unsigned char *buf;

    *r_buffer = NULL;
    if (r_buflen)
        *r_buflen = 0;;

    len = gcry_sexp_sprint (sexp, GCRYSEXP_FMT_CANON, NULL, 0);
    if (!len)
        return gpg_error (GPG_ERR_BUG);
    len += (8 - len % 8) % 8;
    buf = secure? xtrycalloc_secure (1, len) : xtrycalloc (1, len);
    if (!buf)
        return gpg_error_from_syserror ();
    if (!gcry_sexp_sprint (sexp, GCRYSEXP_FMT_CANON, buf, len))
        return gpg_error (GPG_ERR_BUG);

    *r_buffer = buf;
    if (r_buflen)
        *r_buflen = len;

    return 0;
}
예제 #2
0
파일: ecc-eddsa.c 프로젝트: ifzz/libgcrypt
/* Compute the A value as used by EdDSA.  The caller needs to provide
   the context EC and the actual secret D as an MPI.  The function
   returns a newly allocated 64 byte buffer at r_digest; the first 32
   bytes represent the A value.  NULL is returned on error and NULL
   stored at R_DIGEST.  */
gpg_err_code_t
_gcry_ecc_eddsa_compute_h_d (unsigned char **r_digest,
                             gcry_mpi_t d, mpi_ec_t ec)
{
  gpg_err_code_t rc;
  unsigned char *rawmpi = NULL;
  unsigned int rawmpilen;
  unsigned char *digest;
  gcry_buffer_t hvec[2];
  int hashalgo, b;

  *r_digest = NULL;

  hashalgo = GCRY_MD_SHA512;
  if (hashalgo != GCRY_MD_SHA512)
    return GPG_ERR_DIGEST_ALGO;

  b = (ec->nbits+7)/8;
  if (b != 256/8)
    return GPG_ERR_INTERNAL; /* We only support 256 bit. */

  /* Note that we clear DIGEST so we can use it as input to left pad
     the key with zeroes for hashing.  */
  digest = xtrycalloc_secure (2, b);
  if (!digest)
    return gpg_err_code_from_syserror ();

  memset (hvec, 0, sizeof hvec);

  rawmpi = _gcry_mpi_get_buffer (d, 0, &rawmpilen, NULL);
  if (!rawmpi)
    {
      xfree (digest);
      return gpg_err_code_from_syserror ();
    }

  hvec[0].data = digest;
  hvec[0].off = 0;
  hvec[0].len = b > rawmpilen? b - rawmpilen : 0;
  hvec[1].data = rawmpi;
  hvec[1].off = 0;
  hvec[1].len = rawmpilen;
  rc = _gcry_md_hash_buffers (hashalgo, 0, digest, hvec, 2);
  xfree (rawmpi);
  if (rc)
    {
      xfree (digest);
      return rc;
    }

  /* Compute the A value.  */
  reverse_buffer (digest, 32);  /* Only the first half of the hash.  */
  digest[0]   = (digest[0] & 0x7f) | 0x40;
  digest[31] &= 0xf8;

  *r_digest = digest;
  return 0;
}
예제 #3
0
파일: cipher.c 프로젝트: mojoman/libgcrypt
gcry_err_code_t
_gcry_cipher_open_internal (gcry_cipher_hd_t *handle,
			    int algo, int mode, unsigned int flags)
{
  int secure = (flags & GCRY_CIPHER_SECURE);
  gcry_cipher_spec_t *spec;
  gcry_cipher_hd_t h = NULL;
  gcry_err_code_t err;

  /* If the application missed to call the random poll function, we do
     it here to ensure that it is used once in a while. */
  _gcry_fast_random_poll ();

  spec = spec_from_algo (algo);
  if (!spec)
    err = GPG_ERR_CIPHER_ALGO;
  else if (spec->flags.disabled)
    err = GPG_ERR_CIPHER_ALGO;
  else
    err = 0;

  /* check flags */
  if ((! err)
      && ((flags & ~(0
		     | GCRY_CIPHER_SECURE
		     | GCRY_CIPHER_ENABLE_SYNC
		     | GCRY_CIPHER_CBC_CTS
		     | GCRY_CIPHER_CBC_MAC))
	  || (flags & GCRY_CIPHER_CBC_CTS & GCRY_CIPHER_CBC_MAC)))
    err = GPG_ERR_CIPHER_ALGO;

  /* check that a valid mode has been requested */
  if (! err)
    switch (mode)
      {
      case GCRY_CIPHER_MODE_CCM:
#ifdef HAVE_U64_TYPEDEF
	if (spec->blocksize != GCRY_CCM_BLOCK_LEN)
	  err = GPG_ERR_INV_CIPHER_MODE;
	if (!spec->encrypt || !spec->decrypt)
	  err = GPG_ERR_INV_CIPHER_MODE;
	break;
#else
        err = GPG_ERR_NOT_SUPPORTED;
#endif

      case GCRY_CIPHER_MODE_ECB:
      case GCRY_CIPHER_MODE_CBC:
      case GCRY_CIPHER_MODE_CFB:
      case GCRY_CIPHER_MODE_OFB:
      case GCRY_CIPHER_MODE_CTR:
      case GCRY_CIPHER_MODE_AESWRAP:
      case GCRY_CIPHER_MODE_CMAC:
      case GCRY_CIPHER_MODE_GCM:
	if (!spec->encrypt || !spec->decrypt)
	  err = GPG_ERR_INV_CIPHER_MODE;
	break;

      case GCRY_CIPHER_MODE_POLY1305:
	if (!spec->stencrypt || !spec->stdecrypt || !spec->setiv)
	  err = GPG_ERR_INV_CIPHER_MODE;
	else if (spec->algo != GCRY_CIPHER_CHACHA20)
	  err = GPG_ERR_INV_CIPHER_MODE;
	break;

      case GCRY_CIPHER_MODE_OCB:
        /* Note that our implementation allows only for 128 bit block
           length algorithms.  Lower block lengths would be possible
           but we do not implement them because they limit the
           security too much.  */
	if (!spec->encrypt || !spec->decrypt)
	  err = GPG_ERR_INV_CIPHER_MODE;
	else if (spec->blocksize != (128/8))
	  err = GPG_ERR_INV_CIPHER_MODE;
	break;

      case GCRY_CIPHER_MODE_STREAM:
	if (!spec->stencrypt || !spec->stdecrypt)
	  err = GPG_ERR_INV_CIPHER_MODE;
	break;

      case GCRY_CIPHER_MODE_NONE:
        /* This mode may be used for debugging.  It copies the main
           text verbatim to the ciphertext.  We do not allow this in
           fips mode or if no debug flag has been set.  */
	if (fips_mode () || !_gcry_get_debug_flag (0))
          err = GPG_ERR_INV_CIPHER_MODE;
	break;

      default:
	err = GPG_ERR_INV_CIPHER_MODE;
      }

  /* Perform selftest here and mark this with a flag in cipher_table?
     No, we should not do this as it takes too long.  Further it does
     not make sense to exclude algorithms with failing selftests at
     runtime: If a selftest fails there is something seriously wrong
     with the system and thus we better die immediately. */

  if (! err)
    {
      size_t size = (sizeof (*h)
                     + 2 * spec->contextsize
                     - sizeof (cipher_context_alignment_t)
#ifdef NEED_16BYTE_ALIGNED_CONTEXT
                     + 15  /* Space for leading alignment gap.  */
#endif /*NEED_16BYTE_ALIGNED_CONTEXT*/
                     );

      if (secure)
	h = xtrycalloc_secure (1, size);
      else
	h = xtrycalloc (1, size);

      if (! h)
	err = gpg_err_code_from_syserror ();
      else
	{
          size_t off = 0;

#ifdef NEED_16BYTE_ALIGNED_CONTEXT
          if ( ((uintptr_t)h & 0x0f) )
            {
              /* The malloced block is not aligned on a 16 byte
                 boundary.  Correct for this.  */
              off = 16 - ((uintptr_t)h & 0x0f);
              h = (void*)((char*)h + off);
            }
#endif /*NEED_16BYTE_ALIGNED_CONTEXT*/

	  h->magic = secure ? CTX_MAGIC_SECURE : CTX_MAGIC_NORMAL;
          h->actual_handle_size = size - off;
          h->handle_offset = off;
	  h->spec = spec;
          h->algo = algo;
	  h->mode = mode;
	  h->flags = flags;

          /* Setup bulk encryption routines.  */
          switch (algo)
            {
#ifdef USE_AES
            case GCRY_CIPHER_AES128:
            case GCRY_CIPHER_AES192:
            case GCRY_CIPHER_AES256:
              h->bulk.cfb_enc = _gcry_aes_cfb_enc;
              h->bulk.cfb_dec = _gcry_aes_cfb_dec;
              h->bulk.cbc_enc = _gcry_aes_cbc_enc;
              h->bulk.cbc_dec = _gcry_aes_cbc_dec;
              h->bulk.ctr_enc = _gcry_aes_ctr_enc;
              h->bulk.ocb_crypt = _gcry_aes_ocb_crypt;
              h->bulk.ocb_auth  = _gcry_aes_ocb_auth;
              break;
#endif /*USE_AES*/
#ifdef USE_BLOWFISH
	    case GCRY_CIPHER_BLOWFISH:
              h->bulk.cfb_dec = _gcry_blowfish_cfb_dec;
              h->bulk.cbc_dec = _gcry_blowfish_cbc_dec;
              h->bulk.ctr_enc = _gcry_blowfish_ctr_enc;
              break;
#endif /*USE_BLOWFISH*/
#ifdef USE_CAST5
	    case GCRY_CIPHER_CAST5:
              h->bulk.cfb_dec = _gcry_cast5_cfb_dec;
              h->bulk.cbc_dec = _gcry_cast5_cbc_dec;
              h->bulk.ctr_enc = _gcry_cast5_ctr_enc;
              break;
#endif /*USE_CAMELLIA*/
#ifdef USE_CAMELLIA
	    case GCRY_CIPHER_CAMELLIA128:
	    case GCRY_CIPHER_CAMELLIA192:
	    case GCRY_CIPHER_CAMELLIA256:
              h->bulk.cbc_dec = _gcry_camellia_cbc_dec;
              h->bulk.cfb_dec = _gcry_camellia_cfb_dec;
              h->bulk.ctr_enc = _gcry_camellia_ctr_enc;
              h->bulk.ocb_crypt = _gcry_camellia_ocb_crypt;
              h->bulk.ocb_auth  = _gcry_camellia_ocb_auth;
              break;
#endif /*USE_CAMELLIA*/
#ifdef USE_DES
            case GCRY_CIPHER_3DES:
              h->bulk.cbc_dec =  _gcry_3des_cbc_dec;
              h->bulk.cfb_dec =  _gcry_3des_cfb_dec;
              h->bulk.ctr_enc =  _gcry_3des_ctr_enc;
              break;
#endif /*USE_DES*/
#ifdef USE_SERPENT
	    case GCRY_CIPHER_SERPENT128:
	    case GCRY_CIPHER_SERPENT192:
	    case GCRY_CIPHER_SERPENT256:
              h->bulk.cbc_dec = _gcry_serpent_cbc_dec;
              h->bulk.cfb_dec = _gcry_serpent_cfb_dec;
              h->bulk.ctr_enc = _gcry_serpent_ctr_enc;
              h->bulk.ocb_crypt = _gcry_serpent_ocb_crypt;
              h->bulk.ocb_auth  = _gcry_serpent_ocb_auth;
              break;
#endif /*USE_SERPENT*/
#ifdef USE_TWOFISH
	    case GCRY_CIPHER_TWOFISH:
	    case GCRY_CIPHER_TWOFISH128:
              h->bulk.cbc_dec = _gcry_twofish_cbc_dec;
              h->bulk.cfb_dec = _gcry_twofish_cfb_dec;
              h->bulk.ctr_enc = _gcry_twofish_ctr_enc;
              h->bulk.ocb_crypt = _gcry_twofish_ocb_crypt;
              h->bulk.ocb_auth  = _gcry_twofish_ocb_auth;
              break;
#endif /*USE_TWOFISH*/

            default:
              break;
            }

          /* Setup defaults depending on the mode.  */
          switch (mode)
            {
            case GCRY_CIPHER_MODE_OCB:
              h->u_mode.ocb.taglen = 16; /* Bytes.  */
              break;

            default:
              break;
            }

	}
    }

  /* Done.  */

  *handle = err ? NULL : h;

  return err;
}
예제 #4
0
파일: encrypt.c 프로젝트: GroovIM/transport
/* Perform an encrypt operation.  

   Encrypt the data received on DATA-FD and write it to OUT_FP.  The
   recipients are take from the certificate given in recplist; if this
   is NULL it will be encrypted for a default recipient */
int
gpgsm_encrypt (ctrl_t ctrl, certlist_t recplist, int data_fd, FILE *out_fp)
{
  int rc = 0;
  Base64Context b64writer = NULL;
  gpg_error_t err;
  ksba_writer_t writer;
  ksba_reader_t reader = NULL;
  ksba_cms_t cms = NULL;
  ksba_stop_reason_t stopreason;
  KEYDB_HANDLE kh = NULL;
  struct encrypt_cb_parm_s encparm;
  DEK dek = NULL;
  int recpno;
  FILE *data_fp = NULL;
  certlist_t cl;
  int count;

  memset (&encparm, 0, sizeof encparm);

  audit_set_type (ctrl->audit, AUDIT_TYPE_ENCRYPT);

  /* Check that the certificate list is not empty and that at least
     one certificate is not flagged as encrypt_to; i.e. is a real
     recipient. */
  for (cl = recplist; cl; cl = cl->next)
    if (!cl->is_encrypt_to)
      break;
  if (!cl)
    {
      log_error(_("no valid recipients given\n"));
      gpgsm_status (ctrl, STATUS_NO_RECP, "0");
      audit_log_i (ctrl->audit, AUDIT_GOT_RECIPIENTS, 0);
      rc = gpg_error (GPG_ERR_NO_PUBKEY);
      goto leave;
    }

  for (count = 0, cl = recplist; cl; cl = cl->next)
    count++;
  audit_log_i (ctrl->audit, AUDIT_GOT_RECIPIENTS, count);

  kh = keydb_new (0);
  if (!kh)
    {
      log_error (_("failed to allocated keyDB handle\n"));
      rc = gpg_error (GPG_ERR_GENERAL);
      goto leave;
    }

  data_fp = fdopen ( dup (data_fd), "rb");
  if (!data_fp)
    {
      rc = gpg_error (gpg_err_code_from_errno (errno));
      log_error ("fdopen() failed: %s\n", strerror (errno));
      goto leave;
    }

  err = ksba_reader_new (&reader);
  if (err)
      rc = err;
  if (!rc)
    rc = ksba_reader_set_cb (reader, encrypt_cb, &encparm);
  if (rc)
      goto leave;

  encparm.fp = data_fp;

  ctrl->pem_name = "ENCRYPTED MESSAGE";
  rc = gpgsm_create_writer (&b64writer, ctrl, out_fp, NULL, &writer);
  if (rc)
    {
      log_error ("can't create writer: %s\n", gpg_strerror (rc));
      goto leave;
    }

  err = ksba_cms_new (&cms);
  if (err)
    {
      rc = err;
      goto leave;
    }

  err = ksba_cms_set_reader_writer (cms, reader, writer);
  if (err)
    {
      log_debug ("ksba_cms_set_reader_writer failed: %s\n",
                 gpg_strerror (err));
      rc = err;
      goto leave;
    }

  audit_log (ctrl->audit, AUDIT_GOT_DATA);

  /* We are going to create enveloped data with uninterpreted data as
     inner content */
  err = ksba_cms_set_content_type (cms, 0, KSBA_CT_ENVELOPED_DATA);
  if (!err)
    err = ksba_cms_set_content_type (cms, 1, KSBA_CT_DATA);
  if (err)
    {
      log_debug ("ksba_cms_set_content_type failed: %s\n",
                 gpg_strerror (err));
      rc = err;
      goto leave;
    }

  /* Create a session key */
  dek = xtrycalloc_secure (1, sizeof *dek); 
  if (!dek)
    rc = out_of_core ();
  else
  {
    dek->algoid = opt.def_cipher_algoid;
    rc = init_dek (dek);
  }
  if (rc)
    {
      log_error ("failed to create the session key: %s\n",
                 gpg_strerror (rc));
      goto leave;
    }

  err = ksba_cms_set_content_enc_algo (cms, dek->algoid, dek->iv, dek->ivlen);
  if (err)
    {
      log_error ("ksba_cms_set_content_enc_algo failed: %s\n",
                 gpg_strerror (err));
      rc = err;
      goto leave;
    }

  encparm.dek = dek;
  /* Use a ~8k (AES) or ~4k (3DES) buffer */
  encparm.bufsize = 500 * dek->ivlen;
  encparm.buffer = xtrymalloc (encparm.bufsize);
  if (!encparm.buffer)
    {
      rc = out_of_core ();
      goto leave;
    }
  
  audit_log_s (ctrl->audit, AUDIT_SESSION_KEY, dek->algoid);

  /* Gather certificates of recipients, encrypt the session key for
     each and store them in the CMS object */
  for (recpno = 0, cl = recplist; cl; recpno++, cl = cl->next)
    {
      unsigned char *encval;
      
      rc = encrypt_dek (dek, cl->cert, &encval);
      if (rc)
        {
          audit_log_cert (ctrl->audit, AUDIT_ENCRYPTED_TO, cl->cert, rc);
          log_error ("encryption failed for recipient no. %d: %s\n",
                     recpno, gpg_strerror (rc));
          goto leave;
        }
      
      err = ksba_cms_add_recipient (cms, cl->cert);
      if (err)
        {
          audit_log_cert (ctrl->audit, AUDIT_ENCRYPTED_TO, cl->cert, err);
          log_error ("ksba_cms_add_recipient failed: %s\n",
                     gpg_strerror (err));
          rc = err;
          xfree (encval);
          goto leave;
        }
      
      err = ksba_cms_set_enc_val (cms, recpno, encval);
      xfree (encval);
      audit_log_cert (ctrl->audit, AUDIT_ENCRYPTED_TO, cl->cert, err);
      if (err)
        {
          log_error ("ksba_cms_set_enc_val failed: %s\n",
                     gpg_strerror (err));
          rc = err;
          goto leave;
        }
    }

  /* Main control loop for encryption. */
  recpno = 0;
  do 
    {
      err = ksba_cms_build (cms, &stopreason);
      if (err)
        {
          log_debug ("ksba_cms_build failed: %s\n", gpg_strerror (err));
          rc = err;
          goto leave;
        }
    }
  while (stopreason != KSBA_SR_READY);   

  if (encparm.readerror)
    {
      log_error ("error reading input: %s\n", strerror (encparm.readerror));
      rc = gpg_error (gpg_err_code_from_errno (encparm.readerror));
      goto leave;
    }


  rc = gpgsm_finish_writer (b64writer);
  if (rc) 
    {
      log_error ("write failed: %s\n", gpg_strerror (rc));
      goto leave;
    }
  audit_log (ctrl->audit, AUDIT_ENCRYPTION_DONE);
  log_info ("encrypted data created\n");

 leave:
  ksba_cms_release (cms);
  gpgsm_destroy_writer (b64writer);
  ksba_reader_release (reader);
  keydb_release (kh); 
  xfree (dek);
  if (data_fp)
    fclose (data_fp);
  xfree (encparm.buffer);
  return rc;
}