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