@@ -29,6 +29,11 @@ struct aead_sg_list {
2929 struct scatterlist sg [ALG_MAX_PAGES ];
3030};
3131
32+ struct aead_tfm {
33+ struct crypto_aead * aead ;
34+ bool has_key ;
35+ };
36+
3237struct aead_ctx {
3338 struct aead_sg_list tsgl ;
3439 /*
@@ -513,24 +518,146 @@ static struct proto_ops algif_aead_ops = {
513518 .poll = aead_poll ,
514519};
515520
521+ static int aead_check_key (struct socket * sock )
522+ {
523+ int err = 0 ;
524+ struct sock * psk ;
525+ struct alg_sock * pask ;
526+ struct aead_tfm * tfm ;
527+ struct sock * sk = sock -> sk ;
528+ struct alg_sock * ask = alg_sk (sk );
529+
530+ lock_sock (sk );
531+ if (ask -> refcnt )
532+ goto unlock_child ;
533+
534+ psk = ask -> parent ;
535+ pask = alg_sk (ask -> parent );
536+ tfm = pask -> private ;
537+
538+ err = - ENOKEY ;
539+ lock_sock_nested (psk , SINGLE_DEPTH_NESTING );
540+ if (!tfm -> has_key )
541+ goto unlock ;
542+
543+ if (!pask -> refcnt ++ )
544+ sock_hold (psk );
545+
546+ ask -> refcnt = 1 ;
547+ sock_put (psk );
548+
549+ err = 0 ;
550+
551+ unlock :
552+ release_sock (psk );
553+ unlock_child :
554+ release_sock (sk );
555+
556+ return err ;
557+ }
558+
559+ static int aead_sendmsg_nokey (struct socket * sock , struct msghdr * msg ,
560+ size_t size )
561+ {
562+ int err ;
563+
564+ err = aead_check_key (sock );
565+ if (err )
566+ return err ;
567+
568+ return aead_sendmsg (sock , msg , size );
569+ }
570+
571+ static ssize_t aead_sendpage_nokey (struct socket * sock , struct page * page ,
572+ int offset , size_t size , int flags )
573+ {
574+ int err ;
575+
576+ err = aead_check_key (sock );
577+ if (err )
578+ return err ;
579+
580+ return aead_sendpage (sock , page , offset , size , flags );
581+ }
582+
583+ static int aead_recvmsg_nokey (struct socket * sock , struct msghdr * msg ,
584+ size_t ignored , int flags )
585+ {
586+ int err ;
587+
588+ err = aead_check_key (sock );
589+ if (err )
590+ return err ;
591+
592+ return aead_recvmsg (sock , msg , ignored , flags );
593+ }
594+
595+ static struct proto_ops algif_aead_ops_nokey = {
596+ .family = PF_ALG ,
597+
598+ .connect = sock_no_connect ,
599+ .socketpair = sock_no_socketpair ,
600+ .getname = sock_no_getname ,
601+ .ioctl = sock_no_ioctl ,
602+ .listen = sock_no_listen ,
603+ .shutdown = sock_no_shutdown ,
604+ .getsockopt = sock_no_getsockopt ,
605+ .mmap = sock_no_mmap ,
606+ .bind = sock_no_bind ,
607+ .accept = sock_no_accept ,
608+ .setsockopt = sock_no_setsockopt ,
609+
610+ .release = af_alg_release ,
611+ .sendmsg = aead_sendmsg_nokey ,
612+ .sendpage = aead_sendpage_nokey ,
613+ .recvmsg = aead_recvmsg_nokey ,
614+ .poll = aead_poll ,
615+ };
616+
516617static void * aead_bind (const char * name , u32 type , u32 mask )
517618{
518- return crypto_alloc_aead (name , type , mask );
619+ struct aead_tfm * tfm ;
620+ struct crypto_aead * aead ;
621+
622+ tfm = kzalloc (sizeof (* tfm ), GFP_KERNEL );
623+ if (!tfm )
624+ return ERR_PTR (- ENOMEM );
625+
626+ aead = crypto_alloc_aead (name , type , mask );
627+ if (IS_ERR (aead )) {
628+ kfree (tfm );
629+ return ERR_CAST (aead );
630+ }
631+
632+ tfm -> aead = aead ;
633+
634+ return tfm ;
519635}
520636
521637static void aead_release (void * private )
522638{
523- crypto_free_aead (private );
639+ struct aead_tfm * tfm = private ;
640+
641+ crypto_free_aead (tfm -> aead );
642+ kfree (tfm );
524643}
525644
526645static int aead_setauthsize (void * private , unsigned int authsize )
527646{
528- return crypto_aead_setauthsize (private , authsize );
647+ struct aead_tfm * tfm = private ;
648+
649+ return crypto_aead_setauthsize (tfm -> aead , authsize );
529650}
530651
531652static int aead_setkey (void * private , const u8 * key , unsigned int keylen )
532653{
533- return crypto_aead_setkey (private , key , keylen );
654+ struct aead_tfm * tfm = private ;
655+ int err ;
656+
657+ err = crypto_aead_setkey (tfm -> aead , key , keylen );
658+ tfm -> has_key = !err ;
659+
660+ return err ;
534661}
535662
536663static void aead_sock_destruct (struct sock * sk )
@@ -546,12 +673,14 @@ static void aead_sock_destruct(struct sock *sk)
546673 af_alg_release_parent (sk );
547674}
548675
549- static int aead_accept_parent (void * private , struct sock * sk )
676+ static int aead_accept_parent_nokey (void * private , struct sock * sk )
550677{
551678 struct aead_ctx * ctx ;
552679 struct alg_sock * ask = alg_sk (sk );
553- unsigned int len = sizeof (* ctx ) + crypto_aead_reqsize (private );
554- unsigned int ivlen = crypto_aead_ivsize (private );
680+ struct aead_tfm * tfm = private ;
681+ struct crypto_aead * aead = tfm -> aead ;
682+ unsigned int len = sizeof (* ctx ) + crypto_aead_reqsize (aead );
683+ unsigned int ivlen = crypto_aead_ivsize (aead );
555684
556685 ctx = sock_kmalloc (sk , len , GFP_KERNEL );
557686 if (!ctx )
@@ -577,7 +706,7 @@ static int aead_accept_parent(void *private, struct sock *sk)
577706
578707 ask -> private = ctx ;
579708
580- aead_request_set_tfm (& ctx -> aead_req , private );
709+ aead_request_set_tfm (& ctx -> aead_req , aead );
581710 aead_request_set_callback (& ctx -> aead_req , CRYPTO_TFM_REQ_MAY_BACKLOG ,
582711 af_alg_complete , & ctx -> completion );
583712
@@ -586,13 +715,25 @@ static int aead_accept_parent(void *private, struct sock *sk)
586715 return 0 ;
587716}
588717
718+ static int aead_accept_parent (void * private , struct sock * sk )
719+ {
720+ struct aead_tfm * tfm = private ;
721+
722+ if (!tfm -> has_key )
723+ return - ENOKEY ;
724+
725+ return aead_accept_parent_nokey (private , sk );
726+ }
727+
589728static const struct af_alg_type algif_type_aead = {
590729 .bind = aead_bind ,
591730 .release = aead_release ,
592731 .setkey = aead_setkey ,
593732 .setauthsize = aead_setauthsize ,
594733 .accept = aead_accept_parent ,
734+ .accept_nokey = aead_accept_parent_nokey ,
595735 .ops = & algif_aead_ops ,
736+ .ops_nokey = & algif_aead_ops_nokey ,
596737 .name = "aead" ,
597738 .owner = THIS_MODULE
598739};
0 commit comments