algapi.c 22.4 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12
/*
 * Cryptographic API for algorithms (i.e., low-level API).
 *
 * Copyright (c) 2006 Herbert Xu <herbert@gondor.apana.org.au>
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the Free
 * Software Foundation; either version 2 of the License, or (at your option)
 * any later version.
 *
 */

13
#include <crypto/algapi.h>
H
Herbert Xu 已提交
14
#include <linux/err.h>
15
#include <linux/errno.h>
H
Herbert Xu 已提交
16
#include <linux/fips.h>
17 18
#include <linux/init.h>
#include <linux/kernel.h>
19
#include <linux/list.h>
20
#include <linux/module.h>
21
#include <linux/rtnetlink.h>
22
#include <linux/slab.h>
23 24 25 26
#include <linux/string.h>

#include "internal.h"

27 28
static LIST_HEAD(crypto_template_list);

29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
static inline int crypto_set_driver_name(struct crypto_alg *alg)
{
	static const char suffix[] = "-generic";
	char *driver_name = alg->cra_driver_name;
	int len;

	if (*driver_name)
		return 0;

	len = strlcpy(driver_name, alg->cra_name, CRYPTO_MAX_ALG_NAME);
	if (len + sizeof(suffix) > CRYPTO_MAX_ALG_NAME)
		return -ENAMETOOLONG;

	memcpy(driver_name + len, suffix, sizeof(suffix));
	return 0;
}

46 47
static inline void crypto_check_module_sig(struct module *mod)
{
48
	if (fips_enabled && mod && !module_sig_ok(mod))
49
		panic("Module %s signature verification failed in FIPS mode\n",
50
		      module_name(mod));
51 52
}

53
static int crypto_check_alg(struct crypto_alg *alg)
54
{
55 56
	crypto_check_module_sig(alg->cra_module);

57 58 59 60 61 62
	if (alg->cra_alignmask & (alg->cra_alignmask + 1))
		return -EINVAL;

	if (alg->cra_blocksize > PAGE_SIZE / 8)
		return -EINVAL;

63 64 65 66 67 68 69 70 71
	if (!alg->cra_type && (alg->cra_flags & CRYPTO_ALG_TYPE_MASK) ==
			       CRYPTO_ALG_TYPE_CIPHER) {
		if (alg->cra_alignmask > MAX_CIPHER_ALIGNMASK)
			return -EINVAL;

		if (alg->cra_blocksize > MAX_CIPHER_BLOCKSIZE)
			return -EINVAL;
	}

72 73 74
	if (alg->cra_priority < 0)
		return -EINVAL;

75
	refcount_set(&alg->cra_refcnt, 1);
76

77 78 79
	return crypto_set_driver_name(alg);
}

80 81 82 83 84 85 86 87 88 89
static void crypto_free_instance(struct crypto_instance *inst)
{
	if (!inst->alg.cra_type->free) {
		inst->tmpl->free(inst);
		return;
	}

	inst->alg.cra_type->free(inst);
}

H
Herbert Xu 已提交
90 91 92 93 94
static void crypto_destroy_instance(struct crypto_alg *alg)
{
	struct crypto_instance *inst = (void *)alg;
	struct crypto_template *tmpl = inst->tmpl;

95
	crypto_free_instance(inst);
H
Herbert Xu 已提交
96 97 98
	crypto_tmpl_put(tmpl);
}

99 100 101 102 103 104 105
static struct list_head *crypto_more_spawns(struct crypto_alg *alg,
					    struct list_head *stack,
					    struct list_head *top,
					    struct list_head *secondary_spawns)
{
	struct crypto_spawn *spawn, *n;

106 107
	spawn = list_first_entry_or_null(stack, struct crypto_spawn, list);
	if (!spawn)
108 109
		return NULL;

110
	n = list_next_entry(spawn, list);
111 112 113

	if (spawn->alg && &n->list != stack && !n->alg)
		n->alg = (n->list.next == stack) ? alg :
114
			 &list_next_entry(n, list)->inst->alg;
115 116 117 118 119 120

	list_move(&spawn->list, secondary_spawns);

	return &n->list == stack ? top : &n->inst->alg.cra_users;
}

121 122
static void crypto_remove_instance(struct crypto_instance *inst,
				   struct list_head *list)
