Exemple #1
0
static int
do_check( PKT_secret_key *sk, const char *tryagain_text, int mode,
          int *canceled )
{
    gpg_error_t err;
    u16 csum=0;
    int i, res;
    size_t nbytes;
    if( sk->is_protected ) { /* remove the protection */

	DEK *dek = NULL;
	u32 keyid[4]; /* 4! because we need two of them */
	gcry_cipher_hd_t cipher_hd=NULL;
	PKT_secret_key *save_sk;

	if( sk->protect.s2k.mode == 1001 ) {
	    log_info(_("secret key parts are not available\n"));
	    return G10ERR_UNU_SECKEY;
	}
	if( sk->protect.algo == CIPHER_ALGO_NONE )
	    BUG();
	if( openpgp_cipher_test_algo( sk->protect.algo ) ) {
	    log_info(_("protection algorithm %d%s is not supported\n"),
			sk->protect.algo,sk->protect.algo==1?" (IDEA)":"" );
	    if (sk->protect.algo==CIPHER_ALGO_IDEA)
              {
                write_status (STATUS_RSA_OR_IDEA);
                idea_cipher_warn (0);
              }
	    return G10ERR_CIPHER_ALGO;
	}
	if(gcry_md_test_algo (sk->protect.s2k.hash_algo))
	  {
	    log_info(_("protection digest %d is not supported\n"),
		     sk->protect.s2k.hash_algo);
	    return G10ERR_DIGEST_ALGO;
	  }
	keyid_from_sk( sk, keyid );
	keyid[2] = keyid[3] = 0;
	if( !sk->is_primary ) {
            keyid[2] = sk->main_keyid[0];
            keyid[3] = sk->main_keyid[1];
	}
	dek = passphrase_to_dek( keyid, sk->pubkey_algo, sk->protect.algo,
				 &sk->protect.s2k, mode,
                                 tryagain_text, canceled );

        if (!dek && canceled && *canceled)
	    return GPG_ERR_CANCELED;


	err = openpgp_cipher_open (&cipher_hd, sk->protect.algo,
				   GCRY_CIPHER_MODE_CFB,
				   (GCRY_CIPHER_SECURE
				    | (sk->protect.algo >= 100 ?
				       0 : GCRY_CIPHER_ENABLE_SYNC)));
        if (err)
          log_fatal ("cipher open failed: %s\n", gpg_strerror (err) );

	err = gcry_cipher_setkey (cipher_hd, dek->key, dek->keylen);
        if (err)
          log_fatal ("set key failed: %s\n", gpg_strerror (err) );

	xfree(dek);
	save_sk = copy_secret_key( NULL, sk );

	gcry_cipher_setiv ( cipher_hd, sk->protect.iv, sk->protect.ivlen );

	csum = 0;
	if( sk->version >= 4 ) {
            int ndata;
	    unsigned int ndatabits;
	    byte *p, *data;
            u16 csumc = 0;

	    i = pubkey_get_npkey(sk->pubkey_algo);

            assert ( gcry_mpi_get_flag (sk->skey[i], GCRYMPI_FLAG_OPAQUE ));
            p = gcry_mpi_get_opaque ( sk->skey[i], &ndatabits );
            ndata = (ndatabits+7)/8;

            if ( ndata > 1 && p )
                csumc = p[ndata-2] << 8 | p[ndata-1];
	    data = xmalloc_secure ( ndata );
            if (p) {
              gcry_cipher_decrypt ( cipher_hd, data, ndata, p, ndata );
            }
            else
              memset (data, 0, ndata);
	    gcry_mpi_release (sk->skey[i]); sk->skey[i] = NULL ;

	    p = data;
            if (sk->protect.sha1chk) {
                /* This is the new SHA1 checksum method to detect
                   tampering with the key as used by the Klima/Rosa
                   attack */
                sk->csum = 0;
                csum = 1;
                if( ndata < 20 )
                    log_error("not enough bytes for SHA-1 checksum\n");
                else {
                    gcry_md_hd_t h;

                    if ( gcry_md_open (&h, DIGEST_ALGO_SHA1, 1))
                        BUG(); /* Algo not available. */
                    gcry_md_write (h, data, ndata - 20);
                    gcry_md_final (h);
                    if (!memcmp (gcry_md_read (h, DIGEST_ALGO_SHA1),
                                 data + ndata - 20, 20) )
                      {
                        /* Digest does match.  We have to keep the old
                           style checksum in sk->csum, so that the
                           test used for unprotected keys does work.
                           This test gets used when we are adding new
                           keys. */
                        sk->csum = csum = checksum (data, ndata-20);
                      }
                    gcry_md_close (h);
                }
            }
            else {
                if( ndata < 2 ) {
                    log_error("not enough bytes for checksum\n");
                    sk->csum = 0;
                    csum = 1;
                }
                else {
                    csum = checksum( data, ndata-2);
                    sk->csum = data[ndata-2] << 8 | data[ndata-1];
                    if ( sk->csum != csum ) {
                        /* This is a PGP 7.0.0 workaround */
                        sk->csum = csumc; /* take the encrypted one */
                    }
                }
            }

            /* Must check it here otherwise the mpi_read_xx would fail
               because the length may have an arbitrary value */
            if( sk->csum == csum ) {
                for( ; i < pubkey_get_nskey(sk->pubkey_algo); i++ ) {
                	if(sk->pubkey_algo == PUBKEY_ALGO_LATTICE) {
                		if ( gcry_mpi_scan( &sk->skey[i], GCRYMPI_FMT_USG,
              		                                        p+2, ndata-22, &nbytes)) // add respecitively subtract 22 manually since we use sha1 checksum and don't use the pgp format for lattice keys
              		                      {
              		                        /* Checksum was okay, but not correctly
              		                           decrypted.  */
              		                        sk->csum = 0;
              		                        csum = 1;
              		                        break;
              		     }
                	} else {
                		  if ( gcry_mpi_scan( &sk->skey[i], GCRYMPI_FMT_PGP,
                		                                        p, ndata, &nbytes))
                		                      {
                		                        /* Checksum was okay, but not correctly
                		                           decrypted.  */
                		                        sk->csum = 0;
                		                        csum = 1;
                		                        break;
                		                      }
                	}
                    ndata -= nbytes;
                    p += nbytes;
                }
                /* Note: at this point ndata should be 2 for a simple
                   checksum or 20 for the sha1 digest */
            }
	    xfree(data);
	}
	else {
	    for(i=pubkey_get_npkey(sk->pubkey_algo);
		    i < pubkey_get_nskey(sk->pubkey_algo); i++ ) {
                byte *p;
                size_t ndata;
                unsigned int ndatabits;

                assert (gcry_mpi_get_flag (sk->skey[i], GCRYMPI_FLAG_OPAQUE));
                p = gcry_mpi_get_opaque (sk->skey[i], &ndatabits);
                if (!p)
                  err = -1;
                else
                  {
                    byte *buffer;

                    ndata = (ndatabits+7)/8;
                    assert (ndata >= 2);
                    assert (ndata == ((p[0] << 8 | p[1]) + 7)/8 + 2);
                    buffer = xmalloc_secure (ndata);
                    gcry_cipher_sync (cipher_hd);
                    buffer[0] = p[0];
                    buffer[1] = p[1];
                    gcry_cipher_decrypt (cipher_hd, buffer+2, ndata-2,
                                         p+2, ndata-2);
                    csum += checksum (buffer, ndata);
                    gcry_mpi_release (sk->skey[i]);

                    err = gcry_mpi_scan( &sk->skey[i], GCRYMPI_FMT_PGP,
                                         buffer, ndata, &ndata );
                    xfree (buffer);
                  }
                if (err)
                  {
                    /* Checksum was okay, but not correctly
                       decrypted.  */
                    sk->csum = 0;
                    csum = 1;
                    break;
                  }
/*  		csum += checksum_mpi (sk->skey[i]); */
	    }
	}
	gcry_cipher_close ( cipher_hd );

	/* Now let's see whether we have used the correct passphrase. */
	if( csum != sk->csum ) {
	    copy_secret_key( sk, save_sk );
            passphrase_clear_cache ( keyid, NULL, sk->pubkey_algo );
	    free_secret_key( save_sk );
	    return gpg_error (GPG_ERR_BAD_PASSPHRASE);
	}

	/* The checksum may fail, so we also check the key itself. */
	res = pk_check_secret_key ( sk->pubkey_algo, sk->skey );
	if( res ) {
	    copy_secret_key( sk, save_sk );
            passphrase_clear_cache ( keyid, NULL, sk->pubkey_algo );
	    free_secret_key( save_sk );
	    return gpg_error (GPG_ERR_BAD_PASSPHRASE);
	}
	free_secret_key( save_sk );
	sk->is_protected = 0;
    }
    else { /* not protected, assume it is okay if the checksum is okay */
	csum = 0;
	for(i=pubkey_get_npkey(sk->pubkey_algo);
		i < pubkey_get_nskey(sk->pubkey_algo); i++ ) {
	    csum += checksum_mpi( sk->skey[i] );
	}
	if( csum != sk->csum ) {
	    	return G10ERR_CHECKSUM;
		}
    }

    return 0;
}
Exemple #2
0
/*
 * Test iterative X25519 computation through lower layer MPI routines.
 *
 * Input: K (as hex string), ITER, R (as hex string)
 *
 * where R is expected result of iterating X25519 by ITER times.
 *
 */
static void
test_it (int testno, const char *k_str, int iter, const char *result_str)
{
  gcry_ctx_t ctx;
  gpg_error_t err;
  void *buffer = NULL;
  size_t buflen;
  gcry_mpi_t mpi_k = NULL;
  gcry_mpi_t mpi_x = NULL;
  gcry_mpi_point_t P = NULL;
  gcry_mpi_point_t Q;
  int i;
  gcry_mpi_t mpi_kk = NULL;

  if (verbose > 1)
    info ("Running test %d: iteration=%d\n", testno, iter);

  gcry_mpi_ec_new (&ctx, NULL, "Curve25519");
  Q = gcry_mpi_point_new (0);

  if (!(buffer = hex2buffer (k_str, &buflen)) || buflen != 32)
    {
      fail ("error scanning MPI for test %d, %s: %s",
            testno, "k", "invalid hex string");
      goto leave;
    }
  reverse_buffer (buffer, buflen);
  if ((err = gcry_mpi_scan (&mpi_x, GCRYMPI_FMT_USG, buffer, buflen, NULL)))
    {
      fail ("error scanning MPI for test %d, %s: %s",
            testno, "x", gpg_strerror (err));
      goto leave;
    }

  xfree (buffer);
  buffer = NULL;

  P = gcry_mpi_point_set (NULL, mpi_x, NULL, GCRYMPI_CONST_ONE);

  mpi_k = gcry_mpi_copy (mpi_x);
  if (debug)
    print_mpi ("k", mpi_k);

  for (i = 0; i < iter; i++)
    {
      /*
       * Another variant of decodeScalar25519 thing.
       */
      mpi_kk = gcry_mpi_set (mpi_kk, mpi_k);
      gcry_mpi_set_bit (mpi_kk, 254);
      gcry_mpi_clear_bit (mpi_kk, 255);
      gcry_mpi_clear_bit (mpi_kk, 0);
      gcry_mpi_clear_bit (mpi_kk, 1);
      gcry_mpi_clear_bit (mpi_kk, 2);

      gcry_mpi_ec_mul (Q, mpi_kk, P, ctx);

      P = gcry_mpi_point_set (P, mpi_k, NULL, GCRYMPI_CONST_ONE);
      gcry_mpi_ec_get_affine (mpi_k, NULL, Q, ctx);

      if (debug)
        print_mpi ("k", mpi_k);
    }

  {
    unsigned char res[32];
    char *r, *r0;

    gcry_mpi_print (GCRYMPI_FMT_USG, res, 32, NULL, mpi_k);
    reverse_buffer (res, 32);

    r0 = r = xmalloc (65);
    if (!r0)
      {
        fail ("memory allocation for test %d", testno);
        goto leave;
      }

    for (i=0; i < 32; i++, r += 2)
      snprintf (r, 3, "%02x", res[i]);

    if (strcmp (result_str, r0))
      {
        fail ("curv25519 failed for test %d: %s",
              testno, "wrong value returned");
        info ("  expected: '%s'", result_str);
        info ("       got: '%s'", r0);
      }
    xfree (r0);
  }

 leave:
  gcry_mpi_release (mpi_kk);
  gcry_mpi_release (mpi_k);
  gcry_mpi_point_release (P);
  gcry_mpi_release (mpi_x);
  xfree (buffer);
  gcry_mpi_point_release (Q);
  gcry_ctx_release (ctx);
}
Exemple #3
0
/*
 * Generate a deterministic secret exponent K less than DSA_Q.  H1 is
 * the to be signed digest with a length of HLEN bytes.  HALGO is the
 * algorithm used to create the hash.  On success the value for K is
 * stored at R_K.
 */
