|
root / base / usr / src / lib / pkcs11 / pkcs11_softtoken / common / softAESCrypt.c
softAESCrypt.c C 1723 lines 48.1 KB
   1
   2
   3
   4
   5
   6
   7
   8
   9
  10
  11
  12
  13
  14
  15
  16
  17
  18
  19
  20
  21
  22
  23
  24
  25
  26
  27
  28
  29
  30
  31
  32
  33
  34
  35
  36
  37
  38
  39
  40
  41
  42
  43
  44
  45
  46
  47
  48
  49
  50
  51
  52
  53
  54
  55
  56
  57
  58
  59
  60
  61
  62
  63
  64
  65
  66
  67
  68
  69
  70
  71
  72
  73
  74
  75
  76
  77
  78
  79
  80
  81
  82
  83
  84
  85
  86
  87
  88
  89
  90
  91
  92
  93
  94
  95
  96
  97
  98
  99
 100
 101
 102
 103
 104
 105
 106
 107
 108
 109
 110
 111
 112
 113
 114
 115
 116
 117
 118
 119
 120
 121
 122
 123
 124
 125
 126
 127
 128
 129
 130
 131
 132
 133
 134
 135
 136
 137
 138
 139
 140
 141
 142
 143
 144
 145
 146
 147
 148
 149
 150
 151
 152
 153
 154
 155
 156
 157
 158
 159
 160
 161
 162
 163
 164
 165
 166
 167
 168
 169
 170
 171
 172
 173
 174
 175
 176
 177
 178
 179
 180
 181
 182
 183
 184
 185
 186
 187
 188
 189
 190
 191
 192
 193
 194
 195
 196
 197
 198
 199
 200
 201
 202
 203
 204
 205
 206
 207
 208
 209
 210
 211
 212
 213
 214
 215
 216
 217
 218
 219
 220
 221
 222
 223
 224
 225
 226
 227
 228
 229
 230
 231
 232
 233
 234
 235
 236
 237
 238
 239
 240
 241
 242
 243
 244
 245
 246
 247
 248
 249
 250
 251
 252
 253
 254
 255
 256
 257
 258
 259
 260
 261
 262
 263
 264
 265
 266
 267
 268
 269
 270
 271
 272
 273
 274
 275
 276
 277
 278
 279
 280
 281
 282
 283
 284
 285
 286
 287
 288
 289
 290
 291
 292
 293
 294
 295
 296
 297
 298
 299
 300
 301
 302
 303
 304
 305
 306
 307
 308
 309
 310
 311
 312
 313
 314
 315
 316
 317
 318
 319
 320
 321
 322
 323
 324
 325
 326
 327
 328
 329
 330
 331
 332
 333
 334
 335
 336
 337
 338
 339
 340
 341
 342
 343
 344
 345
 346
 347
 348
 349
 350
 351
 352
 353
 354
 355
 356
 357
 358
 359
 360
 361
 362
 363
 364
 365
 366
 367
 368
 369
 370
 371
 372
 373
 374
 375
 376
 377
 378
 379
 380
 381
 382
 383
 384
 385
 386
 387
 388
 389
 390
 391
 392
 393
 394
 395
 396
 397
 398
 399
 400
 401
 402
 403
 404
 405
 406
 407
 408
 409
 410
 411
 412
 413
 414
 415
 416
 417
 418
 419
 420
 421
 422
 423
 424
 425
 426
 427
 428
 429
 430
 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
 466
 467
 468
 469
 470
 471
 472
 473
 474
 475
 476
 477
 478
 479
 480
 481
 482
 483
 484
 485
 486
 487
 488
 489
 490
 491
 492
 493
 494
 495
 496
 497
 498
 499
 500
 501
 502
 503
 504
 505
 506
 507
 508
 509
 510
 511
 512
 513
 514
 515
 516
 517
 518
 519
 520
 521
 522
 523
 524
 525
 526
 527
 528
 529
 530
 531
 532
 533
 534
 535
 536
 537
 538
 539
 540
 541
 542
 543
 544
 545
 546
 547
 548
 549
 550
 551
 552
 553
 554
 555
 556
 557
 558
 559
 560
 561
 562
 563
 564
 565
 566
 567
 568
 569
 570
 571
 572
 573
 574
 575
 576
 577
 578
 579
 580
 581
 582
 583
 584
 585
 586
 587
 588
 589
 590
 591
 592
 593
 594
 595
 596
 597
 598
 599
 600
 601
 602
 603
 604
 605
 606
 607
 608
 609
 610
 611
 612
 613
 614
 615
 616
 617
 618
 619
 620
 621
 622
 623
 624
 625
 626
 627
 628
 629
 630
 631
 632
 633
 634
 635
 636
 637
 638
 639
 640
 641
 642
 643
 644
 645
 646
 647
 648
 649
 650
 651
 652
 653
 654
 655
 656
 657
 658
 659
 660
 661
 662
 663
 664
 665
 666
 667
 668
 669
 670
 671
 672
 673
 674
 675
 676
 677
 678
 679
 680
 681
 682
 683
 684
 685
 686
 687
 688
 689
 690
 691
 692
 693
 694
 695
 696
 697
 698
 699
 700
 701
 702
 703
 704
 705
 706
 707
 708
 709
 710
 711
 712
 713
 714
 715
 716
 717
 718
 719
 720
 721
 722
 723
 724
 725
 726
 727
 728
 729
 730
 731
 732
 733
 734
 735
 736
 737
 738
 739
 740
 741
 742
 743
 744
 745
 746
 747
 748
 749
 750
 751
 752
 753
 754
 755
 756
 757
 758
 759
 760
 761
 762
 763
 764
 765
 766
 767
 768
 769
 770
 771
 772
 773
 774
 775
 776
 777
 778
 779
 780
 781
 782
 783
 784
 785
 786
 787
 788
 789
 790
 791
 792
 793
 794
 795
 796
 797
 798
 799
 800
 801
 802
 803
 804
 805
 806
 807
 808
 809
 810
 811
 812
 813
 814
 815
 816
 817
 818
 819
 820
 821
 822
 823
 824
 825
 826
 827
 828
 829
 830
 831
 832
 833
 834
 835
 836
 837
 838
 839
 840
 841
 842
 843
 844
 845
 846
 847
 848
 849
 850
 851
 852
 853
 854
 855
 856
 857
 858
 859
 860
 861
 862
 863
 864
 865
 866
 867
 868
 869
 870
 871
 872
 873
 874
 875
 876
 877
 878
 879
 880
 881
 882
 883
 884
 885
 886
 887
 888
 889
 890
 891
 892
 893
 894
 895
 896
 897
 898
 899
 900
 901
 902
 903
 904
 905
 906
 907
 908
 909
 910
 911
 912
 913
 914
 915
 916
 917
 918
 919
 920
 921
 922
 923
 924
 925
 926
 927
 928
 929
 930
 931
 932
 933
 934
 935
 936
 937
 938
 939
 940
 941
 942
 943
 944
 945
 946
 947
 948
 949
 950
 951
 952
 953
 954
 955
 956
 957
 958
 959
 960
 961
 962
 963
 964
 965
 966
 967
 968
 969
 970
 971
 972
 973
 974
 975
 976
 977
 978
 979
 980
 981
 982
 983
 984
 985
 986
 987
 988
 989
 990
 991
 992
 993
 994
 995
 996
 997
 998
 999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License (the "License").
 * You may not use this file except in compliance with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */

/*
 * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
 * Copyright 2014 Nexenta Systems, Inc.  All rights reserved.
 * Copyright 2019 Joyent, Inc.
 * Copyright 2017 Jason King.
 * Copyright 2025 RackTop Systems, Inc.
 */

#include <pthread.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <sys/debug.h>
#include <sys/types.h>
#include <security/cryptoki.h>
#include <aes_impl.h>
#include <cryptoutil.h>
#include "softSession.h"
#include "softObject.h"
#include "softCrypt.h"
#include "softOps.h"

/*
 * Check that the mechanism parameter is present (if required)
 * and has the correct size. If so, allocate an AES context.
 *
 * Special handling for AES_GMAC paramters:
 *
 * The current PKCS#11 documentation for using AES_GMAC is:
 *	https://docs.oasis-open.org/pkcs11/pkcs11-curr/v2.40/
 *	errata01/os/pkcs11-curr-v2.40-errata01-os-complete.html
 * According to that, the C_SignInit parameter for AES_GMAC is
 * just the 12-byte Initialization Vector (IV).  The passed IV
 * is converted to CK_AES_GMAC_PARAMS soft_aes_init_ctx().
 */
