FreeBSD/sys/opencrypto/cryptosoft.c
/*
 * Apply a combined encryption-authentication transformation
 */
Apply a combined encryption-authentication transformation
Apply a combined encryption - authentication transformation
static int
swcr_authenc(struct cryptop *crp)
{
	uint32_t blkbuf[howmany(EALG_MAX_BLOCK_LEN, sizeof(uint32_t))];
	u_char *blk = (u_char *)blkbuf;
	u_char aalg[AALG_MAX_RESULT_LEN];
	u_char uaalg[AALG_MAX_RESULT_LEN];
	u_char iv[EALG_MAX_BLOCK_LEN];
	union authctx ctx;
	struct cryptodesc *crd, *crda = NULL, *crde = NULL;
	struct swcr_data *sw, *swa, *swe = NULL;
	struct auth_hash *axf = NULL;
	struct enc_xform *exf = NULL;
	caddr_t buf = (caddr_t)crp->crp_buf;
	uint32_t *blkp;
	int aadlen, blksz, i, ivlen, len, iskip, oskip, r;
	ivlen = blksz = iskip = oskip = 0;
	for (crd = crp->crp_desc; crd; crd = crd->crd_next) {
		for (sw = swcr_sessions[crp->crp_sid & 0xffffffff];
		     sw && sw->sw_alg != crd->crd_alg;
		     sw = sw->sw_next)
			;
		if (sw == NULL)
			return (EINVAL);
		switch (sw->sw_alg) {
		case CRYPTO_AES_NIST_GCM_16:
		case CRYPTO_AES_NIST_GMAC:
			swe = sw;
			crde = crd;
			exf = swe->sw_exf;
			ivlen = 12;
			break;
		case CRYPTO_AES_128_NIST_GMAC:
		case CRYPTO_AES_192_NIST_GMAC:
		case CRYPTO_AES_256_NIST_GMAC:
			swa = sw;
			crda = crd;
			axf = swa->sw_axf;
			if (swa->sw_ictx == 0)
				return (EINVAL);
			bcopy(swa->sw_ictx, &ctx, axf->ctxsize);
			blksz = axf->blocksize;
			break;
		default:
			return (EINVAL);
		}
	}
	if (crde == NULL || crda == NULL)
		return (EINVAL);
	if (crde->crd_alg == CRYPTO_AES_NIST_GCM_16 &&
	    (crde->crd_flags & CRD_F_IV_EXPLICIT) == 0)
		return (EINVAL);
	if (crde->crd_klen != crda->crd_klen)
		return (EINVAL);
	if (crde->crd_flags & CRD_F_ENCRYPT) {
		if (crde->crd_flags & CRD_F_IV_EXPLICIT)
			bcopy(crde->crd_iv, iv, ivlen);
		else
			arc4rand(iv, ivlen, 0);
		if (!(crde->crd_flags & CRD_F_IV_PRESENT))
			crypto_copyback(crp->crp_flags, buf, crde->crd_inject,
			    ivlen, iv);
	} else {	
		if (crde->crd_flags & CRD_F_IV_EXPLICIT)
			bcopy(crde->crd_iv, iv, ivlen);
		else {
			crypto_copydata(crp->crp_flags, buf, crde->crd_inject,
			    ivlen, iv);
		}
	}
	if (axf->Reinit)
		axf->Reinit(&ctx, iv, ivlen);
	aadlen = crda->crd_len;
	for (i = iskip; i < crda->crd_len; i += blksz) {
		len = MIN(crda->crd_len - i, blksz - oskip);
		crypto_copydata(crp->crp_flags, buf, crda->crd_skip + i, len,
		    blk + oskip);
		bzero(blk + len + oskip, blksz - len - oskip);
		axf->Update(&ctx, blk, blksz);
		oskip = 0; 
	}
	if (exf->reinit)
		exf->reinit(swe->sw_kschedule, iv);
	for (i = 0; i < crde->crd_len; i += blksz) {
		len = MIN(crde->crd_len - i, blksz);
		if (len < blksz)
			bzero(blk, blksz);
		crypto_copydata(crp->crp_flags, buf, crde->crd_skip + i, len,
		    blk);
		if (crde->crd_flags & CRD_F_ENCRYPT) {
			exf->encrypt(swe->sw_kschedule, blk);
			axf->Update(&ctx, blk, len);
			crypto_copyback(crp->crp_flags, buf,
			    crde->crd_skip + i, len, blk);
		} else {
			axf->Update(&ctx, blk, len);
		}
	}
	switch (crda->crd_alg) {
		case CRYPTO_AES_128_NIST_GMAC:
		case CRYPTO_AES_192_NIST_GMAC:
		case CRYPTO_AES_256_NIST_GMAC:
			bzero(blk, blksz);
			blkp = (uint32_t *)blk + 1;
			*blkp = htobe32(aadlen * 8);
			blkp = (uint32_t *)blk + 3;
			*blkp = htobe32(crde->crd_len * 8);
			axf->Update(&ctx, blk, blksz);
			break;
	}
	axf->Final(aalg, &ctx);
	if (!(crde->crd_flags & CRD_F_ENCRYPT)) {
		crypto_copydata(crp->crp_flags, buf, crda->crd_inject,
		    axf->hashsize, uaalg);
		r = timingsafe_bcmp(aalg, uaalg, axf->hashsize);
		if (r == 0) {
			for (i = 0; i < crde->crd_len; i += blksz) {
				len = MIN(crde->crd_len - i, blksz);
				if (len < blksz)
					bzero(blk, blksz);
				crypto_copydata(crp->crp_flags, buf,
				    crde->crd_skip + i, len, blk);
				if (!(crde->crd_flags & CRD_F_ENCRYPT)) {
					exf->decrypt(swe->sw_kschedule, blk);
				}
				crypto_copyback(crp->crp_flags, buf,
				    crde->crd_skip + i, len, blk);
			}
		} else
			return (EBADMSG);
	} else {
		crypto_copyback(crp->crp_flags, buf, crda->crd_inject,
		    axf->hashsize, aalg);
	}
	return (0);
}
static int swcr_authenc ( struct cryptop * crp ) { uint32_t blkbuf [ howmany ( EALG_MAX_BLOCK_LEN , sizeof ( uint32_t ) ) ] ; u_char * blk = ( u_char * ) blkbuf ; u_char aalg [ AALG_MAX_RESULT_LEN ] ; u_char uaalg [ AALG_MAX_RESULT_LEN ] ; u_char iv [ EALG_MAX_BLOCK_LEN ] ; union authctx ctx ; struct cryptodesc * crd , * crda = NULL , * crde = NULL ; struct swcr_data * sw , * swa , * swe = NULL ; struct auth_hash * axf = NULL ; struct enc_xform * exf = NULL ; caddr_t buf = ( caddr_t ) crp -> crp_buf ; uint32_t * blkp ; int aadlen , blksz , i , ivlen , len , iskip , oskip , r ; ivlen = blksz = iskip = oskip = 0 ; for ( crd = crp -> crp_desc ; crd ; crd = crd -> crd_next ) { for ( sw = swcr_sessions [ crp -> crp_sid & 0xffffffff ] ; sw && sw -> sw_alg != crd -> crd_alg ; sw = sw -> sw_next ) ; if ( sw == NULL ) return ( EINVAL ) ; switch ( sw -> sw_alg ) { case CRYPTO_AES_NIST_GCM_16 : case CRYPTO_AES_NIST_GMAC : swe = sw ; crde = crd ; exf = swe -> sw_exf ; ivlen = 12 ; break ; case CRYPTO_AES_128_NIST_GMAC : case CRYPTO_AES_192_NIST_GMAC : case CRYPTO_AES_256_NIST_GMAC : swa = sw ; crda = crd ; axf = swa -> sw_axf ; if ( swa -> sw_ictx == 0 ) return ( EINVAL ) ; bcopy ( swa -> sw_ictx , & ctx , axf -> ctxsize ) ; blksz = axf -> blocksize ; break ; default : return ( EINVAL ) ; } } if ( crde == NULL || crda == NULL ) return ( EINVAL ) ; if ( crde -> crd_alg == CRYPTO_AES_NIST_GCM_16 && ( crde -> crd_flags & CRD_F_IV_EXPLICIT ) == 0 ) return ( EINVAL ) ; if ( crde -> crd_klen != crda -> crd_klen ) return ( EINVAL ) ; if ( crde -> crd_flags & CRD_F_ENCRYPT ) { if ( crde -> crd_flags & CRD_F_IV_EXPLICIT ) bcopy ( crde -> crd_iv , iv , ivlen ) ; else arc4rand ( iv , ivlen , 0 ) ; if ( ! ( crde -> crd_flags & CRD_F_IV_PRESENT ) ) crypto_copyback ( crp -> crp_flags , buf , crde -> crd_inject , ivlen , iv ) ; } else { if ( crde -> crd_flags & CRD_F_IV_EXPLICIT ) bcopy ( crde -> crd_iv , iv , ivlen ) ; else { crypto_copydata ( crp -> crp_flags , buf , crde -> crd_inject , ivlen , iv ) ; } } if ( axf -> Reinit ) axf -> Reinit ( & ctx , iv , ivlen ) ; aadlen = crda -> crd_len ; for ( i = iskip ; i < crda -> crd_len ; i += blksz ) { len = MIN ( crda -> crd_len - i , blksz - oskip ) ; crypto_copydata ( crp -> crp_flags , buf , crda -> crd_skip + i , len , blk + oskip ) ; bzero ( blk + len + oskip , blksz - len - oskip ) ; axf -> Update ( & ctx , blk , blksz ) ; oskip = 0 ; } if ( exf -> reinit ) exf -> reinit ( swe -> sw_kschedule , iv ) ; for ( i = 0 ; i < crde -> crd_len ; i += blksz ) { len = MIN ( crde -> crd_len - i , blksz ) ; if ( len < blksz ) bzero ( blk , blksz ) ; crypto_copydata ( crp -> crp_flags , buf , crde -> crd_skip + i , len , blk ) ; if ( crde -> crd_flags & CRD_F_ENCRYPT ) { exf -> encrypt ( swe -> sw_kschedule , blk ) ; axf -> Update ( & ctx , blk , len ) ; crypto_copyback ( crp -> crp_flags , buf , crde -> crd_skip + i , len , blk ) ; } else { axf -> Update ( & ctx , blk , len ) ; } } switch ( crda -> crd_alg ) { case CRYPTO_AES_128_NIST_GMAC : case CRYPTO_AES_192_NIST_GMAC : case CRYPTO_AES_256_NIST_GMAC : bzero ( blk , blksz ) ; blkp = ( uint32_t * ) blk + 1 ; * blkp = htobe32 ( aadlen * 8 ) ; blkp = ( uint32_t * ) blk + 3 ; * blkp = htobe32 ( crde -> crd_len * 8 ) ; axf -> Update ( & ctx , blk , blksz ) ; break ; } axf -> Final ( aalg , & ctx ) ; if ( ! ( crde -> crd_flags & CRD_F_ENCRYPT ) ) { crypto_copydata ( crp -> crp_flags , buf , crda -> crd_inject , axf -> hashsize , uaalg ) ; r = timingsafe_bcmp ( aalg , uaalg , axf -> hashsize ) ; if ( r == 0 ) { for ( i = 0 ; i < crde -> crd_len ; i += blksz ) { len = MIN ( crde -> crd_len - i , blksz ) ; if ( len < blksz ) bzero ( blk , blksz ) ; crypto_copydata ( crp -> crp_flags , buf , crde -> crd_skip + i , len , blk ) ; if ( ! ( crde -> crd_flags & CRD_F_ENCRYPT ) ) { exf -> decrypt ( swe -> sw_kschedule , blk ) ; } crypto_copyback ( crp -> crp_flags , buf , crde -> crd_skip + i , len , blk ) ; } } else return ( EBADMSG ) ; } else { crypto_copyback ( crp -> crp_flags , buf , crda -> crd_inject , axf -> hashsize , aalg ) ; } return ( 0 ) ; }
Apply a combined encryption-authentication transformation
Apply a combined encryption - authentication transformation
/* Initialize the IV */ /* IV explicitly provided ? */ /* Do we need to write the IV */ /* Decryption */ /* IV explicitly provided ? */ /* Get IV off buf */ /* Supply MAC with IV */ /* Supply MAC with AAD */ /* reset initial output offset */ /* Do encryption/decryption with MAC */ /* Do any required special finalization */ /* length block */ /* Finalize MAC */ /* Validate tag */ /* tag matches, decrypt data */ /* Inject the authentication data */