@@ -34,6 +34,11 @@ struct hash_ctx {
3434 struct ahash_request req ;
3535};
3636
37+ struct algif_hash_tfm {
38+ struct crypto_ahash * hash ;
39+ bool has_key ;
40+ };
41+
3742static int hash_sendmsg (struct socket * sock , struct msghdr * msg ,
3843 size_t ignored )
3944{
@@ -235,38 +240,192 @@ static struct proto_ops algif_hash_ops = {
235240 .accept = hash_accept ,
236241};
237242
243+ static int hash_check_key (struct socket * sock )
244+ {
245+ int err ;
246+ struct sock * psk ;
247+ struct alg_sock * pask ;
248+ struct algif_hash_tfm * tfm ;
249+ struct sock * sk = sock -> sk ;
250+ struct alg_sock * ask = alg_sk (sk );
251+
252+ if (ask -> refcnt )
253+ return 0 ;
254+
255+ psk = ask -> parent ;
256+ pask = alg_sk (ask -> parent );
257+ tfm = pask -> private ;
258+
259+ err = - ENOKEY ;
260+ lock_sock (psk );
261+ if (!tfm -> has_key )
262+ goto unlock ;
263+
264+ if (!pask -> refcnt ++ )
265+ sock_hold (psk );
266+
267+ ask -> refcnt = 1 ;
268+ sock_put (psk );
269+
270+ err = 0 ;
271+
272+ unlock :
273+ release_sock (psk );
274+
275+ return err ;
276+ }
277+
278+ static int hash_sendmsg_nokey (struct socket * sock , struct msghdr * msg ,
279+ size_t size )
280+ {
281+ int err ;
282+
283+ err = hash_check_key (sock );
284+ if (err )
285+ return err ;
286+
287+ return hash_sendmsg (sock , msg , size );
288+ }
289+
290+ static ssize_t hash_sendpage_nokey (struct socket * sock , struct page * page ,
291+ int offset , size_t size , int flags )
292+ {
293+ int err ;
294+
295+ err = hash_check_key (sock );
296+ if (err )
297+ return err ;
298+
299+ return hash_sendpage (sock , page , offset , size , flags );
300+ }
301+
302+ static int hash_recvmsg_nokey (struct socket * sock , struct msghdr * msg ,
303+ size_t ignored , int flags )
304+ {
305+ int err ;
306+
307+ err = hash_check_key (sock );
308+ if (err )
309+ return err ;
310+
311+ return hash_recvmsg (sock , msg , ignored , flags );
312+ }
313+
314+ static int hash_accept_nokey (struct socket * sock , struct socket * newsock ,
315+ int flags )
316+ {
317+ int err ;
318+
319+ err = hash_check_key (sock );
320+ if (err )
321+ return err ;
322+
323+ return hash_accept (sock , newsock , flags );
324+ }
325+
326+ static struct proto_ops algif_hash_ops_nokey = {
327+ .family = PF_ALG ,
328+
329+ .connect = sock_no_connect ,
330+ .socketpair = sock_no_socketpair ,
331+ .getname = sock_no_getname ,
332+ .ioctl = sock_no_ioctl ,
333+ .listen = sock_no_listen ,
334+ .shutdown = sock_no_shutdown ,
335+ .getsockopt = sock_no_getsockopt ,
336+ .mmap = sock_no_mmap ,
337+ .bind = sock_no_bind ,
338+ .setsockopt = sock_no_setsockopt ,
339+ .poll = sock_no_poll ,
340+
341+ .release = af_alg_release ,
342+ .sendmsg = hash_sendmsg_nokey ,
343+ .sendpage = hash_sendpage_nokey ,
344+ .recvmsg = hash_recvmsg_nokey ,
345+ .accept = hash_accept_nokey ,
346+ };
347+
238348static void * hash_bind (const char * name , u32 type , u32 mask )
239349{
240- return crypto_alloc_ahash (name , type , mask );
350+ struct algif_hash_tfm * tfm ;
351+ struct crypto_ahash * hash ;
352+
353+ tfm = kzalloc (sizeof (* tfm ), GFP_KERNEL );
354+ if (!tfm )
355+ return ERR_PTR (- ENOMEM );
356+
357+ hash = crypto_alloc_ahash (name , type , mask );
358+ if (IS_ERR (hash )) {
359+ kfree (tfm );
360+ return ERR_CAST (hash );
361+ }
362+
363+ tfm -> hash = hash ;
364+
365+ return tfm ;
241366}
242367
243368static void hash_release (void * private )
244369{
245- crypto_free_ahash (private );
370+ struct algif_hash_tfm * tfm = private ;
371+
372+ crypto_free_ahash (tfm -> hash );
373+ kfree (tfm );
246374}
247375
248376static int hash_setkey (void * private , const u8 * key , unsigned int keylen )
249377{
250- return crypto_ahash_setkey (private , key , keylen );
378+ struct algif_hash_tfm * tfm = private ;
379+ int err ;
380+
381+ err = crypto_ahash_setkey (tfm -> hash , key , keylen );
382+ tfm -> has_key = !err ;
383+
384+ return err ;
251385}
252386
253- static void hash_sock_destruct (struct sock * sk )
387+ static void hash_sock_destruct_common (struct sock * sk )
254388{
255389 struct alg_sock * ask = alg_sk (sk );
256390 struct hash_ctx * ctx = ask -> private ;
257391
258392 sock_kzfree_s (sk , ctx -> result ,
259393 crypto_ahash_digestsize (crypto_ahash_reqtfm (& ctx -> req )));
260394 sock_kfree_s (sk , ctx , ctx -> len );
395+ }
396+
397+ static void hash_sock_destruct (struct sock * sk )
398+ {
399+ hash_sock_destruct_common (sk );
261400 af_alg_release_parent (sk );
262401}
263402
264- static int hash_accept_parent (void * private , struct sock * sk )
403+ static void hash_release_parent_nokey (struct sock * sk )
404+ {
405+ struct alg_sock * ask = alg_sk (sk );
406+
407+ if (!ask -> refcnt ) {
408+ sock_put (ask -> parent );
409+ return ;
410+ }
411+
412+ af_alg_release_parent (sk );
413+ }
414+
415+ static void hash_sock_destruct_nokey (struct sock * sk )
416+ {
417+ hash_sock_destruct_common (sk );
418+ hash_release_parent_nokey (sk );
419+ }
420+
421+ static int hash_accept_parent_common (void * private , struct sock * sk )
265422{
266423 struct hash_ctx * ctx ;
267424 struct alg_sock * ask = alg_sk (sk );
268- unsigned len = sizeof (* ctx ) + crypto_ahash_reqsize (private );
269- unsigned ds = crypto_ahash_digestsize (private );
425+ struct algif_hash_tfm * tfm = private ;
426+ struct crypto_ahash * hash = tfm -> hash ;
427+ unsigned len = sizeof (* ctx ) + crypto_ahash_reqsize (hash );
428+ unsigned ds = crypto_ahash_digestsize (hash );
270429
271430 ctx = sock_kmalloc (sk , len , GFP_KERNEL );
272431 if (!ctx )
@@ -286,7 +445,7 @@ static int hash_accept_parent(void *private, struct sock *sk)
286445
287446 ask -> private = ctx ;
288447
289- ahash_request_set_tfm (& ctx -> req , private );
448+ ahash_request_set_tfm (& ctx -> req , hash );
290449 ahash_request_set_callback (& ctx -> req , CRYPTO_TFM_REQ_MAY_BACKLOG ,
291450 af_alg_complete , & ctx -> completion );
292451
@@ -295,12 +454,38 @@ static int hash_accept_parent(void *private, struct sock *sk)
295454 return 0 ;
296455}
297456
457+ static int hash_accept_parent (void * private , struct sock * sk )
458+ {
459+ struct algif_hash_tfm * tfm = private ;
460+
461+ if (!tfm -> has_key && crypto_ahash_has_setkey (tfm -> hash ))
462+ return - ENOKEY ;
463+
464+ return hash_accept_parent_common (private , sk );
465+ }
466+
467+ static int hash_accept_parent_nokey (void * private , struct sock * sk )
468+ {
469+ int err ;
470+
471+ err = hash_accept_parent_common (private , sk );
472+ if (err )
473+ goto out ;
474+
475+ sk -> sk_destruct = hash_sock_destruct_nokey ;
476+
477+ out :
478+ return err ;
479+ }
480+
298481static const struct af_alg_type algif_type_hash = {
299482 .bind = hash_bind ,
300483 .release = hash_release ,
301484 .setkey = hash_setkey ,
302485 .accept = hash_accept_parent ,
486+ .accept_nokey = hash_accept_parent_nokey ,
303487 .ops = & algif_hash_ops ,
488+ .ops_nokey = & algif_hash_ops_nokey ,
304489 .name = "hash" ,
305490 .owner = THIS_MODULE
306491};
0 commit comments