static CK_RV
soft_aes_check_mech_param(CK_MECHANISM_PTR mech, aes_ctx_t **ctxp)
{
	void *(*allocf)(int) = NULL;
	size_t param_len = 0;
	boolean_t param_req = B_TRUE;

	switch (mech->mechanism) {
	case CKM_AES_ECB:
		param_req = B_FALSE;
		allocf = ecb_alloc_ctx;
		break;
	case CKM_AES_CMAC:
		param_req = B_FALSE;
		allocf = cmac_alloc_ctx;
		break;
	case CKM_AES_CMAC_GENERAL:
		param_len = sizeof (CK_MAC_GENERAL_PARAMS);
		allocf = cmac_alloc_ctx;
		break;
	case CKM_AES_GMAC:
		/* See comment above this function. */
		param_len = AES_GMAC_IV_LEN;
		allocf = gmac_alloc_ctx;
		break;
	case CKM_AES_CBC:
	case CKM_AES_CBC_PAD:
		param_len = AES_BLOCK_LEN;
		allocf = cbc_alloc_ctx;
		break;
	case CKM_AES_CTR:
		param_len = sizeof (CK_AES_CTR_PARAMS);
		allocf = ctr_alloc_ctx;
		break;
	case CKM_AES_CCM:
		param_len = sizeof (CK_CCM_PARAMS);
		allocf = ccm_alloc_ctx;
		break;
	case CKM_AES_GCM:
		param_len = sizeof (CK_GCM_PARAMS);
		allocf = gcm_alloc_ctx;
		break;
	default:
		return (CKR_MECHANISM_INVALID);
	}

	if (param_req && (mech->pParameter == NULL ||
	    mech->ulParameterLen != param_len)) {
		return (CKR_MECHANISM_PARAM_INVALID);
	}

	*ctxp = allocf(0);
	if (*ctxp == NULL) {
		return (CKR_HOST_MEMORY);
	}

	return (CKR_OK);
}

/*
 * Create an AES key schedule for the given AES context from the given key.
 * If the key is not sensitive, cache a copy of the key schedule in the
 * key object and/or use the cached copy of the key schedule.
 *
 * Must be called before the init function for a given mode is called.
 */
static CK_RV
soft_aes_init_key(aes_ctx_t *aes_ctx, soft_object_t *key_p)
{
	void *ks = NULL;
	size_t size = 0;
	CK_RV rv = CKR_OK;

	(void) pthread_mutex_lock(&key_p->object_mutex);

	/*
	 * AES keys should be either 128, 192, or 256 bits long.
	 * soft_object_t stores the key size in bytes, so we check those sizes
	 * in bytes.
	 *
	 * While soft_build_secret_key_object() does these same validations for
	 * keys created by the user, it may be possible that a key loaded from
	 * disk could be invalid or corrupt.  We err on the side of caution
	 * and check again that it's the correct size before performing any
	 * AES operations.
	 */
	switch (OBJ_SEC_VALUE_LEN(key_p)) {
	case AES_MIN_KEY_BYTES:
	case AES_MAX_KEY_BYTES:
	case AES_192_KEY_BYTES:
		break;
	default:
		rv = CKR_KEY_SIZE_RANGE;
		goto done;
	}

	ks = aes_alloc_keysched(&size, 0);
	if (ks == NULL) {
		rv = CKR_HOST_MEMORY;
		goto done;
	}

	/* If this is a sensitive key, always expand the key schedule */
	if (key_p->bool_attr_mask & SENSITIVE_BOOL_ON) {
		/* aes_init_keysched() requires key length in bits.  */
#ifdef	__sparcv9
		/* LINTED */
		aes_init_keysched(OBJ_SEC_VALUE(key_p), (uint_t)
		    (OBJ_SEC_VALUE_LEN(key_p) * NBBY), ks);
#else	/* !__sparcv9 */
		aes_init_keysched(OBJ_SEC_VALUE(key_p),
		    (OBJ_SEC_VALUE_LEN(key_p) * NBBY), ks);
#endif	/* __sparcv9 */

		goto done;
	}

	/* If a non-sensitive key and doesn't have a key schedule, create it */
	if (OBJ_KEY_SCHED(key_p) == NULL) {
		void *obj_ks = NULL;

		obj_ks = aes_alloc_keysched(&size, 0);
		if (obj_ks == NULL) {
			rv = CKR_HOST_MEMORY;
			goto done;
		}

#ifdef	__sparcv9
		/* LINTED */
		aes_init_keysched(OBJ_SEC_VALUE(key_p),
		    (uint_t)(OBJ_SEC_VALUE_LEN(key_p) * 8), obj_ks);
#else	/* !__sparcv9 */
		aes_init_keysched(OBJ_SEC_VALUE(key_p),
		    (OBJ_SEC_VALUE_LEN(key_p) * 8), obj_ks);
#endif	/* __sparcv9 */

		OBJ_KEY_SCHED_LEN(key_p) = size;
		OBJ_KEY_SCHED(key_p) = obj_ks;
	}

	(void) memcpy(ks, OBJ_KEY_SCHED(key_p), OBJ_KEY_SCHED_LEN(key_p));

done:
	(void) pthread_mutex_unlock(&key_p->object_mutex);

	if (rv == CKR_OK) {
		aes_ctx->ac_keysched = ks;
		aes_ctx->ac_keysched_len = size;
	} else {
		freezero(ks, size);
	}

	return (rv);
}

/*
 * Initialize the AES context for the given mode, including allocating and
 * expanding the key schedule if required.
 */
static CK_RV
soft_aes_init_ctx(aes_ctx_t *aes_ctx, CK_MECHANISM_PTR mech_p,
    boolean_t encrypt)
{
	int rc = CRYPTO_SUCCESS;

	switch (mech_p->mechanism) {
	case CKM_AES_ECB:
		aes_ctx->ac_flags |= ECB_MODE;
		break;
	case CKM_AES_CMAC:
	case CKM_AES_CMAC_GENERAL:
		rc = cmac_init_ctx((cbc_ctx_t *)aes_ctx, AES_BLOCK_LEN);
		break;
	case CKM_AES_GMAC: {
		/*
		 * Given params are just the initialization vector.
		 * See comment above soft_aes_check_mech_param.
		 * Convert to CK_AES_GMAC_PARAMS for gmac_init_ctx.
		 */
		CK_AES_GMAC_PARAMS gmac_params = {
			.pIv = mech_p->pParameter,
			.pAAD = NULL,
			.ulAADLen = 0
		};
		rc = gmac_init_ctx((gcm_ctx_t *)aes_ctx, (char *)&gmac_params,
		    AES_BLOCK_LEN, aes_encrypt_block, aes_copy_block,
		    aes_xor_block);
		break;
	}
	case CKM_AES_CBC:
	case CKM_AES_CBC_PAD:
		rc = cbc_init_ctx((cbc_ctx_t *)aes_ctx, mech_p->pParameter,
		    mech_p->ulParameterLen, AES_BLOCK_LEN, aes_copy_block64);
		break;
	case CKM_AES_CTR:
	{
		/*
		 * soft_aes_check_param() verifies this is !NULL and is the
		 * correct size.
		 */
		CK_AES_CTR_PARAMS *pp = (CK_AES_CTR_PARAMS *)mech_p->pParameter;

		rc = ctr_init_ctx((ctr_ctx_t *)aes_ctx, pp->ulCounterBits,
		    pp->cb, aes_encrypt_block, aes_copy_block);
		break;
	}
	case CKM_AES_CCM: {
		CK_CCM_PARAMS *pp = (CK_CCM_PARAMS *)mech_p->pParameter;

		/*
		 * The illumos ccm mode implementation predates the PKCS#11
		 * version that specifies CK_CCM_PARAMS.  As a result, the order
		 * and names of the struct members are different, so we must
		 * translate.  ccm_init_ctx() does not store a ref ccm_params,
		 * so it is safe to allocate on the stack.
		 */
		CK_AES_CCM_PARAMS ccm_params = {
			.ulMACSize = pp->ulMACLen,
			.ulNonceSize = pp->ulNonceLen,
			.ulAuthDataSize = pp->ulAADLen,
			.ulDataSize = pp->ulDataLen,
			.nonce = pp->pNonce,
			.authData = pp->pAAD
		};

		rc = ccm_init_ctx((ccm_ctx_t *)aes_ctx, (char *)&ccm_params, 0,
		    encrypt, AES_BLOCK_LEN, aes_encrypt_block, aes_xor_block);
		break;
	}
	case CKM_AES_GCM:
		/*
		 * Similar to the ccm mode implementation, the gcm mode also
		 * predates PKCS#11 2.40, however in this instance
		 * CK_AES_GCM_PARAMS and CK_GCM_PARAMS are identical except
		 * for the member names, so we can just pass it along.
		 */
		rc = gcm_init_ctx((gcm_ctx_t *)aes_ctx, mech_p->pParameter,
		    AES_BLOCK_LEN, aes_encrypt_block, aes_copy_block,
		    aes_xor_block);
		break;
	}

	return (crypto2pkcs11_error_number(rc));
}

/*
 * Allocate context for the active encryption or decryption operation, and
 * generate AES key schedule to speed up the operation.
 */