H
Herbert Xu 已提交
123
{
124
	struct crypto_template *tmpl = inst->tmpl;
H
Herbert Xu 已提交
125

126 127
	if (crypto_is_dead(&inst->alg))
		return;
H
Herbert Xu 已提交
128

129
	inst->alg.cra_flags |= CRYPTO_ALG_DEAD;
130 131 132
	if (hlist_unhashed(&inst->list))
		return;

133 134 135 136 137 138 139
	if (!tmpl || !crypto_tmpl_get(tmpl))
		return;

	list_move(&inst->alg.cra_list, list);
	hlist_del(&inst->list);
	inst->alg.cra_destroy = crypto_destroy_instance;

140
	BUG_ON(!list_empty(&inst->alg.cra_users));
141 142
}

143 144
void crypto_remove_spawns(struct crypto_alg *alg, struct list_head *list,
			  struct crypto_alg *nalg)
145
{
146
	u32 new_type = (nalg ?: alg)->cra_flags;
147 148
	struct crypto_spawn *spawn, *n;
	LIST_HEAD(secondary_spawns);
149 150 151
	struct list_head *spawns;
	LIST_HEAD(stack);
	LIST_HEAD(top);
H
Herbert Xu 已提交
152

153
	spawns = &alg->cra_users;
154 155
	list_for_each_entry_safe(spawn, n, spawns, list) {
		if ((spawn->alg->cra_flags ^ new_type) & spawn->mask)
H
Herbert Xu 已提交
156 157
			continue;

158
		list_move(&spawn->list, &top);
159
	}
H
Herbert Xu 已提交
160

161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178
	spawns = &top;
	do {
		while (!list_empty(spawns)) {
			struct crypto_instance *inst;

			spawn = list_first_entry(spawns, struct crypto_spawn,
						 list);
			inst = spawn->inst;

			BUG_ON(&inst->alg == alg);

			list_move(&spawn->list, &stack);

			if (&inst->alg == nalg)
				break;

			spawn->alg = NULL;
			spawns = &inst->alg.cra_users;
179 180 181 182 183 184 185 186 187 188 189 190

			/*
			 * We may encounter an unregistered instance here, since
			 * an instance's spawns are set up prior to the instance
			 * being registered.  An unregistered instance will have
			 * NULL ->cra_users.next, since ->cra_users isn't
			 * properly initialized until registration.  But an
			 * unregistered instance cannot have any users, so treat
			 * it the same as ->cra_users being empty.
			 */
			if (spawns->next == NULL)
				break;
191 192 193 194 195 196 197 198
		}
	} while ((spawns = crypto_more_spawns(alg, &stack, &top,
					      &secondary_spawns)));

	list_for_each_entry_safe(spawn, n, &secondary_spawns, list) {
		if (spawn->alg)
			list_move(&spawn->list, &spawn->alg->cra_users);
		else
199
			crypto_remove_instance(spawn->inst, list);
H
Herbert Xu 已提交
200 201
	}
}
202
EXPORT_SYMBOL_GPL(crypto_remove_spawns);
H
Herbert Xu 已提交
203

204
static struct crypto_larval *__crypto_register_alg(struct crypto_alg *alg)
205 206
{
	struct crypto_alg *q;
207
	struct crypto_larval *larval;
H
Herbert Xu 已提交
208 209 210
	int ret = -EAGAIN;

	if (crypto_is_dead(alg))
211
		goto err;
H
Herbert Xu 已提交
212 213 214

	INIT_LIST_HEAD(&alg->cra_users);

215 216 217
	/* No cheating! */
	alg->cra_flags &= ~CRYPTO_ALG_TESTED;

H
Herbert Xu 已提交
218
	ret = -EEXIST;
219

220
	list_for_each_entry(q, &crypto_alg_list, cra_list) {
221
		if (q == alg)
222 223
			goto err;

224 225 226
		if (crypto_is_moribund(q))
			continue;

227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247
		if (crypto_is_larval(q)) {
			if (!strcmp(alg->cra_driver_name, q->cra_driver_name))
				goto err;
			continue;
		}

		if (!strcmp(q->cra_driver_name, alg->cra_name) ||
		    !strcmp(q->cra_name, alg->cra_driver_name))
			goto err;
	}

	larval = crypto_larval_alloc(alg->cra_name,
				     alg->cra_flags | CRYPTO_ALG_TESTED, 0);
	if (IS_ERR(larval))
		goto out;

	ret = -ENOENT;
	larval->adult = crypto_mod_get(alg);
	if (!larval->adult)
		goto free_larval;

248
	refcount_set(&larval->alg.cra_refcnt, 1);
249 250 251 252 253 254 255
	memcpy(larval->alg.cra_driver_name, alg->cra_driver_name,
	       CRYPTO_MAX_ALG_NAME);
	larval->alg.cra_priority = alg->cra_priority;

	list_add(&alg->cra_list, &crypto_alg_list);
	list_add(&larval->alg.cra_list, &crypto_alg_list);

256
out:
257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274
	return larval;

free_larval:
	kfree(larval);
err:
	larval = ERR_PTR(ret);
	goto out;
}

