Exemple #1
0
/* Create an OTR Data message.  Pass the plaintext as msg, and an
 * optional chain of TLVs.  A newly-allocated string will be returned in
 * *encmessagep. Put the current extra symmetric key into extrakey
 * (if non-NULL). */
gcry_error_t otrl_proto_create_data(char **encmessagep, ConnContext *context,
	const char *msg, const OtrlTLV *tlvs, unsigned char flags,
	unsigned char *extrakey)
{
    size_t justmsglen = strlen(msg);
    size_t msglen = justmsglen + 1 + otrl_tlv_seriallen(tlvs);
    size_t buflen;
    size_t pubkeylen;
    unsigned char *buf = NULL;
    unsigned char *bufp;
    size_t lenp;
    DH_sesskeys *sess = &(context->context_priv->sesskeys[1][0]);
    gcry_error_t err;
    size_t reveallen = 20 * context->context_priv->numsavedkeys;
    char *base64buf = NULL;
    unsigned char *msgbuf = NULL;
    enum gcry_mpi_format format = GCRYMPI_FMT_USG;
    char *msgdup;
    int version = context->protocol_version;

    *encmessagep = NULL;

    /* Make sure we're actually supposed to be able to encrypt */
    if (context->msgstate != OTRL_MSGSTATE_ENCRYPTED ||
	    context->context_priv->their_keyid == 0) {
	return gcry_error(GPG_ERR_CONFLICT);
    }

    /* We need to copy the incoming msg, since it might be an alias for
     * context->lastmessage, which we'll be freeing soon. */
    msgdup = gcry_malloc_secure(justmsglen + 1);
    if (msgdup == NULL) {
	return gcry_error(GPG_ERR_ENOMEM);
    }
    strcpy(msgdup, msg);

    /* Header, msg flags, send keyid, recv keyid, counter, msg len, msg
     * len of revealed mac keys, revealed mac keys, MAC */
    buflen = OTRL_HEADER_LEN + (version == 3 ? 8 : 0)
	+ (version == 2 || version == 3 ? 1 : 0) + 4 + 4
	+ 8 + 4 + msglen + 4 + reveallen + 20;
    gcry_mpi_print(format, NULL, 0, &pubkeylen,
	    context->context_priv->our_dh_key.pub);
    buflen += pubkeylen + 4;
    buf = malloc(buflen);
    msgbuf = gcry_malloc_secure(msglen);
    if (buf == NULL || msgbuf == NULL) {
	free(buf);
	gcry_free(msgbuf);
	gcry_free(msgdup);
	return gcry_error(GPG_ERR_ENOMEM);
    }
    memmove(msgbuf, msgdup, justmsglen);
    msgbuf[justmsglen] = '\0';
    otrl_tlv_serialize(msgbuf + justmsglen + 1, tlvs);
    bufp = buf;
    lenp = buflen;
    if (version == 1) {
	memmove(bufp, "\x00\x01\x03", 3);  /* header */
    } else if (version == 2) {
	memmove(bufp, "\x00\x02\x03", 3);  /* header */
    } else {
	memmove(bufp, "\x00\x03\x03", 3);  /* header */
    }

    debug_data("Header", bufp, 3);
    bufp += 3; lenp -= 3;

    if (version == 3) {
	/* v3 instance tags */
	write_int(context->our_instance);
	debug_int("Sender instag", bufp-4);
	write_int(context->their_instance);
	debug_int("Recipient instag", bufp-4);
    }

    if (version == 2 || version == 3) {
	bufp[0] = flags;
	bufp += 1; lenp -= 1;
    }

    write_int(context->context_priv->our_keyid-1); /* sender keyid */
    debug_int("Sender keyid", bufp-4);
    write_int(context->context_priv->their_keyid); /* recipient keyid */
    debug_int("Recipient keyid", bufp-4);

    write_mpi(context->context_priv->our_dh_key.pub, pubkeylen, "Y");  /* Y */

    otrl_dh_incctr(sess->sendctr);
    memmove(bufp, sess->sendctr, 8);      /* Counter (top 8 bytes only) */
    debug_data("Counter", bufp, 8);
    bufp += 8; lenp -= 8;

    write_int(msglen);                        /* length of encrypted data */
    debug_int("Msg len", bufp-4);

    err = gcry_cipher_reset(sess->sendenc);
    if (err) goto err;
    err = gcry_cipher_setctr(sess->sendenc, sess->sendctr, 16);
    if (err) goto err;
    err = gcry_cipher_encrypt(sess->sendenc, bufp, msglen, msgbuf, msglen);
    if (err) goto err;                              /* encrypted data */
    debug_data("Enc data", bufp, msglen);
    bufp += msglen;
    lenp -= msglen;

    gcry_md_reset(sess->sendmac);
    gcry_md_write(sess->sendmac, buf, bufp-buf);
    memmove(bufp, gcry_md_read(sess->sendmac, GCRY_MD_SHA1), 20);
    debug_data("MAC", bufp, 20);
    bufp += 20;                                         /* MAC */
    lenp -= 20;

    write_int(reveallen);                     /* length of revealed MAC keys */
    debug_int("Revealed MAC length", bufp-4);

    if (reveallen > 0) {
	memmove(bufp, context->context_priv->saved_mac_keys, reveallen);
	debug_data("Revealed MAC data", bufp, reveallen);
	bufp += reveallen; lenp -= reveallen;
	free(context->context_priv->saved_mac_keys);
	context->context_priv->saved_mac_keys = NULL;
	context->context_priv->numsavedkeys = 0;
    }

    assert(lenp == 0);

    /* Make the base64-encoding. */
    base64buf = otrl_base64_otr_encode(buf, buflen);
    if (base64buf == NULL) {
	err = gcry_error(GPG_ERR_ENOMEM);
	goto err;
    }

    free(buf);
    gcry_free(msgbuf);
    *encmessagep = base64buf;
    gcry_free(context->context_priv->lastmessage);
    context->context_priv->lastmessage = NULL;
    context->context_priv->may_retransmit = 0;
    if (msglen > 0) {
	context->context_priv->lastmessage = gcry_malloc_secure(justmsglen + 1);
	if (context->context_priv->lastmessage) {
	    strcpy(context->context_priv->lastmessage, msgdup);
	}
    }
    gcry_free(msgdup);

    /* Save a copy of the current extra key */
    if (extrakey) {
	memmove(extrakey, sess->extrakey, OTRL_EXTRAKEY_BYTES);
    }

    return gcry_error(GPG_ERR_NO_ERROR);
err:
    free(buf);
    gcry_free(msgbuf);
    gcry_free(msgdup);
    *encmessagep = NULL;
    return err;
}
Exemple #2
0
static void
slow_gatherer_windowsNT( void (*add)(const void*, size_t, int), int requester )
{
    static int is_initialized = 0;
    static NETSTATISTICSGET pNetStatisticsGet = NULL;
    static NETAPIBUFFERSIZE pNetApiBufferSize = NULL;
    static NETAPIBUFFERFREE pNetApiBufferFree = NULL;
    static int is_workstation = 1;

    static int cbPerfData = PERFORMANCE_BUFFER_SIZE;
    PERF_DATA_BLOCK *pPerfData;
    HANDLE hDevice, hNetAPI32 = NULL;
    DWORD dwSize, status;
    int nDrive;

    if ( !is_initialized ) {
	HKEY hKey;

	if ( debug_me )
	    log_debug ("rndw32#slow_gatherer_nt: init toolkit\n" );
	/* Find out whether this is an NT server or workstation if necessary */
	if (RegOpenKeyEx (HKEY_LOCAL_MACHINE,
			  "SYSTEM\\CurrentControlSet\\Control\\ProductOptions",
			  0, KEY_READ, &hKey) == ERROR_SUCCESS) {
	    BYTE szValue[32];
	    dwSize = sizeof (szValue);

	    if ( debug_me )
		log_debug ("rndw32#slow_gatherer_nt: check product options\n" );
	    status = RegQueryValueEx (hKey, "ProductType", 0, NULL,
				      szValue, &dwSize);
	    if (status == ERROR_SUCCESS && stricmp (szValue, "WinNT")) {
		/* Note: There are (at least) three cases for ProductType:
		 * WinNT = NT Workstation, ServerNT = NT Server, LanmanNT =
		 * NT Server acting as a Domain Controller */
		is_workstation = 0;
		if ( debug_me )
		    log_debug ("rndw32: this is a NT server\n");
	    }
	    RegCloseKey (hKey);
	}

	/* Initialize the NetAPI32 function pointers if necessary */
	if ( (hNetAPI32 = LoadLibrary ("NETAPI32.DLL")) ) {
	    if ( debug_me )
		log_debug ("rndw32#slow_gatherer_nt: netapi32 loaded\n" );
	    pNetStatisticsGet = (NETSTATISTICSGET) GetProcAddress (hNetAPI32,
						       "NetStatisticsGet");
	    pNetApiBufferSize = (NETAPIBUFFERSIZE) GetProcAddress (hNetAPI32,
						       "NetApiBufferSize");
	    pNetApiBufferFree = (NETAPIBUFFERFREE) GetProcAddress (hNetAPI32,
						       "NetApiBufferFree");

	    if ( !pNetStatisticsGet
		 || !pNetApiBufferSize || !pNetApiBufferFree ) {
		FreeLibrary (hNetAPI32);
		hNetAPI32 = NULL;
		log_debug ("rndw32: No NETAPI found\n" );
	    }
	}

	is_initialized = 1;
    }

    /* Get network statistics.	Note: Both NT Workstation and NT Server by
     * default will be running both the workstation and server services.  The
     * heuristic below is probably useful though on the assumption that the
     * majority of the network traffic will be via the appropriate service.
     * In any case the network statistics return almost no randomness */
    {	LPBYTE lpBuffer;
	if (hNetAPI32 && !pNetStatisticsGet (NULL,
			   is_workstation ? L"LanmanWorkstation" :
			   L"LanmanServer", 0, 0, &lpBuffer) ) {
	    if ( debug_me )
		log_debug ("rndw32#slow_gatherer_nt: get netstats\n" );
	    pNetApiBufferSize (lpBuffer, &dwSize);
	    (*add) ( lpBuffer, dwSize,requester );
	    pNetApiBufferFree (lpBuffer);
	}
    }

    /* Get disk I/O statistics for all the hard drives */
    for (nDrive = 0;; nDrive++) {
        char diskPerformance[SIZEOF_DISK_PERFORMANCE_STRUCT];
	char szDevice[50];

	/* Check whether we can access this device */
	sprintf (szDevice, "\\\\.\\PhysicalDrive%d", nDrive);
	hDevice = CreateFile (szDevice, 0, FILE_SHARE_READ | FILE_SHARE_WRITE,
			      NULL, OPEN_EXISTING, 0, NULL);
	if (hDevice == INVALID_HANDLE_VALUE)
	    break;

	/* Note: This only works if you have turned on the disk performance
	 * counters with 'diskperf -y'.  These counters are off by default */
	if (DeviceIoControl (hDevice, IOCTL_DISK_PERFORMANCE, NULL, 0,
			     diskPerformance, SIZEOF_DISK_PERFORMANCE_STRUCT,
			     &dwSize, NULL))
	{
	    if ( debug_me )
		log_debug ("rndw32#slow_gatherer_nt: iostats drive %d\n",
								  nDrive );
	    (*add) (diskPerformance, dwSize, requester );
	}
	else {
	    log_info ("NOTE: you should run 'diskperf -y' "
		      "to enable the disk statistics\n");
	}
	CloseHandle (hDevice);
    }

#if 0 /* we don't need this in GnuPG  */
    /* Wait for any async keyset driver binding to complete.  You may be
     * wondering what this call is doing here... the reason it's necessary is
     * because RegQueryValueEx() will hang indefinitely if the async driver
     * bind is in progress.  The problem occurs in the dynamic loading and
     * linking of driver DLL's, which work as follows:
     *
     * hDriver = LoadLibrary( DRIVERNAME );
     * pFunction1 = ( TYPE_FUNC1 ) GetProcAddress( hDriver, NAME_FUNC1 );
     * pFunction2 = ( TYPE_FUNC1 ) GetProcAddress( hDriver, NAME_FUNC2 );
     *
     * If RegQueryValueEx() is called while the GetProcAddress()'s are in
     * progress, it will hang indefinitely.  This is probably due to some
     * synchronisation problem in the NT kernel where the GetProcAddress()
     * calls affect something like a module reference count or function
     * reference count while RegQueryValueEx() is trying to take a snapshot
     * of the statistics, which include the reference counts.  Because of
     * this, we have to wait until any async driver bind has completed
     * before we can call RegQueryValueEx() */
    waitSemaphore (SEMAPHORE_DRIVERBIND);
#endif

    /* Get information from the system performance counters.  This can take
     * a few seconds to do.  In some environments the call to
     * RegQueryValueEx() can produce an access violation at some random time
     * in the future, adding a short delay after the following code block
     * makes the problem go away.  This problem is extremely difficult to
     * reproduce, I haven't been able to get it to occur despite running it
     * on a number of machines.  The best explanation for the problem is that
     * on the machine where it did occur, it was caused by an external driver
     * or other program which adds its own values under the
     * HKEY_PERFORMANCE_DATA key.  The NT kernel calls the required external
     * modules to map in the data, if there's a synchronisation problem the
     * external module would write its data at an inappropriate moment,
     * causing the access violation.  A low-level memory checker indicated
     * that ExpandEnvironmentStrings() in KERNEL32.DLL, called an
     * interminable number of calls down inside RegQueryValueEx(), was
     * overwriting memory (it wrote twice the allocated size of a buffer to a
     * buffer allocated by the NT kernel).  This may be what's causing the
     * problem, but since it's in the kernel there isn't much which can be
     * done.
     *
     * In addition to these problems the code in RegQueryValueEx() which
     * estimates the amount of memory required to return the performance
     * counter information isn't very accurate, since it always returns a
     * worst-case estimate which is usually nowhere near the actual amount
     * required.  For example it may report that 128K of memory is required,
     * but only return 64K of data */
    {	pPerfData =  gcry_xmalloc (cbPerfData);
	for (;;) {
	    dwSize = cbPerfData;
	    if ( debug_me )
		log_debug ("rndw32#slow_gatherer_nt: get perf data\n" );
	    status = RegQueryValueEx (HKEY_PERFORMANCE_DATA, "Global", NULL,
				      NULL, (LPBYTE) pPerfData, &dwSize);
	    if (status == ERROR_SUCCESS) {
		if (!memcmp (pPerfData->Signature, L"PERF", 8)) {
		    (*add) ( pPerfData, dwSize, requester );
		}
		else
		    log_debug ( "rndw32: no PERF signature\n");
		break;
	    }
	    else if (status == ERROR_MORE_DATA) {
		cbPerfData += PERFORMANCE_BUFFER_STEP;
		pPerfData = gcry_realloc (pPerfData, cbPerfData);
	    }
	    else {
		log_debug ( "rndw32: get performance data problem\n");
		break;
	    }
	}
	gcry_free (pPerfData);
    }
    /* Although this isn't documented in the Win32 API docs, it's necessary
       to explicitly close the HKEY_PERFORMANCE_DATA key after use (it's
       implicitly opened on the first call to RegQueryValueEx()).  If this
       isn't done then any system components which provide performance data
       can't be removed or changed while the handle remains active */
    RegCloseKey (HKEY_PERFORMANCE_DATA);
}
Exemple #3
0
/* Return the secret key as an S-Exp in RESULT after locating it using
   the GRIP.  Stores NULL at RESULT if the operation shall be diverted
   to a token; in this case an allocated S-expression with the
   shadow_info part from the file is stored at SHADOW_INFO.
   CACHE_MODE defines now the cache shall be used.  DESC_TEXT may be
   set to present a custom description for the pinentry.  LOOKUP_TTL
   is an optional function to convey a TTL to the cache manager; we do
   not simply pass the TTL value because the value is only needed if
   an unprotect action was needed and looking up the TTL may have some
   overhead (e.g. scanning the sshcontrol file).  If a CACHE_NONCE is
   given that cache item is first tried to get a passphrase.  If
   R_PASSPHRASE is not NULL, the function succeeded and the key was
   protected the used passphrase (entered or from the cache) is stored
   there; if not NULL will be stored.  The caller needs to free the
   returned passphrase.   */