CK_RV
soft_aes_crypt_init_common(soft_session_t *session_p,
    CK_MECHANISM_PTR pMechanism, soft_object_t *key_p,
    boolean_t encrypt)
{
	aes_ctx_t *aes_ctx = NULL;
	CK_RV rv = CKR_OK;

	if (key_p->key_type != CKK_AES)
		return (CKR_KEY_TYPE_INCONSISTENT);

	/* C_{Encrypt,Decrypt}Init() validate pMechanism != NULL */
	rv = soft_aes_check_mech_param(pMechanism, &aes_ctx);
	if (rv != CKR_OK) {
		goto done;
	}

	rv = soft_aes_init_key(aes_ctx, key_p);
	if (rv != CKR_OK) {
		goto done;
	}

	rv = soft_aes_init_ctx(aes_ctx, pMechanism, encrypt);
	if (rv != CKR_OK) {
		goto done;
	}

	(void) pthread_mutex_lock(&session_p->session_mutex);
	if (encrypt) {
		/* Called by C_EncryptInit. */
		session_p->encrypt.context = aes_ctx;
		session_p->encrypt.mech.mechanism = pMechanism->mechanism;
	} else {
		/* Called by C_DecryptInit. */
		session_p->decrypt.context = aes_ctx;
		session_p->decrypt.mech.mechanism = pMechanism->mechanism;
	}
	(void) pthread_mutex_unlock(&session_p->session_mutex);

done:
	if (rv != CKR_OK) {
		soft_aes_free_ctx(aes_ctx);
	}

	return (rv);
}


CK_RV
soft_aes_encrypt(soft_session_t *session_p, CK_BYTE_PTR pData,
    CK_ULONG ulDataLen, CK_BYTE_PTR pEncryptedData,
    CK_ULONG_PTR pulEncryptedDataLen)
{
	aes_ctx_t *aes_ctx = session_p->encrypt.context;
	CK_MECHANISM_TYPE mech = session_p->encrypt.mech.mechanism;
	size_t length_needed;
	size_t remainder;
	int rc = CRYPTO_SUCCESS;
	CK_RV rv = CKR_OK;
	crypto_data_t out = {
		.cd_format = CRYPTO_DATA_RAW,
		.cd_offset = 0,
		.cd_length = *pulEncryptedDataLen,
		.cd_raw.iov_base = (char *)pEncryptedData,
		.cd_raw.iov_len = *pulEncryptedDataLen
	};

	/*
	 * A bit unusual, but it's permissible for ccm and gcm modes to not
	 * encrypt any data.  This ends up being equivalent to CKM_AES_CMAC
	 * or CKM_AES_GMAC of the additional authenticated data (AAD).
	 */
	if ((pData == NULL || ulDataLen == 0) &&
	    !(aes_ctx->ac_flags & (CCM_MODE|GCM_MODE|CMAC_MODE|GMAC_MODE))) {
		return (CKR_ARGUMENTS_BAD);
	}

	remainder = ulDataLen % AES_BLOCK_LEN;

	/*
	 * CTR, CCM, CMAC, and GCM modes do not require the plaintext
	 * to be a multiple of the AES block size. CKM_AES_CBC_PAD as the
	 * name suggests pads it's output, so it can also accept any
	 * size plaintext.
	 */
	switch (mech) {
	case CKM_AES_CBC_PAD:
	case CKM_AES_CMAC:
	case CKM_AES_CMAC_GENERAL:
	case CKM_AES_CTR:
	case CKM_AES_CCM:
	case CKM_AES_GCM:
	case CKM_AES_GMAC:
		break;
	default:
		if (remainder != 0) {
			rv = CKR_DATA_LEN_RANGE;
			goto cleanup;
		}
	}

	switch (mech) {
	case CKM_AES_CCM:
		length_needed = ulDataLen + aes_ctx->ac_mac_len;
		break;
	case CKM_AES_GCM:
		length_needed = ulDataLen + aes_ctx->ac_tag_len;
		break;
	case CKM_AES_CMAC:
	case CKM_AES_CMAC_GENERAL:
		length_needed = AES_BLOCK_LEN;
		break;
	case CKM_AES_GMAC:
		length_needed = AES_BLOCK_LEN;
		break;
	case CKM_AES_CBC_PAD:
		/* CKM_AES_CBC_PAD always adds 1..AES_BLOCK_LEN of padding */
		length_needed = ulDataLen + AES_BLOCK_LEN - remainder;
		break;
	default:
		length_needed = ulDataLen;
		break;
	}

	if (pEncryptedData == NULL) {
		/*
		 * The application can ask for the size of the output buffer
		 * with a NULL output buffer (pEncryptedData).
		 * C_Encrypt() guarantees pulEncryptedDataLen != NULL.
		 */
		*pulEncryptedDataLen = length_needed;
		return (CKR_OK);
	}

	if (*pulEncryptedDataLen < length_needed) {
		*pulEncryptedDataLen = length_needed;
		return (CKR_BUFFER_TOO_SMALL);
	}

	if (ulDataLen > 0) {
		rv = soft_aes_encrypt_update(session_p, pData, ulDataLen,
		    pEncryptedData, pulEncryptedDataLen);

		if (rv != CKR_OK) {
			rv = CKR_FUNCTION_FAILED;
			goto cleanup;
		}

		/*
		 * Some modes (e.g. CCM and GCM) will append data such as a MAC
		 * to the ciphertext after the plaintext has been encrypted.
		 * Update out to reflect the amount of data in pEncryptedData
		 * after encryption.
		 */
		out.cd_offset = *pulEncryptedDataLen;
	}

	switch (mech) {
	case CKM_AES_CBC_PAD: {
		/*
		 * aes_encrypt_contiguous_blocks() accumulates plaintext
		 * in aes_ctx until it has at least one full block of
		 * plaintext.  Any partial blocks of data remaining after
		 * encrypting are left for subsequent calls to
		 * aes_encrypt_contiguous_blocks().  If the input happened
		 * to be an exact multiple of AES_BLOCK_LEN, we must still
		 * append a block of padding (a full block in that case) so
		 * that the correct amount of padding to remove is known
		 * during decryption.
		 *
		 * soft_add_pkcs7_padding() is a bit overkill -- we just
		 * create a block filled with the pad amount using memset(),
		 * and encrypt 'amt' bytes of the block to pad out the input.
		 */
		char block[AES_BLOCK_LEN];
		size_t amt = AES_BLOCK_LEN - remainder;

		VERIFY3U(remainder, ==, aes_ctx->ac_remainder_len);

		(void) memset(block, amt & 0xff, sizeof (block));
		rc = aes_encrypt_contiguous_blocks(aes_ctx, block, amt, &out);
		rv = crypto2pkcs11_error_number(rc);
		explicit_bzero(block, sizeof (block));
		break;
	}
	case CKM_AES_CCM:
		rc = ccm_encrypt_final((ccm_ctx_t *)aes_ctx, &out,
		    AES_BLOCK_LEN, aes_encrypt_block, aes_xor_block);
		rv = crypto2pkcs11_error_number(rc);
		break;
	case CKM_AES_GCM:
		rc = gcm_encrypt_final((gcm_ctx_t *)aes_ctx, &out,
		    AES_BLOCK_LEN, aes_encrypt_block, aes_copy_block,
		    aes_xor_block);
		rv = crypto2pkcs11_error_number(rc);
		break;
	case CKM_AES_CMAC:
	case CKM_AES_CMAC_GENERAL:
		rc = cmac_mode_final((cbc_ctx_t *)aes_ctx, &out,
		    aes_encrypt_block, aes_xor_block);
		rv = crypto2pkcs11_error_number(rc);
		aes_ctx->ac_remainder_len = 0;
		break;
	case CKM_AES_GMAC:
		rc = gmac_mode_final((gcm_ctx_t *)aes_ctx, &out,
		    AES_BLOCK_LEN, aes_encrypt_block, aes_xor_block);
		rv = crypto2pkcs11_error_number(rc);
		break;
	case CKM_AES_CTR:
		/*
		 * As CKM_AES_CTR is a stream cipher, ctr_mode_final is always
		 * invoked in the xx_update() functions, so we do not need to
		 * call it again here.
		 */
		break;
	case CKM_AES_ECB:
	case CKM_AES_CBC:
		/*
		 * These mechanisms do not have nor require a xx_final function.
		 */
		break;
	default:
		rv = CKR_MECHANISM_INVALID;
		break;
	}

cleanup:
	switch (rv) {
	case CKR_OK:
		*pulEncryptedDataLen = out.cd_offset;
		break;
	case CKR_BUFFER_TOO_SMALL:
		/* *pulEncryptedDataLen was set earlier */
		break;
	default:
		/* something else failed */
		*pulEncryptedDataLen = 0;
		break;
	}

	(void) pthread_mutex_lock(&session_p->session_mutex);
	soft_aes_free_ctx(aes_ctx);
	session_p->encrypt.context = NULL;
	(void) pthread_mutex_unlock(&session_p->session_mutex);

	return (rv);
}