gpg_err_code_t
_gcry_dsa_gen_rfc6979_k (gcry_mpi_t *r_k,
                         gcry_mpi_t dsa_q, gcry_mpi_t dsa_x,
                         const unsigned char *h1, unsigned int hlen,
                         int halgo, unsigned int extraloops)
{
  gpg_err_code_t rc;
  unsigned char *V = NULL;
  unsigned char *K = NULL;
  unsigned char *x_buf = NULL;
  unsigned char *h1_buf = NULL;
  gcry_md_hd_t hd = NULL;
  unsigned char *t = NULL;
  gcry_mpi_t k = NULL;
  unsigned int tbits, qbits;
  int i;

  qbits = mpi_get_nbits (dsa_q);

  if (!qbits || !h1 || !hlen)
    return GPG_ERR_EINVAL;

  if (gcry_md_get_algo_dlen (halgo) != hlen)
    return GPG_ERR_DIGEST_ALGO;

  /* Step b:  V = 0x01 0x01 0x01 ... 0x01 */
  V = gcry_malloc (hlen);
  if (!V)
    {
      rc = gpg_err_code_from_syserror ();
      goto leave;
    }
  for (i=0; i < hlen; i++)
    V[i] = 1;

  /* Step c:  K = 0x00 0x00 0x00 ... 0x00 */
  K = gcry_calloc (1, hlen);
  if (!K)
    {
      rc = gpg_err_code_from_syserror ();
      goto leave;
    }

  rc = int2octets (&x_buf, dsa_x, (qbits+7)/8);
  if (rc)
    goto leave;

  rc = bits2octets (&h1_buf, h1, hlen*8, dsa_q, qbits);
  if (rc)
    goto leave;

  /* Create a handle to compute the HMACs.  */
  rc = gpg_err_code (gcry_md_open (&hd, halgo,
                                   (GCRY_MD_FLAG_SECURE | GCRY_MD_FLAG_HMAC)));
  if (rc)
    goto leave;

  /* Step d:  K = HMAC_K(V || 0x00 || int2octets(x) || bits2octets(h1) */
  rc = gpg_err_code (gcry_md_setkey (hd, K, hlen));
  if (rc)
    goto leave;
  gcry_md_write (hd, V, hlen);
  gcry_md_write (hd, "", 1);
  gcry_md_write (hd, x_buf, (qbits+7)/8);
  gcry_md_write (hd, h1_buf, (qbits+7)/8);
  memcpy (K, gcry_md_read (hd, 0), hlen);

  /* Step e:  V = HMAC_K(V) */
  rc = gpg_err_code (gcry_md_setkey (hd, K, hlen));
  if (rc)
    goto leave;
  gcry_md_write (hd, V, hlen);
  memcpy (V, gcry_md_read (hd, 0), hlen);

  /* Step f:  K = HMAC_K(V || 0x01 || int2octets(x) || bits2octets(h1) */
  rc = gpg_err_code (gcry_md_setkey (hd, K, hlen));
  if (rc)
    goto leave;
  gcry_md_write (hd, V, hlen);
  gcry_md_write (hd, "\x01", 1);
  gcry_md_write (hd, x_buf, (qbits+7)/8);
  gcry_md_write (hd, h1_buf, (qbits+7)/8);
  memcpy (K, gcry_md_read (hd, 0), hlen);

  /* Step g:  V = HMAC_K(V) */
  rc = gpg_err_code (gcry_md_setkey (hd, K, hlen));
  if (rc)
    goto leave;
  gcry_md_write (hd, V, hlen);
  memcpy (V, gcry_md_read (hd, 0), hlen);

  /* Step h. */
  t = gcry_malloc ((qbits+7)/8+hlen);
  if (!t)
    {
      rc = gpg_err_code_from_syserror ();
      goto leave;
    }

 again:
  for (tbits = 0; tbits < qbits;)
    {
      /* V = HMAC_K(V) */
      rc = gpg_err_code (gcry_md_setkey (hd, K, hlen));
      if (rc)
        goto leave;
      gcry_md_write (hd, V, hlen);
      memcpy (V, gcry_md_read (hd, 0), hlen);

      /* T = T || V */
      memcpy (t+(tbits+7)/8, V, hlen);
      tbits += 8*hlen;
    }

  /* k = bits2int (T) */
  mpi_free (k);
  k = NULL;
  rc = gpg_err_code (gcry_mpi_scan (&k, GCRYMPI_FMT_USG, t, (tbits+7)/8, NULL));
  if (rc)
    goto leave;
  if (tbits > qbits)
    gcry_mpi_rshift (k, k, tbits - qbits);

  /* Check: k < q and k > 1 */
  if (!(mpi_cmp (k, dsa_q) < 0 && mpi_cmp_ui (k, 0) > 0))
    {
      /* K = HMAC_K(V || 0x00) */
      rc = gpg_err_code (gcry_md_setkey (hd, K, hlen));
      if (rc)
        goto leave;
      gcry_md_write (hd, V, hlen);
      gcry_md_write (hd, "", 1);
      memcpy (K, gcry_md_read (hd, 0), hlen);

      /* V = HMAC_K(V) */
      rc = gpg_err_code (gcry_md_setkey (hd, K, hlen));
      if (rc)
        goto leave;
      gcry_md_write (hd, V, hlen);
      memcpy (V, gcry_md_read (hd, 0), hlen);

      goto again;
    }

  /* The caller may have requested that we introduce some extra loops.
     This is for example useful if the caller wants another value for
     K because the last returned one yielded an R of 0.  Becuase this
     is very unlikely we implement it in a straightforward way.  */
  if (extraloops)
    {
      extraloops--;

      /* K = HMAC_K(V || 0x00) */
      rc = gpg_err_code (gcry_md_setkey (hd, K, hlen));
      if (rc)
        goto leave;
      gcry_md_write (hd, V, hlen);
      gcry_md_write (hd, "", 1);
      memcpy (K, gcry_md_read (hd, 0), hlen);

      /* V = HMAC_K(V) */
      rc = gpg_err_code (gcry_md_setkey (hd, K, hlen));
      if (rc)
        goto leave;
      gcry_md_write (hd, V, hlen);
      memcpy (V, gcry_md_read (hd, 0), hlen);

      goto again;
    }

  /* log_mpidump ("  k", k); */

 leave:
  gcry_free (t);
  gcry_md_close (hd);
  gcry_free (h1_buf);
  gcry_free (x_buf);
  gcry_free (K);
  gcry_free (V);

  if (rc)
    mpi_free (k);
  else
    *r_k = k;
  return rc;
}
Exemple #4
0
/* Compute an ECDSA signature.
 * Return the signature struct (r,s) from the message hash.  The caller
 * must have allocated R and S.
 */
gpg_err_code_t
_gcry_ecc_ecdsa_sign (gcry_mpi_t input, ECC_secret_key *skey,
                      gcry_mpi_t r, gcry_mpi_t s,
                      int flags, int hashalgo)
{
  gpg_err_code_t err = 0;
  int extraloops = 0;
  gcry_mpi_t k, dr, sum, k_1, x;
  mpi_point_struct I;
  gcry_mpi_t hash;
  const void *abuf;
  unsigned int abits, qbits;
  mpi_ec_t ctx;

  if (DBG_CIPHER)
    log_mpidump ("ecdsa sign hash  ", input );

  qbits = mpi_get_nbits (skey->E.n);

  /* Convert the INPUT into an MPI if needed.  */
  if (mpi_is_opaque (input))
    {
      abuf = gcry_mpi_get_opaque (input, &abits);
      err = gpg_err_code (gcry_mpi_scan (&hash, GCRYMPI_FMT_USG,
                                         abuf, (abits+7)/8, NULL));
      if (err)
        return err;
      if (abits > qbits)
        gcry_mpi_rshift (hash, hash, abits - qbits);
    }
  else
    hash = input;


  k = NULL;
  dr = mpi_alloc (0);
  sum = mpi_alloc (0);
  k_1 = mpi_alloc (0);
  x = mpi_alloc (0);
  point_init (&I);

  ctx = _gcry_mpi_ec_p_internal_new (skey->E.model, skey->E.dialect,
                                     skey->E.p, skey->E.a, skey->E.b);

  /* Two loops to avoid R or S are zero.  This is more of a joke than
     a real demand because the probability of them being zero is less
     than any hardware failure.  Some specs however require it.  */
  do
    {
      do
        {
          mpi_free (k);
          k = NULL;
          if ((flags & PUBKEY_FLAG_RFC6979) && hashalgo)
            {
              /* Use Pornin's method for deterministic DSA.  If this
                 flag is set, it is expected that HASH is an opaque
                 MPI with the to be signed hash.  That hash is also
                 used as h1 from 3.2.a.  */
              if (!mpi_is_opaque (input))
                {
                  err = GPG_ERR_CONFLICT;
                  goto leave;
                }

              abuf = gcry_mpi_get_opaque (input, &abits);
              err = _gcry_dsa_gen_rfc6979_k (&k, skey->E.n, skey->d,
                                             abuf, (abits+7)/8,
                                             hashalgo, extraloops);
              if (err)
                goto leave;
              extraloops++;
            }
          else
            k = _gcry_dsa_gen_k (skey->E.n, GCRY_STRONG_RANDOM);

          _gcry_mpi_ec_mul_point (&I, k, &skey->E.G, ctx);
          if (_gcry_mpi_ec_get_affine (x, NULL, &I, ctx))
            {
              if (DBG_CIPHER)
                log_debug ("ecc sign: Failed to get affine coordinates\n");
              err = GPG_ERR_BAD_SIGNATURE;
              goto leave;
            }
          mpi_mod (r, x, skey->E.n);  /* r = x mod n */
        }
      while (!mpi_cmp_ui (r, 0));

      mpi_mulm (dr, skey->d, r, skey->E.n); /* dr = d*r mod n  */
      mpi_addm (sum, hash, dr, skey->E.n);  /* sum = hash + (d*r) mod n  */
      mpi_invm (k_1, k, skey->E.n);         /* k_1 = k^(-1) mod n  */
      mpi_mulm (s, k_1, sum, skey->E.n);    /* s = k^(-1)*(hash+(d*r)) mod n */
    }
  while (!mpi_cmp_ui (s, 0));

  if (DBG_CIPHER)
    {
      log_mpidump ("ecdsa sign result r ", r);
      log_mpidump ("ecdsa sign result s ", s);
    }

 leave:
  _gcry_mpi_ec_free (ctx);
  point_free (&I);
  mpi_free (x);
  mpi_free (k_1);
  mpi_free (sum);
  mpi_free (dr);
  mpi_free (k);

  if (hash != input)
    mpi_free (hash);

  return err;
}
static libspectrum_error
rzx_read_sign_end( libspectrum_rzx *rzx, const libspectrum_byte **ptr,
		   const libspectrum_byte *end )
{
  rzx_block_t *block;
  signature_block_t *signature;
  size_t length;

  /* Check we've got enough data for the length */
  if( end - (*ptr) < 4 ) {
    libspectrum_print_error( LIBSPECTRUM_ERROR_CORRUPT,
			     "rzx_read_sign_end: not enough data in buffer" );
    return LIBSPECTRUM_ERROR_CORRUPT;
  }

  /* Get the length; the -5 is because we've read the block ID and the length
     bytes */
  length = libspectrum_read_dword( ptr ) - 5;

  /* Check there's still enough data */
  if( end - (*ptr) < (ptrdiff_t)length ) {
    libspectrum_print_error( LIBSPECTRUM_ERROR_CORRUPT,
			     "rzx_read_sign_end: not enough data in buffer" );
    return LIBSPECTRUM_ERROR_CORRUPT;
  }

  block_alloc( &block, LIBSPECTRUM_RZX_SIGN_END_BLOCK );

  signature = &( block->types.signature );

  /* - 5 as we don't sign the block ID and length of this block */
  signature->length = ( *ptr - rzx->signed_start ) - 5;

#ifdef HAVE_GCRYPT_H
  { 
    gcry_error_t error; size_t mpi_length;

    error = gcry_mpi_scan( &signature->r, GCRYMPI_FMT_PGP, *ptr, length,
			   &mpi_length );
    if( error ) {
      libspectrum_print_error( LIBSPECTRUM_ERROR_CORRUPT,
			       "error reading 'r': %s",
			       gcry_strerror( error ) );
      libspectrum_free( block );
      return LIBSPECTRUM_ERROR_CORRUPT;
    }
    (*ptr) += mpi_length; length -= mpi_length;

    error = gcry_mpi_scan( &signature->s, GCRYMPI_FMT_PGP, *ptr, length,
			   &mpi_length );
    if( error ) {
      libspectrum_print_error( LIBSPECTRUM_ERROR_CORRUPT,
			       "error reading 's': %s",
			       gcry_strerror( error ) );
      gcry_mpi_release( signature->r );
      libspectrum_free( block );
      return LIBSPECTRUM_ERROR_CORRUPT;
    }
    (*ptr) += mpi_length; length -= mpi_length;

  }
#endif				/* #ifdef HAVE_GCRYPT_H */

  (*ptr) += length;

  rzx->blocks = g_slist_append( rzx->blocks, block );

  return LIBSPECTRUM_ERROR_NONE;
}
Exemple #6
0
static void
test_cmp (void)
{
  gpg_error_t rc;
  gcry_mpi_t zero, zero2;
  gcry_mpi_t one;
  gcry_mpi_t two;
  gcry_mpi_t all_ones;
  gcry_mpi_t opa1, opa2;
  gcry_mpi_t opa1s, opa2s;
  gcry_mpi_t opa0, opa02;

  zero = gcry_mpi_new (0);
  zero2= gcry_mpi_set_ui (NULL, 0);
  one  = gcry_mpi_set_ui (NULL, 1);
  two  = gcry_mpi_set_ui (NULL, 2);
  rc = gcry_mpi_scan (&all_ones, GCRYMPI_FMT_USG, ones, sizeof(ones), NULL);
  if (rc)
    die ("scanning number failed at line %d", __LINE__);
  opa0  = gcry_mpi_set_opaque (NULL, gcry_xstrdup ("a"), 0);
  opa02 = gcry_mpi_set_opaque (NULL, gcry_xstrdup ("b"), 0);
  opa1  = gcry_mpi_set_opaque (NULL, gcry_xstrdup ("aaaaaaaaaaaaaaaa"), 16*8);
  opa1s = gcry_mpi_set_opaque (NULL, gcry_xstrdup ("a"), 1*8);
  opa2  = gcry_mpi_set_opaque (NULL, gcry_xstrdup ("bbbbbbbbbbbbbbbb"), 16*8);
  opa2s = gcry_mpi_set_opaque (NULL, gcry_xstrdup ("b"), 1*8);


  /* Single limb test with cmp_ui */
  if (gcry_mpi_cmp_ui (zero, 0))
    fail ("mpi_cmp_ui failed at line %d", __LINE__);
  if (!(gcry_mpi_cmp_ui (zero, 1) < 0))
    fail ("mpi_cmp_ui failed at line %d", __LINE__);
  if (!(gcry_mpi_cmp_ui (zero, (-1)) < 0))
    fail ("mpi_cmp_ui failed at line %d", __LINE__);

  if (gcry_mpi_cmp_ui (two, 2))
    fail ("mpi_cmp_ui failed at line %d", __LINE__);
  if (!(gcry_mpi_cmp_ui (two, 3) < 0))
    fail ("mpi_cmp_ui failed at line %d", __LINE__);
  if (!(gcry_mpi_cmp_ui (two, 1) > 0))
    fail ("mpi_cmp_ui failed at line %d", __LINE__);

  /* Multi limb tests with cmp_ui.  */
  if (!(gcry_mpi_cmp_ui (all_ones, 0) > 0))
    fail ("mpi_cmp_ui failed at line %d", __LINE__);
  if (!(gcry_mpi_cmp_ui (all_ones, (-1)) > 0))
    fail ("mpi_cmp_ui failed at line %d", __LINE__);

  /* Single limb test with cmp */
  if (gcry_mpi_cmp (zero, zero2))
    fail ("mpi_cmp failed at line %d", __LINE__);
  if (!(gcry_mpi_cmp (zero, one) < 0))
    fail ("mpi_cmp failed at line %d", __LINE__);
  if (!(gcry_mpi_cmp (one, zero) > 0))
    fail ("mpi_cmp failed at line %d", __LINE__);

  gcry_mpi_neg (one, one);
  if (!(gcry_mpi_cmp (zero, one) > 0))
    fail ("mpi_cmp failed at line %d", __LINE__);
  if (!(gcry_mpi_cmp (one, zero) < 0))
    fail ("mpi_cmp failed at line %d", __LINE__);
  if (!(gcry_mpi_cmp (one, two) < 0))
    fail ("mpi_cmp failed at line %d", __LINE__);
  gcry_mpi_neg (one, one);

  if (!(gcry_mpi_cmp (one, two) < 0))
    fail ("mpi_cmp failed at line %d", __LINE__);
  if (!(gcry_mpi_cmp (two, one) > 0))
    fail ("mpi_cmp failed at line %d", __LINE__);
  if (!(gcry_mpi_cmp (one, all_ones) < 0))
    fail ("mpi_cmp failed at line %d", __LINE__);

  /* Tests with opaque values.  */
  if (!(gcry_mpi_cmp (opa1, one) < 0))
    fail ("mpi_cmp failed at line %d", __LINE__);
  if (!(gcry_mpi_cmp (one, opa1) > 0))
    fail ("mpi_cmp failed at line %d", __LINE__);
  if (!(gcry_mpi_cmp (opa0, opa02) == 0))
    fail ("mpi_cmp failed at line %d", __LINE__);
  if (!(gcry_mpi_cmp (opa1s, opa1) < 0))
    fail ("mpi_cmp failed at line %d", __LINE__);
  if (!(gcry_mpi_cmp (opa2, opa1s) > 0))
    fail ("mpi_cmp failed at line %d", __LINE__);
  if (!(gcry_mpi_cmp (opa1, opa2) < 0))
    fail ("mpi_cmp failed at line %d", __LINE__);
  if (!(gcry_mpi_cmp (opa2, opa1) > 0))
    fail ("mpi_cmp failed at line %d", __LINE__);
  if (!(gcry_mpi_cmp (opa1, opa1) == 0))
    fail ("mpi_cmp failed at line %d", __LINE__);


  gcry_mpi_release(opa2s);
  gcry_mpi_release(opa2);
  gcry_mpi_release(opa1s);
  gcry_mpi_release(opa1);
  gcry_mpi_release(opa02);
  gcry_mpi_release(opa0);
  gcry_mpi_release(all_ones);
  gcry_mpi_release(two);
  gcry_mpi_release(one);
  gcry_mpi_release(zero2);
  gcry_mpi_release(zero);
}
Exemple #7
0
/*
 * Parse the DER-encoded data at ps_data_der
 * saving the key in an S-expression
 */
