Exemplo n.º 1
0
int dh_tests (void)
{
  unsigned char buf[3][4096];
  unsigned long x, y, z;
  int           stat, stat2;
  dh_key        usera, userb;

  DO(dh_test());

  /* make up two keys */
  DO(dh_make_key (&test_yarrow, find_prng ("yarrow"), 96, &usera));
  DO(dh_make_key (&test_yarrow, find_prng ("yarrow"), 96, &userb));

  /* make the shared secret */
  x = 4096;
  DO(dh_shared_secret (&usera, &userb, buf[0], &x));

  y = 4096;
  DO(dh_shared_secret (&userb, &usera, buf[1], &y));
  if (y != x) {
    printf ("DH Shared keys are not same size.\n");
    return 1;
  }
  if (memcmp (buf[0], buf[1], x)) {
    printf ("DH Shared keys not same contents.\n");
    return 1;
  }

  /* now export userb */
  y = 4096;
  DO(dh_export (buf[1], &y, PK_PUBLIC, &userb));
	  dh_free (&userb);

  /* import and make the shared secret again */
  DO(dh_import (buf[1], y, &userb));
  z = 4096;
  DO(dh_shared_secret (&usera, &userb, buf[2], &z));

  if (z != x) {
    printf ("failed.  Size don't match?\n");
    return 1;
  }
  if (memcmp (buf[0], buf[2], x)) {
    printf ("Failed.  Content didn't match.\n");
    return 1;
  }
  dh_free (&usera);
  dh_free (&userb);

/* test encrypt_key */
  dh_make_key (&test_yarrow, find_prng ("yarrow"), 128, &usera);
  for (x = 0; x < 16; x++) {
    buf[0][x] = x;
  }
  y = sizeof (buf[1]);
  DO(dh_encrypt_key (buf[0], 16, buf[1], &y, &test_yarrow, find_prng ("yarrow"), find_hash ("md5"), &usera));
  zeromem (buf[0], sizeof (buf[0]));
  x = sizeof (buf[0]);
  DO(dh_decrypt_key (buf[1], y, buf[0], &x, &usera));
  if (x != 16) {
    printf ("Failed (length)\n");
    return 1;
  }
  for (x = 0; x < 16; x++)
    if (buf[0][x] != x) {
      printf ("Failed (contents)\n");
      return 1;
    }

/* test sign_hash */
  for (x = 0; x < 16; x++) {
     buf[0][x] = x;
  }
  x = sizeof (buf[1]);
  DO(dh_sign_hash (buf[0], 16, buf[1], &x, &test_yarrow		, find_prng ("yarrow"), &usera));
  DO(dh_verify_hash (buf[1], x, buf[0], 16, &stat, &usera));
  buf[0][0] ^= 1;
  DO(dh_verify_hash (buf[1], x, buf[0], 16, &stat2, &usera));
  if (!(stat == 1 && stat2 == 0)) { 
     printf("dh_sign/verify_hash %d %d", stat, stat2);
     return 1;
  }
  dh_free (&usera);
  return 0;
}
Exemplo n.º 2
0
/**
  Encrypt a short symmetric key with a public DH key
  @param in        The symmetric key to encrypt
  @param inlen     The length of the key (octets)
  @param out       [out] The ciphertext
  @param outlen    [in/out]  The max size and resulting size of the ciphertext
  @param prng      An active PRNG state
  @param wprng     The index of the PRNG desired
  @param hash      The index of the hash desired (must produce a digest of size >= the size of the plaintext)
  @param key       The public key you wish to encrypt with.
  @return CRYPT_OK if successful
*/
int dh_encrypt_key(const unsigned char *in,   unsigned long inlen,
                         unsigned char *out,  unsigned long *outlen,
                         prng_state *prng, int wprng, int hash,
                         dh_key *key)
{
    unsigned char *pub_expt, *dh_shared, *skey;
    dh_key        pubkey;
    unsigned long x, y, z, hashsize, pubkeysize;
    int           err;

    LTC_ARGCHK(in != NULL);
    LTC_ARGCHK(out   != NULL);
    LTC_ARGCHK(outlen   != NULL);
    LTC_ARGCHK(key   != NULL);

    /* check that wprng/hash are not invalid */
    if ((err = prng_is_valid(wprng)) != CRYPT_OK) {
       return err;
    }

    if ((err = hash_is_valid(hash)) != CRYPT_OK) {
       return err;
    }

    if (inlen > hash_descriptor[hash].hashsize)  {
        return CRYPT_INVALID_HASH;
    }

    /* allocate memory */
    pub_expt  = XMALLOC(DH_BUF_SIZE);
    dh_shared = XMALLOC(DH_BUF_SIZE);
    skey      = XMALLOC(MAXBLOCKSIZE);
    if (pub_expt == NULL || dh_shared == NULL || skey == NULL) {
       if (pub_expt != NULL) {
          XFREE(pub_expt);
       }
       if (dh_shared != NULL) {
          XFREE(dh_shared);
       }
       if (skey != NULL) {
          XFREE(skey);
       }
       return CRYPT_MEM;
    }

    /* make a random key and export the public copy */
    if ((err = dh_make_key(prng, wprng, dh_get_size(key), &pubkey)) != CRYPT_OK) {
       goto LBL_ERR;
    }

    pubkeysize = DH_BUF_SIZE;
    if ((err = dh_export(pub_expt, &pubkeysize, PK_PUBLIC, &pubkey)) != CRYPT_OK) {
       dh_free(&pubkey);
       goto LBL_ERR;
    }

    /* now check if the out buffer is big enough */
    if (*outlen < (1 + 4 + 4 + PACKET_SIZE + pubkeysize + inlen)) {
       dh_free(&pubkey);
       err = CRYPT_BUFFER_OVERFLOW;
       goto LBL_ERR;
    }

    /* make random key */
    hashsize  = hash_descriptor[hash].hashsize;

    x = DH_BUF_SIZE;
    if ((err = dh_shared_secret(&pubkey, key, dh_shared, &x)) != CRYPT_OK) {
       dh_free(&pubkey);
       goto LBL_ERR;
    }
    dh_free(&pubkey);

    z = MAXBLOCKSIZE;
    if ((err = hash_memory(hash, dh_shared, x, skey, &z)) != CRYPT_OK) {
       goto LBL_ERR;
    }

    /* store header */
    packet_store_header(out, PACKET_SECT_DH, PACKET_SUB_ENC_KEY);

    /* output header */
    y = PACKET_SIZE;

    /* size of hash name and the name itself */
    out[y++] = hash_descriptor[hash].ID;

    /* length of DH pubkey and the key itself */
    STORE32L(pubkeysize, out+y);
    y += 4;
    for (x = 0; x < pubkeysize; x++, y++) {
        out[y] = pub_expt[x];
    }

    /* Store the encrypted key */
    STORE32L(inlen, out+y);
    y += 4;

    for (x = 0; x < inlen; x++, y++) {
      out[y] = skey[x] ^ in[x];
    }
    *outlen = y;

    err = CRYPT_OK;
LBL_ERR:
#ifdef LTC_CLEAN_STACK
    /* clean up */
    zeromem(pub_expt,  DH_BUF_SIZE);
    zeromem(dh_shared, DH_BUF_SIZE);
    zeromem(skey,      MAXBLOCKSIZE);
#endif
    XFREE(skey);
    XFREE(dh_shared);
    XFREE(pub_expt);

    return err;
}