static CK_RV
soft_aes_cbc_pad_decrypt(aes_ctx_t *aes_ctx, CK_BYTE_PTR pEncryptedData,
    CK_ULONG ulEncryptedDataLen, crypto_data_t *out_orig)
{
	aes_ctx_t *ctx = aes_ctx;
	uint8_t *buf = NULL;
	uint8_t *outbuf = (uint8_t *)out_orig->cd_raw.iov_base;
	crypto_data_t out = *out_orig;
	size_t i;
	int rc;
	CK_RV rv = CKR_OK;
	uint8_t pad_len;
	boolean_t speculate = B_FALSE;

	/*
	 * Just a query for the output size.  When the output buffer is
	 * NULL, we are allowed to return a size slightly larger than
	 * necessary.  We know the output will never be larger than the
	 * input ciphertext, so we use that as an estimate.
	 */
	if (out_orig->cd_raw.iov_base == NULL) {
		out_orig->cd_length = ulEncryptedDataLen;
		return (CKR_OK);
	}

	/*
	 * The output plaintext size will be 1..AES_BLOCK_LEN bytes
	 * smaller than the input ciphertext.  However we cannot know
	 * exactly how much smaller until we decrypt the entire
	 * input ciphertext.  If we are unsure we have enough output buffer
	 * space, we have to allocate our own memory to hold the output,
	 * then see if we have enough room to hold the result.
	 *
	 * Unfortunately, having an output buffer that's too small does
	 * not terminate the operation, nor are we allowed to return
	 * partial results.  Therefore we must also duplicate the initial
	 * aes_ctx so that this can potentially be run again.
	 */
	if (out_orig->cd_length < ulEncryptedDataLen) {
		void *ks = malloc(aes_ctx->ac_keysched_len);

		ctx = malloc(sizeof (*aes_ctx));
		buf = malloc(ulEncryptedDataLen);
		if (ks == NULL || ctx == NULL || buf == NULL) {
			free(ks);
			free(ctx);
			free(buf);
			return (CKR_HOST_MEMORY);
		}

		bcopy(aes_ctx, ctx, sizeof (*ctx));
		bcopy(aes_ctx->ac_keysched, ks, aes_ctx->ac_keysched_len);
		ctx->ac_keysched = ks;

		out.cd_length = ulEncryptedDataLen;
		out.cd_raw.iov_base = (char *)buf;
		out.cd_raw.iov_len = ulEncryptedDataLen;
		outbuf = buf;

		speculate = B_TRUE;
	}

	rc = aes_decrypt_contiguous_blocks(ctx, (char *)pEncryptedData,
	    ulEncryptedDataLen, &out);
	if (rc != CRYPTO_SUCCESS) {
		out_orig->cd_offset = 0;
		rv = CKR_FUNCTION_FAILED;
		goto done;
	}

	/*
	 * RFC5652 6.3 The amount of padding must be
	 * block_sz - (len mod block_size).  This means
	 * the amount of padding must always be in the
	 * range [1..block_size].
	 */
	pad_len = outbuf[ulEncryptedDataLen - 1];
	if (pad_len == 0 || pad_len > AES_BLOCK_LEN) {
		rv = CKR_ENCRYPTED_DATA_INVALID;
		goto done;
	}
	out.cd_offset -= pad_len;

	/*
	 * Verify pad values, trying to do so in as close to constant
	 * time as possible.
	 */
	for (i = ulEncryptedDataLen - pad_len; i < ulEncryptedDataLen; i++) {
		if (outbuf[i] != pad_len) {
			rv = CKR_ENCRYPTED_DATA_INVALID;
		}
	}
	if (rv != CKR_OK) {
		goto done;
	}

	if (speculate) {
		if (out.cd_offset <= out_orig->cd_length) {
			bcopy(out.cd_raw.iov_base, out_orig->cd_raw.iov_base,
			    out.cd_offset);
		} else {
			rv = CKR_BUFFER_TOO_SMALL;
		}
	}

	/*
	 * No matter what, we report the exact size required.
	 */
	out_orig->cd_offset = out.cd_offset;

done:
	freezero(buf, ulEncryptedDataLen);
	if (ctx != aes_ctx) {
		VERIFY(speculate);
		soft_aes_free_ctx(ctx);
	}

	return (rv);
}

CK_RV
soft_aes_decrypt(soft_session_t *session_p, CK_BYTE_PTR pEncryptedData,
    CK_ULONG ulEncryptedDataLen, CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen)
{
	aes_ctx_t *aes_ctx = session_p->decrypt.context;
	CK_MECHANISM_TYPE mech = session_p->decrypt.mech.mechanism;
	size_t length_needed;
	size_t remainder;
	int rc = CRYPTO_SUCCESS;
	CK_RV rv = CKR_OK;
	crypto_data_t out = {
		.cd_format = CRYPTO_DATA_RAW,
		.cd_offset = 0,
		.cd_length = *pulDataLen,
		.cd_raw.iov_base = (char *)pData,
		.cd_raw.iov_len = *pulDataLen
	};

	/*
	 * A bit unusual, but it's permissible for ccm and gcm modes to not
	 * decrypt any data.  This ends up being equivalent to CKM_AES_CMAC
	 * or CKM_AES_GMAC of the additional authenticated data (AAD).
	 */
	if ((pEncryptedData == NULL || ulEncryptedDataLen == 0) &&
	    !(aes_ctx->ac_flags & (CCM_MODE|GCM_MODE))) {
		return (CKR_ARGUMENTS_BAD);
	}

	remainder = ulEncryptedDataLen % AES_BLOCK_LEN;

	/*
	 * CTR, CCM, CMAC, and GCM modes do not require the ciphertext
	 * to be a multiple of the AES block size.  Note that while
	 * CKM_AES_CBC_PAD accepts an arbitrary sized plaintext, the
	 * ciphertext is always a multiple of the AES block size
	 */
	switch (mech) {
	case CKM_AES_CMAC:
	case CKM_AES_CMAC_GENERAL:
	case CKM_AES_CTR:
	case CKM_AES_CCM:
	case CKM_AES_GCM:
	case CKM_AES_GMAC:
		break;
	default:
		if (remainder != 0) {
			rv = CKR_DATA_LEN_RANGE;
			goto cleanup;
		}
	}

	if (mech == CKM_AES_CBC_PAD) {
		rv = soft_aes_cbc_pad_decrypt(aes_ctx, pEncryptedData,
		    ulEncryptedDataLen, &out);
		if (pData == NULL || rv == CKR_BUFFER_TOO_SMALL) {
			*pulDataLen = out.cd_offset;
			return (rv);
		}
		goto cleanup;
	}

	switch (aes_ctx->ac_flags & (CCM_MODE|GCM_MODE)) {
	case CCM_MODE:
		length_needed = aes_ctx->ac_processed_data_len;
		break;
	case GCM_MODE:
		length_needed = ulEncryptedDataLen - aes_ctx->ac_tag_len;
		break;
	default:
		/*
		 * Note: for CKM_AES_CBC_PAD, we cannot know exactly how much
		 * space is needed for the plaintext until after we decrypt it.
		 * However, it is permissible to return a value 'somewhat'
		 * larger than necessary (PKCS#11 Base Specification, sec 5.2).
		 *
		 * Since CKM_AES_CBC_PAD adds at most AES_BLOCK_LEN bytes to
		 * the plaintext, we report the ciphertext length as the
		 * required plaintext length.  This means we specify at most
		 * AES_BLOCK_LEN additional bytes of memory for the plaintext.
		 *
		 * This behavior is slightly different from the earlier
		 * version of this code which returned the value of
		 * (ulEncryptedDataLen - AES_BLOCK_LEN), which was only ever
		 * correct when the original plaintext was already a multiple
		 * of AES_BLOCK_LEN (i.e. when AES_BLOCK_LEN of padding was
		 * added).  This should not be a concern for existing
		 * consumers -- if they were previously using the value of
		 * *pulDataLen to size the outbut buffer, the resulting
		 * plaintext would be truncated anytime the original plaintext
		 * wasn't a multiple of AES_BLOCK_LEN.  No consumer should
		 * be relying on such wrong behavior.  More likely they are
		 * using the size of the ciphertext or larger for the
		 * buffer to hold the decrypted plaintext (which is always
		 * acceptable).
		 */
		length_needed = ulEncryptedDataLen;
	}

	if (pData == NULL) {
		/*
		 * The application can ask for the size of the output buffer
		 * with a NULL output buffer (pData).
		 * C_Decrypt() guarantees pulDataLen != NULL.
		 */
		*pulDataLen = length_needed;
		return (CKR_OK);
	}

	if (*pulDataLen < length_needed) {
		*pulDataLen = length_needed;
		return (CKR_BUFFER_TOO_SMALL);
	}

	if (ulEncryptedDataLen > 0) {
		rv = soft_aes_decrypt_update(session_p, pEncryptedData,
		    ulEncryptedDataLen, pData, pulDataLen);
	}

	if (rv != CKR_OK) {
		rv = CKR_FUNCTION_FAILED;
		goto cleanup;
	}

	/*
	 * Some modes (e.g. CCM and GCM) will output additional data
	 * after the plaintext (such as the MAC).  Update out to
	 * reflect the amount of data in pData for the _final() functions.
	 */
	out.cd_offset = *pulDataLen;

	/*
	 * As CKM_AES_CTR is a stream cipher, ctr_mode_final is always
	 * invoked in the _update() functions, so we do not need to call it
	 * here.
	 */
	if (aes_ctx->ac_flags & CCM_MODE) {
		ASSERT3U(aes_ctx->ac_processed_data_len, ==,
		    aes_ctx->ac_data_len);
		ASSERT3U(aes_ctx->ac_processed_mac_len, ==,
		    aes_ctx->ac_mac_len);

		rc = ccm_decrypt_final((ccm_ctx_t *)aes_ctx, &out,
		    AES_BLOCK_LEN, aes_encrypt_block, aes_copy_block,
		    aes_xor_block);
		rv = crypto2pkcs11_error_number(rc);
	} else if (aes_ctx->ac_flags & GCM_MODE) {
		rc = gcm_decrypt_final((gcm_ctx_t *)aes_ctx, &out,
		    AES_BLOCK_LEN, aes_encrypt_block, aes_xor_block);
		rv = crypto2pkcs11_error_number(rc);
	}

cleanup:
	if (rv == CKR_OK) {
		*pulDataLen = out.cd_offset;
	} else {
		*pulDataLen = 0;
	}

	(void) pthread_mutex_lock(&session_p->session_mutex);
	soft_aes_free_ctx(aes_ctx);
	session_p->decrypt.context = NULL;
	(void) pthread_mutex_unlock(&session_p->session_mutex);

	return (rv);
}

