Пример #1
0
/* Initializes the nonce level random generator.
 *
 * the @new_key must be provided.
 *
 * @init must be non zero on first initialization, and
 * zero on any subsequent reinitializations.
 */
static int single_prng_init(struct prng_ctx_st *ctx,
			    uint8_t new_key[PRNG_KEY_SIZE],
			    unsigned new_key_size,
			    unsigned init)
{
	uint8_t nonce[CHACHA_NONCE_SIZE];

	memset(nonce, 0, sizeof(nonce)); /* to prevent valgrind from whinning */

	if (init == 0) {
		/* use the previous key to generate IV as well */
		chacha_crypt(&ctx->ctx, sizeof(nonce), nonce, nonce);

		/* Add key continuity by XORing the new key with data generated
		 * from the old key */
		chacha_crypt(&ctx->ctx, new_key_size, new_key, new_key);
	} else {
		struct timespec now; /* current time */

		ctx->forkid = _gnutls_get_forkid();

		gettime(&now);
		memcpy(nonce, &now, MIN(sizeof(nonce), sizeof(now)));
		ctx->last_reseed = now.tv_sec;
	}

	chacha_set_key(&ctx->ctx, new_key);
	chacha_set_nonce(&ctx->ctx, nonce);

	zeroize_key(new_key, new_key_size);

	ctx->counter = 0;

	return 0;
}
Пример #2
0
/**
  Generate a stream of random bytes via ChaCha
  @param st      The ChaCha20 state
  @param out     [out] The output buffer
  @param outlen  The output length
  @return CRYPT_OK on success
 */
