Beispiel #1
0
int
main (int argc, char *argv[])
{
  struct GNUNET_CRYPTO_EcdhePrivateKey *priv1;
  struct GNUNET_CRYPTO_EcdhePrivateKey *priv2;
  struct GNUNET_CRYPTO_EcdhePublicKey pub1;
  struct GNUNET_CRYPTO_EcdhePublicKey pub2;
  struct GNUNET_HashCode ecdh1;
  struct GNUNET_HashCode ecdh2;

  if (! gcry_check_version ("1.6.0"))
  {
    FPRINTF (stderr,
             _
             ("libgcrypt has not the expected version (version %s is required).\n"),
             "1.6.0");
    return 0;
  }
  if (getenv ("GNUNET_GCRYPT_DEBUG"))
    gcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1u , 0);
  GNUNET_log_setup ("test-crypto-ecdhe", "WARNING", NULL);

  priv1 = GNUNET_CRYPTO_ecdhe_key_create ();
  priv2 = GNUNET_CRYPTO_ecdhe_key_create ();
  GNUNET_CRYPTO_ecdhe_key_get_public (priv1, &pub1);
  GNUNET_CRYPTO_ecdhe_key_get_public (priv2, &pub2);
  GNUNET_CRYPTO_ecc_ecdh (priv1, &pub2, &ecdh1);
  GNUNET_CRYPTO_ecc_ecdh (priv2, &pub1, &ecdh2);
  GNUNET_assert (0 == memcmp (&ecdh1, &ecdh2,
			      sizeof (struct GNUNET_HashCode)));
  GNUNET_free (priv1);
  GNUNET_free (priv2);
  return 0;
}
int
main (int argc, char *argv[])
{
  int i;
  struct GNUNET_CRYPTO_EcdhePrivateKey *ecdhe[l];
  struct GNUNET_CRYPTO_EcdhePublicKey dhpub[l];
  struct GNUNET_CRYPTO_EddsaPrivateKey *eddsa[l];
  struct GNUNET_CRYPTO_EddsaPublicKey dspub[l];
  struct TestSig sig[l];

  start = GNUNET_TIME_absolute_get();
  for (i = 0; i < l; i++)
  {
    sig[i].purp.purpose = 0;
    sig[i].purp.size = htonl (sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose)
                              + sizeof (struct GNUNET_HashCode));
    GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK,
                                &sig[i].h,
                                sizeof (sig[i].h));
  }
  log_duration ("", "Init");

  start = GNUNET_TIME_absolute_get();
  for (i = 0; i < l; i++)
    eddsa[i] = GNUNET_CRYPTO_eddsa_key_create();
  log_duration ("EdDSA", "create key");

  start = GNUNET_TIME_absolute_get();
  for (i = 0; i < l; i++)
    GNUNET_CRYPTO_eddsa_key_get_public (eddsa[i], &dspub[i]);
  log_duration ("EdDSA", "get pubilc");

  start = GNUNET_TIME_absolute_get();
  for (i = 0; i < l; i++)
    GNUNET_assert (GNUNET_OK ==
                   GNUNET_CRYPTO_eddsa_sign (eddsa[i],
                                             &sig[i].purp,
                                             &sig[i].sig));
  log_duration ("EdDSA", "sign HashCode");

  start = GNUNET_TIME_absolute_get();
  for (i = 0; i < l; i++)
    GNUNET_assert (GNUNET_OK ==
                   GNUNET_CRYPTO_eddsa_verify (0,
                                               &sig[i].purp,
                                               &sig[i].sig,
                                               &dspub[i]));
  log_duration ("EdDSA", "verify HashCode");

  start = GNUNET_TIME_absolute_get();
  for (i = 0; i < l; i++)
    ecdhe[i] = GNUNET_CRYPTO_ecdhe_key_create();
  log_duration ("ECDH", "create key");

  start = GNUNET_TIME_absolute_get();
  for (i = 0; i < l; i++)
    GNUNET_CRYPTO_ecdhe_key_get_public (ecdhe[i], &dhpub[i]);
  log_duration ("ECDH", "get public");

  start = GNUNET_TIME_absolute_get();
  for (i = 0; i < l - 1; i+=2)
  {
    GNUNET_CRYPTO_ecc_ecdh (ecdhe[i], &dhpub[i+1], &sig[i].h);
    GNUNET_CRYPTO_ecc_ecdh (ecdhe[i+1], &dhpub[i], &sig[i+1].h);
  }
  log_duration ("ECDH", "do DH");

  return 0;
}
/**
 * Encrypt data with the axolotl tunnel key.
 *
 * @param t Tunnel whose key to use.
 * @param dst Destination with @a size bytes for the encrypted data.
 * @param src Source of the plaintext. Can overlap with @c dst, must contain @a size bytes
 * @param size Size of the buffers at @a src and @a dst
 */