CK_RV
soft_aes_encrypt_update(soft_session_t *session_p, CK_BYTE_PTR pData,
    CK_ULONG ulDataLen, CK_BYTE_PTR pEncryptedData,
    CK_ULONG_PTR pulEncryptedDataLen)
{
	aes_ctx_t *aes_ctx = session_p->encrypt.context;
	crypto_data_t out = {
		.cd_format = CRYPTO_DATA_RAW,
		.cd_offset = 0,
		.cd_length = *pulEncryptedDataLen,
		.cd_raw.iov_base = (char *)pEncryptedData,
		.cd_raw.iov_len = *pulEncryptedDataLen
	};
	CK_MECHANISM_TYPE mech = session_p->encrypt.mech.mechanism;
	CK_RV rv = CKR_OK;
	size_t out_len;
	int rc;

	/*
	 * If pData is NULL, we should have zero bytes to process, and
	 * the aes_encrypt_contiguous_blocks() call will be an effective no-op.
	 */
	IMPLY(pData == NULL, ulDataLen == 0);

	/* Check size of the output buffer */
	switch (mech) {
	case CKM_AES_CMAC:
		/*
		 * The underlying CMAC implementation handles the storing of
		 * extra bytes and does not output any data until *_final,
		 * so do not bother looking at the size of the output
		 * buffer at this time.
		 */
		out_len = 0;
		break;
	case CKM_AES_GMAC:
		out_len = 0;
		break;
	case CKM_AES_CTR:
		/*
		 * CTR mode is a stream cipher, so we always output exactly as
		 * much ciphertext as input plaintext
		 */
		out_len = ulDataLen;
		break;
	default:
		out_len = aes_ctx->ac_remainder_len + ulDataLen;

		/*
		 * The number of complete blocks we can encrypt right now.
		 * The underlying implementation will buffer any remaining data
		 * until the next *_update call.
		 */
		out_len &= ~(AES_BLOCK_LEN - 1);
		break;
	}

	if (pEncryptedData == NULL) {
		*pulEncryptedDataLen = out_len;
		return (CKR_OK);
	}

	if (*pulEncryptedDataLen < out_len) {
		*pulEncryptedDataLen = out_len;
		return (CKR_BUFFER_TOO_SMALL);
	}

	rc = aes_encrypt_contiguous_blocks(aes_ctx, (char *)pData, ulDataLen,
	    &out);

	/*
	 * Since out.cd_offset is set to 0 initially and the underlying
	 * implementation increments out.cd_offset by the amount of output
	 * written, so we can just use the value as the amount written.
	 */
	*pulEncryptedDataLen = out.cd_offset;

	if (rc != CRYPTO_SUCCESS) {
		return (CKR_FUNCTION_FAILED);
	}

	rv = crypto2pkcs11_error_number(rc);

	return (rv);
}