void crypto_alg_tested(const char *name, int err)
{
	struct crypto_larval *test;
	struct crypto_alg *alg;
	struct crypto_alg *q;
	LIST_HEAD(list);

	down_write(&crypto_alg_sem);
	list_for_each_entry(q, &crypto_alg_list, cra_list) {
275
		if (crypto_is_moribund(q) || !crypto_is_larval(q))
276 277 278 279 280 281 282 283
			continue;

		test = (struct crypto_larval *)q;

		if (!strcmp(q->cra_driver_name, name))
			goto found;
	}

284
	pr_err("alg: Unexpected test result for %s: %d\n", name, err);
285 286 287
	goto unlock;

found:
288
	q->cra_flags |= CRYPTO_ALG_DEAD;
289 290 291 292 293 294 295 296 297
	alg = test->adult;
	if (err || list_empty(&alg->cra_list))
		goto complete;

	alg->cra_flags |= CRYPTO_ALG_TESTED;

	list_for_each_entry(q, &crypto_alg_list, cra_list) {
		if (q == alg)
			continue;
H
Herbert Xu 已提交
298 299 300 301 302

		if (crypto_is_moribund(q))
			continue;

		if (crypto_is_larval(q)) {
303 304
			struct crypto_larval *larval = (void *)q;

305 306 307 308 309
			/*
			 * Check to see if either our generic name or
			 * specific name can satisfy the name requested
			 * by the larval entry q.
			 */
H
Herbert Xu 已提交
310 311 312 313 314 315
			if (strcmp(alg->cra_name, q->cra_name) &&
			    strcmp(alg->cra_driver_name, q->cra_name))
				continue;

			if (larval->adult)
				continue;
316 317
			if ((q->cra_flags ^ alg->cra_flags) & larval->mask)
				continue;
318 319
			if (!crypto_mod_get(alg))
				continue;
H
Herbert Xu 已提交
320

321
			larval->adult = alg;
H
Herbert Xu 已提交
322
			continue;
323
		}
H
Herbert Xu 已提交
324 325 326 327 328 329 330 331

		if (strcmp(alg->cra_name, q->cra_name))
			continue;

		if (strcmp(alg->cra_driver_name, q->cra_driver_name) &&
		    q->cra_priority > alg->cra_priority)
			continue;

332
		crypto_remove_spawns(q, &list, alg);
333
	}
334

335 336
complete:
	complete_all(&test->completion);
337

338 339 340 341
unlock:
	up_write(&crypto_alg_sem);

	crypto_remove_final(&list);
342
}
343
EXPORT_SYMBOL_GPL(crypto_alg_tested);
344

345
void crypto_remove_final(struct list_head *list)
H
Herbert Xu 已提交
346 347 348 349 350 351 352 353 354
{
	struct crypto_alg *alg;
	struct crypto_alg *n;

	list_for_each_entry_safe(alg, n, list, cra_list) {
		list_del_init(&alg->cra_list);
		crypto_alg_put(alg);
	}
}
355
EXPORT_SYMBOL_GPL(crypto_remove_final);
H
Herbert Xu 已提交
356

357 358 359 360 361 362 363 364 365 366 367
static void crypto_wait_for_test(struct crypto_larval *larval)
{
	int err;

	err = crypto_probing_notify(CRYPTO_MSG_ALG_REGISTER, larval->adult);
	if (err != NOTIFY_STOP) {
		if (WARN_ON(err != NOTIFY_DONE))
			goto out;
		crypto_alg_tested(larval->alg.cra_driver_name, 0);
	}

368
	err = wait_for_completion_killable(&larval->completion);
369 370 371 372 373 374
	WARN_ON(err);

out:
	crypto_larval_kill(&larval->alg);
}

375 376
int crypto_register_alg(struct crypto_alg *alg)
{
377
	struct crypto_larval *larval;
378 379
	int err;

380
	alg->cra_flags &= ~CRYPTO_ALG_DEAD;
381 382 383 384 385
	err = crypto_check_alg(alg);
	if (err)
		return err;

	down_write(&crypto_alg_sem);
386
	larval = __crypto_register_alg(alg);
387 388
	up_write(&crypto_alg_sem);

389 390 391 392 393
	if (IS_ERR(larval))
		return PTR_ERR(larval);

	crypto_wait_for_test(larval);
	return 0;
394
}
395 396
EXPORT_SYMBOL_GPL(crypto_register_alg);