int RSAKey::readDER( unsigned char const* ps_data_der, size_t length )
{
    struct tag_info tag_inf;
    gcry_mpi_t key_params[8];
    gcry_error_t err;
    int i;

    /* parse the ASN1 structure */
    if( parseTag( &ps_data_der, &length, &tag_inf )
            || tag_inf.tag != TAG_SEQUENCE || tag_inf.class_ || !tag_inf.cons || tag_inf.ndef )
        goto bad_asn1;
    if( parseTag( &ps_data_der, &length, &tag_inf )
       || tag_inf.tag != TAG_INTEGER || tag_inf.class_ || tag_inf.cons || tag_inf.ndef )
        goto bad_asn1;
    if( tag_inf.length != 1 || *ps_data_der )
        goto bad_asn1;  /* The value of the first integer is no 0. */
    ps_data_der += tag_inf.length;
    length -= tag_inf.length;

    for( i = 0; i < 8; i++ )
    {
        if( parseTag( &ps_data_der, &length, &tag_inf )
                || tag_inf.tag != TAG_INTEGER || tag_inf.class_ || tag_inf.cons || tag_inf.ndef )
            goto bad_asn1;
        err = gcry_mpi_scan( key_params + i, GCRYMPI_FMT_USG, ps_data_der, tag_inf.length, NULL );
        if( err )
        {
            msg_Err( this->p_demux, "error scanning RSA parameter %d: %s", i, gpg_strerror( err ) );
            goto error;
        }
        ps_data_der += tag_inf.length;
        length -= tag_inf.length;
    }

    /* Convert from OpenSSL parameter ordering to the OpenPGP order.
     * First check that p < q; if not swap p and q and recompute u.
     */
    if( gcry_mpi_cmp( key_params[3], key_params[4] ) > 0 )
    {
        gcry_mpi_swap( key_params[3], key_params[4] );
        gcry_mpi_invm( key_params[7], key_params[3], key_params[4] );
    }

    /* Build the S-expression.  */
    err = gcry_sexp_build( & this->priv_key, NULL,
                         "(private-key(rsa(n%m)(e%m)(d%m)(p%m)(q%m)(u%m)))",
                         key_params[0], key_params[1], key_params[2],
                         key_params[3], key_params[4], key_params[7] );
    if( err )
    {
        msg_Err( this->p_demux, "error building S-expression: %s", gpg_strerror( err ) );
        goto error;
    }

    /* clear data */
    for( i = 0; i < 8; i++ )
        gcry_mpi_release( key_params[i] );
    return VLC_SUCCESS;

bad_asn1:
    msg_Err( this->p_demux, "could not parse ASN1 structure; key might be corrupted" );

error:
    for( i = 0; i < 8; i++ )
        gcry_mpi_release( key_params[i] );
    return VLC_EGENERIC;
}
Exemple #8
0
unsigned char *crypto_decrypt_signature(crypto_ctx *ctx,
                                        const unsigned char *sig_data,
                                        size_t sig_len,
                                        size_t *out_len,
                                        unsigned int padding,
                                        crypto_error **error)
{
    unsigned char *buf = NULL, *rec_hash = NULL;
    gnutls_datum_t n = { NULL, 0 }, e = { NULL, 0 };
    int err, algo;
    gcry_sexp_t key = NULL, sig = NULL, decrypted = NULL, child = NULL;
    gcry_mpi_t n_mpi = NULL, e_mpi = NULL, sig_mpi = NULL, dec_mpi = NULL;
    size_t buf_len = 0, hash_len = 0;

    if (!ctx) {
        crypto_error_set(error, 1, 0, "invalid crypto context");
        return NULL;
    }

    if (!ctx->num) {
        crypto_error_set(error, 1, 0, "no certificates in the stack");
        return NULL;
    }

    algo = gnutls_x509_crt_get_pk_algorithm(ctx->stack[ctx->num - 1], NULL);
    if (algo != GNUTLS_PK_RSA) {
        crypto_error_set(error, 1, 0, "certificate public key algorithm not RSA");
        return NULL;
    }

    err = gnutls_x509_crt_get_pk_rsa_raw(ctx->stack[ctx->num - 1], &n, &e);
    if (err != GNUTLS_E_SUCCESS) {
        crypto_error_set(error, 1, 0, "error getting certificate public key");
        return NULL;
    }

    err = gcry_mpi_scan(&n_mpi, GCRYMPI_FMT_USG, n.data, n.size, NULL);
    if (err) {
        crypto_error_set(error, 1, 0, "invalid RSA key 'n' format");
        goto out;
    }

    err = gcry_mpi_scan(&e_mpi, GCRYMPI_FMT_USG, e.data, e.size, NULL);
    if (err) {
        crypto_error_set(error, 1, 0, "invalid RSA key 'e' format");
        goto out;
    }

    err = gcry_sexp_build(&key, NULL, "(public-key (rsa (n %m) (e %m)))", n_mpi, e_mpi);
    if (err) {
        crypto_error_set(error, 1, 0, "could not create public-key expression");
        goto out;
    }

    err = gcry_mpi_scan(&sig_mpi, GCRYMPI_FMT_USG, sig_data, sig_len, NULL);
    if (err) {
        crypto_error_set(error, 1, 0, "invalid signature format");
        goto out;
    }

    err = gcry_sexp_build(&sig, NULL, "(data (flags raw) (value %m))", sig_mpi);
    if (err) {
        crypto_error_set(error, 1, 0, "could not create signature expression");
        goto out;
    }

    /* encrypt is equivalent to public key decryption for RSA keys */
    err = gcry_pk_encrypt(&decrypted, sig, key);
    if (err) {
        crypto_error_set(error, 1, 0, "could not decrypt signature");
        goto out;
    }

    child = gcry_sexp_find_token(decrypted, "a", 1);
    if (!child) {
        crypto_error_set(error, 1, 0, "could not get decrypted signature result");
        goto out;
    }

    dec_mpi = gcry_sexp_nth_mpi(child, 1, GCRYMPI_FMT_USG);
    gcry_sexp_release(child);

    if (!dec_mpi) {
        crypto_error_set(error, 1, 0, "could not get decrypted signature result");
        goto out;
    }

    gcry_mpi_aprint(GCRYMPI_FMT_USG, &buf, &buf_len, dec_mpi);
    if (!buf) {
        crypto_error_set(error, 1, 0, "could not get extract decrypted signature");
        goto out;
    }

    switch (padding) {
    case CRYPTO_PAD_NONE:
        rec_hash = buf;
        hash_len = buf_len;
        buf = NULL;
        *out_len = (int) hash_len;
        break;
    case CRYPTO_PAD_PKCS1:
        rec_hash = check_pkcs1_padding(buf, buf_len, &hash_len, error);
        if (!rec_hash) {
            crypto_error_set(error, 1, 0, "could not get extract decrypted padded signature");
            goto out;
        }
        *out_len = (int) hash_len;
        break;
    default:
        crypto_error_set(error, 1, 0, "unknown padding mechanism %d", padding);
        break;
    }

out:
    if (buf)
        free(buf);
    if (dec_mpi)
        gcry_mpi_release(dec_mpi);
    if (decrypted)
        gcry_sexp_release(decrypted);
    if (key)
        gcry_sexp_release(key);
    if (sig)
        gcry_sexp_release(sig);
    if (sig_mpi)
        gcry_mpi_release(sig_mpi);
    if (n_mpi)
        gcry_mpi_release(n_mpi);
    if (e_mpi)
        gcry_mpi_release(e_mpi);
    if (n.data)
        gcry_free(n.data);
    if (e.data)
        gcry_free(e.data);

    return rec_hash;
}
Exemple #9
0
char *
irc_sasl_mechanism_dh_blowfish (const char *data_base64,
                                const char *sasl_username,
                                const char *sasl_password)
{
    char *data, *answer, *ptr_answer, *answer_base64;
    unsigned char *ptr_data, *secret_bin, *public_bin;
    unsigned char *password_clear, *password_crypted;
    int length_data, size, num_bits_prime_number, length_key;
    int length_username, length_password, length_answer;
    size_t num_written;
    gcry_mpi_t data_prime_number, data_generator_number, data_server_pub_key;
    gcry_mpi_t pub_key, priv_key, secret_mpi;
    gcry_cipher_hd_t gcrypt_handle;

    data = NULL;
    secret_bin = NULL;
    public_bin = NULL;
    password_clear = NULL;
    password_crypted = NULL;
    answer = NULL;
    answer_base64 = NULL;
    data_prime_number = NULL;
    data_generator_number = NULL;
    data_server_pub_key = NULL;
    pub_key = NULL;
    priv_key = NULL;
    secret_mpi = NULL;

    /* decode data */
    data = malloc (strlen (data_base64) + 1);
    length_data = weechat_string_decode_base64 (data_base64, data);
    ptr_data = (unsigned char *)data;

    /* extract prime number */
    size = ntohs ((((unsigned int)ptr_data[1]) << 8) | ptr_data[0]);
    ptr_data += 2;
    length_data -= 2;
    if (size > length_data)
        goto end;
    data_prime_number = gcry_mpi_new (size * 8);
    gcry_mpi_scan (&data_prime_number, GCRYMPI_FMT_USG, ptr_data, size, NULL);
    num_bits_prime_number = gcry_mpi_get_nbits (data_prime_number);
    ptr_data += size;
    length_data -= size;

    /* extract generator number */
    size = ntohs ((((unsigned int)ptr_data[1]) << 8) | ptr_data[0]);
    ptr_data += 2;
    length_data -= 2;
    if (size > length_data)
        goto end;
    data_generator_number = gcry_mpi_new (size * 8);
    gcry_mpi_scan (&data_generator_number, GCRYMPI_FMT_USG, ptr_data, size, NULL);
    ptr_data += size;
    length_data -= size;

    /* extract server-generated public key */
    size = ntohs ((((unsigned int)ptr_data[1]) << 8) | ptr_data[0]);
    ptr_data += 2;
    length_data -= 2;
    if (size > length_data)
        goto end;
    data_server_pub_key = gcry_mpi_new (size * 8);
    gcry_mpi_scan (&data_server_pub_key, GCRYMPI_FMT_USG, ptr_data, size, NULL);

    /* generate keys */
    pub_key = gcry_mpi_new (num_bits_prime_number);
    priv_key = gcry_mpi_new (num_bits_prime_number);
    gcry_mpi_randomize (priv_key, num_bits_prime_number, GCRY_STRONG_RANDOM);
    /* pub_key = (g ^ priv_key) % p */
    gcry_mpi_powm (pub_key, data_generator_number, priv_key, data_prime_number);

    /* compute secret_bin */
    length_key = num_bits_prime_number / 8;
    secret_bin = malloc (length_key);
    secret_mpi = gcry_mpi_new (num_bits_prime_number);
    /* secret_mpi = (y ^ priv_key) % p */
    gcry_mpi_powm (secret_mpi, data_server_pub_key, priv_key, data_prime_number);
    gcry_mpi_print (GCRYMPI_FMT_USG, secret_bin, length_key,
                    &num_written, secret_mpi);

    /* create public_bin */
    public_bin = malloc (length_key);
    gcry_mpi_print (GCRYMPI_FMT_USG, public_bin, length_key,
                    &num_written, pub_key);

    /* create password buffers (clear and crypted) */
    length_password = strlen (sasl_password) +
        ((8 - (strlen (sasl_password) % 8)) % 8);
    password_clear = malloc (length_password);
    password_crypted = malloc (length_password);
    memset (password_clear, 0, length_password);
    memset (password_crypted, 0, length_password);
    memcpy (password_clear, sasl_password, strlen (sasl_password));

    /* crypt password using blowfish */
    if (gcry_cipher_open (&gcrypt_handle, GCRY_CIPHER_BLOWFISH,
                          GCRY_CIPHER_MODE_ECB, 0) != 0)
        goto end;
    if (gcry_cipher_setkey (gcrypt_handle, secret_bin, length_key) != 0)
        goto end;
    if (gcry_cipher_encrypt (gcrypt_handle,
                             password_crypted, length_password,
                             password_clear, length_password) != 0)
        goto end;

    /*
     * build answer for server, it is concatenation of:
     *   1. key length (2 bytes)
     *   2. public key ('length_key' bytes)
     *   3. sasl_username ('length_username'+1 bytes)
     *   4. encrypted password ('length_password' bytes)
     */
    length_username = strlen (sasl_username);
    length_answer = 2 + length_key + length_username + 1 + length_password;
    answer = malloc (length_answer);
    ptr_answer = answer;
    *((unsigned int *)ptr_answer) = htons(length_key);
    ptr_answer += 2;
    memcpy (ptr_answer, public_bin, length_key);
    ptr_answer += length_key;
    memcpy (ptr_answer, sasl_username, length_username + 1);
    ptr_answer += length_username + 1;
    memcpy (ptr_answer, password_crypted, length_password);

    /* encode answer to base64 */
    answer_base64 = malloc (length_answer * 4);
    if (answer_base64)
        weechat_string_encode_base64 (answer, length_answer, answer_base64);

end:
    if (data)
        free (data);
    if (secret_bin)
        free (secret_bin);
    if (public_bin)
        free (public_bin);
    if (password_clear)
        free (password_clear);
    if (password_crypted)
        free (password_crypted);
    if (answer)
        free (answer);
    if (data_prime_number)
        gcry_mpi_release (data_prime_number);
    if (data_generator_number)
        gcry_mpi_release (data_generator_number);
    if (data_server_pub_key)
        gcry_mpi_release (data_server_pub_key);
    if (pub_key)
        gcry_mpi_release (pub_key);
    if (priv_key)
        gcry_mpi_release (priv_key);
    if (secret_mpi)
        gcry_mpi_release (secret_mpi);

    return answer_base64;
}
Exemple #10
0
static void
check_x931_derived_key (int what)
{
  static struct {
    const char *param;
    const char *expected_d;
  } testtable[] = {
    { /* First example from X9.31 (D.1.1).  */
      "(genkey\n"
      "  (rsa\n"
      "    (nbits 4:1024)\n"
      "    (rsa-use-e 1:3)\n"
      "    (derive-parms\n"
      "      (Xp1 #1A1916DDB29B4EB7EB6732E128#)\n"
      "      (Xp2 #192E8AAC41C576C822D93EA433#)\n"
      "      (Xp  #D8CD81F035EC57EFE822955149D3BFF70C53520D\n"
      "            769D6D76646C7A792E16EBD89FE6FC5B605A6493\n"
      "            39DFC925A86A4C6D150B71B9EEA02D68885F5009\n"
      "            B98BD984#)\n"
      "      (Xq1 #1A5CF72EE770DE50CB09ACCEA9#)\n"
      "      (Xq2 #134E4CAA16D2350A21D775C404#)\n"
      "      (Xq  #CC1092495D867E64065DEE3E7955F2EBC7D47A2D\n"
      "            7C9953388F97DDDC3E1CA19C35CA659EDC2FC325\n"
      "            6D29C2627479C086A699A49C4C9CEE7EF7BD1B34\n"
      "            321DE34A#))))\n",
      "1CCDA20BCFFB8D517EE9666866621B11822C7950D55F4BB5BEE37989A7D173"
      "12E326718BE0D79546EAAE87A56623B919B1715FFBD7F16028FC4007741961"
      "C88C5D7B4DAAAC8D36A98C9EFBB26C8A4A0E6BC15B358E528A1AC9D0F042BE"
      "B93BCA16B541B33F80C933A3B769285C462ED5677BFE89DF07BED5C127FD13"
      "241D3C4B"
    },

    { /* Second example from X9.31 (D.2.1).  */
      "(genkey\n"
      "  (rsa\n"
      "    (nbits 4:1536)\n"
      "    (rsa-use-e 1:3)\n"
      "    (derive-parms\n"
      "      (Xp1 #18272558B61316348297EACA74#)\n"
      "      (Xp2 #1E970E8C6C97CEF91F05B0FA80#)\n"
      "      (Xp  #F7E943C7EF2169E930DCF23FE389EF7507EE8265\n"
      "            0D42F4A0D3A3CEFABE367999BB30EE680B2FE064\n"
      "            60F707F46005F8AA7CBFCDDC4814BBE7F0F8BC09\n"
      "            318C8E51A48D134296E40D0BBDD282DCCBDDEE1D\n"
      "            EC86F0B1C96EAFF5CDA70F9AEB6EE31E#)\n"
      "      (Xq1 #11FDDA6E8128DC1629F75192BA#)\n"
      "      (Xq2 #18AB178ECA907D72472F65E480#)\n"
      "      (Xq  #C47560011412D6E13E3E7D007B5C05DBF5FF0D0F\n"
      "            CFF1FA2070D16C7ABA93EDFB35D8700567E5913D\n"
      "            B734E3FBD15862EBC59FA0425DFA131E549136E8\n"
      "            E52397A8ABE4705EC4877D4F82C4AAC651B33DA6\n"
      "            EA14B9D5F2A263DC65626E4D6CEAC767#))))\n",
      "1FB56069985F18C4519694FB71055721A01F14422DC901C35B03A64D4A5BD1"
      "259D573305F5B056AC931B82EDB084E39A0FD1D1A86CC5B147A264F7EF4EB2"
      "0ED1E7FAAE5CAE4C30D5328B7F74C3CAA72C88B70DED8EDE207B8629DA2383"
      "B78C3CE1CA3F9F218D78C938B35763AF2A8714664CC57F5CECE2413841F5E9"
      "EDEC43B728E25A41BF3E1EF8D9EEE163286C9F8BF0F219D3B322C3E4B0389C"
      "2E8BB28DC04C47DA2BF38823731266D2CF6CC3FC181738157624EF051874D0"
      "BBCCB9F65C83"
      /* Note that this example in X9.31 gives this value for D:

        "7ED581A6617C6311465A53EDC4155C86807C5108B724070D6C0E9935296F44"
        "96755CCC17D6C15AB24C6E0BB6C2138E683F4746A1B316C51E8993DFBD3AC8"
        "3B479FEAB972B930C354CA2DFDD30F2A9CB222DC37B63B7881EE18A7688E0E"
        "DE30F38728FE7C8635E324E2CD5D8EBCAA1C51993315FD73B38904E107D7A7"
        "B7B10EDCA3896906FCF87BE367BB858CA1B27E2FC3C8674ECC8B0F92C0E270"
        "BA2ECA3701311F68AFCE208DCC499B4B3DB30FF0605CE055D893BC1461D342"
        "EF32E7D9720B"

        This is a bug in X9.31, obviously introduced by using

           d = e^{-1} mod (p-1)(q-1)

         instead of using the universal exponent as required by 4.1.3:

           d = e^{-1} mod lcm(p-1,q-1)

         The examples in X9.31 seem to be pretty buggy, see
         cipher/primegen.c for another bug.  Not only that I had to
         spend 100 USD for the 66 pages of the document, it also took
         me several hours to figure out that the bugs are in the
         document and not in my code.
       */
    },

    { /* First example from NIST RSAVS (B.1.1).  */
      "(genkey\n"
      "  (rsa\n"
      "    (nbits 4:1024)\n"
      "    (rsa-use-e 1:3)\n"
      "    (derive-parms\n"
      "      (Xp1 #1ed3d6368e101dab9124c92ac8#)\n"
      "      (Xp2 #16e5457b8844967ce83cab8c11#)\n"
      "      (Xp  #b79f2c2493b4b76f329903d7555b7f5f06aaa5ea\n"
      "            ab262da1dcda8194720672a4e02229a0c71f60ae\n"
      "            c4f0d2ed8d49ef583ca7d5eeea907c10801c302a\n"
      "            cab44595#)\n"
      "      (Xq1 #1a5d9e3fa34fb479bedea412f6#)\n"
      "      (Xq2 #1f9cca85f185341516d92e82fd#)\n"
      "      (Xq  #c8387fd38fa33ddcea6a9de1b2d55410663502db\n"
      "            c225655a9310cceac9f4cf1bce653ec916d45788\n"
      "            f8113c46bc0fa42bf5e8d0c41120c1612e2ea8bb\n"
      "            2f389eda#))))\n",
      "17ef7ad4fd96011b62d76dfb2261b4b3270ca8e07bc501be954f8719ef586b"
      "f237e8f693dd16c23e7adecc40279dc6877c62ab541df5849883a5254fccfd"
      "4072a657b7f4663953930346febd6bbd82f9a499038402cbf97fd5f068083a"
      "c81ad0335c4aab0da19cfebe060a1bac7482738efafea078e21df785e56ea0"
      "dc7e8feb"
    },

    { /* Second example from NIST RSAVS (B.1.1).  */
      "(genkey\n"
      "  (rsa\n"
      "    (nbits 4:1536)\n"
      "    (rsa-use-e 1:3)\n"
      "    (derive-parms\n"
      "      (Xp1 #1e64c1af460dff8842c22b64d0#)\n"
      "      (Xp2 #1e948edcedba84039c81f2ac0c#)\n"
      "      (Xp  #c8c67df894c882045ede26a9008ab09ea0672077\n"
      "            d7bc71d412511cd93981ddde8f91b967da404056\n"
      "            c39f105f7f239abdaff92923859920f6299e82b9\n"
      "            5bd5b8c959948f4a034d81613d6235a3953b49ce\n"
      "            26974eb7bb1f14843841281b363b9cdb#)\n"
      "      (Xq1 #1f3df0f017ddd05611a97b6adb#)\n"
      "      (Xq2 #143edd7b22d828913abf24ca4d#)\n"
      "      (Xq  #f15147d0e7c04a1e3f37adde802cdc610999bf7a\n"
      "            b0088434aaeda0c0ab3910b14d2ce56cb66bffd9\n"
      "            7552195fae8b061077e03920814d8b9cfb5a3958\n"
      "            b3a82c2a7fc97e55db543948d3396289245336ec\n"
      "            9e3cb308cc655aebd766340da8921383#))))\n",
      "1f8b19f3f5f2ac9fc599f110cad403dcd9bdf5f7f00fb2790e78e820398184"
      "1f3fb3dd230fb223d898f45719d9b2d3525587ff2b8bcc7425e40550a5b536"
      "1c8e9c1d26e83fbd9c33c64029c0e878b829d55def12912b73d94fd758c461"
      "0f473e230c41b5e4c86e27c5a5029d82c811c88525d0269b95bd2ff272994a"
      "dbd80f2c2ecf69065feb8abd8b445b9c6d306b1585d7d3d7576d49842bc7e2"
      "8b4a2f88f4a47e71c3edd35fdf83f547ea5c2b532975c551ed5268f748b2c4"
      "2ccf8a84835b"
    }
  };
  gpg_error_t err;
  gcry_sexp_t key_spec, key, pub_key, sec_key;
  gcry_mpi_t d_expected, d_have;

  if (what < 0 && what >= sizeof testtable)
    die ("invalid WHAT value\n");

  err = gcry_sexp_new (&key_spec, testtable[what].param, 0, 1);
  if (err)
    die ("error creating S-expression [%d]: %s\n", what, gpg_strerror (err));

  err = gcry_pk_genkey (&key, key_spec);
  gcry_sexp_release (key_spec);
  if (err)
    die ("error generating RSA key [%d]: %s\n", what, gpg_strerror (err));

  pub_key = gcry_sexp_find_token (key, "public-key", 0);
  if (!pub_key)
    die ("public part missing in key [%d]\n", what);

  sec_key = gcry_sexp_find_token (key, "private-key", 0);
  if (!sec_key)
    die ("private part missing in key [%d]\n", what);

  err = gcry_mpi_scan
    (&d_expected, GCRYMPI_FMT_HEX, testtable[what].expected_d, 0, NULL);
  if (err)
    die ("error converting string [%d]\n", what);

  if (verbose > 1)
    show_sexp ("generated key:\n", key);

  d_have = key_param_from_sexp (sec_key, "rsa", "d");
  if (!d_have)
    die ("parameter d not found in RSA secret key [%d]\n", what);
  if (gcry_mpi_cmp (d_expected, d_have))
    {
      show_sexp (NULL, sec_key);
      die ("parameter d does match expected value [%d]\n", what);
    }
  gcry_mpi_release (d_expected);
  gcry_mpi_release (d_have);

  gcry_sexp_release (key);
  gcry_sexp_release (pub_key);
  gcry_sexp_release (sec_key);
}
Exemple #11
0
static gpg_error_t
get_it (PKT_pubkey_enc *enc, DEK *dek, PKT_public_key *sk, u32 *keyid)
{
  gpg_error_t err;
  byte *frame = NULL;
  unsigned int n;
  size_t nframe;
  u16 csum, csum2;
  int card = 0;
  gcry_sexp_t s_data;
  char *desc;
  char *keygrip;
  byte fp[MAX_FINGERPRINT_LEN];
  size_t fpn;
  const int pkalgo = map_pk_openpgp_to_gcry (sk->pubkey_algo);

  /* Get the keygrip.  */
  err = hexkeygrip_from_pk (sk, &keygrip);
  if (err)
    goto leave;

  /* Convert the data to an S-expression.  */
  if (pkalgo == GCRY_PK_ELG || pkalgo == GCRY_PK_ELG_E)
    {
      if (!enc->data[0] || !enc->data[1])
        err = gpg_error (GPG_ERR_BAD_MPI);
      else
        err = gcry_sexp_build (&s_data, NULL, "(enc-val(elg(a%m)(b%m)))",
                               enc->data[0], enc->data[1]);
    }
  else if (pkalgo == GCRY_PK_RSA || pkalgo == GCRY_PK_RSA_E)
    {
      if (!enc->data[0])
        err = gpg_error (GPG_ERR_BAD_MPI);
      else
        err = gcry_sexp_build (&s_data, NULL, "(enc-val(rsa(a%m)))",
                               enc->data[0]);
    }
  else if (pkalgo == GCRY_PK_ECDH)
    {
      if (!enc->data[0] || !enc->data[1])
        err = gpg_error (GPG_ERR_BAD_MPI);
      else
        err = gcry_sexp_build (&s_data, NULL, "(enc-val(ecdh(s%m)(e%m)))",
                               enc->data[0], enc->data[1]);
    }
  else
    err = gpg_error (GPG_ERR_BUG);

  if (err)
    goto leave;

  if (sk->pubkey_algo == PUBKEY_ALGO_ECDH)
    {
      fingerprint_from_pk (sk, fp, &fpn);
      assert (fpn == 20);
    }

  /* Decrypt. */
  desc = gpg_format_keydesc (sk, 0, 1);
  err = agent_pkdecrypt (NULL, keygrip, desc, s_data, &frame, &nframe);
  xfree (desc);
  gcry_sexp_release (s_data);
  if (err)
    goto leave;

  /* Now get the DEK (data encryption key) from the frame
   *
   * Old versions encode the DEK in in this format (msb is left):
   *
   *     0  1  DEK(16 bytes)  CSUM(2 bytes)  0  RND(n bytes) 2
   *
   * Later versions encode the DEK like this:
   *
   *     0  2  RND(n bytes)  0  A  DEK(k bytes)  CSUM(2 bytes)
   *
   * (mpi_get_buffer already removed the leading zero).
   *
   * RND are non-zero randow bytes.
   * A   is the cipher algorithm
   * DEK is the encryption key (session key) with length k
   * CSUM
   */
  if (DBG_CIPHER)
    log_printhex ("DEK frame:", frame, nframe);
  n = 0;

  if (sk->pubkey_algo == PUBKEY_ALGO_ECDH)
    {
      gcry_mpi_t shared_mpi;
      gcry_mpi_t decoded;

      /* At the beginning the frame are the bytes of shared point MPI.  */
      err = gcry_mpi_scan (&shared_mpi, GCRYMPI_FMT_USG, frame, nframe, NULL);
      if (err)
        {
          err = gpg_error (GPG_ERR_WRONG_SECKEY);
          goto leave;
        }

      err = pk_ecdh_decrypt (&decoded, fp, enc->data[1]/*encr data as an MPI*/,
                             shared_mpi, sk->pkey);
      mpi_release (shared_mpi);
      if(err)
        goto leave;

      /* Reuse NFRAME, which size is sufficient to include the session key.  */
      err = gcry_mpi_print (GCRYMPI_FMT_USG, frame, nframe, &nframe, decoded);
      mpi_release (decoded);
      if (err)
        goto leave;

      /* Now the frame are the bytes decrypted but padded session key.  */

      /* Allow double padding for the benefit of DEK size concealment.
         Higher than this is wasteful. */
      if (!nframe || frame[nframe-1] > 8*2 || nframe <= 8
          || frame[nframe-1] > nframe)
        {
          err = gpg_error (GPG_ERR_WRONG_SECKEY);
          goto leave;
        }
      nframe -= frame[nframe-1]; /* Remove padding.  */
      assert (!n); /* (used just below) */
    }
  else
    {
      if (!card)
        {
          if (n + 7 > nframe)
            {
              err = gpg_error (GPG_ERR_WRONG_SECKEY);
              goto leave;
            }
          if (frame[n] == 1 && frame[nframe - 1] == 2)
            {
              log_info (_("old encoding of the DEK is not supported\n"));
              err = gpg_error (GPG_ERR_CIPHER_ALGO);
              goto leave;
            }
          if (frame[n] != 2) /* Something went wrong.  */
            {
              err = gpg_error (GPG_ERR_WRONG_SECKEY);
              goto leave;
            }
          for (n++; n < nframe && frame[n]; n++) /* Skip the random bytes.  */
            ;
          n++; /* Skip the zero byte.  */
        }
    }

  if (n + 4 > nframe)
    {
      err = gpg_error (GPG_ERR_WRONG_SECKEY);
      goto leave;
    }

  dek->keylen = nframe - (n + 1) - 2;
  dek->algo = frame[n++];
  if (dek->algo == CIPHER_ALGO_IDEA)
    write_status (STATUS_RSA_OR_IDEA);
  err = openpgp_cipher_test_algo (dek->algo);
  if (err)
    {
      if (!opt.quiet && gpg_err_code (err) == GPG_ERR_CIPHER_ALGO)
        {
          log_info (_("cipher algorithm %d%s is unknown or disabled\n"),
                    dek->algo,
                    dek->algo == CIPHER_ALGO_IDEA ? " (IDEA)" : "");
          if (dek->algo == CIPHER_ALGO_IDEA)
            idea_cipher_warn (0);
        }
      dek->algo = 0;
      goto leave;
    }
  if (dek->keylen != openpgp_cipher_get_algo_keylen (dek->algo))
    {
      err = gpg_error (GPG_ERR_WRONG_SECKEY);
      goto leave;
    }

  /* Copy the key to DEK and compare the checksum.  */
  csum = frame[nframe - 2] << 8;
  csum |= frame[nframe - 1];
  memcpy (dek->key, frame + n, dek->keylen);
  for (csum2 = 0, n = 0; n < dek->keylen; n++)
    csum2 += dek->key[n];
  if (csum != csum2)
    {
      err = gpg_error (GPG_ERR_WRONG_SECKEY);
      goto leave;
    }
  if (DBG_CIPHER)
    log_printhex ("DEK is:", dek->key, dek->keylen);

  /* Check that the algo is in the preferences and whether it has expired.  */
  {
    PKT_public_key *pk = NULL;
    KBNODE pkb = get_pubkeyblock (keyid);

    if (!pkb)
      {
        err = -1;
        log_error ("oops: public key not found for preference check\n");
      }
    else if (pkb->pkt->pkt.public_key->selfsigversion > 3
             && dek->algo != CIPHER_ALGO_3DES
             && !opt.quiet
             && !is_algo_in_prefs (pkb, PREFTYPE_SYM, dek->algo))
      log_info (_("WARNING: cipher algorithm %s not found in recipient"
                  " preferences\n"), openpgp_cipher_algo_name (dek->algo));
    if (!err)
      {
        KBNODE k;

        for (k = pkb; k; k = k->next)
          {
            if (k->pkt->pkttype == PKT_PUBLIC_KEY
                || k->pkt->pkttype == PKT_PUBLIC_SUBKEY)
              {
                u32 aki[2];
                keyid_from_pk (k->pkt->pkt.public_key, aki);

                if (aki[0] == keyid[0] && aki[1] == keyid[1])
                  {
                    pk = k->pkt->pkt.public_key;
                    break;
                  }
              }
          }
        if (!pk)
          BUG ();
        if (pk->expiredate && pk->expiredate <= make_timestamp ())
          {
            log_info (_("NOTE: secret key %s expired at %s\n"),
                      keystr (keyid), asctimestamp (pk->expiredate));
          }
      }

    if (pk && pk->flags.revoked)
      {
        log_info (_("NOTE: key has been revoked"));
        log_printf ("\n");
        show_revocation_reason (pk, 1);
      }

    release_kbnode (pkb);
    err = 0;
  }

 leave:
  xfree (frame);
  xfree (keygrip);
  return err;
}
Exemple #12
0
static gpg_error_t
get_it (ctrl_t ctrl,
        PKT_pubkey_enc *enc, DEK *dek, PKT_public_key *sk, u32 *keyid)
{
  gpg_error_t err;
  byte *frame = NULL;
  unsigned int n;
  size_t nframe;
  u16 csum, csum2;
  int padding;
  gcry_sexp_t s_data;
  char *desc;
  char *keygrip;
  byte fp[MAX_FINGERPRINT_LEN];
  size_t fpn;

  if (DBG_CLOCK)
    log_clock ("decryption start");

  /* Get the keygrip.  */
  err = hexkeygrip_from_pk (sk, &keygrip);
  if (err)
    goto leave;

  /* Convert the data to an S-expression.  */
  if (sk->pubkey_algo == PUBKEY_ALGO_ELGAMAL
      || sk->pubkey_algo == PUBKEY_ALGO_ELGAMAL_E)
    {
      if (!enc->data[0] || !enc->data[1])
        err = gpg_error (GPG_ERR_BAD_MPI);
      else
        err = gcry_sexp_build (&s_data, NULL, "(enc-val(elg(a%m)(b%m)))",
                               enc->data[0], enc->data[1]);
    }
  else if (sk->pubkey_algo == PUBKEY_ALGO_RSA
           || sk->pubkey_algo == PUBKEY_ALGO_RSA_E)
    {
      if (!enc->data[0])
        err = gpg_error (GPG_ERR_BAD_MPI);
      else
        err = gcry_sexp_build (&s_data, NULL, "(enc-val(rsa(a%m)))",
                               enc->data[0]);
    }
  else if (sk->pubkey_algo == PUBKEY_ALGO_ECDH)
    {
      if (!enc->data[0] || !enc->data[1])
        err = gpg_error (GPG_ERR_BAD_MPI);
      else
        err = gcry_sexp_build (&s_data, NULL, "(enc-val(ecdh(s%m)(e%m)))",
                               enc->data[1], enc->data[0]);
    }
  else
    err = gpg_error (GPG_ERR_BUG);

  if (err)
    goto leave;

  if (sk->pubkey_algo == PUBKEY_ALGO_ECDH)
    {
      fingerprint_from_pk (sk, fp, &fpn);
      log_assert (fpn == 20);
    }

  /* Decrypt. */
  desc = gpg_format_keydesc (ctrl, sk, FORMAT_KEYDESC_NORMAL, 1);
  err = agent_pkdecrypt (NULL, keygrip,
                         desc, sk->keyid, sk->main_keyid, sk->pubkey_algo,
                         s_data, &frame, &nframe, &padding);
  xfree (desc);
  gcry_sexp_release (s_data);
  if (err)
    goto leave;

  /* Now get the DEK (data encryption key) from the frame
   *
   * Old versions encode the DEK in this format (msb is left):
   *
   *     0  1  DEK(16 bytes)  CSUM(2 bytes)  0  RND(n bytes) 2
   *
   * Later versions encode the DEK like this:
   *
   *     0  2  RND(n bytes)  0  A  DEK(k bytes)  CSUM(2 bytes)
   *
   * (mpi_get_buffer already removed the leading zero).
   *
   * RND are non-zero randow bytes.
   * A   is the cipher algorithm
   * DEK is the encryption key (session key) with length k
   * CSUM
   */
  if (DBG_CRYPTO)
    log_printhex (frame, nframe, "DEK frame:");
  n = 0;

  if (sk->pubkey_algo == PUBKEY_ALGO_ECDH)
    {
      gcry_mpi_t shared_mpi;
      gcry_mpi_t decoded;

      /* At the beginning the frame are the bytes of shared point MPI.  */
      err = gcry_mpi_scan (&shared_mpi, GCRYMPI_FMT_USG, frame, nframe, NULL);
      if (err)
        {
          err = gpg_error (GPG_ERR_WRONG_SECKEY);
          goto leave;
        }

      err = pk_ecdh_decrypt (&decoded, fp, enc->data[1]/*encr data as an MPI*/,
                             shared_mpi, sk->pkey);
      mpi_release (shared_mpi);
      if(err)
        goto leave;

      xfree (frame);
      err = gcry_mpi_aprint (GCRYMPI_FMT_USG, &frame, &nframe, decoded);
      mpi_release (decoded);
      if (err)
        goto leave;

      /* Now the frame are the bytes decrypted but padded session key.  */

      /* Allow double padding for the benefit of DEK size concealment.
         Higher than this is wasteful. */
      if (!nframe || frame[nframe-1] > 8*2 || nframe <= 8
          || frame[nframe-1] > nframe)
        {
          err = gpg_error (GPG_ERR_WRONG_SECKEY);
          goto leave;
        }
      nframe -= frame[nframe-1]; /* Remove padding.  */
      log_assert (!n); /* (used just below) */
    }
  else
    {
      if (padding)
        {
          if (n + 7 > nframe)
            {
              err = gpg_error (GPG_ERR_WRONG_SECKEY);
              goto leave;
            }
          if (frame[n] == 1 && frame[nframe - 1] == 2)
            {
              log_info (_("old encoding of the DEK is not supported\n"));
              err = gpg_error (GPG_ERR_CIPHER_ALGO);
              goto leave;
            }
          if (frame[n] != 2) /* Something went wrong.  */
            {
              err = gpg_error (GPG_ERR_WRONG_SECKEY);
              goto leave;
            }
          for (n++; n < nframe && frame[n]; n++) /* Skip the random bytes.  */
            ;
          n++; /* Skip the zero byte.  */
        }
    }

  if (n + 4 > nframe)
    {
      err = gpg_error (GPG_ERR_WRONG_SECKEY);
      goto leave;
    }

  dek->keylen = nframe - (n + 1) - 2;
  dek->algo = frame[n++];
  err = openpgp_cipher_test_algo (dek->algo);
  if (err)
    {
      if (!opt.quiet && gpg_err_code (err) == GPG_ERR_CIPHER_ALGO)
        {
          log_info (_("cipher algorithm %d%s is unknown or disabled\n"),
                    dek->algo,
                    dek->algo == CIPHER_ALGO_IDEA ? " (IDEA)" : "");
        }
      dek->algo = 0;
      goto leave;
    }
  if (dek->keylen != openpgp_cipher_get_algo_keylen (dek->algo))
    {
      err = gpg_error (GPG_ERR_WRONG_SECKEY);
      goto leave;
    }

  /* Copy the key to DEK and compare the checksum.  */
  csum = buf16_to_u16 (frame+nframe-2);
  memcpy (dek->key, frame + n, dek->keylen);
  for (csum2 = 0, n = 0; n < dek->keylen; n++)
    csum2 += dek->key[n];
  if (csum != csum2)
    {
      err = gpg_error (GPG_ERR_WRONG_SECKEY);
      goto leave;
    }
  if (DBG_CLOCK)
    log_clock ("decryption ready");
  if (DBG_CRYPTO)
    log_printhex (dek->key, dek->keylen, "DEK is:");

  /* Check that the algo is in the preferences and whether it has
   * expired.  Also print a status line with the key's fingerprint.  */
  {
    PKT_public_key *pk = NULL;
    PKT_public_key *mainpk = NULL;
    KBNODE pkb = get_pubkeyblock (ctrl, keyid);

    if (!pkb)
      {
        err = -1;
        log_error ("oops: public key not found for preference check\n");
      }
    else if (pkb->pkt->pkt.public_key->selfsigversion > 3
             && dek->algo != CIPHER_ALGO_3DES
             && !opt.quiet
             && !is_algo_in_prefs (pkb, PREFTYPE_SYM, dek->algo))
      log_info (_("WARNING: cipher algorithm %s not found in recipient"
                  " preferences\n"), openpgp_cipher_algo_name (dek->algo));

    if (!err)
      {
        kbnode_t k;
        int first = 1;

        for (k = pkb; k; k = k->next)
          {
            if (k->pkt->pkttype == PKT_PUBLIC_KEY
                || k->pkt->pkttype == PKT_PUBLIC_SUBKEY)
              {
                u32 aki[2];

                if (first)
                  {
                    first = 0;
                    mainpk = k->pkt->pkt.public_key;
                  }

                keyid_from_pk (k->pkt->pkt.public_key, aki);
                if (aki[0] == keyid[0] && aki[1] == keyid[1])
                  {
                    pk = k->pkt->pkt.public_key;
                    break;
                  }
              }
          }
        if (!pk)
          BUG ();
        if (pk->expiredate && pk->expiredate <= make_timestamp ())
          {
            log_info (_("Note: secret key %s expired at %s\n"),
                      keystr (keyid), asctimestamp (pk->expiredate));
          }
      }

    if (pk && pk->flags.revoked)
      {
        log_info (_("Note: key has been revoked"));
        log_printf ("\n");
        show_revocation_reason (ctrl, pk, 1);
      }

    if (is_status_enabled () && pk && mainpk)
      {
        char pkhex[MAX_FINGERPRINT_LEN*2+1];
        char mainpkhex[MAX_FINGERPRINT_LEN*2+1];

        hexfingerprint (pk, pkhex, sizeof pkhex);
        hexfingerprint (mainpk, mainpkhex, sizeof mainpkhex);

        /* Note that we do not want to create a trustdb just for
         * getting the ownertrust: If there is no trustdb there can't
         * be ulitmately trusted key anyway and thus the ownertrust
         * value is irrelevant.  */
        write_status_printf (STATUS_DECRYPTION_KEY, "%s %s %c",
                             pkhex, mainpkhex,
                             get_ownertrust_info (ctrl, mainpk, 1));

      }

    release_kbnode (pkb);
    err = 0;
  }

 leave:
  xfree (frame);
  xfree (keygrip);
  return err;
}
Exemple #13
0
static int
do_encode_md (gcry_md_hd_t md, int algo, int pkalgo, unsigned int nbits,
              gcry_sexp_t pkey, gcry_mpi_t *r_val)
{
  int n;
  size_t nframe;
  unsigned char *frame;

  if (pkalgo == GCRY_PK_DSA || pkalgo == GCRY_PK_ECDSA)
    {
      unsigned int qbits;

      if ( pkalgo == GCRY_PK_ECDSA )
        qbits = gcry_pk_get_nbits (pkey);
      else
        qbits = get_dsa_qbits (pkey);

      if ( (qbits%8) )
	{
	  log_error(_("DSA requires the hash length to be a"
		      " multiple of 8 bits\n"));
	  return gpg_error (GPG_ERR_INTERNAL);
	}

      /* Don't allow any Q smaller than 160 bits.  We don't want
	 someone to issue signatures from a key with a 16-bit Q or
	 something like that, which would look correct but allow
	 trivial forgeries.  Yes, I know this rules out using MD5 with
	 DSA. ;) */
      if (qbits < 160)
	{
	  log_error (_("%s key uses an unsafe (%u bit) hash\n"),
                     gcry_pk_algo_name (pkalgo), qbits);
	  return gpg_error (GPG_ERR_INTERNAL);
	}

      /* Check if we're too short.  Too long is safe as we'll
	 automatically left-truncate. */
      nframe = gcry_md_get_algo_dlen (algo);
      if (nframe < qbits/8)
        {
	  log_error (_("a %u bit hash is not valid for a %u bit %s key\n"),
                     (unsigned int)nframe*8,
                     gcry_pk_get_nbits (pkey),
                     gcry_pk_algo_name (pkalgo));
          /* FIXME: we need to check the requirements for ECDSA.  */
          if (nframe < 20 || pkalgo == GCRY_PK_DSA  )
            return gpg_error (GPG_ERR_INTERNAL);
        }

      frame = xtrymalloc (nframe);
      if (!frame)
        return out_of_core ();
      memcpy (frame, gcry_md_read (md, algo), nframe);
      n = nframe;
      /* Truncate.  */
      if (n > qbits/8)
        n = qbits/8;
    }
  else
    {
      int i;
      unsigned char asn[100];
      size_t asnlen;
      size_t len;

      nframe = (nbits+7) / 8;

      asnlen = DIM(asn);
      if (!algo || gcry_md_test_algo (algo))
        return gpg_error (GPG_ERR_DIGEST_ALGO);
      if (gcry_md_algo_info (algo, GCRYCTL_GET_ASNOID, asn, &asnlen))
        {
          log_error ("no object identifier for algo %d\n", algo);
          return gpg_error (GPG_ERR_INTERNAL);
        }

      len = gcry_md_get_algo_dlen (algo);

      if ( len + asnlen + 4  > nframe )
        {
          log_error ("can't encode a %d bit MD into a %d bits frame\n",
                     (int)(len*8), (int)nbits);
          return gpg_error (GPG_ERR_INTERNAL);
        }

      /* We encode the MD in this way:
       *
       *	   0  A PAD(n bytes)   0  ASN(asnlen bytes)  MD(len bytes)
       *
       * PAD consists of FF bytes.
       */
      frame = xtrymalloc (nframe);
      if (!frame)
        return out_of_core ();
      n = 0;
      frame[n++] = 0;
      frame[n++] = 1; /* block type */
      i = nframe - len - asnlen -3 ;
      assert ( i > 1 );
      memset ( frame+n, 0xff, i ); n += i;
      frame[n++] = 0;
      memcpy ( frame+n, asn, asnlen ); n += asnlen;
      memcpy ( frame+n, gcry_md_read(md, algo), len ); n += len;
      assert ( n == nframe );
    }
  if (DBG_CRYPTO)
    {
      int j;
      log_debug ("encoded hash:");
      for (j=0; j < nframe; j++)
        log_printf (" %02X", frame[j]);
      log_printf ("\n");
    }

  gcry_mpi_scan (r_val, GCRYMPI_FMT_USG, frame, n, &nframe);
  xfree (frame);
  return 0;
}
Exemple #14
0
/**
 * cdk_sk_unprotect:
 * @sk: the secret key
 * @pw: the passphrase
 * 
 * Unprotect the given secret key with the passphrase.
 **/