gpg_error_t
agent_key_from_file (ctrl_t ctrl, const char *cache_nonce,
                     const char *desc_text,
                     const unsigned char *grip, unsigned char **shadow_info,
                     cache_mode_t cache_mode, lookup_ttl_t lookup_ttl,
                     gcry_sexp_t *result, char **r_passphrase)
{
  int rc;
  unsigned char *buf;
  size_t len, buflen, erroff;
  gcry_sexp_t s_skey;
  int got_shadow_info = 0;

  *result = NULL;
  if (shadow_info)
    *shadow_info = NULL;
  if (r_passphrase)
    *r_passphrase = NULL;

  rc = read_key_file (grip, &s_skey);
  if (rc)
    return rc;

  /* For use with the protection functions we also need the key as an
     canonical encoded S-expression in a buffer.  Create this buffer
     now.  */
  rc = make_canon_sexp (s_skey, &buf, &len);
  if (rc)
    return rc;

  switch (agent_private_key_type (buf))
    {
    case PRIVATE_KEY_CLEAR:
      break; /* no unprotection needed */
    case PRIVATE_KEY_PROTECTED:
      {
	char *desc_text_final;
	char *comment = NULL;

        /* Note, that we will take the comment as a C string for
           display purposes; i.e. all stuff beyond a Nul character is
           ignored.  */
        {
          gcry_sexp_t comment_sexp;

          comment_sexp = gcry_sexp_find_token (s_skey, "comment", 0);
          if (comment_sexp)
            comment = gcry_sexp_nth_string (comment_sexp, 1);
          gcry_sexp_release (comment_sexp);
        }

        desc_text_final = NULL;
	if (desc_text)
          rc = modify_description (desc_text, comment? comment:"", s_skey,
                                   &desc_text_final);
        gcry_free (comment);

	if (!rc)
	  {
	    rc = unprotect (ctrl, cache_nonce, desc_text_final, &buf, grip,
                            cache_mode, lookup_ttl, r_passphrase);
	    if (rc)
	      log_error ("failed to unprotect the secret key: %s\n",
			 gpg_strerror (rc));
	  }

	xfree (desc_text_final);
      }
      break;
    case PRIVATE_KEY_SHADOWED:
      if (shadow_info)
        {
          const unsigned char *s;
          size_t n;

          rc = agent_get_shadow_info (buf, &s);
          if (!rc)
            {
              n = gcry_sexp_canon_len (s, 0, NULL,NULL);
              assert (n);
              *shadow_info = xtrymalloc (n);
              if (!*shadow_info)
                rc = out_of_core ();
              else
                {
                  memcpy (*shadow_info, s, n);
                  rc = 0;
                  got_shadow_info = 1;
                }
            }
          if (rc)
            log_error ("get_shadow_info failed: %s\n", gpg_strerror (rc));
        }
      else
        rc = gpg_error (GPG_ERR_UNUSABLE_SECKEY);
      break;
    default:
      log_error ("invalid private key format\n");
      rc = gpg_error (GPG_ERR_BAD_SECKEY);
      break;
    }
  gcry_sexp_release (s_skey);
  s_skey = NULL;
  if (rc || got_shadow_info)
    {
      xfree (buf);
      if (r_passphrase)
        {
          xfree (*r_passphrase);
          *r_passphrase = NULL;
        }
      return rc;
    }

  buflen = gcry_sexp_canon_len (buf, 0, NULL, NULL);
  rc = gcry_sexp_sscan (&s_skey, &erroff, (char*)buf, buflen);
  wipememory (buf, buflen);
  xfree (buf);
  if (rc)
    {
      log_error ("failed to build S-Exp (off=%u): %s\n",
                 (unsigned int)erroff, gpg_strerror (rc));
      if (r_passphrase)
        {
          xfree (*r_passphrase);
          *r_passphrase = NULL;
        }
      return rc;
    }

  *result = s_skey;
  return 0;
}
Exemple #4
0
static void
check_dsa_gen_186_2 (void)
{
  static struct {
    int nbits;
    const char *p, *q, *g;
    const char *seed;
    int counter;
    const char *h;
  } tbl[] = {
    /* These tests are from FIPS 186-2, B.3.1.  */
    {
      1024,
      "d3aed1876054db831d0c1348fbb1ada72507e5fbf9a62cbd47a63aeb7859d6921"
      "4adeb9146a6ec3f43520f0fd8e3125dd8bbc5d87405d1ac5f82073cd762a3f8d7"
      "74322657c9da88a7d2f0e1a9ceb84a39cb40876179e6a76e400498de4bb9379b0"
      "5f5feb7b91eb8fea97ee17a955a0a8a37587a272c4719d6feb6b54ba4ab69",
      "9c916d121de9a03f71fb21bc2e1c0d116f065a4f",
      "8157c5f68ca40b3ded11c353327ab9b8af3e186dd2e8dade98761a0996dda99ab"
      "0250d3409063ad99efae48b10c6ab2bba3ea9a67b12b911a372a2bba260176fad"
      "b4b93247d9712aad13aa70216c55da9858f7a298deb670a403eb1e7c91b847f1e"
      "ccfbd14bd806fd42cf45dbb69cd6d6b43add2a78f7d16928eaa04458dea44",
      "0cb1990c1fd3626055d7a0096f8fa99807399871",
      98,
      "00000000000000000000000000000000000000000000000000000000000000000"
      "00000000000000000000000000000000000000000000000000000000000000000"
      "00000000000000000000000000000000000000000000000000000000000000000"
      "0000000000000000000000000000000000000000000000000000000000002"
    },
    {
      1024,
      "f5c73304080353357de1b5967597c27d65f70aa2fe9b6aed1d0afc2b499adf22f"
      "8e37937096d88548ac36c4a067f8353c7fed73f96f0d688b19b0624aedbae5dbb"
      "0ee8835a4c269288c0e1d69479e701ee266bb767af39d748fe7d6afc73fdf44be"
      "3eb6e661e599670061203e75fc8b3dbd59e40b54f358d0097013a0f3867f9",
      "f8751166cf4f6f3b07c081fd2a9071f23ca1988d",
      "1e288a442e02461c418ed67a66d24cacbeb8936fbde62ff995f5fd569dee6be62"
      "4e4f0f9f8c8093f5d192ab3b3f9ae3f2665d95d27fb10e382f45cd356e7f4eb7a"
      "665db432113ed06478f93b7cf188ec7a1ee97aec8f91ea7bfceaf8b6e7e5a349c"
      "4ad3225362ef440c57cbc6e69df15b6699caac85f733555075f04781b2b33",
      "34b3520d45d240a8861b82c8b61ffa16e67b5cce",
      622,
      "00000000000000000000000000000000000000000000000000000000000000000"
      "00000000000000000000000000000000000000000000000000000000000000000"
      "00000000000000000000000000000000000000000000000000000000000000000"
      "0000000000000000000000000000000000000000000000000000000000002",
    },
    {
      1024,
      "c6c6f4f4eed927fb1c3b0c81010967e530658e6f9698ebe058b4f47b2dc8fcbc7"
      "b69296b9e8b6cf55681181fe72492668061b262b0046a0d409902e269b0cb69a4"
      "55ed1a086caf41927f5912bf0e0cbc45ee81a4f98bf6146f6168a228aec80e9cc"
      "1162d6f6aa412efe82d4f18b95e34ab790daac5bd7aef0b22fa08ba5dbaad",
      "d32b29f065c1394a30490b6fcbf812a32a8634ab",
      "06f973c879e2e89345d0ac04f9c34ad69b9eff1680f18d1c8f3e1596c2e8fa8e1"
      "ecef6830409e9012d4788bef6ec7414d09c981b47c941b77f39dfc49caff5e714"
      "c97abe25a7a8b5d1fe88700bb96eff91cca64d53700a28b1146d81bad1212d231"
      "80154c95a01f5aeebb553a8365c38a5ebe05539b51734233776ce9aff98b2",
      "b6ec750da2f824cb42c5f7e28c81350d97f75125",
      185,
      "00000000000000000000000000000000000000000000000000000000000000000"
      "00000000000000000000000000000000000000000000000000000000000000000"
      "00000000000000000000000000000000000000000000000000000000000000000"
      "0000000000000000000000000000000000000000000000000000000000002",
    },
    {
      1024,
      "b827a9dc9221a6ed1bec7b64d61232aacb2812f888b0a0b3a95033d7a22e77d0b"
      "ff23bfeed0fb1281b21b8ff7421f0c727d1fb8aa2b843d6885f067e763f83d41f"
      "d800ab15a7e2b12f71ec2058ee7bd62cd72c26989b272e519785da57bfa1f974b"
      "c652e1a2d6cfb68477de5635fd019b37add656cff0b802558b31b6d2851e5",
      "de822c03445b77cec4ad3a6fb0ca39ff97059ddf",
      "65a9e2d43a378d7063813104586868cacf2fccd51aec1e0b6af8ba3e66dee6371"
      "681254c3fb5e3929d65e3c4bcd20abd4ddc7cf815623e17b9fc92f02b8d44278b"
      "848480ffd193104cf5612639511e45bd247708ff6028bd3824f8844c263b46c69"
      "1f2076f8cd13c5d0be95f1f2a1a17ab1f7e5bc73500bac27d57b473ba9748",
      "cd2221dd73815a75224e9fde7faf52829b81ac7a",
      62,
      "00000000000000000000000000000000000000000000000000000000000000000"
      "00000000000000000000000000000000000000000000000000000000000000000"
      "00000000000000000000000000000000000000000000000000000000000000000"
      "0000000000000000000000000000000000000000000000000000000000002",
    },
    {
      1024,
      "898a8d93e295c8ef2ffd46976225a1543640640d155a576fafa0be32136165803"
      "ba2eff2782a2be75cc9ec65db6bd3238cca695b3a5a14726a2a314775c377d891"
      "354b3de6c89e714a05599ca04132c987f889f72c4fe298ccb31f711c03b07e1d9"
      "8d72af590754cf3847398b60cecd55a4611692b308809560a83880404c227",
      "c6d786643d2acfc6b8d576863fda8cfbfbd5e03f",
      "2fd38b8d21c58e8fb5315a177b8d5dc4c450d574e69348b7b9da367c26e72438d"
      "af8372e7f0bee84ef5dcbbc3727194a2228431192f1779be24837f22a0e14d10d"
      "5344da1b8b403df9f9b2655095b3d0f67418ed6cd989f35aa4232e4b7001764fb"
      "e85d6b2c716980f13272fc4271ac1e234f7e24c023cfc2d2dc0aa1e9af2fb",
      "73483e697599871af983a281e3afa22e0ed86b68",
      272,
      "00000000000000000000000000000000000000000000000000000000000000000"
      "00000000000000000000000000000000000000000000000000000000000000000"
      "00000000000000000000000000000000000000000000000000000000000000000"
      "0000000000000000000000000000000000000000000000000000000000002",
    },

    /* These tests are generated by the OpenSSL FIPS version.  */
    {
      1024,
      "A404363903FDCE86839BCFD953AAD2DA2B0E70CAED3B5FF5D68F15A1C4BB0A793C"
      "A9D58FC956804C5901DE0AF99F345ED1A8617C687864BAC044B7C3C3E732A2B255"
      "EC986AA76EA8CB0E0815B3E0E605650AF7D8058EE7E8EBCDEFFDAB8100D3FC1033"
      "11BA3AB232EF06BB74BA9A949EC0C7ED324C19B202F4AB725BBB4080C9",
      "C643946CEA8748E12D430C48DB038F9165814389",
      "59B7E7BA0033CCE8E6837173420FBB382A784D4154A3C166043F5A68CB92945D16"
      "892D4CC5585F2D28C780E75A6C20A379E2B58304C1E5FC0D8C15E4E89C4498C8BC"
      "B90FB36ED8DC0489B9D0BC09EC4411FB0BFADF25485EEAB6700BE0ACF5C44A6ED7"
      "44A015382FF9B8DA7EAA00DEA135FADC59212DBBFFC1537336FA4B7225",
      "02708ab36e3f0bfd67ec3b8bd8829d03b84f56bd",
      50,
      "02"
    },
    {
      1024,
      "9C664033DB8B203D826F896D2293C62EF9351D5CFD0F4C0AD7EFDA4DDC7F15987"
      "6A3C68CAB2586B44FD1BD4DEF7A17905D88D321DD77C4E1720D848CA21D79F9B3"
      "D8F537338E09B44E9F481E8DA3C56569F63146596A050EF8FAEE8ACA32C666450"
      "04F675C8806EB4025B0A5ECC39CE89983EA40A183A7CF5208BA958045ABD5",
      "AD0D8CBA369AF6CD0D2BAC0B4CFCAF0A1F9BCDF7",
      "74D717F7092A2AF725FDD6C2561D1DBE5AEE40203C638BA8B9F49003857873701"
      "95A44E515C4E8B344F5CDC7F4A6D38097CD57675E7643AB9700692C69F0A99B0E"
      "039FDDDFCA8CEB607BDB4ADF2834DE1690F5823FC8199FB8F6F29E5A583B6786A"
      "C14C7E67106C3B30568CBB9383F89287D578159778EB18216799D16D46498",
      "6481a12a50384888ee84b61024f7c9c685d6ac96",
      289,
      "02"
    },
    {
      1024,

      "B0DFB602EB8462B1DC8C2214A52B587D3E6842CCF1C38D0F7C7F967ED30CF6828"
      "1E2675B3BAB594755FB1634E66B4C23936F0725A358F8DFF3C307E2601FD66D63"
      "5B17270450C50BD2BEC29E0E9A471DF1C15B0191517952268A2763D4BD28B8503"
      "B3399686272B76B11227F693D7833105EF70C2289C3194CF4527024B272DF",
      "EA649C04911FAB5A41440287A517EF752A40354B",
      "88C5A4563ECB949763E0B696CD04B21321360F54C0EE7B23E2CEDC30E9E486162"
      "01BFB1619E7C54B653D1F890C50E04B29205F5E3E2F93A13B0751AF25491C5194"
      "93C09DDF6B9C173B3846DFB0E7A5C870BBFC78419260C90E20315410691C8326C"
      "858D7063E7921F3F601158E912C7EE487FF259202BEEB10F6D9E99190F696",
      "5bf9d17bc62fbbf3d569c92bd4505586b2e5ef1a",
      626,
      "02"
    },
    {
      1024,
      "F783C08D7F9463E48BA87893805C4B34B63C85DF7EBDD9EBEE94DB4AF4E4A415C"
      "F0F3793AE55096BA1199598798FA8403B28DED7F7C7AFD54FD535861A0150EF4D"
      "5871465B13837CCF46BEB0A22F8D38DC7D6AE0E14A3845FD0C027CFA97791B977"
      "CE2808BAD9B43CE69390C0F40016056722D82C0D7B1B27413D026A39D7DAD",
      "A40D9EE456AED4C8A653FDB47B6629C0B843FE8F",
      "DF876263E21F263AE6DA57409BD517DCEADB9216048F066D6B58867F8E59A5EEE"
      "700283A946C1455534618979BE6C227673C1B803910262BD93BC94D5089850614"
      "F3E29AB64E8C989A7E3E28FE670FFA3EE21DEEEC1AB0B60E1D8E2AA39663BADD7"
      "2C9F957D7F3D4F17D9FDAD050EB373A6DEFD09F5DA752EAFE046836E14B67",
      "8a9a57706f69f4f566252cdf6d5cbfdf2020150b",
      397,
      "02"
    },
    {
      1024,
      "D40E4F6461E145859CCF60FD57962840BD75FFF12C22F76626F566842252AD068"
      "29745F0147056354F6C016CF12762B0E331787925B8128CF5AF81F9B176A51934"
      "96D792430FF83C7B79BD595BDA10787B34600787FA552EFE3662F37B99AAD3F3A"
      "093732680A01345192A19BECCE6BF5D498E44ED6BED5B0BA72AAD49E8276B",
      "D12F1BD0AA78B99247FD9F18EAFEE5C136686EA5",
      "468EBD20C99449C1E440E6F8E452C6A6BC7551C555FE5E94996E20CFD4DA3B9CC"
      "58499D6CC2374CCF9C392715A537DE10CFCA8A6A37AFBD187CF6B88D26881E5F5"
      "7521D9D2C9BBA51E7B87B070BBE73F5C5FE31E752CAF88183516D8503BAAC1159"
      "928EF50DEE52D96F396B93FB4138D786464C315401A853E57C9A0F9D25839",
      "30b3599944a914a330a3f49d11ec88f555422aef",
      678,
      "02"
    }
  };
  gpg_error_t err;
  int tno;
  gcry_sexp_t key_spec, key, pub_key, sec_key, seed_values;
  gcry_sexp_t l1;

  for (tno = 0; tno < DIM (tbl); tno++)
    {
      if (verbose)
        info ("generating FIPS 186-2 test key %d\n", tno);

      {
        void *data;
        size_t datalen;

        data = data_from_hex (tbl[tno].seed, &datalen);
        err = gcry_sexp_build (&key_spec, NULL,
                               "(genkey (dsa (nbits %d)(use-fips186-2)"
                               "(derive-parms(seed %b))))",
                               tbl[tno].nbits, (int)datalen, data);
        gcry_free (data);
      }
      if (err)
        die ("error creating S-expression %d: %s\n", tno, gpg_strerror (err));

      err = gcry_pk_genkey (&key, key_spec);
      gcry_sexp_release (key_spec);
      if (err)
        {
          fail ("error generating key %d: %s\n", tno, gpg_strerror (err));
          continue;
        }

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

      pub_key = gcry_sexp_find_token (key, "public-key", 0);
      if (!pub_key)
        fail ("public part missing in key %d\n", tno);

      sec_key = gcry_sexp_find_token (key, "private-key", 0);
      if (!sec_key)
        fail ("private part missing in key %d\n", tno);

      l1 = gcry_sexp_find_token (key, "misc-key-info", 0);
      if (!l1)
        fail ("misc_key_info part missing in key %d\n", tno);
      seed_values = gcry_sexp_find_token (l1, "seed-values", 0);
      if (!seed_values)
        fail ("seed-values part missing in key %d\n", tno);
      gcry_sexp_release (l1);

      extract_cmp_mpi (sec_key, "p", tbl[tno].p);
      extract_cmp_mpi (sec_key, "q", tbl[tno].q);
      extract_cmp_mpi (sec_key, "g", tbl[tno].g);

      extract_cmp_data (seed_values, "seed", tbl[tno].seed);
      extract_cmp_int (seed_values, "counter", tbl[tno].counter);
      extract_cmp_mpi (seed_values, "h", tbl[tno].h);

      gcry_sexp_release (seed_values);
      gcry_sexp_release (sec_key);
      gcry_sexp_release (pub_key);
      gcry_sexp_release (key);
    }
}
Exemple #5
0
int
main( int argc, char **argv )
{
    ARGPARSE_ARGS pargs;
    enum cmd_and_opt_values cmd = 0;
    unsigned long from = 0, to = ULONG_MAX;
    int dry_run = 0;

    early_system_init ();
    set_strusage( my_strusage );
    gcry_control (GCRYCTL_DISABLE_SECMEM);
    log_set_prefix ("kbxutil", 1);

    /* Make sure that our subsystems are ready.  */
    i18n_init ();
    init_common_subsystems (&argc, &argv);

    /* Check that the libraries are suitable.  Do it here because
       the option parsing may need services of the library.  */
    if (!gcry_check_version (NEED_LIBGCRYPT_VERSION) )
    {
        log_fatal (_("%s is too old (need %s, have %s)\n"), "libgcrypt",
                   NEED_LIBGCRYPT_VERSION, gcry_check_version (NULL) );
    }

    gcry_set_log_handler (my_gcry_logger, NULL);

    /*create_dotlock(NULL); register locking cleanup */

    /* We need to use the gcry malloc function because jnlib uses them.  */
    keybox_set_malloc_hooks (gcry_malloc, gcry_realloc, gcry_free);
    ksba_set_malloc_hooks (gcry_malloc, gcry_realloc, gcry_free );


    pargs.argc = &argc;
    pargs.argv = &argv;
    pargs.flags=  1;  /* do not remove the args */
    while (arg_parse( &pargs, opts) )
    {
        switch (pargs.r_opt)
        {
        case oVerbose:
            /*opt.verbose++;*/
            /*gcry_control( GCRYCTL_SET_VERBOSITY, (int)opt.verbose );*/
            break;
        case oDebug:
            /*opt.debug |= pargs.r.ret_ulong; */
            break;
        case oDebugAll:
            /*opt.debug = ~0;*/
            break;

        case aFindByFpr:
        case aFindByKid:
        case aFindByUid:
        case aStats:
        case aImportOpenPGP:
        case aFindDups:
        case aCut:
            cmd = pargs.r_opt;
            break;

        case oFrom:
            from = pargs.r.ret_ulong;
            break;
        case oTo:
            to = pargs.r.ret_ulong;
            break;

        case oDryRun:
            dry_run = 1;
            break;

        default:
            pargs.err = 2;
            break;
        }
    }

    if (to < from)
        log_error ("record number of \"--to\" is lower than \"--from\" one\n");


    if (log_get_errorcount(0) )
        myexit(2);

    if (!cmd)
    {   /* Default is to list a KBX file */
        if (!argc)
            _keybox_dump_file (NULL, 0, stdout);
        else
        {
            for (; argc; argc--, argv++)
                _keybox_dump_file (*argv, 0, stdout);
        }
    }
    else if (cmd == aStats )
    {
        if (!argc)
            _keybox_dump_file (NULL, 1, stdout);
        else
        {
            for (; argc; argc--, argv++)
                _keybox_dump_file (*argv, 1, stdout);
        }
    }
    else if (cmd == aFindDups )
    {
        if (!argc)
            _keybox_dump_find_dups (NULL, 0, stdout);
        else
        {
            for (; argc; argc--, argv++)
                _keybox_dump_find_dups (*argv, 0, stdout);
        }
    }
    else if (cmd == aCut )
    {
        if (!argc)
            _keybox_dump_cut_records (NULL, from, to, stdout);
        else
        {
            for (; argc; argc--, argv++)
                _keybox_dump_cut_records (*argv, from, to, stdout);
        }
    }
    else if (cmd == aImportOpenPGP)
    {
        if (!argc)
            import_openpgp ("-", dry_run);
        else
        {
            for (; argc; argc--, argv++)
                import_openpgp (*argv, dry_run);
        }
    }
#if 0
    else if ( cmd == aFindByFpr )
    {
        char *fpr;
        if ( argc != 2 )
            wrong_args ("kbxfile foingerprint");
        fpr = format_fingerprint ( argv[1] );
        if ( !fpr )
            log_error ("invalid formatted fingerprint\n");
        else
        {
            kbxfile_search_by_fpr ( argv[0], fpr );
            gcry_free ( fpr );
        }
    }
    else if ( cmd == aFindByKid )
    {
        u32 kid[2];
        int mode;

        if ( argc != 2 )
            wrong_args ("kbxfile short-or-long-keyid");
        mode = format_keyid ( argv[1], kid );
        if ( !mode )
            log_error ("invalid formatted keyID\n");
        else
        {
            kbxfile_search_by_kid ( argv[0], kid, mode );
        }
    }
    else if ( cmd == aFindByUid )
    {
        if ( argc != 2 )
            wrong_args ("kbxfile userID");
        kbxfile_search_by_uid ( argv[0], argv[1] );
    }
#endif
    else
        log_error ("unsupported action\n");

    myexit(0);
    return 8; /*NEVER REACHED*/
}
Exemple #6
0
gcry_err_code_t
_gcry_kdf_scrypt (const unsigned char *passwd, size_t passwdlen,
                  int algo, int subalgo,
                  const unsigned char *salt, size_t saltlen,
                  unsigned long iterations,
                  size_t dkLen, unsigned char *DK)
{
  u64 N = subalgo;    /* CPU/memory cost paramter.  */
  u32 r;              /* Block size.  */
  u32 p = iterations; /* Parallelization parameter.  */

  gpg_err_code_t ec;
  u32 i;
  unsigned char *B = NULL;
  unsigned char *tmp1 = NULL;
  unsigned char *tmp2 = NULL;
  size_t r128;
  size_t nbytes;

  if (subalgo < 1 || !iterations)
    return GPG_ERR_INV_VALUE;

  if (algo == GCRY_KDF_SCRYPT)
    r = 8;
  else if (algo == 41) /* Hack to allow the use of all test vectors.  */
    r = 1;
  else
    return GPG_ERR_UNKNOWN_ALGORITHM;

  r128 = r * 128;
  if (r128 / 128 != r)
    return GPG_ERR_ENOMEM;

  nbytes = p * r128;
  if (r128 && nbytes / r128 != p)
    return GPG_ERR_ENOMEM;

  nbytes = N * r128;
  if (r128 && nbytes / r128 != N)
    return GPG_ERR_ENOMEM;

  nbytes = 64 + r128;
  if (nbytes < r128)
    return GPG_ERR_ENOMEM;

  B = gcry_malloc (p * r128);
  if (!B)
    {
      ec = gpg_err_code_from_syserror ();
      goto leave;
    }

  tmp1 = gcry_malloc (N * r128);
  if (!tmp1)
    {
      ec = gpg_err_code_from_syserror ();
      goto leave;
    }

  tmp2 = gcry_malloc (64 + r128);
  if (!tmp2)
    {
      ec = gpg_err_code_from_syserror ();
      goto leave;
    }

  ec = _gcry_kdf_pkdf2 (passwd, passwdlen, GCRY_MD_SHA256, salt, saltlen,
                        1 /* iterations */, p * r128, B);

  for (i = 0; !ec && i < p; i++)
    _scryptROMix (r, &B[i * r128], N, tmp1, tmp2);

  for (i = 0; !ec && i < p; i++)
    ec = _gcry_kdf_pkdf2 (passwd, passwdlen, GCRY_MD_SHA256, B, p * r128,
                          1 /* iterations */, dkLen, DK);

 leave:
  gcry_free (tmp2);
  gcry_free (tmp1);
  gcry_free (B);

  return ec;
}
Exemple #7
0
extern void io_encryption_init(IO_HANDLE ptr, enum gcry_cipher_algos c, enum gcry_md_algos h, enum gcry_cipher_modes m, const uint8_t *k, size_t l, io_extra_t x)
{
	io_private_t *io_ptr = ptr;
	if (!io_ptr || io_ptr->fd < 0)
		return errno = EBADF , (void)NULL;
	/*
	 * start setting up the encryption buffer
	 */
	if (!(io_ptr->buffer_crypt = gcry_malloc_secure(sizeof( buffer_t ))))
		die(_("Out of memory @ %s:%d:%s [%zu]"), __FILE__, __LINE__, __func__, sizeof( buffer_t ));

	gcry_md_open(&io_ptr->hash_handle, h, GCRY_MD_FLAG_SECURE);
	gcry_cipher_open(&io_ptr->cipher_handle, c, m, GCRY_CIPHER_SECURE);
	/*
	 * generate a hash of the supplied key data
	 */
	size_t hash_length = gcry_md_get_algo_dlen(h);
	uint8_t *hash = gcry_malloc_secure(hash_length);
	if (!hash)
		die(_("Out of memory @ %s:%d:%s [%zu]"), __FILE__, __LINE__, __func__, hash_length);
	gcry_md_hash_buffer(gcry_md_get_algo(io_ptr->hash_handle), hash, k, l);
	/*
	 * set the key as the hash of supplied data
	 */
	size_t key_length = gcry_cipher_get_algo_keylen(c);
	uint8_t *key = gcry_calloc_secure(key_length, sizeof( byte_t ));
	if (!key)
		die(_("Out of memory @ %s:%d:%s [%zu]"), __FILE__, __LINE__, __func__, key_length);
	memcpy(key, hash, key_length < hash_length ? key_length : hash_length);
	gcry_cipher_setkey(io_ptr->cipher_handle, key, key_length); /* here is where it blows-up on Windows 8, using AES */
	gcry_free(key);
	/*
	 * the 2011.* versions (incorrectly) used key length instead of block
	 * length; versions after 2014.06 randomly generate the IV instead
	 */
	io_ptr->buffer_crypt->block = gcry_cipher_get_algo_blklen(c);
	uint8_t *iv = gcry_calloc_secure(x.x_iv == IV_BROKEN ? key_length : io_ptr->buffer_crypt->block, sizeof( byte_t ));
	if (!iv)
	   die(_("Out of memory @ %s:%d:%s [%zu]"), __FILE__, __LINE__, __func__, io_ptr->buffer_crypt->block);
	if (x.x_iv == IV_RANDOM)
	{
		if (x.x_encrypt)
		{
			gcry_create_nonce(iv, io_ptr->buffer_crypt->block);
			io_write(ptr, iv, io_ptr->buffer_crypt->block);
		}
		else
			io_read(ptr, iv, io_ptr->buffer_crypt->block);
	}
	else
	{
		uint8_t *iv_hash = gcry_malloc_secure(hash_length);
		if (!iv_hash)
			die(_("Out of memory @ %s:%d:%s [%zu]"), __FILE__, __LINE__, __func__, hash_length);
		/*
		 * set the IV as the hash of the hash
		 */
		gcry_md_hash_buffer(gcry_md_get_algo(io_ptr->hash_handle), iv_hash, hash, hash_length);
		memcpy(iv, iv_hash, io_ptr->buffer_crypt->block < hash_length ? io_ptr->buffer_crypt->block : hash_length);
		gcry_free(iv_hash);
	}
	gcry_free(hash);

	if (m == GCRY_CIPHER_MODE_CTR)
		gcry_cipher_setctr(io_ptr->cipher_handle, iv, io_ptr->buffer_crypt->block);
	else
		gcry_cipher_setiv(io_ptr->cipher_handle, iv, io_ptr->buffer_crypt->block);
	gcry_free(iv);
	/*
	 * set the rest of the buffer
	 */
	if (!(io_ptr->buffer_crypt->stream = gcry_malloc_secure(io_ptr->buffer_crypt->block)))
		die(_("Out of memory @ %s:%d:%s [%zu]"), __FILE__, __LINE__, __func__, io_ptr->buffer_crypt->block);
	/*
	 * when encrypting/writing data:
	 *   0: length of data buffered so far (in stream)
	 *   1: length of data processed (from d)
	 * when decrypting/reading data:
	 *   0: length of available data in input buffer (stream)
	 *   1: available space in read buffer (d)
	 *   2: next available memory location for data (from d)
	 */
	for (unsigned i = 0; i < OFFSET_SLOTS; i++)
		io_ptr->buffer_crypt->offset[i] = 0;
	io_ptr->cipher_init = true;
	io_ptr->hash_init = true;
	io_ptr->operation = IO_ENCRYPT;
	return;
}
Exemple #8
0
/* Check against PKCS#1 v1.5 encryption test  vectors as found at
   ftp://ftp.rsa.com/pub/rsalabs/tmp/pkcs1v15crypt-vectors.txt .  */