H
Herbert Xu 已提交
397 398 399 400 401 402 403 404
static int crypto_remove_alg(struct crypto_alg *alg, struct list_head *list)
{
	if (unlikely(list_empty(&alg->cra_list)))
		return -ENOENT;

	alg->cra_flags |= CRYPTO_ALG_DEAD;

	list_del_init(&alg->cra_list);
405
	crypto_remove_spawns(alg, list, NULL);
H
Herbert Xu 已提交
406 407 408 409

	return 0;
}

410 411
int crypto_unregister_alg(struct crypto_alg *alg)
{
H
Herbert Xu 已提交
412 413
	int ret;
	LIST_HEAD(list);
414

415
	down_write(&crypto_alg_sem);
H
Herbert Xu 已提交
416
	ret = crypto_remove_alg(alg, &list);
417 418 419 420 421
	up_write(&crypto_alg_sem);

	if (ret)
		return ret;

422
	BUG_ON(refcount_read(&alg->cra_refcnt) != 1);
423 424 425
	if (alg->cra_destroy)
		alg->cra_destroy(alg);

H
Herbert Xu 已提交
426
	crypto_remove_final(&list);
427 428 429 430
	return 0;
}
EXPORT_SYMBOL_GPL(crypto_unregister_alg);

431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465
int crypto_register_algs(struct crypto_alg *algs, int count)
{
	int i, ret;

	for (i = 0; i < count; i++) {
		ret = crypto_register_alg(&algs[i]);
		if (ret)
			goto err;
	}

	return 0;

err:
	for (--i; i >= 0; --i)
		crypto_unregister_alg(&algs[i]);

	return ret;
}
EXPORT_SYMBOL_GPL(crypto_register_algs);

int crypto_unregister_algs(struct crypto_alg *algs, int count)
{
	int i, ret;

	for (i = 0; i < count; i++) {
		ret = crypto_unregister_alg(&algs[i]);
		if (ret)
			pr_err("Failed to unregister %s %s: %d\n",
			       algs[i].cra_driver_name, algs[i].cra_name, ret);
	}

	return 0;
}
EXPORT_SYMBOL_GPL(crypto_unregister_algs);

466 467 468 469 470 471 472
int crypto_register_template(struct crypto_template *tmpl)
{
	struct crypto_template *q;
	int err = -EEXIST;

	down_write(&crypto_alg_sem);

473 474
	crypto_check_module_sig(tmpl->module);

475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490
	list_for_each_entry(q, &crypto_template_list, list) {
		if (q == tmpl)
			goto out;
	}

	list_add(&tmpl->list, &crypto_template_list);
	err = 0;
out:
	up_write(&crypto_alg_sem);
	return err;
}
EXPORT_SYMBOL_GPL(crypto_register_template);

void crypto_unregister_template(struct crypto_template *tmpl)
{
	struct crypto_instance *inst;
491
	struct hlist_node *n;
492
	struct hlist_head *list;
H
Herbert Xu 已提交
493
	LIST_HEAD(users);
494 495 496 497 498 499 500

	down_write(&crypto_alg_sem);

	BUG_ON(list_empty(&tmpl->list));
	list_del_init(&tmpl->list);

	list = &tmpl->instances;
501
	hlist_for_each_entry(inst, list, list) {
H
Herbert Xu 已提交
502
		int err = crypto_remove_alg(&inst->alg, &users);
503

H
Herbert Xu 已提交
504
		BUG_ON(err);
505 506 507 508
	}

	up_write(&crypto_alg_sem);

509
	hlist_for_each_entry_safe(inst, n, list, list) {
510
		BUG_ON(refcount_read(&inst->alg.cra_refcnt) != 1);
511
		crypto_free_instance(inst);
512
	}
H
Herbert Xu 已提交
513
	crypto_remove_final(&users);
514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537
}
EXPORT_SYMBOL_GPL(crypto_unregister_template);

static struct crypto_template *__crypto_lookup_template(const char *name)
{
	struct crypto_template *q, *tmpl = NULL;

	down_read(&crypto_alg_sem);
	list_for_each_entry(q, &crypto_template_list, list) {
		if (strcmp(q->name, name))
			continue;
		if (unlikely(!crypto_tmpl_get(q)))
			continue;

		tmpl = q;
		break;
	}
	up_read(&crypto_alg_sem);

	return tmpl;
}