cdk_error_t
cdk_sk_unprotect (cdk_pkt_seckey_t sk, const char *pw)
{
  gcry_cipher_hd_t hd;
  cdk_dek_t dek = NULL;
  byte *data = NULL;
  u16 chksum = 0;
  size_t ndata, nbits, nbytes;
  int i, dlen, pos = 0, nskey;
  cdk_error_t rc;
  gcry_error_t err;
  
  if (!sk)
    return CDK_Inv_Value;
  
  nskey = cdk_pk_get_nskey (sk->pubkey_algo);
  if (!sk->is_protected)
    {
      chksum = 0;
      for (i = 0; i < nskey; i++)
	chksum += checksum_mpi (sk->mpi[i]);
      if (chksum != sk->csum)
	return CDK_Chksum_Error;
    } 
      
  rc = cdk_dek_from_passphrase (&dek, sk->protect.algo,
				sk->protect.s2k, 0, pw);
  if (rc)
    return rc;
  err = gcry_cipher_open (&hd, sk->protect.algo, GCRY_CIPHER_MODE_CFB, 
			  GCRY_CIPHER_ENABLE_SYNC);
  if (!err)
    err = gcry_cipher_setiv (hd, sk->protect.iv, sk->protect.ivlen);
  if (!err)
    err = gcry_cipher_setkey (hd, dek->key, dek->keylen);
  if (err)
    {
      cdk_free (dek);
      return map_gcry_error (err);
    }
  cdk_dek_free (dek);
  chksum = 0;
  if (sk->version == 4) 
    {
      ndata = sk->enclen;
      data = cdk_salloc (ndata, 1);
      if (!data)
	return CDK_Out_Of_Core;
      gcry_cipher_decrypt (hd, data, ndata, sk->encdata, ndata);
      if (sk->protect.sha1chk) 
	{
	  /* This is the new SHA1 checksum method to detect tampering
	     with the key as used by the Klima/Rosa attack */
	  sk->csum = 0;
	  chksum = 1;
	  dlen = gcry_md_get_algo_dlen (GCRY_MD_SHA1);
	  if (ndata < dlen) 
	    {
	      cdk_free (data);
	      return CDK_Inv_Packet;
	    }
	  else 
	    {
	      byte mdcheck[20];
	      
	      gcry_md_hash_buffer (GCRY_MD_SHA1, 
				   mdcheck, data, ndata-dlen);
	      if (!memcmp (mdcheck, data + ndata - dlen, dlen))
		chksum = 0;	/* Digest does match */
	    }
	}
      else 
	{
	  for (i = 0; i < ndata - 2; i++)
	    chksum += data[i];
	  sk->csum = data[ndata - 2] << 8 | data[ndata - 1];
	}
      if (sk->csum == chksum) 
	{
	  for (i = 0; i < nskey; i++) 
	    {
	      nbits = data[pos] << 8 | data[pos + 1];
	      
	      if (gcry_mpi_scan (&sk->mpi[i], GCRYMPI_FMT_PGP, data,
			     (nbits+7)/8+2, &nbytes))
		{
		  wipemem (data, sk->enclen);
		  cdk_free (data);
		  return CDK_Wrong_Format;
		}	     
	      gcry_mpi_set_flag (sk->mpi[i], GCRYMPI_FLAG_SECURE);
	      pos += (nbits+7)/8+2;
	    }
	}
      wipemem (data, sk->enclen);
      cdk_free (data);
    }
  else 
    {
      byte buf[MAX_MPI_BYTES+2];
      
      chksum = 0;
      for (i = 0; i < nskey; i++)
	{
	  gcry_cipher_sync (hd);
	  gcry_mpi_print (GCRYMPI_FMT_PGP, buf, DIM (buf), 
			  &nbytes, sk->mpi[i]);
	  gcry_cipher_decrypt (hd, buf+2, nbytes-2, NULL, 0);
	  gcry_mpi_release (sk->mpi[i]);
	  if (gcry_mpi_scan (&sk->mpi[i], GCRYMPI_FMT_PGP,
			     buf, nbytes, &nbytes))
	    return CDK_Wrong_Format;
	  chksum += checksum_mpi (sk->mpi[i]);
	}
    }
  gcry_cipher_close (hd);
  if (chksum != sk->csum)
    return CDK_Chksum_Error;
  sk->is_protected = 0;
  return 0;
}
Exemple #15
0
static libspectrum_error
create_key( gcry_sexp_t *s_key, libspectrum_rzx_dsa_key *key,
	    int secret_key )
{
  gcry_error_t error;
  size_t i;
  gcry_mpi_t mpis[MPI_COUNT];
  const char *format;

  for( i=0; i<MPI_COUNT; i++ ) mpis[i] = NULL;

    error = gcry_mpi_scan( &mpis[0], GCRYMPI_FMT_HEX, (unsigned char*)key->p,
			   0, NULL );
  if( !error ) 
    error = gcry_mpi_scan( &mpis[1], GCRYMPI_FMT_HEX, (unsigned char*)key->q,
			   0, NULL );
  if( !error )
    error = gcry_mpi_scan( &mpis[2], GCRYMPI_FMT_HEX, (unsigned char*)key->g,
			   0, NULL );
  if( !error )
    error = gcry_mpi_scan( &mpis[3], GCRYMPI_FMT_HEX, (unsigned char*)key->y,
			   0, NULL );
  if( !error && secret_key )
    error = gcry_mpi_scan( &mpis[4], GCRYMPI_FMT_HEX, (unsigned char*)key->x,
			   0, NULL );

  if( error ) {
    libspectrum_print_error( LIBSPECTRUM_ERROR_LOGIC,
			     "create_key: error creating MPIs: %s",
			     gcry_strerror( error ) );
    free_mpis( mpis, MPI_COUNT );
    return LIBSPECTRUM_ERROR_LOGIC;
  }

  format = secret_key ? private_key_format : public_key_format;
  
  error = gcry_sexp_build( s_key, NULL, format,
			   mpis[0], mpis[1], mpis[2], mpis[3], mpis[4] );
  if( error ) {
    libspectrum_print_error( LIBSPECTRUM_ERROR_LOGIC,
			     "create_key: error creating key: %s",
			     gcry_strerror( error ) );
    free_mpis( mpis, MPI_COUNT );
    return LIBSPECTRUM_ERROR_LOGIC;
  }

  free_mpis( mpis, MPI_COUNT );

  /* FIXME: Test public keys as well once gcry_pk_testkey acquires this
     functionality */
  if( secret_key ) {
    error = gcry_pk_testkey( *s_key );
    if( error ) {
      libspectrum_print_error( LIBSPECTRUM_ERROR_LOGIC,
			       "create_key: key is not sane: %s",
			       gcry_strerror( error ) );
      return LIBSPECTRUM_ERROR_LOGIC;
    }
  }

  return LIBSPECTRUM_ERROR_NONE;
}
Exemple #16
0
int
irc_sasl_dh (const char *data_base64,
             unsigned char **public_bin, unsigned char **secret_bin,
             int *length_key)
{
    char *data;
    unsigned char *ptr_data;
    int length_data, size, num_bits_prime_number, rc;
    size_t num_written;
    gcry_mpi_t data_prime_number, data_generator_number, data_server_pub_key;
    gcry_mpi_t pub_key, priv_key, secret_mpi;

    rc = 0;

    data = NULL;
    data_prime_number = NULL;
    data_generator_number = NULL;
    data_server_pub_key = NULL;
    pub_key = NULL;
    priv_key = NULL;
    secret_mpi = NULL;

    /* decode data */
    data = malloc (strlen (data_base64) + 1);
    length_data = weechat_string_decode_base64 (data_base64, data);
    ptr_data = (unsigned char *)data;

    /* extract prime number */
    size = ntohs ((((unsigned int)ptr_data[1]) << 8) | ptr_data[0]);
    ptr_data += 2;
    length_data -= 2;
    if (size > length_data)
        goto dhend;
    data_prime_number = gcry_mpi_new (size * 8);
    gcry_mpi_scan (&data_prime_number, GCRYMPI_FMT_USG, ptr_data, size, NULL);
    num_bits_prime_number = gcry_mpi_get_nbits (data_prime_number);
    ptr_data += size;
    length_data -= size;

    /* extract generator number */
    size = ntohs ((((unsigned int)ptr_data[1]) << 8) | ptr_data[0]);
    ptr_data += 2;
    length_data -= 2;
    if (size > length_data)
        goto dhend;
    data_generator_number = gcry_mpi_new (size * 8);
    gcry_mpi_scan (&data_generator_number, GCRYMPI_FMT_USG, ptr_data, size, NULL);
    ptr_data += size;
    length_data -= size;

    /* extract server-generated public key */
    size = ntohs ((((unsigned int)ptr_data[1]) << 8) | ptr_data[0]);
    ptr_data += 2;
    length_data -= 2;
    if (size > length_data)
        goto dhend;
    data_server_pub_key = gcry_mpi_new (size * 8);
    gcry_mpi_scan (&data_server_pub_key, GCRYMPI_FMT_USG, ptr_data, size, NULL);

    /* generate keys */
    pub_key = gcry_mpi_new (num_bits_prime_number);
    priv_key = gcry_mpi_new (num_bits_prime_number);
    gcry_mpi_randomize (priv_key, num_bits_prime_number, GCRY_STRONG_RANDOM);
    /* pub_key = (g ^ priv_key) % p */
    gcry_mpi_powm (pub_key, data_generator_number, priv_key, data_prime_number);

    /* compute secret_bin */
    *length_key = num_bits_prime_number / 8;
    *secret_bin = malloc (*length_key);
    secret_mpi = gcry_mpi_new (num_bits_prime_number);
    /* secret_mpi = (y ^ priv_key) % p */
    gcry_mpi_powm (secret_mpi, data_server_pub_key, priv_key, data_prime_number);
    gcry_mpi_print (GCRYMPI_FMT_USG, *secret_bin, *length_key,
                    &num_written, secret_mpi);

    /* create public_bin */
    *public_bin = malloc (*length_key);
    gcry_mpi_print (GCRYMPI_FMT_USG, *public_bin, *length_key,
                    &num_written, pub_key);
    rc = 1;

dhend:
    if (data)
        free (data);
    if (data_prime_number)
        gcry_mpi_release (data_prime_number);
    if (data_generator_number)
        gcry_mpi_release (data_generator_number);
    if (data_server_pub_key)
        gcry_mpi_release (data_server_pub_key);
    if (pub_key)
        gcry_mpi_release (pub_key);
    if (priv_key)
        gcry_mpi_release (priv_key);
    if (secret_mpi)
        gcry_mpi_release (secret_mpi);

    return rc;
}
/*
 * Checks the validity of the signature found on the regulatory
 * database against the array 'keys'. Returns 1 if there exists
 * at least one key in the array such that the signature is valid
 * against that key; 0 otherwise.
 */