static void
check_v15crypt (void)
{
#include "pkcs1v2-v15c.h"
  gpg_error_t err;
  int tno, mno;

  for (tno = 0; tno < DIM (tbl); tno++)
    {
      void *rsa_n, *rsa_e, *rsa_d;
      size_t rsa_n_len, rsa_e_len, rsa_d_len;
      gcry_sexp_t sec_key, pub_key;

      if (verbose > 1)
        info ("(%s)\n", tbl[tno].desc);

      rsa_n = data_from_hex (tbl[tno].n, &rsa_n_len);
      rsa_e = data_from_hex (tbl[tno].e, &rsa_e_len);
      rsa_d = data_from_hex (tbl[tno].d, &rsa_d_len);
      err = gcry_sexp_build (&sec_key, NULL,
                             "(private-key (rsa (n %b)(e %b)(d %b)))",
                             (int)rsa_n_len, rsa_n,
                             (int)rsa_e_len, rsa_e,
                             (int)rsa_d_len, rsa_d);
      if (err)
        die ("constructing private key failed: %s\n", gpg_strerror (err));
      err = gcry_sexp_build (&pub_key, NULL,
                             "(public-key (rsa (n %b)(e %b)))",
                             (int)rsa_n_len, rsa_n,
                             (int)rsa_e_len, rsa_e);
      if (err)
        die ("constructing public key failed: %s\n", gpg_strerror (err));
      gcry_free (rsa_n);
      gcry_free (rsa_e);
      gcry_free (rsa_d);

      for (mno = 0; mno < DIM (tbl[0].m); mno++)
        {
          void *mesg, *seed, *encr;
          size_t mesg_len, seed_len, encr_len;
          gcry_sexp_t plain, ciph;

          if (verbose)
            info ("running test: %s\n", tbl[tno].m[mno].desc);

          mesg = data_from_hex (tbl[tno].m[mno].mesg, &mesg_len);
          seed = data_from_hex (tbl[tno].m[mno].seed, &seed_len);

          err = gcry_sexp_build (&plain, NULL,
                                 "(data (flags pkcs1)(hash-algo sha1)"
                                 "(value %b)(random-override %b))",
                                 (int)mesg_len, mesg,
                                 (int)seed_len, seed);
          if (err)
            die ("constructing plain data failed: %s\n", gpg_strerror (err));
          gcry_free (mesg);
          gcry_free (seed);

          err = gcry_pk_encrypt (&ciph, plain, pub_key);
          if (err)
            {
              show_sexp ("plain:\n", ciph);
              fail ("gcry_pk_encrypt failed: %s\n", gpg_strerror (err));
            }
          else
            {
              if (extract_cmp_data (ciph, "a", tbl[tno].m[mno].encr,
                                    tbl[tno].m[mno].desc))
                {
                  show_sexp ("encrypt result:\n", ciph);
                  fail ("mismatch in gcry_pk_encrypt\n");
                }
              gcry_sexp_release (ciph);
              ciph = NULL;
            }
          gcry_sexp_release (plain);
          plain = NULL;

          /* Now test the decryption.  */
          seed = data_from_hex (tbl[tno].m[mno].seed, &seed_len);
          encr = data_from_hex (tbl[tno].m[mno].encr, &encr_len);

          err = gcry_sexp_build (&ciph, NULL,
                                 "(enc-val (flags pkcs1)(hash-algo sha1)"
                                 "(random-override %b)"
                                 "(rsa (a %b)))",
                                 (int)seed_len, seed,
                                 (int)encr_len, encr);
          if (err)
            die ("constructing cipher data failed: %s\n", gpg_strerror (err));
          gcry_free (encr);
          gcry_free (seed);

          err = gcry_pk_decrypt (&plain, ciph, sec_key);
          if (err)
            {
              show_sexp ("ciph:\n", ciph);
              fail ("gcry_pk_decrypt failed: %s\n", gpg_strerror (err));
            }
          else
            {
              if (extract_cmp_data (plain, "value", tbl[tno].m[mno].mesg,
                                    tbl[tno].m[mno].desc))
                {
                  show_sexp ("decrypt result:\n", plain);
                  fail ("mismatch in gcry_pk_decrypt\n");
                }
              gcry_sexp_release (plain);
              plain = NULL;
            }
          gcry_sexp_release (ciph);
          ciph = NULL;
        }

      gcry_sexp_release (sec_key);
      gcry_sexp_release (pub_key);
    }
}
Exemple #9
0
/* Check against PKCS#1 v1.5 signature test vectors as found at
   ftp://ftp.rsa.com/pub/rsalabs/tmp/pkcs1v15sign-vectors.txt .  */