struct crypto_template *crypto_lookup_template(const char *name)
{
538 539
	return try_then_request_module(__crypto_lookup_template(name),
				       "crypto-%s", name);
540 541 542 543 544 545
}
EXPORT_SYMBOL_GPL(crypto_lookup_template);

int crypto_register_instance(struct crypto_template *tmpl,
			     struct crypto_instance *inst)
{
546 547
	struct crypto_larval *larval;
	int err;
548 549 550

	err = crypto_check_alg(&inst->alg);
	if (err)
551 552
		return err;

553
	inst->alg.cra_module = tmpl->module;
554
	inst->alg.cra_flags |= CRYPTO_ALG_INSTANCE;
555 556 557

	down_write(&crypto_alg_sem);

558 559
	larval = __crypto_register_alg(&inst->alg);
	if (IS_ERR(larval))
560 561 562 563 564 565 566 567
		goto unlock;

	hlist_add_head(&inst->list, &tmpl->instances);
	inst->tmpl = tmpl;

unlock:
	up_write(&crypto_alg_sem);

568 569 570 571 572 573
	err = PTR_ERR(larval);
	if (IS_ERR(larval))
		goto err;

	crypto_wait_for_test(larval);
	err = 0;
H
Herbert Xu 已提交
574

575 576 577 578
err:
	return err;
}
EXPORT_SYMBOL_GPL(crypto_register_instance);
579

580
int crypto_unregister_instance(struct crypto_instance *inst)
581
{
582
	LIST_HEAD(list);
583 584 585

	down_write(&crypto_alg_sem);

586
	crypto_remove_spawns(&inst->alg, &list, NULL);
587
	crypto_remove_instance(inst, &list);
588 589 590

	up_write(&crypto_alg_sem);

591
	crypto_remove_final(&list);
592 593 594 595

	return 0;
}
EXPORT_SYMBOL_GPL(crypto_unregister_instance);
596

H
Herbert Xu 已提交
597
int crypto_init_spawn(struct crypto_spawn *spawn, struct crypto_alg *alg,
598
		      struct crypto_instance *inst, u32 mask)
H
Herbert Xu 已提交
599 600 601 602
{
	int err = -EAGAIN;

	spawn->inst = inst;
603
	spawn->mask = mask;
H
Herbert Xu 已提交
604 605 606 607 608 609 610 611 612 613 614 615 616

	down_write(&crypto_alg_sem);
	if (!crypto_is_moribund(alg)) {
		list_add(&spawn->list, &alg->cra_users);
		spawn->alg = alg;
		err = 0;
	}
	up_write(&crypto_alg_sem);

	return err;
}
EXPORT_SYMBOL_GPL(crypto_init_spawn);

617 618 619 620 621 622
int crypto_init_spawn2(struct crypto_spawn *spawn, struct crypto_alg *alg,
		       struct crypto_instance *inst,
		       const struct crypto_type *frontend)
{
	int err = -EINVAL;

623
	if ((alg->cra_flags ^ frontend->type) & frontend->maskset)
624 625 626 627 628 629 630 631 632 633
		goto out;

	spawn->frontend = frontend;
	err = crypto_init_spawn(spawn, alg, inst, frontend->maskset);

out:
	return err;
}
EXPORT_SYMBOL_GPL(crypto_init_spawn2);

634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649
int crypto_grab_spawn(struct crypto_spawn *spawn, const char *name,
		      u32 type, u32 mask)
{
	struct crypto_alg *alg;
	int err;

	alg = crypto_find_alg(name, spawn->frontend, type, mask);
	if (IS_ERR(alg))
		return PTR_ERR(alg);

	err = crypto_init_spawn(spawn, alg, spawn->inst, mask);
	crypto_mod_put(alg);
	return err;
}
EXPORT_SYMBOL_GPL(crypto_grab_spawn);

H
Herbert Xu 已提交
650 651
void crypto_drop_spawn(struct crypto_spawn *spawn)
{
652 653 654
	if (!spawn->alg)
		return;

H
Herbert Xu 已提交
655 656 657 658 659 660
	down_write(&crypto_alg_sem);
	list_del(&spawn->list);
	up_write(&crypto_alg_sem);
}
EXPORT_SYMBOL_GPL(crypto_drop_spawn);

661
static struct crypto_alg *crypto_spawn_alg(struct crypto_spawn *spawn)
H
Herbert Xu 已提交
662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678
{
	struct crypto_alg *alg;
	struct crypto_alg *alg2;

	down_read(&crypto_alg_sem);
	alg = spawn->alg;
	alg2 = alg;
	if (alg2)
		alg2 = crypto_mod_get(alg2);
	up_read(&crypto_alg_sem);

	if (!alg2) {
		if (alg)
			crypto_shoot_alg(alg);
		return ERR_PTR(-EAGAIN);
	}

679 680 681 682 683 684 685 686 687 688 689 690 691
	return alg;
}