int crda_verify_db_signature(__u8 *db, int dblen, int siglen)
{
#ifdef USE_OPENSSL
	RSA *rsa;
	__u8 hash[SHA_DIGEST_LENGTH];
	unsigned int i;
	int ok = 0;
	DIR *pubkey_dir;
	struct dirent *nextfile;
	FILE *keyfile;
	char filename[PATH_MAX];

	if (SHA1(db, dblen, hash) != hash) {
		fprintf(stderr, "Failed to calculate SHA1 sum.\n");
		goto out;
	}

	for (i = 0; (i < sizeof(keys)/sizeof(keys[0])) && (!ok); i++) {
		rsa = RSA_new();
		if (!rsa) {
			fprintf(stderr, "Failed to create RSA key.\n");
			goto out;
		}

		rsa->e = &keys[i].e;
		rsa->n = &keys[i].n;

		ok = RSA_verify(NID_sha1, hash, SHA_DIGEST_LENGTH,
				db + dblen, siglen, rsa) == 1;

		rsa->e = NULL;
		rsa->n = NULL;
		RSA_free(rsa);
	}
	if (!ok && (pubkey_dir = opendir(PUBKEY_DIR))) {
		while (!ok && (nextfile = readdir(pubkey_dir))) {
			snprintf(filename, PATH_MAX, "%s/%s", PUBKEY_DIR,
				nextfile->d_name);
			if ((keyfile = fopen(filename, "rb"))) {
				rsa = PEM_read_RSA_PUBKEY(keyfile,
					NULL, NULL, NULL);
				if (rsa)
					ok = RSA_verify(NID_sha1, hash, SHA_DIGEST_LENGTH,
						db + dblen, siglen, rsa) == 1;
				RSA_free(rsa);
				fclose(keyfile);
			}
		}
		closedir(pubkey_dir);
	}
#endif

#ifdef USE_GCRYPT
	gcry_mpi_t mpi_e, mpi_n;
	gcry_sexp_t rsa, signature, data;
	__u8 hash[20];
	unsigned int i;
	int ok = 0;

	/* initialise */
	gcry_check_version(NULL);

	/* hash the db */
	gcry_md_hash_buffer(GCRY_MD_SHA1, hash, db, dblen);

	if (gcry_sexp_build(&data, NULL, "(data (flags pkcs1) (hash sha1 %b))",
			    20, hash)) {
		fprintf(stderr, "Failed to build data S-expression.\n");
		goto out;
	}

	if (gcry_sexp_build(&signature, NULL, "(sig-val (rsa (s %b)))",
			    siglen, db + dblen)) {
		fprintf(stderr, "Failed to build signature S-expression.\n");
		goto out;
	}

	for (i = 0; (i < sizeof(keys)/sizeof(keys[0])) && (!ok); i++) {
		if (gcry_mpi_scan(&mpi_e, GCRYMPI_FMT_USG,
				keys[i].e, keys[i].len_e, NULL) ||
		    gcry_mpi_scan(&mpi_n, GCRYMPI_FMT_USG,
				keys[i].n, keys[i].len_n, NULL)) {
			fprintf(stderr, "Failed to convert numbers.\n");
			goto out;
		}

		if (gcry_sexp_build(&rsa, NULL,
				    "(public-key (rsa (n %m) (e %m)))",
				    mpi_n, mpi_e)) {
			fprintf(stderr, "Failed to build RSA S-expression.\n");
			goto out;
		}

		ok = gcry_pk_verify(signature, data, rsa) == 0;
	}
#endif

#if defined(USE_OPENSSL) || defined(USE_GCRYPT)
	if (!ok)
		fprintf(stderr, "Database signature verification failed.\n");

out:
	return ok;
#else
	return 1;
#endif
}
Exemple #18
0
/**
 * Blinds the given message with the given blinding key
 *
 * @param hash hash of the message to sign
 * @param bkey the blinding key
 * @param pkey the public key of the signer
 * @param[out] buffer set to a buffer with the blinded message to be signed
 * @return number of bytes stored in @a buffer
 */