static void
check_v15sign (void)
{
#include "pkcs1v2-v15s.h"
  gpg_error_t err;
  int tno, mno;

  for (tno = 0; tno < DIM (tbl); tno++)
    {
      void *rsa_n, *rsa_e, *rsa_d;
      size_t rsa_n_len, rsa_e_len, rsa_d_len;
      gcry_sexp_t sec_key, pub_key;

      if (verbose > 1)
        info ("(%s)\n", tbl[tno].desc);

      rsa_n = data_from_hex (tbl[tno].n, &rsa_n_len);
      rsa_e = data_from_hex (tbl[tno].e, &rsa_e_len);
      rsa_d = data_from_hex (tbl[tno].d, &rsa_d_len);
      err = gcry_sexp_build (&sec_key, NULL,
                             "(private-key (rsa (n %b)(e %b)(d %b)))",
                             (int)rsa_n_len, rsa_n,
                             (int)rsa_e_len, rsa_e,
                             (int)rsa_d_len, rsa_d);
      if (err)
        die ("constructing private key failed: %s\n", gpg_strerror (err));
      err = gcry_sexp_build (&pub_key, NULL,
                             "(public-key (rsa (n %b)(e %b)))",
                             (int)rsa_n_len, rsa_n,
                             (int)rsa_e_len, rsa_e);
      if (err)
        die ("constructing public key failed: %s\n", gpg_strerror (err));
      gcry_free (rsa_n);
      gcry_free (rsa_e);
      gcry_free (rsa_d);

      for (mno = 0; mno < DIM (tbl[0].m); mno++)
        {
          void *mesg, *sign;
          size_t mesg_len, sign_len;
          gcry_sexp_t sigtmpl, sig;
          char mhash[20];

          if (verbose)
            info ("running test: %s\n", tbl[tno].m[mno].desc);

          mesg = data_from_hex (tbl[tno].m[mno].mesg, &mesg_len);

          gcry_md_hash_buffer (GCRY_MD_SHA1, mhash, mesg, mesg_len);
          err = gcry_sexp_build (&sigtmpl, NULL,
                                 "(data (flags pkcs1)"
                                 "(hash sha1 %b))",
                                 20, mhash);
          if (err)
            die ("constructing sig template failed: %s\n", gpg_strerror (err));
          gcry_free (mesg);

          err = gcry_pk_sign (&sig, sigtmpl, sec_key);
          if (err)
            {
              show_sexp ("sigtmpl:\n", sigtmpl);
              fail ("gcry_pk_sign failed: %s\n", gpg_strerror (err));
            }
          else
            {
              if (extract_cmp_data (sig, "s", tbl[tno].m[mno].sign,
                                    tbl[tno].m[mno].desc))
                {
                  show_sexp ("sign result:\n", sig);
                  fail ("mismatch in gcry_pk_sign\n");
                }
              gcry_sexp_release (sig);
              sig = NULL;
            }
          gcry_sexp_release (sigtmpl);
          sigtmpl = NULL;

          /* Now test the verification.  */
          sign = data_from_hex (tbl[tno].m[mno].sign, &sign_len);

          err = gcry_sexp_build (&sig, NULL,
                                 "(sig-val(rsa(s %b)))",
                                 (int)sign_len, sign);
          if (err)
            die ("constructing verify data failed: %s\n", gpg_strerror (err));
          err = gcry_sexp_build (&sigtmpl, NULL,
                                 "(data (flags pkcs1)"
                                 "(hash sha1 %b))",
                                 20, mhash);
          if (err)
            die ("constructing verify tmpl failed: %s\n", gpg_strerror (err));
          gcry_free (sign);

          err = gcry_pk_verify (sig, sigtmpl, pub_key);
          if (err)
            {
              show_sexp ("sig:\n", sig);
              show_sexp ("sigtmpl:\n", sigtmpl);
              fail ("gcry_pk_verify failed: %s\n", gpg_strerror (err));
            }
          gcry_sexp_release (sig);
          sig = NULL;
          gcry_sexp_release (sigtmpl);
          sigtmpl = NULL;
        }

      gcry_sexp_release (sec_key);
      gcry_sexp_release (pub_key);
    }
}
Exemple #10
0
void aes256ctr_done(struct aes256ctr *ac)
{
  gcry_cipher_close(ac->ch);
  memset(ac->buf, 0, CIPHER_BLOCK_SIZE);
  gcry_free(ac);
}
void Cipher::computeAES(){
         Util print;
    //rePlain = new QRegExp("^[\\w|/]+\\.(plain)$");
    reCipher = new QRegExp("([\\w]+)");
    // Next line is not needed since we derive the key from the passphrase
    // reKey = new QRegExp("^[\\w|/]+\\.(key)$");

    reIv = new QRegExp("[a-fA-F0-9]+");

    // Let's derive the key given by the password
    if( (leKey->text().isEmpty() || lePlain->text().isEmpty() || leCipher->text().isEmpty() || leIv->text().size() != 16 && radioIv->isChecked()) )
    {
        mb = new QMessageBox(this);
        mb->setWindowTitle("Information");
        mb->setText("One field is still empty!");
        mb->exec();
        return ;
    }

    int keylen = comboSize->currentText().toLocal8Bit().toInt()/8;
    int pass_len = leKey->text().length();

    // Here check whether radioIv is checked and if not randomly generate IV and store in the file
    unsigned char *iv = NULL;
    int blklen = gcry_cipher_get_algo_blklen(GCRY_CIPHER_AES);

    if(!radioIv->isChecked())
    {
        iv = (unsigned char *) gcry_calloc(blklen, sizeof(unsigned char));
        gcry_randomize(iv, blklen, GCRY_STRONG_RANDOM);
    }
    else
        iv = (unsigned char *) leIv->text().toLocal8Bit().constData();

    int hash_len = gcry_md_get_algo_dlen(GCRY_MD_SHA256);

    unsigned char *pass = (unsigned char *) gcry_calloc(sizeof(unsigned char), hash_len);
    strcpy( (char *) pass, leKey->text().toLocal8Bit().constData());

    gcry_error_t err = 0;
    gcry_md_hd_t hd = NULL;

    if(err = gcry_md_open(&hd, GCRY_MD_SHA256, GCRY_MD_FLAG_SECURE))
    {
            fprintf (stderr, "Failure to open MD_SHA256: %s/%s\n",
                                gcry_strsource (err),
                                gcry_strerror (err));
            goto out;
    }

    gcry_md_write(hd, pass, pass_len);

    if(pass)
        gcry_free(pass);

    pass = gcry_md_read(hd, GCRY_MD_SHA256);

    /*
        Dans un soucis de contrôle minimaliste des entrées, nous vérifions, avant toutes opérations, que les
        QLineEdit contienne bien une extension .in pour le fichier d'entrée, une extension .out pour le fi-
        chier de sortie et une extension .key pour le fichier de clé
    */
    if(!reIv->exactMatch(leIv->text()) && radioIv->isChecked())
    {
      mb = new QMessageBox(this);
      mb->setText("The IV field is incorrect");
      mb->setWindowTitle("Information");
      mb->exec();
    return ;
    }

    if(reCipher->exactMatch(leCipher->text()))
    {
        aes = new AES();

        if(!(strcmp(comboMode->currentText().toLocal8Bit().constData(), "CBC") ||
                strcmp(comboSize->currentText().toLocal8Bit().constData(), "128")))
        {
            printf("AES-128-CBC encryption\n");
            rep = aes->aes_encrypt(lePlain->text().toLocal8Bit().constData(),
                                   leCipher->text().toLocal8Bit().constData(),
                                   GCRY_CIPHER_AES, comboMode->currentData().toInt(),
                                   (const char *) pass, (const char*) iv);
        }
        else if(!(strcmp(comboMode->currentText().toLocal8Bit().constData(), "CBC") ||
                  strcmp(comboSize->currentText().toLocal8Bit().constData(), "256")))
        {
            printf("AES-256-CBC encryption\n");
            rep = aes->aes_cbc_256_encrypt(lePlain->text().toLocal8Bit().constData(),
                                           leCipher->text().toLocal8Bit().constData(),
                                           (const char *) pass, (const char *) iv);
        }

        if(rep == 1){
            mb = new QMessageBox(this);
            mb->setText("Symmetric encryption error");
            mb->setWindowTitle("Information");
            mb->exec();

        }else{
            mb = new QMessageBox(this);
            mb->setWindowTitle("Information");
            mb->setText("Success");
            mb->exec();
            this->close();
        }
    }
    else{
        /*if(!rePlain->exactMatch(lePlain->text())){
          mb = new QMessageBox(this);
          mb->setText("The given plain file is wrong.");
          mb->setWindowTitle("Information");
          mb->exec();
          this->close();
        }
        else if(!reKey->exactMatch(leKey->text())){
          mb = new QMessageBox(this);
          mb->setText("The given key is wrong.");
          mb->setWindowTitle("Information");
          mb->exec();
          this->close();
        }*/
        if(!reCipher->exactMatch(leCipher->text())){
          mb = new QMessageBox(this);
          mb->setText("The given name doesn't respect the given format.");
          mb->setWindowTitle("Information");
          mb->exec();
          this->close();
        }
    }

    // not actually needed, it is done by derivePassphrase
    // why is gcry_free(pass) failing?

    out:
    memset(pass, 0, hash_len);
    memset(iv, 0, blklen);

    leKey->clear();
    leIv->clear();

    if(hd)
        gcry_md_close(hd);

    if(iv && !radioIv->isChecked())
        gcry_free(iv);

    return ;
}
Exemple #12
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 #13
0
/* Return the Secure Shell type fingerprint for KEY using digest ALGO.
   The length of the fingerprint is returned at R_LEN and the
   fingerprint itself at R_FPR.  In case of a error code is returned
   and NULL stored at R_FPR.  */