struct crypto_tfm *crypto_spawn_tfm(struct crypto_spawn *spawn, u32 type,
				    u32 mask)
{
	struct crypto_alg *alg;
	struct crypto_tfm *tfm;

	alg = crypto_spawn_alg(spawn);
	if (IS_ERR(alg))
		return ERR_CAST(alg);

H
Herbert Xu 已提交
692 693 694 695
	tfm = ERR_PTR(-EINVAL);
	if (unlikely((alg->cra_flags ^ type) & mask))
		goto out_put_alg;

696
	tfm = __crypto_alloc_tfm(alg, type, mask);
H
Herbert Xu 已提交
697
	if (IS_ERR(tfm))
H
Herbert Xu 已提交
698 699 700
		goto out_put_alg;

	return tfm;
H
Herbert Xu 已提交
701

H
Herbert Xu 已提交
702 703
out_put_alg:
	crypto_mod_put(alg);
H
Herbert Xu 已提交
704 705 706 707
	return tfm;
}
EXPORT_SYMBOL_GPL(crypto_spawn_tfm);

708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728
void *crypto_spawn_tfm2(struct crypto_spawn *spawn)
{
	struct crypto_alg *alg;
	struct crypto_tfm *tfm;

	alg = crypto_spawn_alg(spawn);
	if (IS_ERR(alg))
		return ERR_CAST(alg);

	tfm = crypto_create_tfm(alg, spawn->frontend);
	if (IS_ERR(tfm))
		goto out_put_alg;

	return tfm;

out_put_alg:
	crypto_mod_put(alg);
	return tfm;
}
EXPORT_SYMBOL_GPL(crypto_spawn_tfm2);

729 730 731 732 733 734 735 736 737 738 739 740
int crypto_register_notifier(struct notifier_block *nb)
{
	return blocking_notifier_chain_register(&crypto_chain, nb);
}
EXPORT_SYMBOL_GPL(crypto_register_notifier);

int crypto_unregister_notifier(struct notifier_block *nb)
{
	return blocking_notifier_chain_unregister(&crypto_chain, nb);
}
EXPORT_SYMBOL_GPL(crypto_unregister_notifier);

741
struct crypto_attr_type *crypto_get_attr_type(struct rtattr **tb)
742
{
743
	struct rtattr *rta = tb[0];
744 745 746 747 748 749
	struct crypto_attr_type *algt;

	if (!rta)
		return ERR_PTR(-ENOENT);
	if (RTA_PAYLOAD(rta) < sizeof(*algt))
		return ERR_PTR(-EINVAL);
750 751
	if (rta->rta_type != CRYPTOA_TYPE)
		return ERR_PTR(-EINVAL);
752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773

	algt = RTA_DATA(rta);

	return algt;
}
EXPORT_SYMBOL_GPL(crypto_get_attr_type);

int crypto_check_attr_type(struct rtattr **tb, u32 type)
{
	struct crypto_attr_type *algt;

	algt = crypto_get_attr_type(tb);
	if (IS_ERR(algt))
		return PTR_ERR(algt);

	if ((algt->type ^ type) & algt->mask)
		return -EINVAL;

	return 0;
}
EXPORT_SYMBOL_GPL(crypto_check_attr_type);

774
const char *crypto_attr_alg_name(struct rtattr *rta)
775
{
776 777
	struct crypto_attr_alg *alga;

778 779 780
	if (!rta)
		return ERR_PTR(-ENOENT);
	if (RTA_PAYLOAD(rta) < sizeof(*alga))
781
		return ERR_PTR(-EINVAL);
782 783
	if (rta->rta_type != CRYPTOA_ALG)
		return ERR_PTR(-EINVAL);
784 785 786 787

	alga = RTA_DATA(rta);
	alga->name[CRYPTO_MAX_ALG_NAME - 1] = 0;

788 789 790 791
	return alga->name;
}
EXPORT_SYMBOL_GPL(crypto_attr_alg_name);

792 793 794
struct crypto_alg *crypto_attr_alg2(struct rtattr *rta,
				    const struct crypto_type *frontend,
				    u32 type, u32 mask)