CK_RV
soft_aes_decrypt_update(soft_session_t *session_p, CK_BYTE_PTR pEncryptedData,
    CK_ULONG ulEncryptedDataLen, CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen)
{
	aes_ctx_t *aes_ctx = session_p->decrypt.context;
	uint8_t *buffer_block = NULL;
	crypto_data_t out = {
		.cd_format = CRYPTO_DATA_RAW,
		.cd_offset = 0,
		.cd_length = *pulDataLen,
		.cd_raw.iov_base = (char *)pData,
		.cd_raw.iov_len = *pulDataLen
	};
	CK_MECHANISM_TYPE mech = session_p->decrypt.mech.mechanism;
	CK_RV rv = CKR_OK;
	size_t in_len = ulEncryptedDataLen;
	size_t out_len;
	int rc = CRYPTO_SUCCESS;

	switch (mech) {
	case CKM_AES_CCM:
	case CKM_AES_GCM:
		out_len = 0;
		break;
	case CKM_AES_CBC_PAD:
		/*
		 * For CKM_AES_CBC_PAD, we use the existing code for CBC
		 * mode in libsoftcrypto (which itself uses the code in
		 * usr/src/common/crypto/modes for CBC mode).  For
		 * non-padding AES CBC mode, aes_decrypt_contiguous_blocks()
		 * will accumulate ciphertext in aes_ctx->ac_remainder until
		 * there is at least AES_BLOCK_LEN bytes of ciphertext available
		 * to decrypt.  At that point, as many blocks of AES_BLOCK_LEN
		 * sized ciphertext blocks are decrypted.  Any remainder is
		 * copied into aes_ctx->ac_remainder for decryption in
		 * subsequent calls to aes_decrypt_contiguous_blocks().
		 *
		 * When PKCS#7 padding is used, the buffering
		 * aes_decrypt_contigous_blocks() performs is insufficient.
		 * PKCS#7 padding always adds [1..AES_BLOCK_LEN] bytes of
		 * padding to plaintext, so the resulting ciphertext is always
		 * larger than the input plaintext.  However we cannot know
		 * which block is the final block (and needs its padding
		 * stripped) until C_DecryptFinal() is called.  Additionally,
		 * it is permissible for a caller to use buffers sized to the
		 * output plaintext -- i.e. smaller than the input ciphertext.
		 * This leads to a more complicated buffering/accumulation
		 * strategy than what aes_decrypt_contiguous_blocks() provides
		 * us.
		 *
		 * Our buffering strategy works as follows:
		 *  For each call to C_DecryptUpdate, we calculate the
		 *  total amount of ciphertext available (buffered plus what's
		 *  passed in) as the initial output size (out_len). Based
		 *  on the value of out_len, there are three possibilties:
		 *
		 *  1. We have less than AES_BLOCK_LEN + 1 bytes of
		 *  ciphertext available. Accumulate the ciphertext in
		 *  aes_ctx->ac_remainder. Note that while we could let
		 *  aes_decrypt_contiguous_blocks() buffer the input for us
		 *  when we have less than AES_BLOCK_LEN bytes, we would still
		 *  need to buffer when we have exactly AES_BLOCK_LEN
		 *  bytes available, so we just handle both situations with
		 *  one if clause.
		 *
		 *  2. We have at least AES_BLOCK_LEN + 1 bytes of
		 *  ciphertext, and the total amount available is also an
		 *  exact multiple of AES_BLOCK_LEN. We cannot know if the
		 *  last block of input is the final block (yet), but we
		 *  are an exact multiple of AES_BLOCK_LEN, and we have
		 *  at least AES_BLOCK_LEN + 1 bytes available, therefore
		 *  there must be at least 2 * AES_BLOCK_LEN bytes of input
		 *  ciphertext available. It also means there's at least one
		 *  full block of input ciphertext that can be decrypted. We
		 *  reduce the size of the input (in_len) given to
		 *  aes_decrypt_contiguous_bytes() by AES_BLOCK_LEN to prevent
		 *  it from decrypting the last full block of data.
		 *  aes_decrypt_contiguous_blocks() will when decrypt any
		 *  buffered data in aex_ctx->ac_remainder, and then any
		 *  input data passed. Since we have an exact multiple of
		 *  AES_BLOCK_LEN, aes_ctx->ac_remainder will be empty
		 *  (aes_ctx->ac_remainder_len == 0), once
		 *  aes_decrypt_contiguout_block() completes, and we can
		 *  copy the last block of data into aes_ctx->ac_remainder.
		 *
		 *  3. We have at least AES_BLOCK_LEN + 1 bytes of
		 *  ciphertext, but the total amount available is not an
		 *  exact multiple of AES_BLOCK_LEN. We decrypt all of
		 *  full blocks of data we have. The remainder will be
		 *  less than AES_BLOCK_LEN bytes. We let
		 *  aes_decrypt_contiguous_blocks() buffer the remainder
		 *  for us since it would normally do this anyway. Since there
		 *  is a remainder, the full blocks that are present cannot
		 *  be the last block, so we can safey decrypt all of them.
		 *
		 * Some things to note:
		 *  - The above semantics will cause aes_ctx->ac_remainder to
		 *  never accumulate more than AES_BLOCK_LEN bytes of
		 *  ciphertext. Once we reach at least AES_BLOCK_LEN + 1 bytes,
		 *  we will decrypt the contents of aes_ctx->ac_remainder by one
		 *  of the last two scenarios described above.
		 *
		 *  - We must always end up with AES_BLOCK_LEN bytes of data
		 *  in aes_ctx->ac_remainder when C_DecryptFinal() is called.
		 *  The first and third scenarios above may leave
		 *  aes_ctx->ac_remainder with less than AES_BLOCK_LEN bytes,
		 *  however the total size of the input ciphertext that's
		 *  been decrypted must end up a multiple of AES_BLOCK_LEN.
		 *  Therefore, we can always assume when there is a
		 *  remainder that more data is coming.  If we do end up
		 *  with a remainder that's not AES_BLOCK_LEN bytes long
		 *  when C_DecryptFinal() is called, the input is assumed
		 *  invalid and we return CKR_DATA_LEN_RANGE (see
		 *  soft_aes_decrypt_final()).
		 */

		VERIFY3U(aes_ctx->ac_remainder_len, <=, AES_BLOCK_LEN);
		if (in_len >= SIZE_MAX - AES_BLOCK_LEN)
			return (CKR_ENCRYPTED_DATA_LEN_RANGE);

		out_len = aes_ctx->ac_remainder_len + in_len;

		if (out_len <= AES_BLOCK_LEN) {
			/*
			 * The first scenario detailed above, accumulate
			 * ciphertext in ac_remainder_len and return.
			 */
			uint8_t *dest = (uint8_t *)aes_ctx->ac_remainder +
			    aes_ctx->ac_remainder_len;

			bcopy(pEncryptedData, dest, in_len);
			aes_ctx->ac_remainder_len += in_len;
			*pulDataLen = 0;

			/*
			 * Since we aren't writing an output, and are returning
			 * here, we don't need to adjust out_len -- we never
			 * reach the output buffer size checks after the
			 * switch statement.
			 */
			return (CKR_OK);
		} else if (out_len % AES_BLOCK_LEN == 0) {
			/*
			 * The second scenario decribed above. The total amount
			 * available is a multiple of AES_BLOCK_LEN, and
			 * we have more than one block.  We reduce the
			 * input size (in_len) by AES_BLOCK_LEN. We also
			 * reduce the output size (out_len) by AES_BLOCK_LEN
			 * for the output buffer size checks that follow
			 * the switch statement. In certain situations,
			 * PKCS#11 requires this to be an exact value, so
			 * the size check cannot occur for CKM_AES_CBC_PAD
			 * until after we've determine which scenario we
			 * have.
			 *
			 * Because we never accumulate more than AES_BLOCK_LEN
			 * bytes in aes_ctx->ac_remainder, when we are in
			 * this scenario, the following VERIFYs should always
			 * be true (and serve as a final safeguard against
			 * underflow).
			 */
			VERIFY3U(in_len, >=, AES_BLOCK_LEN);

			buffer_block = pEncryptedData + in_len - AES_BLOCK_LEN;

			in_len -= AES_BLOCK_LEN;

			/*
			 * This else clause explicity checks
			 * out_len > AES_BLOCK_LEN, so this is also safe.
			 */
			out_len -= AES_BLOCK_LEN;
		} else {
			/*
			 * The third scenario above.  We have at least
			 * AES_BLOCK_LEN + 1 bytes, but the total amount of
			 * input ciphertext available is not an exact
			 * multiple of AES_BLOCK_LEN.  Let
			 * aes_decrypt_contiguous_blocks() handle the
			 * buffering of the remainder.  Update the
			 * output size to reflect the actual amount of output
			 * we want to emit for the checks after the switch
			 * statement.
			 */
			out_len &= ~(AES_BLOCK_LEN - 1);
		}
		break;
	case CKM_AES_CTR:
		/*
		 * CKM_AES_CTR is a stream cipher, so we always output
		 * exactly as much output plaintext as input ciphertext
		 */
		out_len = in_len;
		break;
	default:
		out_len = aes_ctx->ac_remainder_len + in_len;
		out_len &= ~(AES_BLOCK_LEN - 1);
		break;
	}

	/*
	 * C_DecryptUpdate() verifies that pulDataLen is not NULL prior
	 * to calling soft_decrypt_common() (which calls us).
	 */

	if (pData == NULL) {
		/*
		 * If the output buffer (pData) is NULL, that means the
		 * caller is inquiring about the size buffer needed to
		 * complete the C_DecryptUpdate() request.  While we are
		 * permitted to set *pulDataLen to an estimated value that can
		 * be 'slightly' larger than the actual value required,
		 * since we know the exact size we need, we stick with the
		 * exact size.
		 */
		*pulDataLen = out_len;
		return (CKR_OK);
	}

	if (*pulDataLen < out_len) {
		/*
		 * Not an inquiry, but the output buffer isn't large enough.
		 * PKCS#11 requires that this scenario not fail fatally (as
		 * well as return a different error value). This situation
		 * also requires us to set *pulDataLen to the _exact_ size
		 * required.
		 */
		*pulDataLen = out_len;
		return (CKR_BUFFER_TOO_SMALL);
	}

	rc = aes_decrypt_contiguous_blocks(aes_ctx, (char *)pEncryptedData,
	    in_len, &out);

	if (rc != CRYPTO_SUCCESS) {
		rv = CKR_FUNCTION_FAILED;
		goto done;
	}

	*pulDataLen = out.cd_offset;

	switch (mech) {
	case CKM_AES_CBC_PAD:
		if (buffer_block == NULL) {
			break;
		}

		VERIFY0(aes_ctx->ac_remainder_len);

		/*
		 * We had multiple blocks of data to decrypt with nothing
		 * left over and deferred decrypting the last block of data.
		 * Copy it into aes_ctx->ac_remainder to decrypt on the
		 * next update call (or final).
		 */
		bcopy(buffer_block, aes_ctx->ac_remainder, AES_BLOCK_LEN);
		aes_ctx->ac_remainder_len = AES_BLOCK_LEN;
		break;
	}

done:
	return (rv);
}