int chacha_keystream(chacha_state *st, unsigned char *out, unsigned long outlen)
{
   if (outlen == 0) return CRYPT_OK; /* nothing to do */
   LTC_ARGCHK(out != NULL);
   XMEMSET(out, 0, outlen);
   return chacha_crypt(st, out, outlen, out);
}
Пример #3
0
int chacha_test(void)
{
#ifndef LTC_TEST
   return CRYPT_NOP;
#else
   unsigned long len;
   unsigned char out[1000];
   /* https://tools.ietf.org/html/rfc7539#section-2.4.2 */
   unsigned char k[]  = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
                          0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f };
   unsigned char n[]  = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x00 };
   unsigned char ct[] = { 0x6E, 0x2E, 0x35, 0x9A, 0x25, 0x68, 0xF9, 0x80, 0x41, 0xBA, 0x07, 0x28, 0xDD, 0x0D, 0x69, 0x81,
                          0xE9, 0x7E, 0x7A, 0xEC, 0x1D, 0x43, 0x60, 0xC2, 0x0A, 0x27, 0xAF, 0xCC, 0xFD, 0x9F, 0xAE, 0x0B,
                          0xF9, 0x1B, 0x65, 0xC5, 0x52, 0x47, 0x33, 0xAB, 0x8F, 0x59, 0x3D, 0xAB, 0xCD, 0x62, 0xB3, 0x57,
                          0x16, 0x39, 0xD6, 0x24, 0xE6, 0x51, 0x52, 0xAB, 0x8F, 0x53, 0x0C, 0x35, 0x9F, 0x08, 0x61, 0xD8,
                          0x07, 0xCA, 0x0D, 0xBF, 0x50, 0x0D, 0x6A, 0x61, 0x56, 0xA3, 0x8E, 0x08, 0x8A, 0x22, 0xB6, 0x5E,
                          0x52, 0xBC, 0x51, 0x4D, 0x16, 0xCC, 0xF8, 0x06, 0x81, 0x8C, 0xE9, 0x1A, 0xB7, 0x79, 0x37, 0x36,
                          0x5A, 0xF9, 0x0B, 0xBF, 0x74, 0xA3, 0x5B, 0xE6, 0xB4, 0x0B, 0x8E, 0xED, 0xF2, 0x78, 0x5E, 0x42,
                          0x87, 0x4D };
   char pt[] = "Ladies and Gentlemen of the class of '99: If I could offer you only one tip for the future, sunscreen would be it.";
   chacha_state st;
   int err;

   len = strlen(pt);

   /* crypt piece by piece - using chacha_ivctr32() */
   if ((err = chacha_setup(&st, k, sizeof(k), 20)) != CRYPT_OK)                            return err;
   if ((err = chacha_ivctr32(&st, n, sizeof(n), 1)) != CRYPT_OK)                           return err;
   if ((err = chacha_crypt(&st, (unsigned char*)pt,      35,       out     )) != CRYPT_OK) return err;
   if ((err = chacha_crypt(&st, (unsigned char*)pt + 35, 35,       out + 35)) != CRYPT_OK) return err;
   if ((err = chacha_crypt(&st, (unsigned char*)pt + 70,  5,       out + 70)) != CRYPT_OK) return err;
   if ((err = chacha_crypt(&st, (unsigned char*)pt + 75,  5,       out + 75)) != CRYPT_OK) return err;
   if ((err = chacha_crypt(&st, (unsigned char*)pt + 80, len - 80, out + 80)) != CRYPT_OK) return err;
   if (compare_testvector(out, len, ct, sizeof(ct), "CHACHA-TV1", 1))                      return CRYPT_FAIL_TESTVECTOR;

   /* crypt in one go - using chacha_ivctr32() */
   if ((err = chacha_setup(&st, k, sizeof(k), 20)) != CRYPT_OK)                            return err;
   if ((err = chacha_ivctr32(&st, n, sizeof(n), 1)) != CRYPT_OK)                           return err;
   if ((err = chacha_crypt(&st, (unsigned char*)pt, len, out)) != CRYPT_OK)                return err;
   if (compare_testvector(out, len, ct, sizeof(ct), "CHACHA-TV2", 1))                      return CRYPT_FAIL_TESTVECTOR;

   /* crypt in one go - using chacha_ivctr64() */
   if ((err = chacha_setup(&st, k, sizeof(k), 20)) != CRYPT_OK)                            return err;
   if ((err = chacha_ivctr64(&st, n + 4, sizeof(n) - 4, 1)) != CRYPT_OK)                   return err;
   if ((err = chacha_crypt(&st, (unsigned char*)pt, len, out)) != CRYPT_OK)                return err;
   if (compare_testvector(out, len, ct, sizeof(ct), "CHACHA-TV3", 1))                      return CRYPT_FAIL_TESTVECTOR;

   /* crypt in a single call using 32-bit counter with a value of 1 */
   if ((err = chacha_memory(k, sizeof(k), 20,
                            n, sizeof(n), 1, (unsigned char*)pt, len, out)) != CRYPT_OK)   return err;
   if (compare_testvector(out, len, ct, sizeof(ct), "CHACHA-TV4", 1))                      return CRYPT_FAIL_TESTVECTOR;

   /* crypt in a single call using 64-bit counter with a value of 1 */
   if ((err = chacha_memory(k, sizeof(k), 20,
                            n + 4, sizeof(n) - 4, 1, (unsigned char*)pt, len, out)) != CRYPT_OK)  return err;
   if (compare_testvector(out, len, ct, sizeof(ct), "CHACHA-TV5", 1))                      return CRYPT_FAIL_TESTVECTOR;

   return CRYPT_OK;