795 796 797 798 799
{
	const char *name;

	name = crypto_attr_alg_name(rta);
	if (IS_ERR(name))
J
Julia Lawall 已提交
800
		return ERR_CAST(name);
801

802
	return crypto_find_alg(name, frontend, type, mask);
803
}
804
EXPORT_SYMBOL_GPL(crypto_attr_alg2);
H
Herbert Xu 已提交
805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822

int crypto_attr_u32(struct rtattr *rta, u32 *num)
{
	struct crypto_attr_u32 *nu32;

	if (!rta)
		return -ENOENT;
	if (RTA_PAYLOAD(rta) < sizeof(*nu32))
		return -EINVAL;
	if (rta->rta_type != CRYPTOA_U32)
		return -EINVAL;

	nu32 = RTA_DATA(rta);
	*num = nu32->num;

	return 0;
}
EXPORT_SYMBOL_GPL(crypto_attr_u32);
823

824 825 826 827 828 829 830 831 832 833 834 835 836 837 838
int crypto_inst_setname(struct crypto_instance *inst, const char *name,
			struct crypto_alg *alg)
{
	if (snprintf(inst->alg.cra_name, CRYPTO_MAX_ALG_NAME, "%s(%s)", name,
		     alg->cra_name) >= CRYPTO_MAX_ALG_NAME)
		return -ENAMETOOLONG;

	if (snprintf(inst->alg.cra_driver_name, CRYPTO_MAX_ALG_NAME, "%s(%s)",
		     name, alg->cra_driver_name) >= CRYPTO_MAX_ALG_NAME)
		return -ENAMETOOLONG;

	return 0;
}
EXPORT_SYMBOL_GPL(crypto_inst_setname);

839 840
void *crypto_alloc_instance2(const char *name, struct crypto_alg *alg,
			     unsigned int head)
841 842
{
	struct crypto_instance *inst;
843
	char *p;
844 845
	int err;

846 847 848
	p = kzalloc(head + sizeof(*inst) + sizeof(struct crypto_spawn),
		    GFP_KERNEL);
	if (!p)
849 850
		return ERR_PTR(-ENOMEM);

851 852
	inst = (void *)(p + head);

853 854
	err = crypto_inst_setname(inst, name, alg);
	if (err)
855 856
		goto err_free_inst;

857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875
	return p;

err_free_inst:
	kfree(p);
	return ERR_PTR(err);
}
EXPORT_SYMBOL_GPL(crypto_alloc_instance2);

struct crypto_instance *crypto_alloc_instance(const char *name,
					      struct crypto_alg *alg)
{
	struct crypto_instance *inst;
	struct crypto_spawn *spawn;
	int err;

	inst = crypto_alloc_instance2(name, alg, 0);
	if (IS_ERR(inst))
		goto out;

876
	spawn = crypto_instance_ctx(inst);
877 878
	err = crypto_init_spawn(spawn, alg, inst,
				CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_ASYNC);
879 880 881 882 883 884 885 886

	if (err)
		goto err_free_inst;

	return inst;

err_free_inst:
	kfree(inst);
887 888 889 890
	inst = ERR_PTR(err);

out:
	return inst;
891 892 893
}
EXPORT_SYMBOL_GPL(crypto_alloc_instance);

894 895 896 897 898 899 900 901 902 903 904 905 906 907 908
void crypto_init_queue(struct crypto_queue *queue, unsigned int max_qlen)
{
	INIT_LIST_HEAD(&queue->list);
	queue->backlog = &queue->list;
	queue->qlen = 0;
	queue->max_qlen = max_qlen;
}
EXPORT_SYMBOL_GPL(crypto_init_queue);

int crypto_enqueue_request(struct crypto_queue *queue,
			   struct crypto_async_request *request)
{
	int err = -EINPROGRESS;

	if (unlikely(queue->qlen >= queue->max_qlen)) {
909 910
		if (!(request->flags & CRYPTO_TFM_REQ_MAY_BACKLOG)) {
			err = -ENOSPC;
911
			goto out;
912 913
		}
		err = -EBUSY;
914 915 916 917 918 919 920 921 922 923 924 925
		if (queue->backlog == &queue->list)
			queue->backlog = &request->list;
	}

	queue->qlen++;
	list_add_tail(&request->list, &queue->list);

out:
	return err;
}
EXPORT_SYMBOL_GPL(crypto_enqueue_request);

926
struct crypto_async_request *crypto_dequeue_request(struct crypto_queue *queue)
927 928 929 930 931 932 933 934 935 936 937 938 939 940
{
	struct list_head *request;

	if (unlikely(!queue->qlen))
		return NULL;

	queue->qlen--;

	if (queue->backlog != &queue->list)
		queue->backlog = queue->backlog->next;

	request = queue->list.next;
	list_del(request);

941
	return list_entry(request, struct crypto_async_request, list);
942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957
}
EXPORT_SYMBOL_GPL(crypto_dequeue_request);

