Ejemplo n.º 1
0
/*
	After encryption this function is used to retreive the authentication tag
*/
void psAesGetGCMTag(psAesGcm_t *ctx,
				uint8_t tagBytes, unsigned char tag[AES_BLOCKLEN])
{
	unsigned char	*pt, *ct;

	psGhashFinal(ctx);

	/* Encrypt authentication tag */
	ctx->OutputBufferCount = 0;

	ct = tag;
	pt = (unsigned char*)ctx->TagTemp;
	while (tagBytes) {
		if (ctx->OutputBufferCount == 0) {
			ctx->OutputBufferCount = 16;
			/* Initial IV has been set aside in IV */
			psAesEncryptBlock(&ctx->key, ctx->IV, ctx->CtrBlock);
			/* No need to increment since we know tag bytes will never be
				larger than 16 */
		}
		*(ct++) = *(pt++) ^ ctx->CtrBlock[16 - ctx->OutputBufferCount];
		tagBytes--;
		ctx->OutputBufferCount--;

	}
}
/**
  Make the PRNG ready to read from and to reseed when desired
  @param prng   The PRNG to seed
*/
int32 psYarrowReseed(psYarrow_t *ctx)
{
	const unsigned char *IV;
	int32				keylen, ctr_mode, x, err;

	IV = ctx->pool;
	keylen = AESBLOCKSIZE;   /* Can only use 16 bytes for the AES key */
	ctr_mode = CTR_COUNTER_LITTLE_ENDIAN; /* little endian counter */

	/* ctrlen == counter width */
	ctx->ctrlen   = (ctr_mode & 255) ? (ctr_mode & 255) : AESBLOCKSIZE;
	if (ctx->ctrlen > AESBLOCKSIZE) {
		return PS_ARG_FAIL;
	}

	if ((ctr_mode & 0x1000) == CTR_COUNTER_BIG_ENDIAN) {
		ctx->ctrlen = AESBLOCKSIZE - ctx->ctrlen;
	}

	/* setup cipher */
	if ((err = psAesInitKey(ctx->pool, keylen, &ctx->key)) != PS_SUCCESS) {
		return err;
	}

	/* copy ctr */
	ctx->padlen   = 0;
	ctx->mode     = ctr_mode & 0x1000;
	for (x = 0; x < ctx->blocklen; x++) {
		ctx->ctr[x] = IV[x];
	}

	/* increment the IV */
	if (ctx->mode == CTR_COUNTER_LITTLE_ENDIAN) {
		/* little-endian */
		for (x = 0; x < ctx->ctrlen; x++) {
			ctx->ctr[x] = (ctx->ctr[x] + (unsigned char)1) & (unsigned char)255;
			if (ctx->ctr[x] != (unsigned char)0) {
				break;
			}
		}
	} else {
		/* big-endian */
		for (x = ctx->blocklen-1; x >= ctx->ctrlen; x--) {
			ctx->ctr[x] = (ctx->ctr[x] + (unsigned char)1) & (unsigned char)255;
			if (ctx->ctr[x] != (unsigned char)0) {
				break;
			}
		}
	}

	psAesEncryptBlock(ctx->ctr, ctx->pad, &ctx->key);
	return PS_SUCCESS;
}
/**
  Read from the PRNG
  @param out      Destination
  @param outlen   Length of output
  @param ctx     The active PRNG to read from
  @return Number of octets read
*/
uint32 psYarrowRead(unsigned char *out, uint32 outlen, psYarrow_t *ctx)
{
	unsigned char	*pt, *ct;
	int32			x;
	uint32			len;

	/* put out in predictable state first */
	memset(out, 0x0, outlen);

	len = outlen;
	pt = ct = out;

	/* is blocklen/padlen valid? */
	if (ctx->blocklen < 1 || ctx->blocklen > (int32)sizeof(ctx->ctr) ||
			ctx->padlen   < 0 || ctx->padlen   > (int32)sizeof(ctx->pad)) {
		return 0;
	}

	while (outlen) {
		/* is the pad empty? */
		if (ctx->padlen == ctx->blocklen) {
			/* increment counter */
			if (ctx->mode == CTR_COUNTER_LITTLE_ENDIAN) {
				/* little-endian */
				for (x = 0; x < ctx->ctrlen; x++) {
					ctx->ctr[x] =
						(ctx->ctr[x] + (unsigned char)1) & (unsigned char)255;
					if (ctx->ctr[x] != (unsigned char)0) {
						break;
					}
				}
			} else {
				/* big-endian */
				for (x = ctx->blocklen-1; x >= ctx->ctrlen; x--) {
					ctx->ctr[x] =
						(ctx->ctr[x] + (unsigned char)1) & (unsigned char)255;
					if (ctx->ctr[x] != (unsigned char)0) {
						break;
					}
				}
			}

			/* encrypt new pad and reset */
			psAesEncryptBlock(ctx->ctr, ctx->pad, &ctx->key);
			ctx->padlen = 0;
		}
		*ct++ = *pt++ ^ ctx->pad[ctx->padlen++];
		--outlen;
	}
	return len;
}
Ejemplo n.º 4
0
/*
	Initialize an AES GCM context
*/
int32_t psAesInitGCM(psAesGcm_t *ctx,
					const unsigned char key[AES_MAXKEYLEN], uint8_t keylen)
{
	int32_t			rc;
	unsigned char	blockIn[16] = { 0 };

	memset(ctx, 0x0, sizeof(psAesGcm_t));
	/* GCM always uses AES in ENCRYPT block mode, even for decrypt */
	rc = psAesInitBlockKey(&ctx->key, key, keylen, PS_AES_ENCRYPT);
	if (rc < 0) {
		return rc;
	}
	psAesEncryptBlock(&ctx->key, blockIn, ctx->gInit);
	return PS_SUCCESS;
}
Ejemplo n.º 5
0
/*
	Internal gcm crypt function that uses direction to determine what gets
	fed to the GHASH update
*/
static void psAesEncryptGCMx(psAesGcm_t *ctx,
				const unsigned char *pt, unsigned char *ct,
				uint32_t len, int8_t direction)
{
	unsigned char	*ctStart;
	uint32_t		outLen;
	int				x;	/* Must be signed due to positive check below */

	outLen = len;
	ctStart = ct;
	if (direction == 0) {
		psGhashUpdate(ctx, pt, len, GHASH_DATATYPE_CIPHERTEXT);
	}
	while (len) {
		if (ctx->OutputBufferCount == 0) {
			ctx->OutputBufferCount = 16;
			psAesEncryptBlock(&ctx->key, ctx->EncCtr, ctx->CtrBlock);

			/* CTR incr */
			for (x = (AES_BLOCKLEN - 1); x >= 0; x--) {
				ctx->EncCtr[x] = (ctx->EncCtr[x] +
					(unsigned char)1) & (unsigned char)255;
				if (ctx->EncCtr[x] != (unsigned char)0) {
					break;
				}
			}
		}

		*(ct++) = *(pt++) ^ ctx->CtrBlock[16 - ctx->OutputBufferCount];
		len--;
		ctx->OutputBufferCount--;
	}
	if (direction == 1) {
		psGhashUpdate(ctx, ctStart, outLen, GHASH_DATATYPE_CIPHERTEXT);
	}
}