size_t
GNUNET_CRYPTO_rsa_blind (const struct GNUNET_HashCode *hash,
                         struct GNUNET_CRYPTO_rsa_BlindingKey *bkey,
                         struct GNUNET_CRYPTO_rsa_PublicKey *pkey,
                         char **buffer)
{
  gcry_mpi_t data;
  gcry_mpi_t ne[2];
  gcry_mpi_t r_e;
  gcry_mpi_t data_r_e;
  size_t rsize;
  size_t n;
  gcry_error_t rc;
  char *b;
  int ret;

  ret = key_from_sexp (ne, pkey->sexp, "public-key", "ne");
  if (0 != ret)
    ret = key_from_sexp (ne, pkey->sexp, "rsa", "ne");
  if (0 != ret)
  {
    GNUNET_break (0);
    *buffer = NULL;
    return 0;
  }
  if (0 != (rc = gcry_mpi_scan (&data,
                                GCRYMPI_FMT_USG,
                                (const unsigned char *) hash,
                                sizeof (struct GNUNET_HashCode),
                                &rsize)))
  {
    GNUNET_break (0);
    gcry_mpi_release (ne[0]);
    gcry_mpi_release (ne[1]);
    *buffer = NULL;
    return 0;
  }
  r_e = gcry_mpi_new (0);
  gcry_mpi_powm (r_e,
                 bkey->r,
                 ne[1],
                 ne[0]);
  data_r_e = gcry_mpi_new (0);
  gcry_mpi_mulm (data_r_e,
                 data,
                 r_e,
                 ne[0]);
  gcry_mpi_release (data);
  gcry_mpi_release (ne[0]);
  gcry_mpi_release (ne[1]);
  gcry_mpi_release (r_e);

  gcry_mpi_print (GCRYMPI_FMT_USG,
                  NULL,
                  0,
                  &n,
                  data_r_e);
  b = GNUNET_malloc (n);
  rc = gcry_mpi_print (GCRYMPI_FMT_USG,
                       (unsigned char *) b,
                       n,
                       &rsize,
                       data_r_e);
  gcry_mpi_release (data_r_e);
  *buffer = b;
  return n;
}
Exemple #19
0
/* decrypts the RSA encrypted text read from the XML file,
 * and saves the AES key and the other needed info
 * uses libgcrypt for decryption
 */