int crypto_tfm_in_queue(struct crypto_queue *queue, struct crypto_tfm *tfm)
{
	struct crypto_async_request *req;

	list_for_each_entry(req, &queue->list, list) {
		if (req->tfm == tfm)
			return 1;
	}

	return 0;
}
EXPORT_SYMBOL_GPL(crypto_tfm_in_queue);

958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975
static inline void crypto_inc_byte(u8 *a, unsigned int size)
{
	u8 *b = (a + size);
	u8 c;

	for (; size; size--) {
		c = *--b + 1;
		*b = c;
		if (c)
			break;
	}
}

void crypto_inc(u8 *a, unsigned int size)
{
	__be32 *b = (__be32 *)(a + size);
	u32 c;

976
	if (IS_ENABLED(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) ||
977
	    IS_ALIGNED((unsigned long)b, __alignof__(*b)))
978 979 980
		for (; size >= 4; size -= 4) {
			c = be32_to_cpu(*--b) + 1;
			*b = cpu_to_be32(c);
981
			if (likely(c))
982 983
				return;
		}
984 985 986 987 988

	crypto_inc_byte(a, size);
}
EXPORT_SYMBOL_GPL(crypto_inc);

989
void __crypto_xor(u8 *dst, const u8 *src1, const u8 *src2, unsigned int len)
990
{
991 992 993 994
	int relalign = 0;

	if (!IS_ENABLED(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS)) {
		int size = sizeof(unsigned long);
995 996 997
		int d = (((unsigned long)dst ^ (unsigned long)src1) |
			 ((unsigned long)dst ^ (unsigned long)src2)) &
			(size - 1);
998 999 1000 1001 1002 1003 1004 1005 1006 1007

		relalign = d ? 1 << __ffs(d) : size;

		/*
		 * If we care about alignment, process as many bytes as
		 * needed to advance dst and src to values whose alignments
		 * equal their relative alignment. This will allow us to
		 * process the remainder of the input using optimal strides.
		 */
		while (((unsigned long)dst & (relalign - 1)) && len > 0) {
1008
			*dst++ = *src1++ ^ *src2++;
1009 1010 1011
			len--;
		}
	}
1012

1013
	while (IS_ENABLED(CONFIG_64BIT) && len >= 8 && !(relalign & 7)) {
1014
		*(u64 *)dst = *(u64 *)src1 ^  *(u64 *)src2;
1015
		dst += 8;
1016 1017
		src1 += 8;
		src2 += 8;
1018 1019
		len -= 8;
	}
1020

1021
	while (len >= 4 && !(relalign & 3)) {
1022
		*(u32 *)dst = *(u32 *)src1 ^ *(u32 *)src2;
1023
		dst += 4;
1024 1025
		src1 += 4;
		src2 += 4;
1026 1027 1028 1029
		len -= 4;
	}

	while (len >= 2 && !(relalign & 1)) {
1030
		*(u16 *)dst = *(u16 *)src1 ^ *(u16 *)src2;
1031
		dst += 2;
1032 1033
		src1 += 2;
		src2 += 2;
1034 1035
		len -= 2;
	}
1036

1037
	while (len--)
1038
		*dst++ = *src1++ ^ *src2++;
1039
}
1040
EXPORT_SYMBOL_GPL(__crypto_xor);
1041

1042 1043
unsigned int crypto_alg_extsize(struct crypto_alg *alg)
{
1044 1045
	return alg->cra_ctxsize +
	       (alg->cra_alignmask & ~(crypto_tfm_ctx_alignment() - 1));
1046 1047 1048
}
EXPORT_SYMBOL_GPL(crypto_alg_extsize);

1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063
int crypto_type_has_alg(const char *name, const struct crypto_type *frontend,
			u32 type, u32 mask)
{
	int ret = 0;
	struct crypto_alg *alg = crypto_find_alg(name, frontend, type, mask);

	if (!IS_ERR(alg)) {
		crypto_mod_put(alg);
		ret = 1;
	}

	return ret;
}
EXPORT_SYMBOL_GPL(crypto_type_has_alg);

1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079
static int __init crypto_algapi_init(void)
{
	crypto_init_proc();
	return 0;
}

static void __exit crypto_algapi_exit(void)
{
	crypto_exit_proc();
}

module_init(crypto_algapi_init);
module_exit(crypto_algapi_exit);

MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Cryptographic algorithms API");