static void
t_ax_encrypt (struct CadetTunnel *t,
              void *dst,
              const void *src,
              size_t size)
{
  struct GNUNET_CRYPTO_SymmetricSessionKey MK;
  struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
  struct CadetTunnelAxolotl *ax;
  size_t out_size;

  ax = &t->ax;
  ax->ratchet_counter++;
  if ( (GNUNET_YES == ax->ratchet_allowed) &&
       ( (ratchet_messages <= ax->ratchet_counter) ||
         (0 == GNUNET_TIME_absolute_get_remaining (ax->ratchet_expiration).rel_value_us)) )
  {
    ax->ratchet_flag = GNUNET_YES;
  }
  if (GNUNET_YES == ax->ratchet_flag)
  {
    /* Advance ratchet */
    struct GNUNET_CRYPTO_SymmetricSessionKey keys[3];
    struct GNUNET_HashCode dh;
    struct GNUNET_HashCode hmac;
    static const char ctx[] = "axolotl ratchet";

    new_ephemeral (t);
    ax->HKs = ax->NHKs;

    /* RK, NHKs, CKs = KDF( HMAC-HASH(RK, DH(DHRs, DHRr)) ) */
    GNUNET_CRYPTO_ecc_ecdh (ax->DHRs,
                            &ax->DHRr,
                            &dh);
    t_ax_hmac_hash (&ax->RK,
                    &hmac,
                    &dh,
                    sizeof (dh));
    GNUNET_CRYPTO_kdf (keys, sizeof (keys),
                       ctx, sizeof (ctx),
                       &hmac, sizeof (hmac),
                       NULL);
    ax->RK = keys[0];
    ax->NHKs = keys[1];
    ax->CKs = keys[2];

    ax->PNs = ax->Ns;
    ax->Ns = 0;
    ax->ratchet_flag = GNUNET_NO;
    ax->ratchet_allowed = GNUNET_NO;
    ax->ratchet_counter = 0;
    ax->ratchet_expiration
      = GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get(),
                                  ratchet_time);
  }

  t_hmac_derive_key (&ax->CKs,
                     &MK,
                     "0",
                     1);
  GNUNET_CRYPTO_symmetric_derive_iv (&iv,
                                     &MK,
                                     NULL, 0,
                                     NULL);

  out_size = GNUNET_CRYPTO_symmetric_encrypt (src,
                                              size,
                                              &MK,
                                              &iv,
                                              dst);
  GNUNET_assert (size == out_size);
  t_hmac_derive_key (&ax->CKs,
                     &ax->CKs,
                     "1",
                     1);
}
/**
 * Decrypt and verify data with the appropriate tunnel key and verify that the
 * data has not been altered since it was sent by the remote peer.
 *
 * @param t Tunnel whose key to use.
 * @param dst Destination for the plaintext.
 * @param src Source of the message. Can overlap with @c dst.
 * @param size Size of the message.
 * @return Size of the decrypted data, -1 if an error was encountered.
 */
static ssize_t
t_ax_decrypt_and_validate (struct CadetTunnel *t,
                           void *dst,
                           const struct GNUNET_CADET_Encrypted *src,
                           size_t size)
{
  struct CadetTunnelAxolotl *ax;
  struct GNUNET_ShortHashCode msg_hmac;
  struct GNUNET_HashCode hmac;
  struct GNUNET_CADET_Encrypted plaintext_header;
  uint32_t Np;
  uint32_t PNp;
  size_t esize; /* Size of encryped payload */

  esize = size - sizeof (struct GNUNET_CADET_Encrypted);
  ax = &t->ax;

  /* Try current HK */
  t_hmac (&src->Ns,
          AX_HEADER_SIZE + esize,
          0, &ax->HKr,
          &msg_hmac);
  if (0 != memcmp (&msg_hmac,
                   &src->hmac,
                   sizeof (msg_hmac)))
  {
    static const char ctx[] = "axolotl ratchet";
    struct GNUNET_CRYPTO_SymmetricSessionKey keys[3]; /* RKp, NHKp, CKp */
    struct GNUNET_CRYPTO_SymmetricSessionKey HK;
    struct GNUNET_HashCode dh;
    struct GNUNET_CRYPTO_EcdhePublicKey *DHRp;

    /* Try Next HK */
    t_hmac (&src->Ns,
            AX_HEADER_SIZE + esize,
            0,
            &ax->NHKr,
            &msg_hmac);
    if (0 != memcmp (&msg_hmac,
                     &src->hmac,
                     sizeof (msg_hmac)))
    {
      /* Try the skipped keys, if that fails, we're out of luck. */
      return try_old_ax_keys (t,
                              dst,
                              src,
                              size);
    }
    HK = ax->HKr;
    ax->HKr = ax->NHKr;
    t_h_decrypt (t,
                 src,
                 &plaintext_header);
    Np = ntohl (plaintext_header.Ns);
    PNp = ntohl (plaintext_header.PNs);
    DHRp = &plaintext_header.DHRs;
    store_ax_keys (t,
                   &HK,
                   PNp);

    /* RKp, NHKp, CKp = KDF (HMAC-HASH (RK, DH (DHRp, DHRs))) */
    GNUNET_CRYPTO_ecc_ecdh (ax->DHRs,
                            DHRp,
                            &dh);
    t_ax_hmac_hash (&ax->RK,
                    &hmac,
                    &dh, sizeof (dh));
    GNUNET_CRYPTO_kdf (keys, sizeof (keys),
                       ctx, sizeof (ctx),
                       &hmac, sizeof (hmac),
                       NULL);

    /* Commit "purported" keys */
    ax->RK = keys[0];
    ax->NHKr = keys[1];
    ax->CKr = keys[2];
    ax->DHRr = *DHRp;
    ax->Nr = 0;
    ax->ratchet_allowed = GNUNET_YES;
  }
  else
  {
    t_h_decrypt (t,
                 src,
                 &plaintext_header);
    Np = ntohl (plaintext_header.Ns);
    PNp = ntohl (plaintext_header.PNs);
  }
  if ( (Np != ax->Nr) &&
       (GNUNET_OK != store_ax_keys (t,
                                    &ax->HKr,
                                    Np)) )
  {
    /* Try the skipped keys, if that fails, we're out of luck. */
    return try_old_ax_keys (t,
                            dst,
                            src,
                            size);
  }

  t_ax_decrypt (t,
                dst,
                &src[1],
                esize);
  ax->Nr = Np + 1;
  return esize;
}