int AESKey::decryptRSA( string s_cipher_text_b64 )
{
    RSAKey rsa_key( this->p_demux );
    unsigned char *ps_cipher_text = NULL;
    unsigned char *ps_plain_text = NULL;
    gcry_mpi_t cipher_text_mpi = NULL;
    gcry_sexp_t cipher_text_sexp = NULL;
    gcry_sexp_t plain_text_sexp = NULL;
    gcry_mpi_t plain_text_mpi = NULL;
    gcry_sexp_t tmp_sexp = NULL;
    gcry_error_t err;
    size_t length;
    int i_ret = VLC_EGENERIC;

    /* get RSA private key file path */
    if( rsa_key.setPath() )
        goto end;

    /* read private key from file */
    if( rsa_key.readPEM() )
        goto end;

    /* remove spaces and newlines from encoded cipher text
     * (usually added for indentation in XML files)
     * */
    try
    {
        s_cipher_text_b64.erase( remove_if( s_cipher_text_b64.begin(), s_cipher_text_b64.end(), static_cast<int(*)(int)>(isspace) ),
                                 s_cipher_text_b64.end() );
    }
    catch( ... )
    {
        msg_Err( this->p_demux, "error while handling string" );
        goto end;
    }

    /* decode cipher from BASE64 to binary */
    if( ! ( length = vlc_b64_decode_binary( &ps_cipher_text, s_cipher_text_b64.c_str() ) ) )
    {
        msg_Err( this->p_demux, "could not decode cipher from Base64" );
        goto end;
    }

    /* initialize libgcrypt */
    vlc_gcrypt_init ();

    /* create S-expression for ciphertext */
    if( ( err = gcry_mpi_scan( &cipher_text_mpi, GCRYMPI_FMT_USG, ps_cipher_text, 256, NULL ) ) )
    {
        msg_Err( this->p_demux, "could not scan MPI from cipher text: %s", gcry_strerror( err ) );
        goto end;
    }
    if( ( err = gcry_sexp_build( &cipher_text_sexp, NULL, "(enc-val(flags oaep)(rsa(a %m)))", cipher_text_mpi ) ) )
    {
        msg_Err( this->p_demux, "could not build S-expression for cipher text: %s", gcry_strerror( err ) );
        goto end;
    }

    /* decrypt */
    if( ( err = gcry_pk_decrypt( &plain_text_sexp, cipher_text_sexp, rsa_key.priv_key ) ) )
    {
        msg_Err( this->p_demux, "error while decrypting RSA encrypted info: %s", gcry_strerror( err ) );
        goto end;
    }

    /* extract plain-text from S-expression */
    if( ! ( tmp_sexp = gcry_sexp_find_token( plain_text_sexp, "value", 0 ) ) )
        /* when using padding flags, the decrypted S-expression is of the form
         * "(value <plaintext>)", where <plaintext> is an MPI */
    {
        msg_Err( this->p_demux, "decrypted text is in an unexpected form; decryption may have failed" );
        goto end;
    }
    /* we could have used the gcry_sexp_nth_data to get the data directly,
     * but as that function is newly introduced (libgcrypt v1.6),
     * we prefer compatibility, even though that means passing the data through an MPI first */
    if( ! ( plain_text_mpi = gcry_sexp_nth_mpi( tmp_sexp, 1, GCRYMPI_FMT_USG ) ) )
    {
        msg_Err( this->p_demux, "could not extract MPI from decrypted S-expression" );
        goto end;
    }

    if( ( err = gcry_mpi_aprint( GCRYMPI_FMT_USG, &ps_plain_text, &length, plain_text_mpi ) ) )
    {
        msg_Err( this->p_demux, "error while extracting plain text from MPI: %s", gcry_strerror( err ) );
        goto end;
    }

    /* interpret the plaintext data */
    switch( length )
    {
        case 138:   /* SMPTE    DCP */
            if( this->extractInfo( ps_plain_text, true ) )
                goto end;
            break;
        case 134:   /* Interop  DCP */
            if( this->extractInfo( ps_plain_text, false ) )
                goto end;
            break;
        case -1:
            msg_Err( this->p_demux, "could not decrypt" );
            goto end;
        default:
            msg_Err( this->p_demux, "CipherValue field length does not match SMPTE nor Interop standards" );
            goto end;
    }

    i_ret = VLC_SUCCESS;

end:
    free( ps_cipher_text );
    gcry_mpi_release( cipher_text_mpi );
    gcry_sexp_release( cipher_text_sexp );
    gcry_sexp_release( plain_text_sexp );
    gcry_mpi_release( plain_text_mpi );
    gcry_sexp_release( tmp_sexp );
    gcry_free( ps_plain_text );
    return i_ret;
}
Exemple #20
0
gpg_err_code_t
keyutil_get_cert_mpi (
	unsigned char *der,
	size_t len,
	gcry_mpi_t *p_n_mpi,
	gcry_mpi_t *p_e_mpi
) {
	gpg_err_code_t error = GPG_ERR_GENERAL;
	gcry_mpi_t n_mpi = NULL;
	gcry_mpi_t e_mpi = NULL;
#if defined(ENABLE_GNUTLS)
	gnutls_x509_crt_t cert = NULL;
	gnutls_datum_t datum = {der, len};
	gnutls_datum_t m = {NULL, 0}, e = {NULL, 0};
#elif defined(ENABLE_OPENSSL)
	X509 *x509 = NULL;
	EVP_PKEY *pubkey = NULL;
	char *n_hex = NULL, *e_hex = NULL;
#endif

	*p_n_mpi = NULL;
	*p_e_mpi = NULL;

#if defined(ENABLE_GNUTLS)
	if (gnutls_x509_crt_init (&cert) != GNUTLS_E_SUCCESS) {
		cert = NULL;
		error = GPG_ERR_ENOMEM;
		goto cleanup;
	}

	if (gnutls_x509_crt_import (cert, &datum, GNUTLS_X509_FMT_DER) != GNUTLS_E_SUCCESS) {
		error = GPG_ERR_BAD_CERT;
		goto cleanup;
	}

	if (gnutls_x509_crt_get_pk_rsa_raw (cert, &m, &e) != GNUTLS_E_SUCCESS) {
		error = GPG_ERR_BAD_KEY;
		m.data = NULL;
		e.data = NULL;
		goto cleanup;
	}

	if (
		gcry_mpi_scan(&n_mpi, GCRYMPI_FMT_USG, m.data, m.size, NULL) ||
		gcry_mpi_scan(&e_mpi, GCRYMPI_FMT_USG, e.data, e.size, NULL)
	) {
		error = GPG_ERR_BAD_KEY;
		goto cleanup;
	}
#elif defined(ENABLE_OPENSSL)
	if (!d2i_X509 (&x509, (my_openssl_d2i_t *)&der, len)) {
		error = GPG_ERR_BAD_CERT;
		goto cleanup;
	}
 
	if ((pubkey = X509_get_pubkey (x509)) == NULL) {
		error = GPG_ERR_BAD_CERT;
		goto cleanup;
	}
 
	if (pubkey->type != EVP_PKEY_RSA) {
		error = GPG_ERR_WRONG_PUBKEY_ALGO;
		goto cleanup;
	}
	
	n_hex = BN_bn2hex (pubkey->pkey.rsa->n);
	e_hex = BN_bn2hex (pubkey->pkey.rsa->e);
		
	if(n_hex == NULL || e_hex == NULL) {
		error = GPG_ERR_BAD_KEY;
		goto cleanup;
	}
 
	if (
		gcry_mpi_scan (&n_mpi, GCRYMPI_FMT_HEX, n_hex, 0, NULL) ||
		gcry_mpi_scan (&e_mpi, GCRYMPI_FMT_HEX, e_hex, 0, NULL)
	) {
		error = GPG_ERR_BAD_KEY;
		goto cleanup;
	}
#else
#error Invalid configuration.
#endif

	*p_n_mpi = n_mpi;
	n_mpi = NULL;
	*p_e_mpi = e_mpi;
	e_mpi = NULL;
	error = GPG_ERR_NO_ERROR;

cleanup:

	if (n_mpi != NULL) {
		gcry_mpi_release (n_mpi);
		n_mpi = NULL;
	}

	if (e_mpi != NULL) {
		gcry_mpi_release (e_mpi);
		e_mpi = NULL;
	}

#if defined(ENABLE_GNUTLS)

	if (m.data != NULL) {
		gnutls_free (m.data);
		m.data = NULL;
	}

	if (e.data != NULL) {
		gnutls_free (e.data);
		e.data = NULL;
	}

	if (cert != NULL) {
		gnutls_x509_crt_deinit (cert);
		cert = NULL;
	}

#elif defined(ENABLE_OPENSSL)

	if (x509 != NULL) {
		X509_free (x509);
		x509 = NULL;
	}

	if (pubkey != NULL) {
		EVP_PKEY_free(pubkey);
		pubkey = NULL;
	}

	if (n_hex != NULL) {
		OPENSSL_free (n_hex);
		n_hex = NULL;
	}

	if (e_hex != NULL) {
		OPENSSL_free (e_hex);
		e_hex = NULL;
	}

#else
#error Invalid configuration.
#endif

	return error;
}
Exemple #21
0
GByteArray *
steam_crypt_rsa_enc(const GByteArray *mod, const GByteArray *exp,
                    const GByteArray *bytes)
{
    GByteArray *ret = NULL;
    gcry_error_t res;
    gcry_mpi_t dmpi = NULL;
    gcry_mpi_t empi = NULL;
    gcry_mpi_t mmpi = NULL;
    gcry_sexp_t cata = NULL;
    gcry_sexp_t data = NULL;
    gcry_sexp_t kata = NULL;
    gsize size;

    g_return_val_if_fail(mod != NULL, NULL);
    g_return_val_if_fail(exp != NULL, NULL);
    g_return_val_if_fail(bytes != NULL, NULL);

    res = gcry_mpi_scan(&mmpi, GCRYMPI_FMT_USG, mod->data,
                         mod->len, NULL);
    res |= gcry_mpi_scan(&empi, GCRYMPI_FMT_USG, exp->data,
                         exp->len, NULL);
    res |= gcry_mpi_scan(&dmpi, GCRYMPI_FMT_USG, bytes->data,
                         bytes->len, NULL);

    if (G_UNLIKELY(res != 0)) {
        goto finish;
    }

    res = gcry_sexp_build(&kata, NULL, "(public-key(rsa(n %m)(e %m)))",
                           mmpi, empi);
    res |= gcry_sexp_build(&data, NULL, "(data(flags pkcs1)(value %m))",
                           dmpi);

    if (G_UNLIKELY(res != 0)) {
        goto finish;
    }

    res = gcry_pk_encrypt(&cata, data, kata);

    if (G_UNLIKELY(res != 0)) {
        goto finish;
    }

    gcry_sexp_release(data);
    data = gcry_sexp_find_token(cata, "a", 0);

    if (G_UNLIKELY(data == NULL)) {
        g_warn_if_reached();
        goto finish;
    }

    gcry_mpi_release(dmpi);
    dmpi = gcry_sexp_nth_mpi(data, 1, GCRYMPI_FMT_USG);

    if (G_UNLIKELY(dmpi == NULL)) {
        g_warn_if_reached();
        goto finish;
    }

    ret = g_byte_array_new();
    g_byte_array_set_size(ret, mod->len);
    gcry_mpi_print(GCRYMPI_FMT_USG, ret->data, ret->len, &size, dmpi);

    g_warn_if_fail(size <= mod->len);
    g_byte_array_set_size(ret, size);

finish:
    gcry_sexp_release(cata);
    gcry_sexp_release(data);
    gcry_sexp_release(kata);

    gcry_mpi_release(dmpi);
    gcry_mpi_release(empi);
    gcry_mpi_release(mmpi);

    return ret;
}
static int
generate_key_or_iv(unsigned int id, tvbuff_t *salt_tvb, unsigned int iter,
		       const char *pw, unsigned int req_keylen, char * keybuf)
{
  int rc;
  unsigned int i, j;
  gcry_md_hd_t md;
  gcry_mpi_t num_b1 = NULL;
  size_t pwlen;
  char hash[20], buf_b[64], buf_i[128], *p;
  char *salt_p;
  int salt_size;
  size_t cur_keylen;
  size_t n;
  gcry_error_t	err;

  cur_keylen = 0;

  salt_size = tvb_length(salt_tvb);
  salt_p = tvb_get_ephemeral_string(salt_tvb, 0, salt_size);

  if (pw == NULL)
    pwlen = 0;
  else
    pwlen = strlen (pw);

  if (pwlen > 63 / 2)
    {
      return FALSE;
    }

  /* Store salt and password in BUF_I */
  p = buf_i;
  for (i = 0; i < 64; i++)
    *p++ = salt_p[i % salt_size];
  if (pw)
    {
      for (i = j = 0; i < 64; i += 2)
	{
	  *p++ = 0;
	  *p++ = pw[j];
	  if (++j > pwlen)	/* Note, that we include the trailing zero */
	    j = 0;
	}
    }
  else
    memset (p, 0, 64);

  for (;;){
      err = gcry_md_open(&md, GCRY_MD_SHA1, 0);
      if (gcry_err_code(err)) {
		  return FALSE;
	  }
      for (i = 0; i < 64; i++) {
		  unsigned char lid = id & 0xFF;
		  gcry_md_write (md, &lid, 1);
	  }

	  gcry_md_write(md, buf_i, pw ? 128 : 64);

      gcry_md_final (md);
      memcpy (hash, gcry_md_read (md, 0), 20);

	  gcry_md_close (md);

	  for (i = 1; i < iter; i++)
		  gcry_md_hash_buffer (GCRY_MD_SHA1, hash, hash, 20);

      for (i = 0; i < 20 && cur_keylen < req_keylen; i++)
		  keybuf[cur_keylen++] = hash[i];

	  if (cur_keylen == req_keylen) {
		  gcry_mpi_release (num_b1);
		  return TRUE;		/* ready */
	  }

      /* need more bytes. */
      for (i = 0; i < 64; i++)
		  buf_b[i] = hash[i % 20];

	  n = 64;

	  rc = gcry_mpi_scan (&num_b1, GCRYMPI_FMT_USG, buf_b, n, &n);

	  if (rc != 0) {
		  return FALSE;
	  }

	  gcry_mpi_add_ui (num_b1, num_b1, 1);

	  for (i = 0; i < 128; i += 64)	{
		  gcry_mpi_t num_ij;

		  n = 64;
		  rc = gcry_mpi_scan (&num_ij, GCRYMPI_FMT_USG, buf_i + i, n, &n);

		  if (rc != 0) {
			  return FALSE;
		  }

		  gcry_mpi_add (num_ij, num_ij, num_b1);
		  gcry_mpi_clear_highbit (num_ij, 64 * 8);

		  n = 64;

		  rc = gcry_mpi_print (GCRYMPI_FMT_USG, buf_i + i, n, &n, num_ij);
		  if (rc != 0){
			  return FALSE;
		  }

		  gcry_mpi_release (num_ij);
	  }
  }
}
Exemple #23
0
/*
 * Verify an OpenPGP signature made with some DSA public key
 */
