1 /* 2 * algif_hash: User-space interface for hash algorithms 3 * 4 * This file provides the user-space API for hash algorithms. 5 * 6 * Copyright (c) 2010 Herbert Xu <herbert@gondor.apana.org.au> 7 * 8 * This program is free software; you can redistribute it and/or modify it 9 * under the terms of the GNU General Public License as published by the Free 10 * Software Foundation; either version 2 of the License, or (at your option) 11 * any later version. 12 * 13 */ 14 15 #include <crypto/hash.h> 16 #include <crypto/if_alg.h> 17 #include <linux/init.h> 18 #include <linux/kernel.h> 19 #include <linux/mm.h> 20 #include <linux/module.h> 21 #include <linux/net.h> 22 #include <net/sock.h> 23 24 struct hash_ctx { 25 struct af_alg_sgl sgl; 26 27 u8 *result; 28 29 struct af_alg_completion completion; 30 31 unsigned int len; 32 bool more; 33 34 struct ahash_request req; 35 }; 36 37 struct algif_hash_tfm { 38 struct crypto_ahash *hash; 39 bool has_key; 40 }; 41 42 static int hash_sendmsg(struct socket *sock, struct msghdr *msg, 43 size_t ignored) 44 { 45 int limit = ALG_MAX_PAGES * PAGE_SIZE; 46 struct sock *sk = sock->sk; 47 struct alg_sock *ask = alg_sk(sk); 48 struct hash_ctx *ctx = ask->private; 49 long copied = 0; 50 int err; 51 52 if (limit > sk->sk_sndbuf) 53 limit = sk->sk_sndbuf; 54 55 lock_sock(sk); 56 if (!ctx->more) { 57 err = af_alg_wait_for_completion(crypto_ahash_init(&ctx->req), 58 &ctx->completion); 59 if (err) 60 goto unlock; 61 } 62 63 ctx->more = 0; 64 65 while (msg_data_left(msg)) { 66 int len = msg_data_left(msg); 67 68 if (len > limit) 69 len = limit; 70 71 len = af_alg_make_sg(&ctx->sgl, &msg->msg_iter, len); 72 if (len < 0) { 73 err = copied ? 0 : len; 74 goto unlock; 75 } 76 77 ahash_request_set_crypt(&ctx->req, ctx->sgl.sg, NULL, len); 78 79 err = af_alg_wait_for_completion(crypto_ahash_update(&ctx->req), 80 &ctx->completion); 81 af_alg_free_sg(&ctx->sgl); 82 if (err) 83 goto unlock; 84 85 copied += len; 86 iov_iter_advance(&msg->msg_iter, len); 87 } 88 89 err = 0; 90 91 ctx->more = msg->msg_flags & MSG_MORE; 92 if (!ctx->more) { 93 ahash_request_set_crypt(&ctx->req, NULL, ctx->result, 0); 94 err = af_alg_wait_for_completion(crypto_ahash_final(&ctx->req), 95 &ctx->completion); 96 } 97 98 unlock: 99 release_sock(sk); 100 101 return err ?: copied; 102 } 103 104 static ssize_t hash_sendpage(struct socket *sock, struct page *page, 105 int offset, size_t size, int flags) 106 { 107 struct sock *sk = sock->sk; 108 struct alg_sock *ask = alg_sk(sk); 109 struct hash_ctx *ctx = ask->private; 110 int err; 111 112 if (flags & MSG_SENDPAGE_NOTLAST) 113 flags |= MSG_MORE; 114 115 lock_sock(sk); 116 sg_init_table(ctx->sgl.sg, 1); 117 sg_set_page(ctx->sgl.sg, page, size, offset); 118 119 ahash_request_set_crypt(&ctx->req, ctx->sgl.sg, ctx->result, size); 120 121 if (!(flags & MSG_MORE)) { 122 if (ctx->more) 123 err = crypto_ahash_finup(&ctx->req); 124 else 125 err = crypto_ahash_digest(&ctx->req); 126 } else { 127 if (!ctx->more) { 128 err = crypto_ahash_init(&ctx->req); 129 err = af_alg_wait_for_completion(err, &ctx->completion); 130 if (err) 131 goto unlock; 132 } 133 134 err = crypto_ahash_update(&ctx->req); 135 } 136 137 err = af_alg_wait_for_completion(err, &ctx->completion); 138 if (err) 139 goto unlock; 140 141 ctx->more = flags & MSG_MORE; 142 143 unlock: 144 release_sock(sk); 145 146 return err ?: size; 147 } 148 149 static int hash_recvmsg(struct socket *sock, struct msghdr *msg, size_t len, 150 int flags) 151 { 152 struct sock *sk = sock->sk; 153 struct alg_sock *ask = alg_sk(sk); 154 struct hash_ctx *ctx = ask->private; 155 unsigned ds = crypto_ahash_digestsize(crypto_ahash_reqtfm(&ctx->req)); 156 int err; 157 158 if (len > ds) 159 len = ds; 160 else if (len < ds) 161 msg->msg_flags |= MSG_TRUNC; 162 163 lock_sock(sk); 164 if (ctx->more) { 165 ctx->more = 0; 166 ahash_request_set_crypt(&ctx->req, NULL, ctx->result, 0); 167 err = af_alg_wait_for_completion(crypto_ahash_final(&ctx->req), 168 &ctx->completion); 169 if (err) 170 goto unlock; 171 } 172 173 err = memcpy_to_msg(msg, ctx->result, len); 174 175 unlock: 176 release_sock(sk); 177 178 return err ?: len; 179 } 180 181 static int hash_accept(struct socket *sock, struct socket *newsock, int flags) 182 { 183 struct sock *sk = sock->sk; 184 struct alg_sock *ask = alg_sk(sk); 185 struct hash_ctx *ctx = ask->private; 186 struct ahash_request *req = &ctx->req; 187 char state[crypto_ahash_statesize(crypto_ahash_reqtfm(req))]; 188 struct sock *sk2; 189 struct alg_sock *ask2; 190 struct hash_ctx *ctx2; 191 bool more; 192 int err; 193 194 lock_sock(sk); 195 more = ctx->more; 196 err = more ? crypto_ahash_export(req, state) : 0; 197 release_sock(sk); 198 199 if (err) 200 return err; 201 202 err = af_alg_accept(ask->parent, newsock); 203 if (err) 204 return err; 205 206 sk2 = newsock->sk; 207 ask2 = alg_sk(sk2); 208 ctx2 = ask2->private; 209 ctx2->more = more; 210 211 if (!more) 212 return err; 213 214 err = crypto_ahash_import(&ctx2->req, state); 215 if (err) { 216 sock_orphan(sk2); 217 sock_put(sk2); 218 } 219 220 return err; 221 } 222 223 static struct proto_ops algif_hash_ops = { 224 .family = PF_ALG, 225 226 .connect = sock_no_connect, 227 .socketpair = sock_no_socketpair, 228 .getname = sock_no_getname, 229 .ioctl = sock_no_ioctl, 230 .listen = sock_no_listen, 231 .shutdown = sock_no_shutdown, 232 .getsockopt = sock_no_getsockopt, 233 .mmap = sock_no_mmap, 234 .bind = sock_no_bind, 235 .setsockopt = sock_no_setsockopt, 236 .poll = sock_no_poll, 237 238 .release = af_alg_release, 239 .sendmsg = hash_sendmsg, 240 .sendpage = hash_sendpage, 241 .recvmsg = hash_recvmsg, 242 .accept = hash_accept, 243 }; 244 245 static int hash_check_key(struct socket *sock) 246 { 247 int err = 0; 248 struct sock *psk; 249 struct alg_sock *pask; 250 struct algif_hash_tfm *tfm; 251 struct sock *sk = sock->sk; 252 struct alg_sock *ask = alg_sk(sk); 253 254 lock_sock(sk); 255 if (ask->refcnt) 256 goto unlock_child; 257 258 psk = ask->parent; 259 pask = alg_sk(ask->parent); 260 tfm = pask->private; 261 262 err = -ENOKEY; 263 lock_sock_nested(psk, SINGLE_DEPTH_NESTING); 264 if (!tfm->has_key) 265 goto unlock; 266 267 if (!pask->refcnt++) 268 sock_hold(psk); 269 270 ask->refcnt = 1; 271 sock_put(psk); 272 273 err = 0; 274 275 unlock: 276 release_sock(psk); 277 unlock_child: 278 release_sock(sk); 279 280 return err; 281 } 282 283 static int hash_sendmsg_nokey(struct socket *sock, struct msghdr *msg, 284 size_t size) 285 { 286 int err; 287 288 err = hash_check_key(sock); 289 if (err) 290 return err; 291 292 return hash_sendmsg(sock, msg, size); 293 } 294 295 static ssize_t hash_sendpage_nokey(struct socket *sock, struct page *page, 296 int offset, size_t size, int flags) 297 { 298 int err; 299 300 err = hash_check_key(sock); 301 if (err) 302 return err; 303 304 return hash_sendpage(sock, page, offset, size, flags); 305 } 306 307 static int hash_recvmsg_nokey(struct socket *sock, struct msghdr *msg, 308 size_t ignored, int flags) 309 { 310 int err; 311 312 err = hash_check_key(sock); 313 if (err) 314 return err; 315 316 return hash_recvmsg(sock, msg, ignored, flags); 317 } 318 319 static int hash_accept_nokey(struct socket *sock, struct socket *newsock, 320 int flags) 321 { 322 int err; 323 324 err = hash_check_key(sock); 325 if (err) 326 return err; 327 328 return hash_accept(sock, newsock, flags); 329 } 330 331 static struct proto_ops algif_hash_ops_nokey = { 332 .family = PF_ALG, 333 334 .connect = sock_no_connect, 335 .socketpair = sock_no_socketpair, 336 .getname = sock_no_getname, 337 .ioctl = sock_no_ioctl, 338 .listen = sock_no_listen, 339 .shutdown = sock_no_shutdown, 340 .getsockopt = sock_no_getsockopt, 341 .mmap = sock_no_mmap, 342 .bind = sock_no_bind, 343 .setsockopt = sock_no_setsockopt, 344 .poll = sock_no_poll, 345 346 .release = af_alg_release, 347 .sendmsg = hash_sendmsg_nokey, 348 .sendpage = hash_sendpage_nokey, 349 .recvmsg = hash_recvmsg_nokey, 350 .accept = hash_accept_nokey, 351 }; 352 353 static void *hash_bind(const char *name, u32 type, u32 mask) 354 { 355 struct algif_hash_tfm *tfm; 356 struct crypto_ahash *hash; 357 358 tfm = kzalloc(sizeof(*tfm), GFP_KERNEL); 359 if (!tfm) 360 return ERR_PTR(-ENOMEM); 361 362 hash = crypto_alloc_ahash(name, type, mask); 363 if (IS_ERR(hash)) { 364 kfree(tfm); 365 return ERR_CAST(hash); 366 } 367 368 tfm->hash = hash; 369 370 return tfm; 371 } 372 373 static void hash_release(void *private) 374 { 375 struct algif_hash_tfm *tfm = private; 376 377 crypto_free_ahash(tfm->hash); 378 kfree(tfm); 379 } 380 381 static int hash_setkey(void *private, const u8 *key, unsigned int keylen) 382 { 383 struct algif_hash_tfm *tfm = private; 384 int err; 385 386 err = crypto_ahash_setkey(tfm->hash, key, keylen); 387 tfm->has_key = !err; 388 389 return err; 390 } 391 392 static void hash_sock_destruct(struct sock *sk) 393 { 394 struct alg_sock *ask = alg_sk(sk); 395 struct hash_ctx *ctx = ask->private; 396 397 sock_kzfree_s(sk, ctx->result, 398 crypto_ahash_digestsize(crypto_ahash_reqtfm(&ctx->req))); 399 sock_kfree_s(sk, ctx, ctx->len); 400 af_alg_release_parent(sk); 401 } 402 403 static int hash_accept_parent_nokey(void *private, struct sock *sk) 404 { 405 struct hash_ctx *ctx; 406 struct alg_sock *ask = alg_sk(sk); 407 struct algif_hash_tfm *tfm = private; 408 struct crypto_ahash *hash = tfm->hash; 409 unsigned len = sizeof(*ctx) + crypto_ahash_reqsize(hash); 410 unsigned ds = crypto_ahash_digestsize(hash); 411 412 ctx = sock_kmalloc(sk, len, GFP_KERNEL); 413 if (!ctx) 414 return -ENOMEM; 415 416 ctx->result = sock_kmalloc(sk, ds, GFP_KERNEL); 417 if (!ctx->result) { 418 sock_kfree_s(sk, ctx, len); 419 return -ENOMEM; 420 } 421 422 memset(ctx->result, 0, ds); 423 424 ctx->len = len; 425 ctx->more = 0; 426 af_alg_init_completion(&ctx->completion); 427 428 ask->private = ctx; 429 430 ahash_request_set_tfm(&ctx->req, hash); 431 ahash_request_set_callback(&ctx->req, CRYPTO_TFM_REQ_MAY_BACKLOG, 432 af_alg_complete, &ctx->completion); 433 434 sk->sk_destruct = hash_sock_destruct; 435 436 return 0; 437 } 438 439 static int hash_accept_parent(void *private, struct sock *sk) 440 { 441 struct algif_hash_tfm *tfm = private; 442 443 if (!tfm->has_key && crypto_ahash_has_setkey(tfm->hash)) 444 return -ENOKEY; 445 446 return hash_accept_parent_nokey(private, sk); 447 } 448 449 static const struct af_alg_type algif_type_hash = { 450 .bind = hash_bind, 451 .release = hash_release, 452 .setkey = hash_setkey, 453 .accept = hash_accept_parent, 454 .accept_nokey = hash_accept_parent_nokey, 455 .ops = &algif_hash_ops, 456 .ops_nokey = &algif_hash_ops_nokey, 457 .name = "hash", 458 .owner = THIS_MODULE 459 }; 460 461 static int __init algif_hash_init(void) 462 { 463 return af_alg_register_type(&algif_type_hash); 464 } 465 466 static void __exit algif_hash_exit(void) 467 { 468 int err = af_alg_unregister_type(&algif_type_hash); 469 BUG_ON(err); 470 } 471 472 module_init(algif_hash_init); 473 module_exit(algif_hash_exit); 474 MODULE_LICENSE("GPL"); 475