static gpg_error_t
get_fingerprint (gcry_sexp_t key, int algo,
                 void **r_fpr, size_t *r_len, int as_string)
{
  gpg_error_t err;
  gcry_sexp_t list = NULL;
  gcry_sexp_t l2 = NULL;
  const char *s;
  char *name = NULL;
  int idx;
  const char *elems;
  gcry_md_hd_t md = NULL;
  int blobmode = 0;

  *r_fpr = NULL;
  *r_len = 0;

  /* Check that the first element is valid. */
  list = gcry_sexp_find_token (key, "public-key", 0);
  if (!list)
    list = gcry_sexp_find_token (key, "private-key", 0);
  if (!list)
    list = gcry_sexp_find_token (key, "protected-private-key", 0);
  if (!list)
    list = gcry_sexp_find_token (key, "shadowed-private-key", 0);
  if (!list)
    {
      err = gpg_err_make (default_errsource, GPG_ERR_UNKNOWN_SEXP);
      goto leave;
    }

  l2 = gcry_sexp_cadr (list);
  gcry_sexp_release (list);
  list = l2;
  l2 = NULL;

  name = gcry_sexp_nth_string (list, 0);
  if (!name)
    {
      err = gpg_err_make (default_errsource, GPG_ERR_INV_SEXP);
      goto leave;
    }

  err = gcry_md_open (&md, algo, 0);
  if (err)
    goto leave;

  switch (gcry_pk_map_name (name))
    {
    case GCRY_PK_RSA:
      elems = "en";
      gcry_md_write (md, "\0\0\0\x07ssh-rsa", 11);
      break;

    case GCRY_PK_DSA:
      elems = "pqgy";
      gcry_md_write (md, "\0\0\0\x07ssh-dss", 11);
      break;

    case GCRY_PK_ECC:
      if (is_eddsa (list))
        {
          elems = "q";
          blobmode = 1;
          /* For now there is just one curve, thus no need to switch
             on it.  */
          gcry_md_write (md, "\0\0\0\x0b" "ssh-ed25519", 15);
        }
      else
        {
          /* We only support the 3 standard curves for now.  It is
             just a quick hack.  */
          elems = "q";
          gcry_md_write (md, "\0\0\0\x13" "ecdsa-sha2-nistp", 20);
          l2 = gcry_sexp_find_token (list, "curve", 0);
          if (!l2)
            elems = "";
          else
            {
              gcry_free (name);
              name = gcry_sexp_nth_string (l2, 1);
              gcry_sexp_release (l2);
              l2 = NULL;
              if (!name)
                elems = "";
              else if (!strcmp (name, "NIST P-256")||!strcmp (name, "nistp256"))
                gcry_md_write (md, "256\0\0\0\x08nistp256", 15);
              else if (!strcmp (name, "NIST P-384")||!strcmp (name, "nistp384"))
                gcry_md_write (md, "384\0\0\0\x08nistp384", 15);
              else if (!strcmp (name, "NIST P-521")||!strcmp (name, "nistp521"))
                gcry_md_write (md, "521\0\0\0\x08nistp521", 15);
              else
                elems = "";
            }
          if (!*elems)
            err = gpg_err_make (default_errsource, GPG_ERR_UNKNOWN_CURVE);
        }
      break;

    default:
      elems = "";
      err = gpg_err_make (default_errsource, GPG_ERR_PUBKEY_ALGO);
      break;
    }
  if (err)
    goto leave;


  for (idx = 0, s = elems; *s; s++, idx++)
    {
      l2 = gcry_sexp_find_token (list, s, 1);
      if (!l2)
        {
          err = gpg_err_make (default_errsource, GPG_ERR_INV_SEXP);
          goto leave;
        }
      if (blobmode)
        {
          const char *blob;
          size_t bloblen;
          unsigned char lenbuf[4];

          blob = gcry_sexp_nth_data (l2, 1, &bloblen);
          if (!blob)
            {
              err = gpg_err_make (default_errsource, GPG_ERR_INV_SEXP);
              goto leave;
            }
          blob++;
          bloblen--;
          lenbuf[0] = bloblen >> 24;
          lenbuf[1] = bloblen >> 16;
          lenbuf[2] = bloblen >>  8;
          lenbuf[3] = bloblen;
          gcry_md_write (md, lenbuf, 4);
          gcry_md_write (md, blob, bloblen);
        }
      else
        {
          gcry_mpi_t a;
          unsigned char *buf;
          size_t buflen;

          a = gcry_sexp_nth_mpi (l2, 1, GCRYMPI_FMT_USG);
          gcry_sexp_release (l2);
          l2 = NULL;
          if (!a)
            {
              err = gpg_err_make (default_errsource, GPG_ERR_INV_SEXP);
              goto leave;
            }

          err = gcry_mpi_aprint (GCRYMPI_FMT_SSH, &buf, &buflen, a);
          gcry_mpi_release (a);
          if (err)
            goto leave;
          gcry_md_write (md, buf, buflen);
          gcry_free (buf);
        }
    }
Exemple #14
0
/* Assume that the reader is at a pkcs#12 message and try to import
   certificates from that stupid format.  We will transfer secret
   keys to the agent.  */
static gpg_error_t
parse_p12 (ctrl_t ctrl, ksba_reader_t reader, struct stats_s *stats)
{
  gpg_error_t err = 0;
  char buffer[1024];
  size_t ntotal, nread;
  membuf_t p12mbuf;
  char *p12buffer = NULL;
  size_t p12buflen;
  size_t p12bufoff;
  gcry_mpi_t *kparms = NULL;
  struct rsa_secret_key_s sk;
  char *passphrase = NULL;
  unsigned char *key = NULL;
  size_t keylen;
  void *kek = NULL;
  size_t keklen;
  unsigned char *wrappedkey = NULL;
  size_t wrappedkeylen;
  gcry_cipher_hd_t cipherhd = NULL;
  gcry_sexp_t s_key = NULL;
  unsigned char grip[20];
  int bad_pass = 0;
  int i;
  struct store_cert_parm_s store_cert_parm;

  memset (&store_cert_parm, 0, sizeof store_cert_parm);
  store_cert_parm.ctrl = ctrl;
  store_cert_parm.stats = stats;

  init_membuf (&p12mbuf, 4096);
  ntotal = 0;
  while (!(err = ksba_reader_read (reader, buffer, sizeof buffer, &nread)))
    {
      if (ntotal >= MAX_P12OBJ_SIZE*1024)
        {
          /* Arbitrary limit to avoid DoS attacks. */
          err = gpg_error (GPG_ERR_TOO_LARGE);
          log_error ("pkcs#12 object is larger than %dk\n", MAX_P12OBJ_SIZE);
          break;
        }
      put_membuf (&p12mbuf, buffer, nread);
      ntotal += nread;
    }
  if (gpg_err_code (err) == GPG_ERR_EOF)
    err = 0;
  if (!err)
    {
      p12buffer = get_membuf (&p12mbuf, &p12buflen);
      if (!p12buffer)
        err = gpg_error_from_syserror ();
    }
  if (err)
    {
      log_error (_("error reading input: %s\n"), gpg_strerror (err));
      goto leave;
    }

  /* GnuPG 2.0.4 accidently created binary P12 files with the string
     "The passphrase is %s encoded.\n\n" prepended to the ASN.1 data.
     We fix that here.  */
  if (p12buflen > 29 && !memcmp (p12buffer, "The passphrase is ", 18))
    {
      for (p12bufoff=18;
           p12bufoff < p12buflen && p12buffer[p12bufoff] != '\n';
           p12bufoff++)
        ;
      p12bufoff++;
      if (p12bufoff < p12buflen && p12buffer[p12bufoff] == '\n')
        p12bufoff++;
    }
  else
    p12bufoff = 0;


  err = gpgsm_agent_ask_passphrase
    (ctrl,
     i18n_utf8 ("Please enter the passphrase to unprotect the PKCS#12 object."),
     0, &passphrase);
  if (err)
    goto leave;

  kparms = p12_parse (p12buffer + p12bufoff, p12buflen - p12bufoff,
                      passphrase, store_cert_cb, &store_cert_parm, &bad_pass);

  xfree (passphrase);
  passphrase = NULL;

  if (!kparms)
    {
      log_error ("error parsing or decrypting the PKCS#12 file\n");
      err = gpg_error (GPG_ERR_INV_OBJ);
      goto leave;
    }

/*    print_mpi ("   n", kparms[0]); */
/*    print_mpi ("   e", kparms[1]); */
/*    print_mpi ("   d", kparms[2]); */
/*    print_mpi ("   p", kparms[3]); */
/*    print_mpi ("   q", kparms[4]); */
/*    print_mpi ("dmp1", kparms[5]); */
/*    print_mpi ("dmq1", kparms[6]); */
/*    print_mpi ("   u", kparms[7]); */

  sk.n = kparms[0];
  sk.e = kparms[1];
  sk.d = kparms[2];
  sk.q = kparms[3];
  sk.p = kparms[4];
  sk.u = kparms[7];
  err = rsa_key_check (&sk);
  if (err)
    goto leave;
/*    print_mpi ("   n", sk.n); */
/*    print_mpi ("   e", sk.e); */
/*    print_mpi ("   d", sk.d); */
/*    print_mpi ("   p", sk.p); */
/*    print_mpi ("   q", sk.q); */
/*    print_mpi ("   u", sk.u); */

  /* Create an S-expresion from the parameters. */
  err = gcry_sexp_build (&s_key, NULL,
                         "(private-key(rsa(n%m)(e%m)(d%m)(p%m)(q%m)(u%m)))",
                         sk.n, sk.e, sk.d, sk.p, sk.q, sk.u, NULL);
  for (i=0; i < 8; i++)
    gcry_mpi_release (kparms[i]);
  gcry_free (kparms);
  kparms = NULL;
  if (err)
    {
      log_error ("failed to create S-expression from key: %s\n",
                 gpg_strerror (err));
      goto leave;
    }

  /* Compute the keygrip. */
  if (!gcry_pk_get_keygrip (s_key, grip))
    {
      err = gpg_error (GPG_ERR_GENERAL);
      log_error ("can't calculate keygrip\n");
      goto leave;
    }
  log_printhex ("keygrip=", grip, 20);

  /* Convert to canonical encoding using a function which pads it to a
     multiple of 64 bits.  We need this padding for AESWRAP.  */
  err = make_canon_sexp_pad (s_key, 1, &key, &keylen);
  if (err)
    {
      log_error ("error creating canonical S-expression\n");
      goto leave;
    }
  gcry_sexp_release (s_key);
  s_key = NULL;

  /* Get the current KEK.  */
  err = gpgsm_agent_keywrap_key (ctrl, 0, &kek, &keklen);
  if (err)
    {
      log_error ("error getting the KEK: %s\n", gpg_strerror (err));
      goto leave;
    }

  /* Wrap the key.  */
  err = gcry_cipher_open (&cipherhd, GCRY_CIPHER_AES128,
                          GCRY_CIPHER_MODE_AESWRAP, 0);
  if (err)
    goto leave;
  err = gcry_cipher_setkey (cipherhd, kek, keklen);
  if (err)
    goto leave;
  xfree (kek);
  kek = NULL;

  wrappedkeylen = keylen + 8;
  wrappedkey = xtrymalloc (wrappedkeylen);
  if (!wrappedkey)
    {
      err = gpg_error_from_syserror ();
      goto leave;
    }

  err = gcry_cipher_encrypt (cipherhd, wrappedkey, wrappedkeylen, key, keylen);
  if (err)
    goto leave;
  xfree (key);
  key = NULL;
  gcry_cipher_close (cipherhd);
  cipherhd = NULL;

  /* Send the wrapped key to the agent.  */
  err = gpgsm_agent_import_key (ctrl, wrappedkey, wrappedkeylen);
  if (!err)
    {
      stats->count++;
      stats->secret_read++;
      stats->secret_imported++;
    }
  else if ( gpg_err_code (err) == GPG_ERR_EEXIST )
    {
      err = 0;
      stats->count++;
      stats->secret_read++;
      stats->secret_dups++;
    }

  /* If we did not get an error from storing the secret key we return
     a possible error from parsing the certificates.  We do this after
     storing the secret keys so that a bad certificate does not
     inhibit our chance to store the secret key.  */
  if (!err && store_cert_parm.err)
    err = store_cert_parm.err;

 leave:
  if (kparms)
    {
      for (i=0; i < 8; i++)
        gcry_mpi_release (kparms[i]);
      gcry_free (kparms);
      kparms = NULL;
    }
  xfree (key);
  gcry_sexp_release (s_key);
  xfree (passphrase);
  gcry_cipher_close (cipherhd);
  xfree (wrappedkey);
  xfree (kek);
  xfree (get_membuf (&p12mbuf, NULL));
  xfree (p12buffer);

  if (bad_pass)
    {
      /* We only write a plain error code and not direct
         BAD_PASSPHRASE because the pkcs12 parser might issue this
         message multiple times, BAD_PASSPHRASE in general requires a
         keyID and parts of the import might actually succeed so that
         IMPORT_PROBLEM is also not appropriate. */
      gpgsm_status_with_err_code (ctrl, STATUS_ERROR,
                                  "import.parsep12", GPG_ERR_BAD_PASSPHRASE);
    }

  return err;
}
Exemple #15
0
gboolean
egg_hkdf_perform (const gchar *hash_algo, gconstpointer input, gsize n_input,
                  gconstpointer salt, gsize n_salt, gconstpointer info,
                  gsize n_info, gpointer output, gsize n_output)
{
	gpointer alloc = NULL;
	gpointer buffer = NULL;
	gcry_md_hd_t md1, md2;
	guint hash_len;
	gint i;
	gint flags, algo;
	gsize step, n_buffer;
	guchar *at;
	gcry_error_t gcry;

	algo = gcry_md_map_name (hash_algo);
	g_return_val_if_fail (algo != 0, FALSE);

	hash_len = gcry_md_get_algo_dlen (algo);
	g_return_val_if_fail (hash_len != 0, FALSE);
	g_return_val_if_fail (n_output <= 255 * hash_len, FALSE);

	/* Buffer we need to for intermediate stuff */
	if (gcry_is_secure (input)) {
		flags = GCRY_MD_FLAG_SECURE;
		buffer = gcry_malloc_secure (hash_len);
	} else {
		flags = 0;
		buffer = gcry_malloc (hash_len);
	}

	g_return_val_if_fail (buffer, FALSE);
	n_buffer = 0;

	/* Salt defaults to hash_len zeros */
	if (!salt) {
		salt = alloc = g_malloc0 (hash_len);
		n_salt = hash_len;
	}

	/* Step 1: Extract */
	gcry = gcry_md_open (&md1, algo, GCRY_MD_FLAG_HMAC | flags);
	g_return_val_if_fail (gcry == 0, FALSE);
	gcry = gcry_md_setkey (md1, salt, n_salt);
	g_return_val_if_fail (gcry == 0, FALSE);
	gcry_md_write (md1, input, n_input);

	/* Step 2: Expand */
	gcry = gcry_md_open (&md2, algo, GCRY_MD_FLAG_HMAC | flags);
	g_return_val_if_fail (gcry == 0, FALSE);
	gcry = gcry_md_setkey (md2, gcry_md_read (md1, algo), hash_len);
	g_return_val_if_fail (gcry == 0, FALSE);
	gcry_md_close (md1);

	at = output;
	for (i = 1; i < 256; ++i) {
		gcry_md_reset (md2);
		gcry_md_write (md2, buffer, n_buffer);
		gcry_md_write (md2, info, n_info);
		gcry_md_putc (md2, i);

		n_buffer = hash_len;
		memcpy (buffer, gcry_md_read (md2, algo), n_buffer);

		step = MIN (n_buffer, n_output);
		memcpy (at, buffer, step);
		n_output -= step;
		at += step;

		if (!n_output)
			break;
	}

	g_free (alloc);
	gcry_free (buffer);
	return TRUE;
}
Exemple #16
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 #17
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 #18
0
/*
 * Generate a random secret exponent K less than Q.
 * Note that ECDSA uses this code also to generate D.
 */
gcry_mpi_t
_gcry_dsa_gen_k (gcry_mpi_t q, int security_level)
{
  gcry_mpi_t k        = mpi_alloc_secure (mpi_get_nlimbs (q));
  unsigned int nbits  = mpi_get_nbits (q);
  unsigned int nbytes = (nbits+7)/8;
  char *rndbuf = NULL;

  /* To learn why we don't use mpi_mod to get the requested bit size,
     read the paper: "The Insecurity of the Digital Signature
     Algorithm with Partially Known Nonces" by Nguyen and Shparlinski.
     Journal of Cryptology, New York. Vol 15, nr 3 (2003)  */

  if (DBG_CIPHER)
    log_debug ("choosing a random k of %u bits at seclevel %d\n",
               nbits, security_level);
  for (;;)
    {
      if ( !rndbuf || nbits < 32 )
        {
          gcry_free (rndbuf);
          rndbuf = gcry_random_bytes_secure (nbytes, security_level);
	}
      else
        { /* Change only some of the higher bits.  We could improve
	     this by directly requesting more memory at the first call
	     to get_random_bytes() and use these extra bytes here.
	     However the required management code is more complex and
	     thus we better use this simple method.  */
          char *pp = gcry_random_bytes_secure (4, security_level);
          memcpy (rndbuf, pp, 4);
          gcry_free (pp);
	}
      _gcry_mpi_set_buffer (k, rndbuf, nbytes, 0);

      /* Make sure we have the requested number of bits.  This code
         looks a bit funny but it is easy to understand if you
         consider that mpi_set_highbit clears all higher bits.  We
         don't have a clear_highbit, thus we first set the high bit
         and then clear it again.  */
      if (mpi_test_bit (k, nbits-1))
        mpi_set_highbit (k, nbits-1);
      else
        {
          mpi_set_highbit (k, nbits-1);
          mpi_clear_bit (k, nbits-1);
	}

      if (!(mpi_cmp (k, q) < 0))    /* check: k < q */
        {
          if (DBG_CIPHER)
            log_debug ("\tk too large - again\n");
          continue; /* no  */
        }
      if (!(mpi_cmp_ui (k, 0) > 0)) /* check: k > 0 */
        {
          if (DBG_CIPHER)
            log_debug ("\tk is zero - again\n");
          continue; /* no */
        }
      break;	/* okay */
    }
  gcry_free (rndbuf);

  return k;
}
Exemple #19
0
static void
cipher_bench ( const char *algoname )
{
  static int header_printed;
  int algo;
  gcry_cipher_hd_t hd;
  int i;
  int keylen, blklen;
  char key[128];
  char *outbuf, *buf;
  char *raw_outbuf, *raw_buf;
  size_t allocated_buflen, buflen;
  int repetitions;
  static struct { int mode; const char *name; int blocked; } modes[] = {
    { GCRY_CIPHER_MODE_ECB, "   ECB/Stream", 1 },
    { GCRY_CIPHER_MODE_CBC, "      CBC", 1 },
    { GCRY_CIPHER_MODE_CFB, "      CFB", 0 },
    { GCRY_CIPHER_MODE_OFB, "      OFB", 0 },
    { GCRY_CIPHER_MODE_CTR, "      CTR", 0 },
    { GCRY_CIPHER_MODE_STREAM, "", 0 },
    {0}
  };
  int modeidx;
  gcry_error_t err = GPG_ERR_NO_ERROR;


  if (!algoname)
    {
      for (i=1; i < 400; i++)
        if ( !gcry_cipher_test_algo (i) )
          cipher_bench (gcry_cipher_algo_name (i));
      return;
    }

  if (large_buffers)
    {
      allocated_buflen = 1024 * 100;
      repetitions = 10;
    }
  else
    {
      allocated_buflen = 1024;
      repetitions = 1000;
    }
  repetitions *= cipher_repetitions;

  raw_buf = gcry_xmalloc (allocated_buflen+15);
  buf = (raw_buf
         + ((16 - ((size_t)raw_buf & 0x0f)) % buffer_alignment));
  outbuf = raw_outbuf = gcry_xmalloc (allocated_buflen+15);
  outbuf = (raw_outbuf
            + ((16 - ((size_t)raw_outbuf & 0x0f)) % buffer_alignment));

  if (!header_printed)
    {
      if (cipher_repetitions != 1)
        printf ("Running each test %d times.\n", cipher_repetitions);
      printf ("%-12s", "");
      for (modeidx=0; modes[modeidx].mode; modeidx++)
        if (*modes[modeidx].name)
          printf (" %-15s", modes[modeidx].name );
      putchar ('\n');
      printf ("%-12s", "");
      for (modeidx=0; modes[modeidx].mode; modeidx++)
        if (*modes[modeidx].name)
          printf (" ---------------" );
      putchar ('\n');
      header_printed = 1;
    }

  algo = gcry_cipher_map_name (algoname);
  if (!algo)
    {
      fprintf (stderr, PGM ": invalid cipher algorithm `%s'\n", algoname);
      exit (1);
    }

  keylen = gcry_cipher_get_algo_keylen (algo);
  if (!keylen)
    {
      fprintf (stderr, PGM ": failed to get key length for algorithm `%s'\n",
	       algoname);
      exit (1);
    }
  if ( keylen > sizeof key )
    {
        fprintf (stderr, PGM ": algo %d, keylength problem (%d)\n",
                 algo, keylen );
        exit (1);
    }
  for (i=0; i < keylen; i++)
    key[i] = i + (clock () & 0xff);

  blklen = gcry_cipher_get_algo_blklen (algo);
  if (!blklen)
    {
      fprintf (stderr, PGM ": failed to get block length for algorithm `%s'\n",
	       algoname);
      exit (1);
    }

  printf ("%-12s", gcry_cipher_algo_name (algo));
  fflush (stdout);

  for (modeidx=0; modes[modeidx].mode; modeidx++)
    {
      if ((blklen > 1 && modes[modeidx].mode == GCRY_CIPHER_MODE_STREAM)
          | (blklen == 1 && modes[modeidx].mode != GCRY_CIPHER_MODE_STREAM))
        continue;

      for (i=0; i < sizeof buf; i++)
        buf[i] = i;

      err = gcry_cipher_open (&hd, algo, modes[modeidx].mode, 0);
      if (err)
        {
          fprintf (stderr, PGM ": error opening cipher `%s'\n", algoname);
          exit (1);
        }

      if (!cipher_with_keysetup)
        {
          err = gcry_cipher_setkey (hd, key, keylen);
          if (err)
            {
              fprintf (stderr, "gcry_cipher_setkey failed: %s\n",
                       gpg_strerror (err));
              gcry_cipher_close (hd);
              exit (1);
            }
        }

      buflen = allocated_buflen;
      if (modes[modeidx].blocked)
        buflen = (buflen / blklen) * blklen;

      start_timer ();
      for (i=err=0; !err && i < repetitions; i++)
        {
          if (cipher_with_keysetup)
            {
              err = gcry_cipher_setkey (hd, key, keylen);
              if (err)
                {
                  fprintf (stderr, "gcry_cipher_setkey failed: %s\n",
                           gpg_strerror (err));
                  gcry_cipher_close (hd);
                  exit (1);
                }
            }
          err = gcry_cipher_encrypt ( hd, outbuf, buflen, buf, buflen);
        }
      stop_timer ();

      printf (" %s", elapsed_time ());
      fflush (stdout);
      gcry_cipher_close (hd);
      if (err)
        {
          fprintf (stderr, "gcry_cipher_encrypt failed: %s\n",
                   gpg_strerror (err) );
          exit (1);
        }

      err = gcry_cipher_open (&hd, algo, modes[modeidx].mode, 0);
      if (err)
        {
          fprintf (stderr, PGM ": error opening cipher `%s'/n", algoname);
          exit (1);
        }

      if (!cipher_with_keysetup)
        {
          err = gcry_cipher_setkey (hd, key, keylen);
          if (err)
            {
              fprintf (stderr, "gcry_cipher_setkey failed: %s\n",
                       gpg_strerror (err));
              gcry_cipher_close (hd);
              exit (1);
            }
        }

      start_timer ();
      for (i=err=0; !err && i < repetitions; i++)
        {
          if (cipher_with_keysetup)
            {
              err = gcry_cipher_setkey (hd, key, keylen);
              if (err)
                {
                  fprintf (stderr, "gcry_cipher_setkey failed: %s\n",
                           gpg_strerror (err));
                  gcry_cipher_close (hd);
                  exit (1);
                }
            }
          err = gcry_cipher_decrypt ( hd, outbuf, buflen,  buf, buflen);
        }
      stop_timer ();
      printf (" %s", elapsed_time ());
      fflush (stdout);
      gcry_cipher_close (hd);
      if (err)
        {
          fprintf (stderr, "gcry_cipher_decrypt failed: %s\n",
                   gpg_strerror (err) );
          exit (1);
        }
    }

  putchar ('\n');
  gcry_free (raw_buf);
  gcry_free (raw_outbuf);
}
Exemple #20
0
int main(int argc, char **argv)
{
	int ret;
	setlocale(LC_ALL, "");

	if (argc != 3) {
		wprintf(L"Usage: psafe file.psafe3 passphrase");
		exit(EXIT_FAILURE);
	}

	init_crypto(64*1024);

	size_t sz;
	uint8_t *ptr;
	ptr = mapfile_ro(argv[1], &sz);
	if (ptr == NULL)
		err(1, "%s", argv[1]);

	struct psafe3_pro *pro;
	pro = (struct psafe3_pro *)(ptr + 4);
	struct safe_sec *sec;
	sec = gcry_malloc_secure(sizeof(*sec));
	ret = stretch_and_check_pass(argv[2], strlen(argv[2]), pro, sec);
	if (ret != 0) {
		gcry_free(sec);
		wprintf(L"Invalid password.\n");
		exit(1);
	}

	uint8_t *safe;
	size_t safe_size;
	safe_size = sz - (4 + sizeof(*pro) + 48);
	assert(safe_size > 0);
	assert(safe_size % TWOF_BLKSIZE == 0);
	safe = gcry_malloc_secure(safe_size);
	assert(safe != NULL);

	gcry_error_t gerr;
	struct decrypt_ctx ctx;
	if (init_decrypt_ctx(&ctx, pro, sec) < 0)
		gcrypt_fatal(ctx.gerr);

	size_t bcnt;
	bcnt = safe_size / TWOF_BLKSIZE;
	assert(bcnt > 0);
	uint8_t *encp;
	uint8_t *safep;
	encp = ptr + 4 + sizeof(*pro);
	safep = safe;
	while (bcnt--) {
		gerr = gcry_cipher_decrypt(ctx.cipher, safep, TWOF_BLKSIZE, encp, TWOF_BLKSIZE);
		if (gerr != GPG_ERR_NO_ERROR)
			gcrypt_fatal(gerr);
		safep += TWOF_BLKSIZE;
		encp += TWOF_BLKSIZE;
	}

	enum { HDR, DB };
	int state = HDR;
	safep = safe;
	while (safep < safe + safe_size) {
		struct field *fld;
		fld = (struct field *)safep;
		wprintf(L"len=%-3u  type=%02x  ", fld->len, fld->type);
		if (state == DB)
			db_print(stdout, fld);
		else
			hd_print(stdout, fld);
		if (fld->type == 0xff)
			state = DB;
		putwc('\n', stdout);
		if (fld->len)
			gcry_md_write(ctx.hmac, safep + sizeof(*fld), fld->len);
		safep += ((fld->len + 5 + 15) / TWOF_BLKSIZE) * TWOF_BLKSIZE;
	}

	assert(memcmp(ptr + (sz - 48), "PWS3-EOFPWS3-EOF", TWOF_BLKSIZE) == 0);

#define EOL() putwc('\n', stdout)
	EOL();
	print_prologue(stdout, pro);
	wprintf(L"KEY    "); printhex(stdout, sec->pprime, 32); EOL();
	wprintf(L"H(KEY) "); printhex(stdout, pro->h_pprime, 32); EOL();

	gcry_md_final(ctx.hmac);
	wprintf(L"HMAC'  ");
	uint8_t hmac[32];
	memmove(hmac, gcry_md_read(ctx.hmac, GCRY_MD_SHA256), 32);
	printhex(stdout, hmac, 32);
	EOL();

	wprintf(L"HMAC   ");
	printhex(stdout, ptr + (sz - 32), 32);
	EOL();
#undef EOL

	gcry_free(safe);
	gcry_free(sec);
	unmapfile(ptr, sz);
	term_decrypt_ctx(&ctx);

	exit(0);
}
Exemple #21
0
/* Convert the big integer A into the external representation
   described by FORMAT and store it in the provided BUFFER which has
   been allocated by the user with a size of BUFLEN bytes.  NWRITTEN
   receives the actual length of the external representation unless it
   has been passed as NULL.  BUFFER may be NULL to query the required
   length.  */
gcry_error_t
gcry_mpi_print (enum gcry_mpi_format format,
                unsigned char *buffer, size_t buflen,
                size_t *nwritten, struct gcry_mpi *a)
{
  unsigned int nbits = mpi_get_nbits (a);
  size_t len;
  size_t dummy_nwritten;

  if (!nwritten)
    nwritten = &dummy_nwritten;

  len = buflen;
  *nwritten = 0;
  if (format == GCRYMPI_FMT_STD)
    {
      unsigned char *tmp;
      int extra = 0;
      unsigned int n;

      if (a->sign)
        return gcry_error (GPG_ERR_INTERNAL); /* Can't handle it yet. */

      tmp = _gcry_mpi_get_buffer (a, &n, NULL);
      if (!tmp)
        return gpg_error_from_syserror ();
      if (n && (*tmp & 0x80))
        {
          n++;
          extra=1;
	}

      if (buffer && n > len)
        {
          /* The provided buffer is too short. */
          gcry_free (tmp);
          return gcry_error (GPG_ERR_TOO_SHORT);
	}
      if (buffer)
        {
          unsigned char *s = buffer;

          if (extra)
            *s++ = 0;
          memcpy (s, tmp, n-extra);
	}
      gcry_free(tmp);
      *nwritten = n;
      return 0;
    }
  else if (format == GCRYMPI_FMT_USG)
    {
      unsigned int n = (nbits + 7)/8;

      /* Note:  We ignore the sign for this format.  */
      /* FIXME: for performance reasons we should put this into
	 mpi_aprint because we can then use the buffer directly.  */
      if (buffer && n > len)
        return gcry_error (GPG_ERR_TOO_SHORT);
      if (buffer)
        {
          unsigned char *tmp;

          tmp = _gcry_mpi_get_buffer (a, &n, NULL);
          if (!tmp)
            return gpg_error_from_syserror ();
          memcpy (buffer, tmp, n);
          gcry_free (tmp);
	}
      *nwritten = n;
      return 0;
    }
  else if (format == GCRYMPI_FMT_PGP)
    {
      unsigned int n = (nbits + 7)/8;

      /* The PGP format can only handle unsigned integers.  */
      if( a->sign )
        return gcry_error (GPG_ERR_INV_ARG);

      if (buffer && n+2 > len)
        return gcry_error (GPG_ERR_TOO_SHORT);

      if (buffer)
        {
          unsigned char *tmp;
          unsigned char *s = buffer;

          s[0] = nbits >> 8;
          s[1] = nbits;

          tmp = _gcry_mpi_get_buffer (a, &n, NULL);
          if (!tmp)
            return gpg_error_from_syserror ();
          memcpy (s+2, tmp, n);
          gcry_free (tmp);
	}
      *nwritten = n+2;
      return 0;
    }
Exemple #22
0
/* Fallback method using the registry to poll the statistics.  */
static void
registry_poll (void (*add)(const void*, size_t, enum random_origins),
               enum random_origins requester)
{
  static int cbPerfData = PERFORMANCE_BUFFER_SIZE;
  int iterations;
  DWORD dwSize, status;
  PERF_DATA_BLOCK *pPerfData;

  /* Get information from the system performance counters.  This can take a
     few seconds to do.  In some environments the call to RegQueryValueEx()
     can produce an access violation at some random time in the future, in
     some cases adding a short delay after the following code block makes
     the problem go away.  This problem is extremely difficult to
     reproduce, I haven't been able to get it to occur despite running it
     on a number of machines.  MS knowledge base article Q178887 covers
     this type of problem, it's typically caused by an external driver or
     other program that adds its own values under the
     HKEY_PERFORMANCE_DATA key.  The NT kernel, via Advapi32.dll, calls the
     required external module to map in the data inside an SEH try/except
     block, so problems in the module's collect function don't pop up until
     after it has finished, so the fault appears to occur in Advapi32.dll.
     There may be problems in the NT kernel as well though, a low-level
     memory checker indicated that ExpandEnvironmentStrings() in
     Kernel32.dll, called an interminable number of calls down inside
     RegQueryValueEx(), was overwriting memory (it wrote twice the
     allocated size of a buffer to a buffer allocated by the NT kernel).
     OTOH this could be coming from the external module calling back into
     the kernel, which eventually causes the problem described above.

     Possibly as an extension of the problem that the krnlWaitSemaphore()
     call above works around, running two instances of cryptlib (e.g. two
     applications that use it) under NT4 can result in one of them hanging
     in the RegQueryValueEx() call.  This happens only under NT4 and is
     hard to reproduce in any consistent manner.

     One workaround that helps a bit is to read the registry as a remote
     (rather than local) registry, it's possible that the use of a network
     RPC call isolates the calling app from the problem in that whatever
     service handles the RPC is taking the hit and not affecting the
     calling app.  Since this would require another round of extensive
     testing to verify and the NT native API call is working fine, we'll
     stick with the native API call for now.

     Some versions of NT4 had a problem where the amount of data returned
     was mis-reported and would never settle down, because of this the code
     below includes a safety-catch that bails out after 10 attempts have
     been made, this results in no data being returned but at does ensure
     that the thread will terminate.

     In addition to these problems the code in RegQueryValueEx() that
     estimates the amount of memory required to return the performance
     counter information isn't very accurate (it's much worse than the
     "slightly-inaccurate" level that the MS docs warn about, it's usually
     wildly off) since it always returns a worst-case estimate which is
     usually nowhere near the actual amount required.  For example it may
     report that 128K of memory is required, but only return 64K of data.

     Even worse than the registry-based performance counters is the
     performance data helper (PDH) shim that tries to make the counters
     look like the old Win16 API (which is also used by Win95).  Under NT
     this can consume tens of MB of memory and huge amounts of CPU time
     while it gathers its data, and even running once can still consume
     about 1/2MB of memory */
  if (getenv ("GNUPG_RNDW32_NOPERF"))
    {
      static int shown;

      if (!shown)
        {
          shown = 1;
          log_info ("note: get performance data has been disabled\n");
        }
    }
  else
    {
      pPerfData = gcry_xmalloc (cbPerfData);
      for (iterations=0; iterations < 10; iterations++)
        {
          dwSize = cbPerfData;
          if ( debug_me )
            log_debug ("rndw32#slow_gatherer_nt: get perf data\n" );

          status = RegQueryValueEx (HKEY_PERFORMANCE_DATA, "Global", NULL,
                                    NULL, (LPBYTE) pPerfData, &dwSize);
          if (status == ERROR_SUCCESS)
            {
              if (!memcmp (pPerfData->Signature, L"PERF", 8))
                (*add) ( pPerfData, dwSize, requester );
              else
                log_debug ("rndw32: no PERF signature\n");
              break;
            }
          else if (status == ERROR_MORE_DATA)
            {
              cbPerfData += PERFORMANCE_BUFFER_STEP;
              pPerfData = gcry_xrealloc (pPerfData, cbPerfData);
            }
          else
            {
              static int been_here;

              /* Silence the error message.  In particular under Wine (as
                 of 2008) we would get swamped with such diagnotiscs.  One
                 such diagnotiscs should be enough.  */
              if (been_here != status)
                {
                  been_here = status;
                  log_debug ("rndw32: get performance data problem: ec=%ld\n",
                             status);
                }
              break;
            }
        }
      gcry_free (pPerfData);
    }

  /* Although this isn't documented in the Win32 API docs, it's necessary
     to explicitly close the HKEY_PERFORMANCE_DATA key after use (it's
     implicitly opened on the first call to RegQueryValueEx()).  If this
     isn't done then any system components which provide performance data
     can't be removed or changed while the handle remains active.  */
  RegCloseKey (HKEY_PERFORMANCE_DATA);
}
Exemple #23
0
/* Run an integrity check on the binary.  Returns 0 on success.  */
static int
check_binary_integrity (void)
{
#ifdef ENABLE_HMAC_BINARY_CHECK
  gpg_error_t err;
  Dl_info info;
  unsigned char digest[32];
  int dlen;
  char *fname = NULL;
  const char key[] = "What am I, a doctor or a moonshuttle conductor?";

  if (!dladdr ("gcry_check_version", &info))
    err = gpg_error_from_syserror ();
  else
    {
      dlen = _gcry_hmac256_file (digest, sizeof digest, info.dli_fname,
                                 key, strlen (key));
      if (dlen < 0)
        err = gpg_error_from_syserror ();
      else if (dlen != 32)
        err = gpg_error (GPG_ERR_INTERNAL);
      else
        {
          fname = gcry_malloc (strlen (info.dli_fname) + 1 + 5 + 1 );
          if (!fname)
            err = gpg_error_from_syserror ();
          else
            {
              FILE *fp;
              char *p;

              /* Prefix the basename with a dot.  */
              strcpy (fname, info.dli_fname);
              p = strrchr (fname, '/');
              if (p)
                p++;
              else
                p = fname;
              memmove (p+1, p, strlen (p)+1);
              *p = '.';
              strcat (fname, ".hmac");

              /* Open the file.  */
              fp = fopen (fname, "r");
              if (!fp)
                err = gpg_error_from_syserror ();
              else
                {
                  /* A buffer of 64 bytes plus one for a LF and one to
                     detect garbage.  */
                  unsigned char buffer[64+1+1];
                  const unsigned char *s;
                  int n;

                  /* The HMAC files consists of lowercase hex digits
                     only with an optional trailing linefeed.  Fail if
                     there is any garbage.  */
                  err = gpg_error (GPG_ERR_SELFTEST_FAILED);
                  n = fread (buffer, 1, sizeof buffer, fp);
                  if (n == 64 || (n == 65 && buffer[64] == '\n'))
                    {
                      buffer[64] = 0;
                      for (n=0, s= buffer;
                           n < 32 && loxdigit_p (s) && loxdigit_p (s+1);
                           n++, s += 2)
                        buffer[n] = loxtoi_2 (s);
                      if ( n == 32 && !memcmp (digest, buffer, 32) )
                        err = 0;
                    }
                  fclose (fp);
                }
            }
        }
    }
  reporter ("binary", 0, fname, err? gpg_strerror (err):NULL);
#ifdef HAVE_SYSLOG
  if (err)
    syslog (LOG_USER|LOG_ERR, "Libgcrypt error: "
            "integrity check using `%s' failed: %s",
            fname? fname:"[?]", gpg_strerror (err));
#endif /*HAVE_SYSLOG*/
  gcry_free (fname);
  return !!err;
#else
  return 0;
#endif
}
Exemple #24
0
static void
slow_gatherer ( void (*add)(const void*, size_t, enum random_origins),
                enum random_origins requester )
{
  static int is_initialized = 0;
  static int is_workstation = 1;
  HANDLE hDevice;
  DWORD dwType, dwSize, dwResult;
  ULONG ulSize;
  int drive_no, status;
  int no_results = 0;
  void *buffer;

  if ( !is_initialized )
    {
      HKEY hKey;

      if ( debug_me )
        log_debug ("rndw32#slow_gatherer: init toolkit\n" );
      /* Find out whether this is an NT server or workstation if necessary */
      if (RegOpenKeyEx (HKEY_LOCAL_MACHINE,
                        "SYSTEM\\CurrentControlSet\\Control\\ProductOptions",
                        0, KEY_READ, &hKey) == ERROR_SUCCESS)
        {
          BYTE szValue[32 + 8];
          dwSize = 32;

          if ( debug_me )
            log_debug ("rndw32#slow_gatherer: check product options\n" );

          status = RegQueryValueEx (hKey, "ProductType", 0, NULL,
                                    szValue, &dwSize);
          if (status == ERROR_SUCCESS && stricmp (szValue, "WinNT"))
            {
              /* Note: There are (at least) three cases for ProductType:
                 WinNT = NT Workstation, ServerNT = NT Server, LanmanNT =
                 NT Server acting as a Domain Controller.  */
              is_workstation = 0;
              if ( debug_me )
                log_debug ("rndw32: this is a NT server\n");
            }
          RegCloseKey (hKey);
        }

      /* The following are fixed for the lifetime of the process so we
         only add them once */
      /* readPnPData ();  - we have not implemented that.  */

      /* Initialize the NetAPI32 function pointers if necessary */
      hNetAPI32 = LoadLibrary ("NETAPI32.DLL");
      if (hNetAPI32)
        {
          if (debug_me)
            log_debug ("rndw32#slow_gatherer: netapi32 loaded\n" );
          pNetStatisticsGet = (NETSTATISTICSGET)
            GetProcAddress (hNetAPI32, "NetStatisticsGet");
          pNetApiBufferSize = (NETAPIBUFFERSIZE)
            GetProcAddress (hNetAPI32, "NetApiBufferSize");
          pNetApiBufferFree = (NETAPIBUFFERFREE)
            GetProcAddress (hNetAPI32, "NetApiBufferFree");

          if (!pNetStatisticsGet || !pNetApiBufferSize || !pNetApiBufferFree)
            {
              FreeLibrary (hNetAPI32);
              hNetAPI32 = NULL;
              log_debug ("rndw32: No NETAPI found\n" );
            }
        }

      /* Initialize the NT kernel native API function pointers if necessary */
      hNTAPI = GetModuleHandle ("NTDll.dll");
      if (hNTAPI)
        {
          /* Get a pointer to the NT native information query functions */
          pNtQuerySystemInformation = (NTQUERYSYSTEMINFORMATION)
            GetProcAddress (hNTAPI, "NtQuerySystemInformation");
          pNtQueryInformationProcess = (NTQUERYINFORMATIONPROCESS)
            GetProcAddress (hNTAPI, "NtQueryInformationProcess");
          pNtPowerInformation = (NTPOWERINFORMATION)
            GetProcAddress(hNTAPI, "NtPowerInformation");

          if (!pNtQuerySystemInformation || !pNtQueryInformationProcess)
            hNTAPI = NULL;
        }


      is_initialized = 1;
    }

  read_system_rng ( add, requester );
  read_mbm_data ( add, requester );

  /* Get network statistics.    Note: Both NT Workstation and NT Server by
     default will be running both the workstation and server services.  The
     heuristic below is probably useful though on the assumption that the
     majority of the network traffic will be via the appropriate service.
     In any case the network statistics return almost no randomness.  */
  {
    LPBYTE lpBuffer;

    if (hNetAPI32
        && !pNetStatisticsGet (NULL,
                               is_workstation ? L"LanmanWorkstation" :
                               L"LanmanServer", 0, 0, &lpBuffer))
      {
        if ( debug_me )
          log_debug ("rndw32#slow_gatherer: get netstats\n" );
        pNetApiBufferSize (lpBuffer, &dwSize);
        (*add) ( lpBuffer, dwSize, requester );
        pNetApiBufferFree (lpBuffer);
      }
  }

  /* Get disk I/O statistics for all the hard drives.  100 is an
     arbitrary failsafe limit.  */
  for (drive_no = 0; drive_no < 100 ; drive_no++)
    {
      char diskPerformance[SIZEOF_DISK_PERFORMANCE_STRUCT + 8];
      char szDevice[50];

      /* Check whether we can access this device.  */
      snprintf (szDevice, sizeof szDevice, "\\\\.\\PhysicalDrive%d",
                drive_no);
      hDevice = CreateFile (szDevice, 0, FILE_SHARE_READ | FILE_SHARE_WRITE,
                            NULL, OPEN_EXISTING, 0, NULL);
      if (hDevice == INVALID_HANDLE_VALUE)
        break; /* No more drives.  */

      /* Note: This only works if you have turned on the disk performance
         counters with 'diskperf -y'.  These counters are off by default. */
      dwSize = sizeof diskPerformance;
      if (DeviceIoControl (hDevice, IOCTL_DISK_PERFORMANCE, NULL, 0,
                           diskPerformance, SIZEOF_DISK_PERFORMANCE_STRUCT,
                           &dwSize, NULL))
        {
          if ( debug_me )
            log_debug ("rndw32#slow_gatherer: iostat drive %d\n",
                       drive_no);
          (*add) (diskPerformance, dwSize, requester);
        }
      else
        {
          log_info ("NOTE: you should run 'diskperf -y' "
                    "to enable the disk statistics\n");
        }
      CloseHandle (hDevice);
    }

  /* In theory we should be using the Win32 performance query API to obtain
     unpredictable data from the system, however this is so unreliable (see
     the multiple sets of comments in registryPoll()) that it's too risky
     to rely on it except as a fallback in emergencies.  Instead, we rely
     mostly on the NT native API function NtQuerySystemInformation(), which
     has the dual advantages that it doesn't have as many (known) problems
     as the Win32 equivalent and that it doesn't access the data indirectly
     via pseudo-registry keys, which means that it's much faster.  Note
     that the Win32 equivalent actually works almost all of the time, the
     problem is that on one or two systems it can fail in strange ways that
     are never the same and can't be reproduced on any other system, which
     is why we use the native API here.  Microsoft officially documented
     this function in early 2003, so it'll be fairly safe to use.  */
  if ( !hNTAPI )
    {
      registry_poll (add, requester);
      return;
    }


  /* Scan the first 64 possible information types (we don't bother with
     increasing the buffer size as we do with the Win32 version of the
     performance data read, we may miss a few classes but it's no big deal).
     This scan typically yields around 20 pieces of data, there's nothing
     in the range 65...128 so chances are there won't be anything above
     there either.  */
  buffer = gcry_xmalloc (PERFORMANCE_BUFFER_SIZE);
  for (dwType = 0; dwType < 64; dwType++)
    {
      switch (dwType)
        {
          /* ID 17 = SystemObjectInformation hangs on some win2k systems.  */
        case 17:
          if (system_is_w2000)
            continue;
          break;

          /* Some information types are write-only (the IDs are shared with
             a set-information call), we skip these.  */
        case 26: case 27: case 38: case 46: case 47: case 48: case 52:
          continue;

          /* ID 53 = SystemSessionProcessInformation reads input from the
             output buffer, which has to contain a session ID and pointer
             to the actual buffer in which to store the session information.
             Because this isn't a standard query, we skip this.  */
        case  53:
          continue;
        }

      /* Query the info for this ID.  Some results (for example for
         ID = 6, SystemCallCounts) are only available in checked builds
         of the kernel.  A smaller subcless of results require that
         certain system config flags be set, for example
         SystemObjectInformation requires that the
         FLG_MAINTAIN_OBJECT_TYPELIST be set in NtGlobalFlags.  To avoid
         having to special-case all of these, we try reading each one and
         only use those for which we get a success status.  */
      dwResult = pNtQuerySystemInformation (dwType, buffer,
                                            PERFORMANCE_BUFFER_SIZE - 2048,
                                            &ulSize);
      if (dwResult != ERROR_SUCCESS)
        continue;

      /* Some calls (e.g. ID = 23, SystemProcessorStatistics, and ID = 24,
         SystemDpcInformation) incorrectly return a length of zero, so we
         manually adjust the length to the correct value.  */
      if ( !ulSize )
        {
          if (dwType == 23)
            ulSize = 6 * sizeof (ULONG);
          else if (dwType == 24)
            ulSize = 5 * sizeof (ULONG);
        }

      /* If we got some data back, add it to the entropy pool.  */
      if (ulSize > 0 && ulSize <= PERFORMANCE_BUFFER_SIZE - 2048)
        {
          if (debug_me)
            log_debug ("rndw32#slow_gatherer: %lu bytes from sysinfo %ld\n",
                       ulSize, dwType);
          (*add) (buffer, ulSize, requester);
          no_results++;
        }
    }

  /* Now we would do the same for the process information.  This
     call would rather ugly in that it requires an exact length
     match for the data returned, failing with a
     STATUS_INFO_LENGTH_MISMATCH error code (0xC0000004) if the
     length isn't an exact match.  It requires a compiler to handle
     complex nested structs, alignment issues, and so on, and
     without the headers in which the entries are declared it's
     almost impossible to do.  Thus we don't.  */


  /* Finally, do the same for the system power status information.  There
     are only a limited number of useful information types available so we
     restrict ourselves to the useful types.  In addition since this
     function doesn't return length information, we have to hardcode in
     length data.  */
  if (pNtPowerInformation)
    {
      static const struct { int type; int size; } powerInfo[] = {
        { 0, 128 },     /* SystemPowerPolicyAc */
        { 1, 128 },     /* SystemPowerPolicyDc */
        { 4, 64 },      /* SystemPowerCapabilities */
        { 5, 48 },      /* SystemBatteryState */
        { 11, 48 },     /* ProcessorInformation */
        { 12, 24 },     /* SystemPowerInformation */
        { -1, -1 }
      };
      int i;

      /* The 100 is a failsafe limit.  */
      for (i = 0; powerInfo[i].type != -1 && i < 100; i++ )
        {
          /* Query the info for this ID */
          dwResult = pNtPowerInformation (powerInfo[i].type, NULL, 0, buffer,
                                          PERFORMANCE_BUFFER_SIZE - 2048);
          if (dwResult != ERROR_SUCCESS)
            continue;
          if (debug_me)
            log_debug ("rndw32#slow_gatherer: %u bytes from powerinfo %d\n",
                       powerInfo[i].size, i);
          (*add) (buffer, powerInfo[i].size, requester);
          no_results++;
        }
      gcry_assert (i < 100);
    }
  gcry_free (buffer);

  /* We couldn't get enough results from the kernel, fall back to the
     somewhat troublesome registry poll.  */
  if (no_results < 15)
    registry_poll (add, requester);
}
Exemple #25
0
/* Return the so called KEYGRIP which is the SHA-1 hash of the public
   key parameters expressed in a way depending on the algorithm.

   ARRAY must either be 20 bytes long or NULL; in the latter case a
   newly allocated array of that size is returned, otherwise ARRAY or
   NULL is returned to indicate an error which is most likely an
   unknown algorithm.  The function accepts public or secret keys. */
unsigned char *
gcry_pk_get_keygrip (gcry_sexp_t key, unsigned char *array)
{
  gcry_sexp_t list = NULL;
  gcry_sexp_t l2 = NULL;
  gcry_pk_spec_t *spec = NULL;
  const char *s;
  char *name = NULL;
  int idx;
  const char *elems;
  gcry_md_hd_t md = NULL;
  int okay = 0;

  /* Check that the first element is valid. */
  list = gcry_sexp_find_token (key, "public-key", 0);
  if (! list)
    list = gcry_sexp_find_token (key, "private-key", 0);
  if (! list)
    list = gcry_sexp_find_token (key, "protected-private-key", 0);
  if (! list)
    list = gcry_sexp_find_token (key, "shadowed-private-key", 0);
  if (! list)
    return NULL; /* No public- or private-key object. */

  l2 = gcry_sexp_cadr (list);
  gcry_sexp_release (list);
  list = l2;
  l2 = NULL;

  name = _gcry_sexp_nth_string (list, 0);
  if (!name)
    goto fail; /* Invalid structure of object. */

  spec = spec_from_name (name);
  if (!spec)
    goto fail; /* Unknown algorithm.  */

  elems = spec->elements_grip;
  if (!elems)
    goto fail; /* No grip parameter.  */

  if (gcry_md_open (&md, GCRY_MD_SHA1, 0))
    goto fail;

  if (spec->comp_keygrip)
    {
      /* Module specific method to compute a keygrip.  */
      if (spec->comp_keygrip (md, list))
        goto fail;
    }
  else
    {
      /* Generic method to compute a keygrip.  */
      for (idx = 0, s = elems; *s; s++, idx++)
        {
          const char *data;
          size_t datalen;
          char buf[30];

          l2 = gcry_sexp_find_token (list, s, 1);
          if (! l2)
            goto fail;
          data = gcry_sexp_nth_data (l2, 1, &datalen);
          if (! data)
            goto fail;

          snprintf (buf, sizeof buf, "(1:%c%u:", *s, (unsigned int)datalen);
          gcry_md_write (md, buf, strlen (buf));
          gcry_md_write (md, data, datalen);
          gcry_sexp_release (l2);
          l2 = NULL;
          gcry_md_write (md, ")", 1);
        }
    }

  if (!array)
    {
      array = gcry_malloc (20);
      if (! array)
        goto fail;
    }

  memcpy (array, gcry_md_read (md, GCRY_MD_SHA1), 20);
  okay = 1;

 fail:
  gcry_free (name);
  gcry_sexp_release (l2);
  gcry_md_close (md);
  gcry_sexp_release (list);
  return okay? array : NULL;
}
Exemple #26
0
/****************
 * Scan the provided buffer and return the S expression in our internal
 * format.  Returns a newly allocated expression.  If erroff is not NULL and
 * a parsing error has occurred, the offset into buffer will be returned.
 * If ARGFLAG is true, the function supports some printf like
 * expressions.
 *  These are:
 *	%m - MPI
 *	%s - string (no autoswitch to secure allocation)
 *	%d - integer stored as string (no autoswitch to secure allocation)
 *      %b - memory buffer; this takes _two_ arguments: an integer with the
 *           length of the buffer and a pointer to the buffer.
 *      %S - Copy an gcry_sexp_t here.  The S-expression needs to be a
 *           regular one, starting with a parenthesis.
 *           (no autoswitch to secure allocation)
 *  all other format elements are currently not defined and return an error.
 *  this includes the "%%" sequence becauce the percent sign is not an
 *  allowed character.
 * FIXME: We should find a way to store the secure-MPIs not in the string
 * but as reference to somewhere - this can help us to save huge amounts
 * of secure memory.  The problem is, that if only one element is secure, all
 * other elements are automagicaly copied to secure memory too, so the most
 * common operation gcry_sexp_cdr_mpi() will always return a secure MPI
 * regardless whether it is needed or not.
 */
static gcry_error_t
vsexp_sscan (gcry_sexp_t *retsexp, size_t *erroff,
	     const char *buffer, size_t length, int argflag,
	     void **arg_list, va_list arg_ptr)
{
  gcry_err_code_t err = 0;
  static const char tokenchars[] =
    "abcdefghijklmnopqrstuvwxyz"
    "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
    "0123456789-./_:*+=";
  const char *p;
  size_t n;
  const char *digptr = NULL;
  const char *quoted = NULL;
  const char *tokenp = NULL;
  const char *hexfmt = NULL;
  const char *base64 = NULL;
  const char *disphint = NULL;
  const char *percent = NULL;
  int hexcount = 0;
  int quoted_esc = 0;
  int datalen = 0;
  size_t dummy_erroff;
  struct make_space_ctx c;
  int arg_counter = 0;
  int level = 0;

  if (!erroff)
    erroff = &dummy_erroff;

  /* Depending on whether ARG_LIST is non-zero or not, this macro gives
     us the next argument, either from the variable argument list as
     specified by ARG_PTR or from the argument array ARG_LIST.  */
#define ARG_NEXT(storage, type)                          \
  do                                                     \
    {                                                    \
      if (!arg_list)                                     \
	storage = va_arg (arg_ptr, type);                \
      else                                               \
	storage = *((type *) (arg_list[arg_counter++])); \
    }                                                    \
  while (0)

  /* The MAKE_SPACE macro is used before each store operation to
     ensure that the buffer is large enough.  It requires a global
     context named C and jumps out to the label LEAVE on error! It
     also sets ERROFF using the variables BUFFER and P.  */
#define MAKE_SPACE(n)  do {                                                \
                            gpg_err_code_t _ms_err = make_space (&c, (n)); \
                            if (_ms_err)                                   \
                              {                                            \
                                err = _ms_err;                             \
                                *erroff = p - buffer;                      \
                                goto leave;                                \
                              }                                            \
                       } while (0)

  /* The STORE_LEN macro is used to store the length N at buffer P. */
#define STORE_LEN(p,n) do {						   \
			    DATALEN ashort = (n);			   \
			    memcpy ( (p), &ashort, sizeof(ashort) );	   \
			    (p) += sizeof (ashort);			   \
			} while (0)

  /* We assume that the internal representation takes less memory than
     the provided one.  However, we add space for one extra datalen so
     that the code which does the ST_CLOSE can use MAKE_SPACE */
  c.allocated = length + sizeof(DATALEN);
  if (buffer && length && gcry_is_secure (buffer))
    c.sexp = gcry_malloc_secure (sizeof *c.sexp + c.allocated - 1);
  else
    c.sexp = gcry_malloc (sizeof *c.sexp + c.allocated - 1);
  if (!c.sexp)
    {
      err = gpg_err_code_from_errno (errno);
      *erroff = 0;
      goto leave;
    }
  c.pos = c.sexp->d;

  for (p = buffer, n = length; n; p++, n--)
    {
      if (tokenp && !hexfmt)
	{
	  if (strchr (tokenchars, *p))
	    continue;
	  else
	    {
	      datalen = p - tokenp;
	      MAKE_SPACE (datalen);
	      *c.pos++ = ST_DATA;
	      STORE_LEN (c.pos, datalen);
	      memcpy (c.pos, tokenp, datalen);
	      c.pos += datalen;
	      tokenp = NULL;
	    }
	}

      if (quoted)
	{
	  if (quoted_esc)
	    {
	      switch (*p)
		{
		case 'b': case 't': case 'v': case 'n': case 'f':
		case 'r': case '"': case '\'': case '\\':
		  quoted_esc = 0;
		  break;

		case '0': case '1': case '2': case '3': case '4':
		case '5': case '6': case '7':
		  if (!((n > 2)
                        && (p[1] >= '0') && (p[1] <= '7')
                        && (p[2] >= '0') && (p[2] <= '7')))
		    {
		      *erroff = p - buffer;
		      /* Invalid octal value.  */
		      err = GPG_ERR_SEXP_BAD_QUOTATION;
                      goto leave;
		    }
		  p += 2;
		  n -= 2;
		  quoted_esc = 0;
		  break;

		case 'x':
		  if (!((n > 2) && hexdigitp (p+1) && hexdigitp (p+2)))
		    {
		      *erroff = p - buffer;
		      /* Invalid hex value.  */
		      err = GPG_ERR_SEXP_BAD_QUOTATION;
                      goto leave;
		    }
		  p += 2;
		  n -= 2;
		  quoted_esc = 0;
		  break;

		case '\r':
		  /* ignore CR[,LF] */
		  if (n && (p[1] == '\n'))
		    {
		      p++;
		      n--;
		    }
		  quoted_esc = 0;
		  break;

		case '\n':
		  /* ignore LF[,CR] */
		  if (n && (p[1] == '\r'))
		    {
		      p++;
		      n--;
		    }
		  quoted_esc = 0;
		  break;

		default:
		  *erroff = p - buffer;
		  /* Invalid quoted string escape.  */
		  err = GPG_ERR_SEXP_BAD_QUOTATION;
                  goto leave;
		}
	    }
	  else if (*p == '\\')
	    quoted_esc = 1;
	  else if (*p == '\"')
	    {
	      /* Keep it easy - we know that the unquoted string will
		 never be larger. */
	      unsigned char *save;
	      size_t len;

	      quoted++; /* Skip leading quote.  */
	      MAKE_SPACE (p - quoted);
	      *c.pos++ = ST_DATA;
	      save = c.pos;
	      STORE_LEN (c.pos, 0); /* Will be fixed up later.  */
	      len = unquote_string (quoted, p - quoted, c.pos);
	      c.pos += len;
	      STORE_LEN (save, len);
	      quoted = NULL;
	    }
	}
      else if (hexfmt)
	{
	  if (isxdigit (*p))
	    hexcount++;
	  else if (*p == '#')
	    {
	      if ((hexcount & 1))
		{
		  *erroff = p - buffer;
		  err = GPG_ERR_SEXP_ODD_HEX_NUMBERS;
                  goto leave;
		}

	      datalen = hexcount / 2;
	      MAKE_SPACE (datalen);
	      *c.pos++ = ST_DATA;
	      STORE_LEN (c.pos, datalen);
	      for (hexfmt++; hexfmt < p; hexfmt++)
		{
                  int tmpc;

		  if (whitespacep (hexfmt))
		    continue;
		  tmpc = hextonibble (*(const unsigned char*)hexfmt);
                  for (hexfmt++; hexfmt < p && whitespacep (hexfmt); hexfmt++)
		    ;
                  if (hexfmt < p)
                    {
                      tmpc *= 16;
                      tmpc += hextonibble (*(const unsigned char*)hexfmt);
                    }
                  *c.pos++ = tmpc;
		}
	      hexfmt = NULL;
	    }
	  else if (!whitespacep (p))
	    {
	      *erroff = p - buffer;
	      err = GPG_ERR_SEXP_BAD_HEX_CHAR;
              goto leave;
	    }
	}
      else if (base64)
	{
	  if (*p == '|')
	    base64 = NULL;
	}
      else if (digptr)
	{
	  if (digitp (p))
	    ;
	  else if (*p == ':')
	    {
	      datalen = atoi (digptr); /* FIXME: check for overflow.  */
	      digptr = NULL;
	      if (datalen > n - 1)
		{
		  *erroff = p - buffer;
		  /* Buffer too short.  */
		  err = GPG_ERR_SEXP_STRING_TOO_LONG;
                  goto leave;
		}
	      /* Make a new list entry.  */
	      MAKE_SPACE (datalen);
	      *c.pos++ = ST_DATA;
	      STORE_LEN (c.pos, datalen);
	      memcpy (c.pos, p + 1, datalen);
	      c.pos += datalen;
	      n -= datalen;
	      p += datalen;
	    }
	  else if (*p == '\"')
	    {
	      digptr = NULL; /* We ignore the optional length.  */
	      quoted = p;
	      quoted_esc = 0;
	    }
	  else if (*p == '#')
	    {
	      digptr = NULL; /* We ignore the optional length.  */
	      hexfmt = p;
	      hexcount = 0;
	    }
	  else if (*p == '|')
	    {
	      digptr = NULL; /* We ignore the optional length.  */
	      base64 = p;
	    }
	  else
	    {
	      *erroff = p - buffer;
	      err = GPG_ERR_SEXP_INV_LEN_SPEC;
              goto leave;
	    }
	}
      else if (percent)
	{
	  if (*p == 'm' || *p == 'M')
	    {
	      /* Insert an MPI.  */
	      gcry_mpi_t m;
	      size_t nm = 0;
              int mpifmt = *p == 'm'? GCRYMPI_FMT_STD: GCRYMPI_FMT_USG;

	      ARG_NEXT (m, gcry_mpi_t);

              if (gcry_mpi_get_flag (m, GCRYMPI_FLAG_OPAQUE))
                {
                  void *mp;
                  unsigned int nbits;

                  mp = gcry_mpi_get_opaque (m, &nbits);
                  nm = (nbits+7)/8;
                  if (mp && nm)
                    {
                      MAKE_SPACE (nm);
                      if (!gcry_is_secure (c.sexp->d)
                          && gcry_mpi_get_flag (m, GCRYMPI_FLAG_SECURE))
                        {
                          /* We have to switch to secure allocation.  */
                          gcry_sexp_t newsexp;
                          byte *newhead;

                          newsexp = gcry_malloc_secure (sizeof *newsexp
                                                        + c.allocated - 1);
                          if (!newsexp)
                            {
                              err = gpg_err_code_from_errno (errno);
                              goto leave;
                            }
                          newhead = newsexp->d;
                          memcpy (newhead, c.sexp->d, (c.pos - c.sexp->d));
                          c.pos = newhead + (c.pos - c.sexp->d);
                          gcry_free (c.sexp);
                          c.sexp = newsexp;
                        }

                      *c.pos++ = ST_DATA;
                      STORE_LEN (c.pos, nm);
                      memcpy (c.pos, mp, nm);
                      c.pos += nm;
                    }
                }
              else
                {
                  if (gcry_mpi_print (mpifmt, NULL, 0, &nm, m))
                    BUG ();

                  MAKE_SPACE (nm);
                  if (!gcry_is_secure (c.sexp->d)
                      && gcry_mpi_get_flag ( m, GCRYMPI_FLAG_SECURE))
                    {
                      /* We have to switch to secure allocation.  */
                      gcry_sexp_t newsexp;
                      byte *newhead;

                      newsexp = gcry_malloc_secure (sizeof *newsexp
                                                    + c.allocated - 1);
                      if (!newsexp)
                        {
                          err = gpg_err_code_from_errno (errno);
                          goto leave;
                        }
                      newhead = newsexp->d;
                      memcpy (newhead, c.sexp->d, (c.pos - c.sexp->d));
                      c.pos = newhead + (c.pos - c.sexp->d);
                      gcry_free (c.sexp);
                      c.sexp = newsexp;
                    }

                  *c.pos++ = ST_DATA;
                  STORE_LEN (c.pos, nm);
                  if (gcry_mpi_print (mpifmt, c.pos, nm, &nm, m))
                    BUG ();
                  c.pos += nm;
                }
	    }
	  else if (*p == 's')
	    {
	      /* Insert an string.  */
	      const char *astr;
	      size_t alen;

	      ARG_NEXT (astr, const char *);
	      alen = strlen (astr);

	      MAKE_SPACE (alen);
	      *c.pos++ = ST_DATA;
	      STORE_LEN (c.pos, alen);
	      memcpy (c.pos, astr, alen);
	      c.pos += alen;
	    }
	  else if (*p == 'b')
	    {
	      /* Insert a memory buffer.  */
	      const char *astr;
	      int alen;

	      ARG_NEXT (alen, int);
	      ARG_NEXT (astr, const char *);

	      MAKE_SPACE (alen);
	      if (alen
                  && !gcry_is_secure (c.sexp->d)
		  && gcry_is_secure (astr))
              {
		  /* We have to switch to secure allocation.  */
		  gcry_sexp_t newsexp;
		  byte *newhead;

		  newsexp = gcry_malloc_secure (sizeof *newsexp
                                                + c.allocated - 1);
                  if (!newsexp)
                    {
                      err = gpg_err_code_from_errno (errno);
                      goto leave;
                    }
		  newhead = newsexp->d;
		  memcpy (newhead, c.sexp->d, (c.pos - c.sexp->d));
		  c.pos = newhead + (c.pos - c.sexp->d);
		  gcry_free (c.sexp);
		  c.sexp = newsexp;
		}

	      *c.pos++ = ST_DATA;
	      STORE_LEN (c.pos, alen);
	      memcpy (c.pos, astr, alen);
	      c.pos += alen;
	    }
	  else if (*p == 'd')
	    {
	      /* Insert an integer as string.  */
	      int aint;
	      size_t alen;
	      char buf[35];

	      ARG_NEXT (aint, int);
	      sprintf (buf, "%d", aint);
	      alen = strlen (buf);
	      MAKE_SPACE (alen);
	      *c.pos++ = ST_DATA;
	      STORE_LEN (c.pos, alen);
	      memcpy (c.pos, buf, alen);
	      c.pos += alen;
	    }
	  else if (*p == 'u')
	    {
	      /* Insert an unsigned integer as string.  */
	      unsigned int aint;
	      size_t alen;
	      char buf[35];

	      ARG_NEXT (aint, unsigned int);
	      sprintf (buf, "%u", aint);
	      alen = strlen (buf);
	      MAKE_SPACE (alen);
	      *c.pos++ = ST_DATA;
	      STORE_LEN (c.pos, alen);
	      memcpy (c.pos, buf, alen);
	      c.pos += alen;
	    }
	  else if (*p == 'S')
	    {
	      /* Insert a gcry_sexp_t.  */
	      gcry_sexp_t asexp;
	      size_t alen, aoff;

	      ARG_NEXT (asexp, gcry_sexp_t);
              alen = get_internal_buffer (asexp, &aoff);
              if (alen)
                {
                  MAKE_SPACE (alen);
                  memcpy (c.pos, asexp->d + aoff, alen);
                  c.pos += alen;
                }
	    }
	  else
	    {
	      *erroff = p - buffer;
	      /* Invalid format specifier.  */
	      err = GPG_ERR_SEXP_INV_LEN_SPEC;
              goto leave;
	    }
	  percent = NULL;
	}
      else if (*p == '(')
	{
	  if (disphint)
	    {
	      *erroff = p - buffer;
	      /* Open display hint.  */
	      err = GPG_ERR_SEXP_UNMATCHED_DH;
              goto leave;
	    }
	  MAKE_SPACE (0);
	  *c.pos++ = ST_OPEN;
	  level++;
	}
      else if (*p == ')')
	{
	  /* Walk up.  */
	  if (disphint)
	    {
	      *erroff = p - buffer;
	      /* Open display hint.  */
	      err = GPG_ERR_SEXP_UNMATCHED_DH;
              goto leave;
	    }
	  MAKE_SPACE (0);
	  *c.pos++ = ST_CLOSE;
	  level--;
	}
      else if (*p == '\"')
	{
	  quoted = p;
	  quoted_esc = 0;
	}
      else if (*p == '#')
	{
	  hexfmt = p;
	  hexcount = 0;
	}
      else if (*p == '|')
	base64 = p;
      else if (*p == '[')
	{
	  if (disphint)
	    {
	      *erroff = p - buffer;
	      /* Open display hint.  */
	      err = GPG_ERR_SEXP_NESTED_DH;
              goto leave;
	    }
	  disphint = p;
	}
      else if (*p == ']')
	{
	  if (!disphint)
	    {
	      *erroff = p - buffer;
	      /* Open display hint.  */
	      err = GPG_ERR_SEXP_UNMATCHED_DH;
              goto leave;
	    }
	  disphint = NULL;
	}
      else if (digitp (p))
	{
	  if (*p == '0')
	    {
	      /* A length may not begin with zero.  */
	      *erroff = p - buffer;
	      err = GPG_ERR_SEXP_ZERO_PREFIX;
              goto leave;
	    }
	  digptr = p;
	}
      else if (strchr (tokenchars, *p))
	tokenp = p;
      else if (whitespacep (p))
	;
      else if (*p == '{')
	{
	  /* fixme: handle rescanning: we can do this by saving our
	     current state and start over at p+1 -- Hmmm. At this
	     point here we are in a well defined state, so we don't
	     need to save it.  Great.  */
	  *erroff = p - buffer;
	  err = GPG_ERR_SEXP_UNEXPECTED_PUNC;
          goto leave;
	}
      else if (strchr ("&\\", *p))
	{
	  /* Reserved punctuation.  */
	  *erroff = p - buffer;
	  err = GPG_ERR_SEXP_UNEXPECTED_PUNC;
          goto leave;
	}
      else if (argflag && (*p == '%'))
	percent = p;
      else
	{
	  /* Bad or unavailable.  */
	  *erroff = p - buffer;
	  err = GPG_ERR_SEXP_BAD_CHARACTER;
          goto leave;
	}
    }
  MAKE_SPACE (0);
  *c.pos++ = ST_STOP;

  if (level && !err)
    err = GPG_ERR_SEXP_UNMATCHED_PAREN;

 leave:
  if (err)
    {
      /* Error -> deallocate.  */
      if (c.sexp)
        {
          /* Extra paranoid wipe on error. */
          if (gcry_is_secure (c.sexp))
            wipememory (c.sexp, sizeof (struct gcry_sexp) + c.allocated - 1);
          gcry_free (c.sexp);
        }
      /* This might be expected by existing code...  */
      *retsexp = NULL;
    }
  else
    *retsexp = normalize (c.sexp);

  return gcry_error (err);
#undef MAKE_SPACE
#undef STORE_LEN
}
Exemple #27
0
void
_gsti_free (void *p)
{
  gcry_free (p);
}
Exemple #28
0
static int
soft_sign (const uint8_t *to_sign, size_t len,
      jwa_t alg, void *cookie,
      uint8_t **out, size_t *out_len)
{

    assert (NULL != key_f);

    int rc = -1;
    uint8_t *hash;
    gcry_sexp_t key, sig, digest;

    const unsigned int DLEN = gcry_md_get_algo_dlen (GCRY_MD_SHA256);
    hash = malloc (DLEN);
    assert (NULL != hash);

    gcry_md_hash_buffer (GCRY_MD_SHA256, hash, to_sign, len);

    rc = gcry_sexp_build (&digest, NULL,
                          "(data (flags raw)\n"
                          " (value %b))",
                          DLEN, hash);

    if (rc)
        goto OUT;


    if (rc = lca_load_signing_key (key_f, &key))
        goto DIG;




    /* if (show_digest) */
    /* { */
    /*     lca_set_log_level (DEBUG); */
    /*     lca_print_sexp (digest); */
    /*     lca_set_log_level (INFO); */
    /* } */


    if (rc = gcry_pk_sign (&sig, digest, key))
        goto KEY;

    lca_print_sexp (sig);

    struct lca_octet_buffer signature = lca_sig2buf (&sig);

    if (NULL != signature.ptr)
    {
        *out = signature.ptr;
        *out_len = signature.len;
        rc = 0;
    }

    gcry_free (sig);


KEY:
    gcry_free (key);
DIG:
    gcry_free (digest);
OUT:
    free (hash);
    return rc;
}
Exemple #29
0
static void
back_and_forth_one (int testno, const char *buffer, size_t length)
{
  gcry_error_t rc;
  gcry_sexp_t se, se1;
  size_t n, n1;
  char *p1;

  rc = gcry_sexp_new (&se, buffer, length, 1);
  if (rc)
    {
      fail ("baf %d: gcry_sexp_new failed: %s\n", testno, gpg_strerror (rc));
      return;
    }
  n1 = gcry_sexp_sprint (se, GCRYSEXP_FMT_CANON, NULL, 0);
  if (!n1)
    {
      fail ("baf %d: get required length for canon failed\n", testno);
      return;
    }
  p1 = gcry_xmalloc (n1);
  n = gcry_sexp_sprint (se, GCRYSEXP_FMT_CANON, p1, n1);
  if (n1 != n+1) /* sprints adds an extra 0 but dies not return it */
    {
      fail ("baf %d: length mismatch for canon\n", testno);
      return;
    }
  rc = gcry_sexp_create (&se1, p1, n, 0, gcry_free);
  if (rc)
    {
      fail ("baf %d: gcry_sexp_create failed: %s\n",
            testno, gpg_strerror (rc));
      return;
    }
  gcry_sexp_release (se1);

  /* Again but with memory checking. */
  p1 = gcry_xmalloc (n1+2);
  *p1 = '\x55';
  p1[n1+1] = '\xaa';
  n = gcry_sexp_sprint (se, GCRYSEXP_FMT_CANON, p1+1, n1);
  if (n1 != n+1) /* sprints adds an extra 0 but does not return it */
    {
      fail ("baf %d: length mismatch for canon\n", testno);
      return;
    }
  if (*p1 != '\x55' || p1[n1+1] != '\xaa')
    fail ("baf %d: memory corrupted (1)\n", testno);
  rc = gcry_sexp_create (&se1, p1+1, n, 0, NULL);
  if (rc)
    {
      fail ("baf %d: gcry_sexp_create failed: %s\n",
            testno, gpg_strerror (rc));
      return;
    }
  if (*p1 != '\x55' || p1[n1+1] != '\xaa')
    fail ("baf %d: memory corrupted (2)\n", testno);
  gcry_sexp_release (se1);
  if (*p1 != '\x55' || p1[n1+1] != '\xaa')
    fail ("baf %d: memory corrupted (3)\n", testno);
  gcry_free (p1);
  
  /* FIXME: we need a lot more tests */

  gcry_sexp_release (se);
}
Exemple #30
0
/* Run the self-tests for <block cipher>-CBC-<block size>, tests bulk CBC
   decryption.  Returns NULL on success. */