CK_RV
soft_aes_encrypt_final(soft_session_t *session_p,
    CK_BYTE_PTR pLastEncryptedPart, CK_ULONG_PTR pulLastEncryptedPartLen)
{
	aes_ctx_t *aes_ctx = session_p->encrypt.context;
	crypto_data_t data = {
		.cd_format = CRYPTO_DATA_RAW,
		.cd_offset = 0,
		.cd_length = *pulLastEncryptedPartLen,
		.cd_raw.iov_base = (char *)pLastEncryptedPart,
		.cd_raw.iov_len = *pulLastEncryptedPartLen
	};
	CK_MECHANISM_TYPE mech = session_p->encrypt.mech.mechanism;
	CK_RV rv = CKR_OK;
	size_t out_len;
	int rc = CRYPTO_SUCCESS;

	switch (mech) {
	case CKM_AES_CBC_PAD:
		/*
		 * We always add 1..AES_BLOCK_LEN of padding to the input
		 * plaintext to round up to a multiple of AES_BLOCK_LEN.
		 * During encryption, we never output a partially encrypted
		 * block (that is the amount encrypted by each call of
		 * C_EncryptUpdate() is always either 0 or n * AES_BLOCK_LEN).
		 * As a result, at the end of the encryption operation, we
		 * output AES_BLOCK_LEN bytes of data -- this could be a full
		 * block of padding, or a combination of data + padding.
		 */
		out_len = AES_BLOCK_LEN;
		break;
	case CKM_AES_CTR:
		/*
		 * Since CKM_AES_CTR is a stream cipher, we never buffer any
		 * input, so we always have 0 remaining bytes of output.
		 */
		out_len = 0;
		break;
	case CKM_AES_CCM:
		out_len = aes_ctx->ac_remainder_len +
		    aes_ctx->acu.acu_ccm.ccm_mac_len;
		break;
	case CKM_AES_GCM:
		out_len = aes_ctx->ac_remainder_len +
		    aes_ctx->acu.acu_gcm.gcm_tag_len;
		break;
	case CKM_AES_CMAC:
	case CKM_AES_CMAC_GENERAL:
		out_len = AES_BLOCK_LEN;
		break;
	case CKM_AES_GMAC:
		out_len = AES_BLOCK_LEN;
		break;
	default:
		/*
		 * Everything other AES mechansism requires full blocks of
		 * input.  If the input was not an exact multiple of
		 * AES_BLOCK_LEN, it is a fatal error.
		 */
		if (aes_ctx->ac_remainder_len > 0) {
			rv = CKR_DATA_LEN_RANGE;
			goto done;
		}
		out_len = 0;
	}

	if (*pulLastEncryptedPartLen < out_len || pLastEncryptedPart == NULL) {
		*pulLastEncryptedPartLen = out_len;
		return ((pLastEncryptedPart == NULL) ?
		    CKR_OK : CKR_BUFFER_TOO_SMALL);
	}

	switch (mech) {
	case CKM_AES_CBC_PAD: {
		char block[AES_BLOCK_LEN] = { 0 };
		size_t padlen = AES_BLOCK_LEN - aes_ctx->ac_remainder_len;

		if (padlen == 0) {
			padlen = AES_BLOCK_LEN;
		}

		(void) memset(block, padlen & 0xff, sizeof (block));
		rc = aes_encrypt_contiguous_blocks(aes_ctx, block,
		    padlen, &data);
		explicit_bzero(block, sizeof (block));
		break;
	}
	case CKM_AES_CTR:
		/*
		 * Since CKM_AES_CTR is a stream cipher, we never
		 * buffer any data, and thus have no remaining data
		 * to output at the end
		 */
		break;
	case CKM_AES_CCM:
		rc = ccm_encrypt_final((ccm_ctx_t *)aes_ctx, &data,
		    AES_BLOCK_LEN, aes_encrypt_block, aes_xor_block);
		break;
	case CKM_AES_GCM:
		rc = gcm_encrypt_final((gcm_ctx_t *)aes_ctx, &data,
		    AES_BLOCK_LEN, aes_encrypt_block, aes_copy_block,
		    aes_xor_block);
		break;
	case CKM_AES_CMAC:
	case CKM_AES_CMAC_GENERAL:
		rc = cmac_mode_final((cbc_ctx_t *)aes_ctx, &data,
		    aes_encrypt_block, aes_xor_block);
		break;
	case CKM_AES_GMAC:
		rc = gmac_mode_final((gcm_ctx_t *)aes_ctx, &data,
		    AES_BLOCK_LEN, aes_encrypt_block, aes_xor_block);
		break;
	default:
		break;
	}
	rv = crypto2pkcs11_error_number(rc);

done:
	if (rv == CKR_OK) {
		*pulLastEncryptedPartLen = data.cd_offset;
	}

	soft_aes_free_ctx(aes_ctx);
	session_p->encrypt.context = NULL;
	return (rv);
}

CK_RV
soft_aes_decrypt_final(soft_session_t *session_p, CK_BYTE_PTR pLastPart,
    CK_ULONG_PTR pulLastPartLen)
{
	aes_ctx_t *aes_ctx = session_p->decrypt.context;
	CK_MECHANISM_TYPE mech = session_p->decrypt.mech.mechanism;
	CK_RV rv = CKR_OK;
	int rc = CRYPTO_SUCCESS;
	size_t out_len;
	crypto_data_t out = {
		.cd_format = CRYPTO_DATA_RAW,
		.cd_offset = 0,
		.cd_length = *pulLastPartLen,
		.cd_raw.iov_base = (char *)pLastPart,
		.cd_raw.iov_len = *pulLastPartLen
	};

	switch (mech) {
	case CKM_AES_CBC_PAD:
		/*
		 * PKCS#11 requires that a caller can discover the size of
		 * the output buffer required by calling
		 * C_DecryptFinal(hSession, NULL, &len) which sets
		 * *pulLastPartLen to the size required.  However, it also
		 * allows if one calls C_DecryptFinal with a buffer (i.e.
		 * pLastPart != NULL) that is too small, to return
		 * CKR_BUFFER_TOO_SMALL with *pulLastPartLen set to the
		 * _exact_ size required (when pLastPart is NULL, the
		 * implementation is allowed to set a 'sightly' larger
		 * value than is strictly necessary.  In either case, the
		 * caller is allowed to retry the operation (the operation
		 * is not terminated).
		 *
		 * With PKCS#7 padding, we cannot determine the exact size of
		 * the output until we decrypt the final block.  As such, the
		 * first time for a given decrypt operation we are called,
		 * we decrypt the final block and stash it in the aes_ctx
		 * remainder block.  On any subsequent calls in the
		 * current decrypt operation, we then can use the decrypted
		 * block as necessary to provide the correct semantics.
		 *
		 * The cleanup of aes_ctx when the operation terminates
		 * will take care of clearing out aes_ctx->ac_remainder_len.
		 */
		if ((aes_ctx->ac_flags & P11_DECRYPTED) == 0) {
			uint8_t block[AES_BLOCK_LEN] = { 0 };
			crypto_data_t block_out = {
				.cd_format = CRYPTO_DATA_RAW,
				.cd_offset = 0,
				.cd_length = sizeof (block),
				.cd_raw.iov_base = (char *)block,
				.cd_raw.iov_len = sizeof (block)
			};
			size_t amt, i;
			uint8_t pad_len;

			if (aes_ctx->ac_remainder_len != AES_BLOCK_LEN) {
				return (CKR_DATA_LEN_RANGE);
			}

			rc = aes_decrypt_contiguous_blocks(aes_ctx,
			    (char *)block, 0, &block_out);
			if (rc != CRYPTO_SUCCESS) {
				explicit_bzero(block, sizeof (block));
				return (CKR_FUNCTION_FAILED);
			}

			pad_len = block[AES_BLOCK_LEN - 1];

			/*
			 * RFC5652 6.3 The amount of padding must be
			 * block_sz - (len mod block_size).  This means
			 * the amount of padding must always be in the
			 * range [1..block_size].
			 */
			if (pad_len == 0 || pad_len > AES_BLOCK_LEN) {
				rv = CKR_ENCRYPTED_DATA_INVALID;
				explicit_bzero(block, sizeof (block));
				goto done;
			}
			amt = AES_BLOCK_LEN - pad_len;

			/*
			 * Verify the padding is correct.  Try to do so
			 * in as constant a time as possible.
			 */
			for (i = amt; i < AES_BLOCK_LEN; i++) {
				if (block[i] != pad_len) {
					rv = CKR_ENCRYPTED_DATA_INVALID;
				}
			}
			if (rv != CKR_OK) {
				explicit_bzero(block, sizeof (block));
				goto done;
			}

			bcopy(block, aes_ctx->ac_remainder, amt);
			explicit_bzero(block, sizeof (block));

			aes_ctx->ac_flags |= P11_DECRYPTED;
			aes_ctx->ac_remainder_len = amt;
		}

		out_len = aes_ctx->ac_remainder_len;
		break;
	case CKM_AES_CTR:
		/*
		 * Since CKM_AES_CTR is a stream cipher, we never have
		 * any remaining bytes to output.
		 */
		out_len = 0;
		break;
	case CKM_AES_CCM:
		out_len = aes_ctx->ac_data_len;
		break;
	case CKM_AES_GCM:
		out_len = aes_ctx->acu.acu_gcm.gcm_processed_data_len -
		    aes_ctx->acu.acu_gcm.gcm_tag_len;
		break;
	default:
		/*
		 * The remaining mechanims require an exact multiple of
		 * AES_BLOCK_LEN of ciphertext.  Any other value is an error.
		 */
		if (aes_ctx->ac_remainder_len > 0) {
			rv = CKR_DATA_LEN_RANGE;
			goto done;
		}
		out_len = 0;
		break;
	}

	if (*pulLastPartLen < out_len || pLastPart == NULL) {
		*pulLastPartLen = out_len;
		return ((pLastPart == NULL) ? CKR_OK : CKR_BUFFER_TOO_SMALL);
	}

	switch (mech) {
	case CKM_AES_CBC_PAD:
		*pulLastPartLen = out_len;
		if (out_len == 0) {
			break;
		}
		bcopy(aes_ctx->ac_remainder, pLastPart, out_len);
		out.cd_offset += out_len;
		break;
	case CKM_AES_CCM:
		ASSERT3U(aes_ctx->ac_processed_data_len, ==, out_len);
		ASSERT3U(aes_ctx->ac_processed_mac_len, ==,
		    aes_ctx->ac_mac_len);

		rc = ccm_decrypt_final((ccm_ctx_t *)aes_ctx, &out,
		    AES_BLOCK_LEN, aes_encrypt_block, aes_copy_block,
		    aes_xor_block);
		break;
	case CKM_AES_GCM:
		rc = gcm_decrypt_final((gcm_ctx_t *)aes_ctx, &out,
		    AES_BLOCK_LEN, aes_encrypt_block, aes_xor_block);
		break;
	default:
		break;
	}

	VERIFY3U(out.cd_offset, ==, out_len);
	rv = crypto2pkcs11_error_number(rc);

done:
	if (rv == CKR_OK) {
		*pulLastPartLen = out.cd_offset;
	}

	soft_aes_free_ctx(aes_ctx);
	session_p->decrypt.context = NULL;

	return (rv);
}

