FreeBSD/sys/crypto/aesni/aesni.c
/*
 * authcrd contains the associated date.
 */
authcrd contains the associated date.
authcrd contains the associated date .
static int
aesni_cipher_process(struct aesni_session *ses, struct cryptodesc *enccrd,
    struct cryptodesc *authcrd, struct cryptop *crp)
{
	struct fpu_kern_ctx *ctx;
	uint8_t iv[AES_BLOCK_LEN];
	uint8_t tag[GMAC_DIGEST_LEN];
	uint8_t *buf, *authbuf;
	int error, allocated, authallocated;
	int ivlen, encflag;
	int kt, ctxidx;
	encflag = (enccrd->crd_flags & CRD_F_ENCRYPT) == CRD_F_ENCRYPT;
	if ((enccrd->crd_alg == CRYPTO_AES_ICM ||
	    enccrd->crd_alg == CRYPTO_AES_NIST_GCM_16) &&
	    (enccrd->crd_flags & CRD_F_IV_EXPLICIT) == 0)
		return (EINVAL);
	buf = aesni_cipher_alloc(enccrd, crp, &allocated);
	if (buf == NULL)
		return (ENOMEM);
	error = 0;
	authbuf = NULL;
	authallocated = 0;
	if (authcrd != NULL) {
		authbuf = aesni_cipher_alloc(authcrd, crp, &authallocated);
		if (authbuf == NULL) {
			error = ENOMEM;
			goto out1;
		}
	}
	kt = is_fpu_kern_thread(0);
	if (!kt) {
		AQUIRE_CTX(ctxidx, ctx);
		error = fpu_kern_enter(curthread, ctx,
		    FPU_KERN_NORMAL|FPU_KERN_KTHR);
		if (error != 0)
			goto out2;
	}
	if ((enccrd->crd_flags & CRD_F_KEY_EXPLICIT) != 0) {
		error = aesni_cipher_setup_common(ses, enccrd->crd_key,
		    enccrd->crd_klen);
		if (error != 0)
			goto out;
	}
	switch (enccrd->crd_alg) {
	case CRYPTO_AES_CBC:
	case CRYPTO_AES_ICM:
		ivlen = AES_BLOCK_LEN;
		break;
	case CRYPTO_AES_XTS:
		ivlen = 8;
		break;
	case CRYPTO_AES_NIST_GCM_16:
		ivlen = 12;	
		break;
	}
	if (encflag) {
		if ((enccrd->crd_flags & CRD_F_IV_EXPLICIT) != 0)
			bcopy(enccrd->crd_iv, iv, ivlen);
		else
			arc4rand(iv, ivlen, 0);
		if ((enccrd->crd_flags & CRD_F_IV_PRESENT) == 0)
			crypto_copyback(crp->crp_flags, crp->crp_buf,
			    enccrd->crd_inject, ivlen, iv);
	} else {
		if ((enccrd->crd_flags & CRD_F_IV_EXPLICIT) != 0)
			bcopy(enccrd->crd_iv, iv, ivlen);
		else
			crypto_copydata(crp->crp_flags, crp->crp_buf,
			    enccrd->crd_inject, ivlen, iv);
	}
	if (authcrd != NULL && !encflag)
		crypto_copydata(crp->crp_flags, crp->crp_buf,
		    authcrd->crd_inject, GMAC_DIGEST_LEN, tag);
	else
		bzero(tag, sizeof tag);
	switch (ses->algo) {
	case CRYPTO_AES_CBC:
		if (encflag)
			aesni_encrypt_cbc(ses->rounds, ses->enc_schedule,
			    enccrd->crd_len, buf, buf, iv);
		else
			aesni_decrypt_cbc(ses->rounds, ses->dec_schedule,
			    enccrd->crd_len, buf, iv);
		break;
	case CRYPTO_AES_ICM:
		aesni_encrypt_icm(ses->rounds, ses->enc_schedule,
		    enccrd->crd_len, buf, buf, iv);
		break;
	case CRYPTO_AES_XTS:
		if (encflag)
			aesni_encrypt_xts(ses->rounds, ses->enc_schedule,
			    ses->xts_schedule, enccrd->crd_len, buf, buf,
			    iv);
		else
			aesni_decrypt_xts(ses->rounds, ses->dec_schedule,
			    ses->xts_schedule, enccrd->crd_len, buf, buf,
			    iv);
		break;
	case CRYPTO_AES_NIST_GCM_16:
		if (encflag)
			AES_GCM_encrypt(buf, buf, authbuf, iv, tag,
			    enccrd->crd_len, authcrd->crd_len, ivlen,
			    ses->enc_schedule, ses->rounds);
		else {
			if (!AES_GCM_decrypt(buf, buf, authbuf, iv, tag,
			    enccrd->crd_len, authcrd->crd_len, ivlen,
			    ses->enc_schedule, ses->rounds))
				error = EBADMSG;
		}
		break;
	}
	if (allocated)
		crypto_copyback(crp->crp_flags, crp->crp_buf, enccrd->crd_skip,
		    enccrd->crd_len, buf);
	if (!error && authcrd != NULL) {
		crypto_copyback(crp->crp_flags, crp->crp_buf,
		    authcrd->crd_inject, GMAC_DIGEST_LEN, tag);
	}
out:
	if (!kt) {
		fpu_kern_leave(curthread, ctx);
out2:
		RELEASE_CTX(ctxidx, ctx);
	}
out1:
	if (allocated) {
		bzero(buf, enccrd->crd_len);
		free(buf, M_AESNI);
	}
	if (authallocated)
		free(authbuf, M_AESNI);
	return (error);
}
static int aesni_cipher_process ( struct aesni_session * ses , struct cryptodesc * enccrd , struct cryptodesc * authcrd , struct cryptop * crp ) { struct fpu_kern_ctx * ctx ; uint8_t iv [ AES_BLOCK_LEN ] ; uint8_t tag [ GMAC_DIGEST_LEN ] ; uint8_t * buf , * authbuf ; int error , allocated , authallocated ; int ivlen , encflag ; int kt , ctxidx ; encflag = ( enccrd -> crd_flags & CRD_F_ENCRYPT ) == CRD_F_ENCRYPT ; if ( ( enccrd -> crd_alg == CRYPTO_AES_ICM || enccrd -> crd_alg == CRYPTO_AES_NIST_GCM_16 ) && ( enccrd -> crd_flags & CRD_F_IV_EXPLICIT ) == 0 ) return ( EINVAL ) ; buf = aesni_cipher_alloc ( enccrd , crp , & allocated ) ; if ( buf == NULL ) return ( ENOMEM ) ; error = 0 ; authbuf = NULL ; authallocated = 0 ; if ( authcrd != NULL ) { authbuf = aesni_cipher_alloc ( authcrd , crp , & authallocated ) ; if ( authbuf == NULL ) { error = ENOMEM ; goto out1 ; } } kt = is_fpu_kern_thread ( 0 ) ; if ( ! kt ) { AQUIRE_CTX ( ctxidx , ctx ) ; error = fpu_kern_enter ( curthread , ctx , FPU_KERN_NORMAL | FPU_KERN_KTHR ) ; if ( error != 0 ) goto out2 ; } if ( ( enccrd -> crd_flags & CRD_F_KEY_EXPLICIT ) != 0 ) { error = aesni_cipher_setup_common ( ses , enccrd -> crd_key , enccrd -> crd_klen ) ; if ( error != 0 ) goto out ; } switch ( enccrd -> crd_alg ) { case CRYPTO_AES_CBC : case CRYPTO_AES_ICM : ivlen = AES_BLOCK_LEN ; break ; case CRYPTO_AES_XTS : ivlen = 8 ; break ; case CRYPTO_AES_NIST_GCM_16 : ivlen = 12 ; break ; } if ( encflag ) { if ( ( enccrd -> crd_flags & CRD_F_IV_EXPLICIT ) != 0 ) bcopy ( enccrd -> crd_iv , iv , ivlen ) ; else arc4rand ( iv , ivlen , 0 ) ; if ( ( enccrd -> crd_flags & CRD_F_IV_PRESENT ) == 0 ) crypto_copyback ( crp -> crp_flags , crp -> crp_buf , enccrd -> crd_inject , ivlen , iv ) ; } else { if ( ( enccrd -> crd_flags & CRD_F_IV_EXPLICIT ) != 0 ) bcopy ( enccrd -> crd_iv , iv , ivlen ) ; else crypto_copydata ( crp -> crp_flags , crp -> crp_buf , enccrd -> crd_inject , ivlen , iv ) ; } if ( authcrd != NULL && ! encflag ) crypto_copydata ( crp -> crp_flags , crp -> crp_buf , authcrd -> crd_inject , GMAC_DIGEST_LEN , tag ) ; else bzero ( tag , sizeof tag ) ; switch ( ses -> algo ) { case CRYPTO_AES_CBC : if ( encflag ) aesni_encrypt_cbc ( ses -> rounds , ses -> enc_schedule , enccrd -> crd_len , buf , buf , iv ) ; else aesni_decrypt_cbc ( ses -> rounds , ses -> dec_schedule , enccrd -> crd_len , buf , iv ) ; break ; case CRYPTO_AES_ICM : aesni_encrypt_icm ( ses -> rounds , ses -> enc_schedule , enccrd -> crd_len , buf , buf , iv ) ; break ; case CRYPTO_AES_XTS : if ( encflag ) aesni_encrypt_xts ( ses -> rounds , ses -> enc_schedule , ses -> xts_schedule , enccrd -> crd_len , buf , buf , iv ) ; else aesni_decrypt_xts ( ses -> rounds , ses -> dec_schedule , ses -> xts_schedule , enccrd -> crd_len , buf , buf , iv ) ; break ; case CRYPTO_AES_NIST_GCM_16 : if ( encflag ) AES_GCM_encrypt ( buf , buf , authbuf , iv , tag , enccrd -> crd_len , authcrd -> crd_len , ivlen , ses -> enc_schedule , ses -> rounds ) ; else { if ( ! AES_GCM_decrypt ( buf , buf , authbuf , iv , tag , enccrd -> crd_len , authcrd -> crd_len , ivlen , ses -> enc_schedule , ses -> rounds ) ) error = EBADMSG ; } break ; } if ( allocated ) crypto_copyback ( crp -> crp_flags , crp -> crp_buf , enccrd -> crd_skip , enccrd -> crd_len , buf ) ; if ( ! error && authcrd != NULL ) { crypto_copyback ( crp -> crp_flags , crp -> crp_buf , authcrd -> crd_inject , GMAC_DIGEST_LEN , tag ) ; } out : if ( ! kt ) { fpu_kern_leave ( curthread , ctx ) ; out2 : RELEASE_CTX ( ctxidx , ctx ) ; } out1 : if ( allocated ) { bzero ( buf , enccrd -> crd_len ) ; free ( buf , M_AESNI ) ; } if ( authallocated ) free ( authbuf , M_AESNI ) ; return ( error ) ; }
authcrd contains the associated date.
authcrd contains the associated date .
/* XXX - validate that enccrd and authcrd have/use same key? */ /* should support arbitarily larger */ /* Setup iv */ /* Do work */ /* encryption & decryption are the same */