const char *
_gcry_selftest_helper_cbc (const char *cipher, gcry_cipher_setkey_t setkey_func,
			   gcry_cipher_encrypt_t encrypt_one,
			   gcry_cipher_bulk_cbc_dec_t bulk_cbc_dec,
			   const int nblocks, const int blocksize,
			   const int context_size)
{
  int i, offs;
  unsigned char *ctx, *plaintext, *plaintext2, *ciphertext, *iv, *iv2, *mem;
  unsigned int ctx_aligned_size, memsize;

  static const unsigned char key[16] ATTR_ALIGNED_16 = {
      0x66,0x9A,0x00,0x7F,0xC7,0x6A,0x45,0x9F,
      0x98,0xBA,0xF9,0x17,0xFE,0xDF,0x95,0x22
    };

  /* Allocate buffers, align first two elements to 16 bytes and latter to
     block size.  */
  ctx_aligned_size = context_size + 15;
  ctx_aligned_size -= ctx_aligned_size & 0xf;

  memsize = ctx_aligned_size + (blocksize * 2) + (blocksize * nblocks * 3) + 16;

  mem = gcry_calloc (1, memsize);
  if (!mem)
    return "failed to allocate memory";

  offs = (16 - ((uintptr_t)mem & 15)) & 15;
  ctx = (void*)(mem + offs);
  iv = ctx + ctx_aligned_size;
  iv2 = iv + blocksize;
  plaintext = iv2 + blocksize;
  plaintext2 = plaintext + nblocks * blocksize;
  ciphertext = plaintext2 + nblocks * blocksize;

  /* Initialize ctx */
  setkey_func (ctx, key, sizeof(key));

  /* Test single block code path */
  memset (iv, 0x4e, blocksize);
  memset (iv2, 0x4e, blocksize);
  for (i = 0; i < blocksize; i++)
    plaintext[i] = i;

  /* CBC manually.  */
  buf_xor (ciphertext, iv, plaintext, blocksize);
  encrypt_one (ctx, ciphertext, ciphertext);
  memcpy (iv, ciphertext, blocksize);

  /* CBC decrypt.  */
  bulk_cbc_dec (ctx, iv2, plaintext2, ciphertext, 1);
  if (memcmp (plaintext2, plaintext, blocksize))
    {
      gcry_free (mem);
#ifdef HAVE_SYSLOG
      syslog (LOG_USER|LOG_WARNING, "Libgcrypt warning: "
              "%s-CBC-%d test failed (plaintext mismatch)", cipher,
	      blocksize * 8);
#endif
      return "selftest for CBC failed - see syslog for details";
    }

  if (memcmp (iv2, iv, blocksize))
    {
      gcry_free (mem);
#ifdef HAVE_SYSLOG
      syslog (LOG_USER|LOG_WARNING, "Libgcrypt warning: "
              "%s-CBC-%d test failed (IV mismatch)", cipher, blocksize * 8);
#endif
      return "selftest for CBC failed - see syslog for details";
    }

  /* Test parallelized code paths */
  memset (iv, 0x5f, blocksize);
  memset (iv2, 0x5f, blocksize);

  for (i = 0; i < nblocks * blocksize; i++)
    plaintext[i] = i;

  /* Create CBC ciphertext manually.  */
  for (i = 0; i < nblocks * blocksize; i+=blocksize)
    {
      buf_xor (&ciphertext[i], iv, &plaintext[i], blocksize);
      encrypt_one (ctx, &ciphertext[i], &ciphertext[i]);
      memcpy (iv, &ciphertext[i], blocksize);
    }

  /* Decrypt using bulk CBC and compare result.  */
  bulk_cbc_dec (ctx, iv2, plaintext2, ciphertext, nblocks);

  if (memcmp (plaintext2, plaintext, nblocks * blocksize))
    {
      gcry_free (mem);
#ifdef HAVE_SYSLOG
      syslog (LOG_USER|LOG_WARNING, "Libgcrypt warning: "
              "%s-CBC-%d test failed (plaintext mismatch, parallel path)",
	      cipher, blocksize * 8);
#endif
      return "selftest for CBC failed - see syslog for details";
    }
  if (memcmp (iv2, iv, blocksize))
    {
      gcry_free (mem);
#ifdef HAVE_SYSLOG
      syslog (LOG_USER|LOG_WARNING, "Libgcrypt warning: "
              "%s-CBC-%d test failed (IV mismatch, parallel path)",
	      cipher, blocksize * 8);
#endif
      return "selftest for CBC failed - see syslog for details";
    }

  gcry_free (mem);
  return NULL;
}