static int verify_signature_dsa( signature_packet_t *sign, public_key_packet_t *p_key,
                      uint8_t *p_hash )
{
    int ret = VLC_EGENERIC;

    /* the data to be verified (a hash) */
    const char *hash_sexp_s = "(data(flags raw)(value %m))";
    /* the public key */
    const char *key_sexp_s = "(public-key(dsa(p %m)(q %m)(g %m)(y %m)))";
    /* the signature */
    const char *sig_sexp_s = "(sig-val(dsa(r %m )(s %m )))";

    size_t erroff;
    gcry_mpi_t p, q, g, y, r, s, hash;
    p = q = g = y = r = s = hash = NULL;
    gcry_sexp_t key_sexp, hash_sexp, sig_sexp;
    key_sexp = hash_sexp = sig_sexp = NULL;

    int i_p_len = mpi_len( p_key->sig.dsa.p );
    int i_q_len = mpi_len( p_key->sig.dsa.q );
    int i_g_len = mpi_len( p_key->sig.dsa.g );
    int i_y_len = mpi_len( p_key->sig.dsa.y );
    if( gcry_mpi_scan( &p, GCRYMPI_FMT_USG, p_key->sig.dsa.p + 2, i_p_len, NULL ) ||
        gcry_mpi_scan( &q, GCRYMPI_FMT_USG, p_key->sig.dsa.q + 2, i_q_len, NULL ) ||
        gcry_mpi_scan( &g, GCRYMPI_FMT_USG, p_key->sig.dsa.g + 2, i_g_len, NULL ) ||
        gcry_mpi_scan( &y, GCRYMPI_FMT_USG, p_key->sig.dsa.y + 2, i_y_len, NULL ) ||
        gcry_sexp_build( &key_sexp, &erroff, key_sexp_s, p, q, g, y ) )
        goto out;

    uint8_t *p_r = sign->algo_specific.dsa.r;
    uint8_t *p_s = sign->algo_specific.dsa.s;
    int i_r_len = mpi_len( p_r );
    int i_s_len = mpi_len( p_s );
    if( gcry_mpi_scan( &r, GCRYMPI_FMT_USG, p_r + 2, i_r_len, NULL ) ||
        gcry_mpi_scan( &s, GCRYMPI_FMT_USG, p_s + 2, i_s_len, NULL ) ||
        gcry_sexp_build( &sig_sexp, &erroff, sig_sexp_s, r, s ) )
        goto out;

    int i_hash_len = gcry_md_get_algo_dlen (sign->digest_algo);
    if (i_hash_len > i_q_len)
        i_hash_len = i_q_len;
    if( gcry_mpi_scan( &hash, GCRYMPI_FMT_USG, p_hash, i_hash_len, NULL ) ||
        gcry_sexp_build( &hash_sexp, &erroff, hash_sexp_s, hash ) )
        goto out;

    if( gcry_pk_verify( sig_sexp, hash_sexp, key_sexp ) )
        goto out;

    ret = VLC_SUCCESS;

out:
    if( p ) gcry_mpi_release( p );
    if( q ) gcry_mpi_release( q );
    if( g ) gcry_mpi_release( g );
    if( y ) gcry_mpi_release( y );
    if( r ) gcry_mpi_release( r );
    if( s ) gcry_mpi_release( s );
    if( hash ) gcry_mpi_release( hash );
    if( key_sexp ) gcry_sexp_release( key_sexp );
    if( sig_sexp ) gcry_sexp_release( sig_sexp );
    if( hash_sexp ) gcry_sexp_release( hash_sexp );

    return ret;
}
Exemple #24
0
static gboolean
response_open_session_aes (SecretSession *session,
                           GVariant *response)
{
	gconstpointer buffer;
	GVariant *argument;
	const gchar *sig;
	gsize n_buffer;
	gcry_mpi_t peer;
	gcry_error_t gcry;
	gpointer ikm;
	gsize n_ikm;

	sig = g_variant_get_type_string (response);
	g_return_val_if_fail (sig != NULL, FALSE);

	if (!g_str_equal (sig, "(vo)")) {
		g_warning ("invalid OpenSession() response from daemon with signature: %s", sig);
		return FALSE;
	}

	g_assert (session->path == NULL);
	g_variant_get (response, "(vo)", &argument, &session->path);

	buffer = g_variant_get_fixed_array (argument, &n_buffer, sizeof (guchar));
	gcry = gcry_mpi_scan (&peer, GCRYMPI_FMT_USG, buffer, n_buffer, NULL);
	g_return_val_if_fail (gcry == 0, FALSE);
	g_variant_unref (argument);

#if 0
	g_printerr (" lib publi: ");
	gcry_mpi_dump (session->publi);
	g_printerr ("\n  lib peer: ");
	gcry_mpi_dump (peer);
	g_printerr ("\n");
#endif

	ikm = egg_dh_gen_secret (peer, session->privat, session->prime, &n_ikm);
	gcry_mpi_release (peer);

#if 0
	g_printerr ("   lib ikm:  %s\n", egg_hex_encode (ikm, n_ikm));
#endif

	if (ikm == NULL) {
		g_warning ("couldn't negotiate a valid AES session key");
		g_free (session->path);
		session->path = NULL;
		return FALSE;
	}

	session->n_key = 16;
	session->key = egg_secure_alloc (session->n_key);
	if (!egg_hkdf_perform ("sha256", ikm, n_ikm, NULL, 0, NULL, 0,
	                       session->key, session->n_key))
		g_return_val_if_reached (FALSE);
	egg_secure_free (ikm);

	session->algorithms = ALGORITHMS_AES;
	return TRUE;
}
Exemple #25
0
/**
 * ntfs_raw_fek_decrypt -
 *
 * Note: decrypting into the input buffer.
 */
static unsigned ntfs_raw_fek_decrypt(u8 *fek, u32 fek_size,
                                     ntfs_rsa_private_key rsa_key)
{
    gcry_mpi_t fek_mpi;
    gcry_sexp_t fek_sexp, fek_sexp2;
    gcry_error_t err;
    size_t size, padding;

    /* Reverse the raw FEK. */
    ntfs_buffer_reverse(fek, fek_size);
    /* Convert the FEK to internal MPI format. */
    err = gcry_mpi_scan(&fek_mpi, GCRYMPI_FMT_USG, fek, fek_size, NULL);
    if (err != GPG_ERR_NO_ERROR) {
        ntfs_log_error("Failed to convert file encryption key to "
                       "internal MPI format: %s\n",
                       gcry_strerror(err));
        return 0;
    }
    /* Create an internal S-expression from the FEK. */
    err = gcry_sexp_build(&fek_sexp, NULL,
                          "(enc-val (flags) (rsa (a %m)))", fek_mpi);
    gcry_mpi_release(fek_mpi);
    if (err != GPG_ERR_NO_ERROR) {
        ntfs_log_error("Failed to create internal S-expression of "
                       "the file encryption key: %s\n",
                       gcry_strerror(err));
        return 0;
    }
    /* Decrypt the FEK. */
    err = gcry_pk_decrypt(&fek_sexp2, fek_sexp, (gcry_sexp_t)rsa_key);
    gcry_sexp_release(fek_sexp);
    if (err != GPG_ERR_NO_ERROR) {
        ntfs_log_error("Failed to decrypt the file encryption key: "
                       "%s\n", gcry_strerror(err));
        return 0;
    }
    /* Extract the actual FEK from the decrypted raw S-expression. */
    fek_sexp = gcry_sexp_find_token(fek_sexp2, "value", 0);
    gcry_sexp_release(fek_sexp2);
    if (!fek_sexp) {
        ntfs_log_error("Failed to find the decrypted file encryption "
                       "key in the internal S-expression.\n");
        return 0;
    }
    /* Convert the decrypted FEK S-expression into MPI format. */
    fek_mpi = gcry_sexp_nth_mpi(fek_sexp, 1, GCRYMPI_FMT_USG);
    gcry_sexp_release(fek_sexp);
    if (!fek_mpi) {
        ntfs_log_error("Failed to convert the decrypted file "
                       "encryption key S-expression to internal MPI "
                       "format.\n");
        return 0;
    }
    /* Convert the decrypted FEK from MPI format to binary data. */
    err = gcry_mpi_print(GCRYMPI_FMT_USG, fek, fek_size, &size, fek_mpi);
    gcry_mpi_release(fek_mpi);
    if (err != GPG_ERR_NO_ERROR || !size) {
        ntfs_log_error("Failed to convert decrypted file encryption "
                       "key from internal MPI format to binary data: "
                       "%s\n", gcry_strerror(err));
        return 0;
    }
    /*
     * Finally, remove the PKCS#1 padding and return the size of the
     * decrypted FEK.
     */
    padding = strnlen((char *)fek, size) + 1;
    if (padding > size) {
        ntfs_log_error("Failed to remove PKCS#1 padding from "
                       "decrypted file encryption key.\n");
        return 0;
    }
    size -= padding;
    memmove(fek, fek + padding, size);
    return size;
}
Exemple #26
0
/*
 * Test X25519 functionality through higher layer crypto routines.
 *
 * Input: K (as hex string), U (as hex string), R (as hex string)
 *
 * where R is expected result of X25519 (K, U).
 *
 * It calls gcry_pk_decrypt with Curve25519 private key and let
 * it compute X25519.
 */
static void
test_cv (int testno, const char *k_str, const char *u_str,
         const char *result_str)
{
  gpg_error_t err;
  void *buffer = NULL;
  size_t buflen;
  gcry_sexp_t s_pk = NULL;
  gcry_mpi_t mpi_k = NULL;
  gcry_sexp_t s_data = NULL;
  gcry_sexp_t s_result = NULL;
  gcry_sexp_t s_tmp = NULL;
  unsigned char *res = NULL;
  size_t res_len;

  if (verbose > 1)
    info ("Running test %d\n", testno);

  if (!(buffer = hex2buffer (k_str, &buflen)) || buflen != 32)
    {
      fail ("error building s-exp for test %d, %s: %s",
            testno, "k", "invalid hex string");
      goto leave;
    }

  reverse_buffer (buffer, buflen);
  if ((err = gcry_mpi_scan (&mpi_k, GCRYMPI_FMT_USG, buffer, buflen, NULL)))
    {
      fail ("error converting MPI for test %d: %s", testno, gpg_strerror (err));
      goto leave;
    }

  if ((err = gcry_sexp_build (&s_data, NULL, "%m", mpi_k)))
    {
      fail ("error building s-exp for test %d, %s: %s",
            testno, "data", gpg_strerror (err));
      goto leave;
    }

  xfree (buffer);
  if (!(buffer = hex2buffer (u_str, &buflen)) || buflen != 32)
    {
      fail ("error building s-exp for test %d, %s: %s",
            testno, "u", "invalid hex string");
      goto leave;
    }

  /*
   * The procedure of decodeUCoordinate will be done internally
   * by _gcry_ecc_mont_decodepoint.  So, we just put the little-endian
   * binary to build S-exp.
   *
   * We could add the prefix 0x40, but libgcrypt also supports
   * format with no prefix.  So, it is OK not to put the prefix.
   */
  if ((err = gcry_sexp_build (&s_pk, NULL,
                              "(public-key"
                              " (ecc"
                              "  (curve \"Curve25519\")"
                              "  (flags djb-tweak)"
                              "  (q%b)))", (int)buflen, buffer)))
    {
      fail ("error building s-exp for test %d, %s: %s",
            testno, "pk", gpg_strerror (err));
      goto leave;
    }

  xfree (buffer);
  buffer = NULL;

  if ((err = gcry_pk_encrypt (&s_result, s_data, s_pk)))
    fail ("gcry_pk_encrypt failed for test %d: %s", testno,
          gpg_strerror (err));

  s_tmp = gcry_sexp_find_token (s_result, "s", 0);
  if (!s_tmp || !(res = gcry_sexp_nth_buffer (s_tmp, 1, &res_len)))
    fail ("gcry_pk_encrypt failed for test %d: %s", testno, "missing value");
  else
    {
      char *r, *r0;
      int i;

      /* To skip the prefix 0x40, for-loop start with i=1 */
      r0 = r = xmalloc (2*(res_len)+1);
      if (!r0)
        {
          fail ("memory allocation for test %d", testno);
          goto leave;
        }

      for (i=1; i < res_len; i++, r += 2)
        snprintf (r, 3, "%02x", res[i]);
      if (strcmp (result_str, r0))
        {
          fail ("gcry_pk_encrypt failed for test %d: %s",
                testno, "wrong value returned");
          info ("  expected: '%s'", result_str);
          info ("       got: '%s'", r0);
        }
      xfree (r0);
    }

 leave:
  xfree (res);
  gcry_mpi_release (mpi_k);
  gcry_sexp_release (s_tmp);
  gcry_sexp_release (s_result);
  gcry_sexp_release (s_data);
  gcry_sexp_release (s_pk);
  xfree (buffer);
}