#endif
}
Пример #4
0
void
chacha_poly1305_decrypt (struct chacha_poly1305_ctx *ctx,
			 size_t length, uint8_t *dst, const uint8_t *src)
{
  if (!length)
    return;

  assert (ctx->data_size % CHACHA_POLY1305_BLOCK_SIZE == 0);
  poly1305_pad (ctx);

  poly1305_update (ctx, length, src);
  chacha_crypt (&ctx->chacha, length, dst, src);
  ctx->data_size += length;
}
Пример #5
0
void test_chacha(const uint8_t *key, const uint8_t *iv, uint8_t *expected, 
                uint8_t keylength, uint8_t rounds) {
    uint8_t cipher_data[64] =  {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};

    uint8_t cipher_result[64] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
    
    struct chacha_ctx cipher_ctx;

    uint8_t errors;
    
    chacha_set_key(&cipher_ctx, keylength, key);
    chacha_set_iv(&cipher_ctx, iv);
    chacha_crypt(&cipher_ctx, 64, rounds, &cipher_result[0], &cipher_data[0]);

    if (DEBUG) {
        printf("Result after encryption:\n");
        print_block(cipher_result);
      }

    errors = 0;
    for (uint8_t i = 0 ; i < 64 ; i++) {
      if (cipher_result[i] != expected[i]) {
        errors++;
      }
    }
    
    if (errors > 0) {
      printf("Error, expected:\n");
      print_block(&expected[0]);
      printf("Got:\n");
      print_block(cipher_result);
    }
    else {
      printf("Success, result matched expected.\n");
    }
}
Пример #6
0
void
chacha_poly1305_encrypt (struct chacha_poly1305_ctx *ctx,
			 size_t length, uint8_t *dst, const uint8_t *src)
{
  if (!length)
    return;

  assert (ctx->data_size % CHACHA_POLY1305_BLOCK_SIZE == 0);
  if (!ctx->data_size)
    {
      uint8_t buf[8];
      LE_WRITE_UINT64 (buf, ctx->auth_size);
      poly1305_update (ctx, sizeof(buf), buf);
    }
  chacha_crypt (&ctx->chacha, length, dst, src);
  poly1305_update (ctx, length, dst);
  ctx->data_size += length;
}
/**
   Encrypt bytes of ciphertext with ChaCha20Poly1305
   @param st      The ChaCha20Poly1305 state
   @param in      The plaintext
   @param inlen   The length of the input (octets)
   @param out     [out] The ciphertext (length inlen)
   @return CRYPT_OK if successful
*/
int chacha20poly1305_encrypt(chacha20poly1305_state *st, const unsigned char *in, unsigned long inlen, unsigned char *out)
{
   unsigned char padzero[16] = { 0 };
   unsigned long padlen;
   int err;

   if (inlen == 0) return CRYPT_OK; /* nothing to do */
   LTC_ARGCHK(st != NULL);

   if ((err = chacha_crypt(&st->chacha, in, inlen, out)) != CRYPT_OK)         return err;
   if (st->aadflg) {
      padlen = 16 - (unsigned long)(st->aadlen % 16);
      if (padlen < 16) {
        if ((err = poly1305_process(&st->poly, padzero, padlen)) != CRYPT_OK) return err;
      }
      st->aadflg = 0; /* no more AAD */
   }
   if ((err = poly1305_process(&st->poly, out, inlen)) != CRYPT_OK)           return err;
   st->ctlen += (ulong64)inlen;
   return CRYPT_OK;
}
Пример #8
0
static int
wrap_nettle_rnd(void *_ctx, int level, void *data, size_t datasize)
{
	struct generators_ctx_st *ctx = _ctx;
	struct prng_ctx_st *prng_ctx;
	int ret, reseed = 0;
	uint8_t new_key[PRNG_KEY_SIZE];
	time_t now;

	if (level == GNUTLS_RND_RANDOM || level == GNUTLS_RND_KEY)
		prng_ctx = &ctx->normal;
	else if (level == GNUTLS_RND_NONCE)
		prng_ctx = &ctx->nonce;
	else
		return gnutls_assert_val(GNUTLS_E_RANDOM_FAILED);

	/* Two reasons for this memset():
	 *  1. avoid getting filled with valgrind warnings
	 *  2. avoid a cipher/PRNG failure to expose stack data
	 */
	memset(data, 0, datasize);

	now = gnutls_time(0);

	/* We re-seed based on time in addition to output data. That is,
	 * to prevent a temporal state compromise to become permanent for low
	 * traffic sites */
	if (unlikely(_gnutls_detect_fork(prng_ctx->forkid))) {
		reseed = 1;
	} else {
		if (now > prng_ctx->last_reseed + prng_reseed_time[level])
			reseed = 1;
	}

	if (reseed != 0 || prng_ctx->counter > prng_reseed_limits[level]) {
		if (level == GNUTLS_RND_NONCE) {
			ret = wrap_nettle_rnd(_ctx, GNUTLS_RND_RANDOM, new_key, sizeof(new_key));
		} else {

			/* we also use the system entropy to reduce the impact
			 * of a temporal state compromise for these two levels. */
			ret = _rnd_get_system_entropy(new_key, sizeof(new_key));
		}

		if (ret < 0) {
			gnutls_assert();
			goto cleanup;
		}

		ret = single_prng_init(prng_ctx, new_key, sizeof(new_key), 0);
		if (ret < 0) {
			gnutls_assert();
			goto cleanup;
		}

		prng_ctx->last_reseed = now;
		prng_ctx->forkid = _gnutls_get_forkid();
	}

	chacha_crypt(&prng_ctx->ctx, datasize, data, data);
	prng_ctx->counter += datasize;

	if (level == GNUTLS_RND_KEY) { /* prevent backtracking */
		ret = wrap_nettle_rnd(_ctx, GNUTLS_RND_RANDOM, new_key, sizeof(new_key));
		if (ret < 0) {
			gnutls_assert();
			goto cleanup;
		}

		ret = single_prng_init(prng_ctx, new_key, sizeof(new_key), 0);
		if (ret < 0) {
			gnutls_assert();
			goto cleanup;
		}
	}

	ret = 0;

cleanup:
	return ret;
}
Пример #9
0
static void
test_chacha_stream(const struct tstring *key,
		    const struct tstring *iv,
		    const struct tstring *ciphertext,
		    const struct tstring *xor_ref)
{
  struct chacha_ctx ctx;
  uint8_t data[STREAM_LENGTH + 1];
  uint8_t stream[STREAM_LENGTH + 1];
  uint8_t xor[CHACHA_BLOCK_SIZE];
  size_t j;

  ASSERT (iv->length == CHACHA_IV_SIZE);
  ASSERT (ciphertext->length == 4*CHACHA_BLOCK_SIZE);
  ASSERT (xor_ref->length == CHACHA_BLOCK_SIZE);

  chacha_set_key(&ctx, key->length, key->data);
  chacha_set_iv(&ctx, iv->data);
  memset(stream, 0, STREAM_LENGTH + 1);
  chacha_crypt(&ctx, STREAM_LENGTH, stream, stream);
  if (stream[STREAM_LENGTH])
    {
      fprintf(stderr, "Stream of %d bytes wrote too much!\n", STREAM_LENGTH);
      FAIL();
    }
  if (!MEMEQ (64, stream, ciphertext->data))
    {
      fprintf(stderr, "Error failed, offset 0:\n");
      fprintf(stderr, "\nOutput: ");
      print_hex(64, stream);
      fprintf(stderr, "\nExpected:");
      print_hex(64, ciphertext->data);
      fprintf(stderr, "\n");
      FAIL();
    }
  if (!MEMEQ (128, stream + 192, ciphertext->data + 64))
    {
      fprintf(stderr, "Error failed, offset 192:\n");
      fprintf(stderr, "\nOutput: ");
      print_hex(128, stream + 192);
      fprintf(stderr, "\nExpected:");
      print_hex(64, ciphertext->data + 64);
      fprintf(stderr, "\n");
      FAIL();
    }
  if (!MEMEQ (64, stream + 448, ciphertext->data + 192))
    {
      fprintf(stderr, "Error failed, offset 448:\n");
      fprintf(stderr, "\nOutput: ");
      print_hex(64, stream + 448);
      fprintf(stderr, "\nExpected:");
      print_hex(64, ciphertext->data + 192);
      fprintf(stderr, "\n");
      FAIL();
    }

  memxor3 (xor, stream, stream + CHACHA_BLOCK_SIZE, CHACHA_BLOCK_SIZE);
  for (j = 2*CHACHA_BLOCK_SIZE; j < STREAM_LENGTH; j += CHACHA_BLOCK_SIZE)
    memxor (xor, stream + j, CHACHA_BLOCK_SIZE);

  if (!MEMEQ (CHACHA_BLOCK_SIZE, xor, xor_ref->data))
    {
      fprintf(stderr, "Error failed, bad xor 448:\n");
      fprintf(stderr, "\nOutput: ");
      print_hex(CHACHA_BLOCK_SIZE, xor);
      fprintf(stderr, "\nExpected:");
      print_hex(CHACHA_BLOCK_SIZE, xor_ref->data);
      fprintf(stderr, "\n");
      FAIL();
    }

  for (j = 1; j <= STREAM_LENGTH; j++)
    {
      memset(data, 0, STREAM_LENGTH + 1);
      chacha_set_iv(&ctx, iv->data);
      chacha_crypt(&ctx, j, data, data);

      if (!MEMEQ(j, data, stream))
	{
	  fprintf(stderr, "Encrypt failed for length %lu:\n",
		  (unsigned long) j);
	  fprintf(stderr, "\nOutput: ");
	  print_hex(j, data);
	  fprintf(stderr, "\nExpected:");
	  print_hex(j, stream);
	  fprintf(stderr, "\n");
	  FAIL();
	}
      if (!memzero_p (data + j, STREAM_LENGTH + 1 - j))
	{
	  fprintf(stderr, "Encrypt failed for length %lu, wrote too much:\n",
		  (unsigned long) j);
	  fprintf(stderr, "\nOutput: ");
	  print_hex(STREAM_LENGTH + 1 - j, data + j);
	  fprintf(stderr, "\n");
	  FAIL();
	}
    }
}