/*
 * Allocate and initialize AES contexts for sign and verify operations
 * (including the underlying encryption context needed to sign or verify) --
 * called by C_SignInit() and C_VerifyInit() to perform the CKM_AES_* MAC
 * mechanisms. For general-length AES MAC, also validate the MAC length.
 */
CK_RV
soft_aes_sign_verify_init_common(soft_session_t *session_p,
    CK_MECHANISM_PTR pMechanism, soft_object_t *key_p, boolean_t sign_op)
{
	soft_aes_sign_ctx_t	*ctx = NULL;
	size_t		mac_len = AES_BLOCK_LEN;

	/* For AES CMAC the IV is always 0 */
	CK_BYTE		iv_zero[AES_BLOCK_LEN] = { 0 };
	CK_MECHANISM	encrypt_mech = { 0 };
	CK_RV		rv;

	switch (pMechanism->mechanism) {
	case CKM_AES_CMAC_GENERAL:
		if (pMechanism->pParameter == NULL) {
			return (CKR_MECHANISM_PARAM_INVALID);
		}
		mac_len = *(CK_MAC_GENERAL_PARAMS *)pMechanism->pParameter;
		if (mac_len > AES_BLOCK_LEN) {
			return (CKR_MECHANISM_PARAM_INVALID);
		}
		encrypt_mech.mechanism = CKM_AES_CMAC;
		encrypt_mech.pParameter = iv_zero;
		encrypt_mech.ulParameterLen = AES_BLOCK_LEN;
		break;

	case CKM_AES_CMAC:
		encrypt_mech.mechanism = CKM_AES_CMAC;
		encrypt_mech.pParameter = iv_zero;
		encrypt_mech.ulParameterLen = AES_BLOCK_LEN;
		break;

	case CKM_AES_GMAC:
		/* See soft_aes_init_ctx */
		if (pMechanism->pParameter == NULL ||
		    pMechanism->ulParameterLen != AES_GMAC_IV_LEN)
			return (CKR_MECHANISM_PARAM_INVALID);
		encrypt_mech.mechanism = CKM_AES_GMAC;
		encrypt_mech.pParameter = pMechanism->pParameter;
		encrypt_mech.ulParameterLen = pMechanism->ulParameterLen;
		break;

	default:
		return (CKR_MECHANISM_INVALID);
	}

	if (key_p->key_type != CKK_AES)
		return (CKR_KEY_TYPE_INCONSISTENT);

	ctx = calloc(1, sizeof (*ctx));
	if (ctx == NULL) {
		return (CKR_HOST_MEMORY);
	}

	rv = soft_aes_check_mech_param(pMechanism, &ctx->aes_ctx);
	if (rv != CKR_OK) {
		soft_aes_free_ctx(ctx->aes_ctx);
		goto done;
	}

	/* See soft_aes_crypt_init_common */
	if ((rv = soft_encrypt_init_internal(session_p, &encrypt_mech,
	    key_p)) != CKR_OK) {
		soft_aes_free_ctx(ctx->aes_ctx);
		goto done;
	}

	ctx->mac_len = mac_len;

	(void) pthread_mutex_lock(&session_p->session_mutex);

	if (sign_op) {
		session_p->sign.context = ctx;
		session_p->sign.mech.mechanism = pMechanism->mechanism;
	} else {
		session_p->verify.context = ctx;
		session_p->verify.mech.mechanism = pMechanism->mechanism;
	}

	(void) pthread_mutex_unlock(&session_p->session_mutex);

done:
	if (rv != CKR_OK) {
		soft_aes_free_ctx(ctx->aes_ctx);
		free(ctx);
	}

	return (rv);
}

CK_RV
soft_aes_sign_verify_common(soft_session_t *session_p, CK_BYTE_PTR pData,
    CK_ULONG ulDataLen, CK_BYTE_PTR pSigned, CK_ULONG_PTR pulSignedLen,
    boolean_t sign_op, boolean_t Final)
{
	soft_aes_sign_ctx_t	*soft_aes_ctx_sign_verify;
	CK_RV			rv;
	CK_BYTE			*pEncrypted = NULL;
	CK_ULONG		ulEncryptedLen = AES_BLOCK_LEN;
	CK_BYTE			last_block[AES_BLOCK_LEN];

	if (sign_op) {
		soft_aes_ctx_sign_verify =
		    (soft_aes_sign_ctx_t *)session_p->sign.context;

		if (soft_aes_ctx_sign_verify->mac_len == 0) {
			*pulSignedLen = 0;
			goto clean_exit;
		}

		/* Application asks for the length of the output buffer. */
		if (pSigned == NULL) {
			*pulSignedLen = soft_aes_ctx_sign_verify->mac_len;
			return (CKR_OK);
		}

		/* Is the application-supplied buffer large enough? */
		if (*pulSignedLen < soft_aes_ctx_sign_verify->mac_len) {
			*pulSignedLen = soft_aes_ctx_sign_verify->mac_len;
			return (CKR_BUFFER_TOO_SMALL);
		}
	} else {
		soft_aes_ctx_sign_verify =
		    (soft_aes_sign_ctx_t *)session_p->verify.context;
	}

	if (Final) {
		rv = soft_encrypt_final(session_p, last_block,
		    &ulEncryptedLen);
	} else {
		rv = soft_encrypt(session_p, pData, ulDataLen,
		    last_block, &ulEncryptedLen);
	}

	if (rv == CKR_OK) {
		*pulSignedLen = soft_aes_ctx_sign_verify->mac_len;

		/* the leftmost mac_len bytes of last_block is our MAC */
		(void) memcpy(pSigned, last_block, *pulSignedLen);
	}

clean_exit:

	(void) pthread_mutex_lock(&session_p->session_mutex);

	/* soft_encrypt_common() has freed the encrypt context */
	if (sign_op) {
		free(session_p->sign.context);
		session_p->sign.context = NULL;
	} else {
		free(session_p->verify.context);
		session_p->verify.context = NULL;
	}
	session_p->encrypt.flags = 0;

	(void) pthread_mutex_unlock(&session_p->session_mutex);

	if (pEncrypted) {
		free(pEncrypted);
	}

	return (rv);
}

/*
 * Called by soft_sign_update()
 */
CK_RV
soft_aes_mac_sign_verify_update(soft_session_t *session_p, CK_BYTE_PTR pPart,
    CK_ULONG ulPartLen)
{
	CK_BYTE		buf[AES_BLOCK_LEN];
	CK_ULONG	ulEncryptedLen = AES_BLOCK_LEN;
	CK_RV		rv;

	rv = soft_encrypt_update(session_p, pPart, ulPartLen,
	    buf, &ulEncryptedLen);
	explicit_bzero(buf, sizeof (buf));

	return (rv);
}

/*
 * Compare with crypto_free_mode_ctx()
 * in $SRC/common/crypto/modes/modes.c
 */
void
soft_aes_free_ctx(aes_ctx_t *ctx)
{
	size_t len = 0;

	if (ctx == NULL)
		return;

	if (ctx->ac_flags & ECB_MODE) {
		len = sizeof (ecb_ctx_t);
	} else if (ctx->ac_flags & (CBC_MODE|CMAC_MODE)) {
		len = sizeof (cbc_ctx_t);
	} else if (ctx->ac_flags & CTR_MODE) {
		len = sizeof (ctr_ctx_t);
	} else if (ctx->ac_flags & CCM_MODE) {
		ccm_ctx_t *ccm_ctx = &ctx->acu.acu_ccm;
		if (ccm_ctx->ccm_pt_buf != NULL) {
			freezero(ccm_ctx->ccm_pt_buf,
			    ccm_ctx->ccm_data_len);
			ccm_ctx->ccm_pt_buf = NULL;
		}
		len = sizeof (ccm_ctx_t);
	} else if (ctx->ac_flags & GMAC_MODE) {
		len = sizeof (gcm_ctx_t);
	} else if (ctx->ac_flags & GCM_MODE) {
		gcm_ctx_t *gcm_ctx = &ctx->acu.acu_gcm;
		if (gcm_ctx->gcm_pt_buf != NULL) {
			freezero(gcm_ctx->gcm_pt_buf,
			    gcm_ctx->gcm_pt_buf_len);
			gcm_ctx->gcm_pt_buf = NULL;
		}
		len = sizeof (gcm_ctx_t);
	}

	freezero(ctx->ac_keysched, ctx->ac_keysched_len);
	freezero(ctx, len);
}