VeraCrypt
aboutsummaryrefslogtreecommitdiff
path: root/src/Common/Tests.c
blob: 4f53d4ed500624a678d15e4a561f551f5e7c6cfd (plain)
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
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
/*
 Legal Notice: Some portions of the source code contained in this file were
 derived from the source code of TrueCrypt 7.1a, which is
 Copyright (c) 2003-2012 TrueCrypt Developers Association and which is
 governed by the TrueCrypt License 3.0, also from the source code of
 Encryption for the Masses 2.02a, which is Copyright (c) 1998-2000 Paul Le Roux
 and which is governed by the 'License Agreement for Encryption for the Masses'
 Modifications and additions to the original source code (contained in this file)
 and all other portions of this file are Copyright (c) 2013-2017 IDRIX
 and are governed by the Apache License 2.0 the full text of which is
 contained in the file License.txt included in VeraCrypt binary and source
 code distribution packages. */

#include "Tcdefs.h"
#include "Crc.h"
#include "Crypto.h"
#include "Common/Endian.h"
#include "Tests.h"
#include "Xts.h"
#include <string.h>
#include "Pkcs5.h"
#include "cpu.h"

typedef struct {
	CRYPTOPP_ALIGN_DATA(16) unsigned __int8 key1[32];
	CRYPTOPP_ALIGN_DATA(16) unsigned __int8 key2[32];
	unsigned __int8 dataUnitNo[8];
	unsigned int blockNo;
	unsigned __int8 plaintext[ENCRYPTION_DATA_UNIT_SIZE];
	unsigned __int8 ciphertext[ENCRYPTION_DATA_UNIT_SIZE];
} XTS_TEST;

#define XTS_TEST_COUNT 5

XTS_TEST XTS_vectors[XTS_TEST_COUNT] = {
/* XTS-AES-256 */
{
	// IEEE 1619 - Vector 10

	{ 0x27, 0x18, 0x28, 0x18, 0x28, 0x45, 0x90, 0x45, 0x23, 0x53, 0x60, 0x28, 0x74, 0x71, 0x35, 0x26, 0x62, 0x49, 0x77, 0x57, 0x24, 0x70, 0x93, 0x69, 0x99, 0x59, 0x57, 0x49, 0x66, 0x96, 0x76, 0x27 },
	{ 0x31, 0x41, 0x59, 0x26, 0x53, 0x58, 0x97, 0x93, 0x23, 0x84, 0x62, 0x64, 0x33, 0x83, 0x27, 0x95, 0x02, 0x88, 0x41, 0x97, 0x16, 0x93, 0x99, 0x37, 0x51, 0x05, 0x82, 0x09, 0x74, 0x94, 0x45, 0x92 },
	{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff },
	0,
	{
		0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
		0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
		0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
		0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
		0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
		0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
		0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
		0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
		0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
		0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
		0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
		0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
		0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
		0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
		0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
		0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
	},
	{
		0x1c, 0x3b, 0x3a, 0x10, 0x2f, 0x77, 0x03, 0x86, 0xe4, 0x83, 0x6c, 0x99, 0xe3, 0x70, 0xcf, 0x9b, 0xea, 0x00, 0x80, 0x3f, 0x5e, 0x48, 0x23, 0x57, 0xa4, 0xae, 0x12, 0xd4, 0x14, 0xa3, 0xe6, 0x3b,
		0x5d, 0x31, 0xe2, 0x76, 0xf8, 0xfe, 0x4a, 0x8d, 0x66, 0xb3, 0x17, 0xf9, 0xac, 0x68, 0x3f, 0x44, 0x68, 0x0a, 0x86, 0xac, 0x35, 0xad, 0xfc, 0x33, 0x45, 0xbe, 0xfe, 0xcb, 0x4b, 0xb1, 0x88, 0xfd,
		0x57, 0x76, 0x92, 0x6c, 0x49, 0xa3, 0x09, 0x5e, 0xb1, 0x08, 0xfd, 0x10, 0x98, 0xba, 0xec, 0x70, 0xaa, 0xa6, 0x69, 0x99, 0xa7, 0x2a, 0x82, 0xf2, 0x7d, 0x84, 0x8b, 0x21, 0xd4, 0xa7, 0x41, 0xb0,
		0xc5, 0xcd, 0x4d, 0x5f, 0xff, 0x9d, 0xac, 0x89, 0xae, 0xba, 0x12, 0x29, 0x61, 0xd0, 0x3a, 0x75, 0x71, 0x23, 0xe9, 0x87, 0x0f, 0x8a, 0xcf, 0x10, 0x00, 0x02, 0x08, 0x87, 0x89, 0x14, 0x29, 0xca,
		0x2a, 0x3e, 0x7a, 0x7d, 0x7d, 0xf7, 0xb1, 0x03, 0x55, 0x16, 0x5c, 0x8b, 0x9a, 0x6d, 0x0a, 0x7d, 0xe8, 0xb0, 0x62, 0xc4, 0x50, 0x0d, 0xc4, 0xcd, 0x12, 0x0c, 0x0f, 0x74, 0x18, 0xda, 0xe3, 0xd0,
		0xb5, 0x78, 0x1c, 0x34, 0x80, 0x3f, 0xa7, 0x54, 0x21, 0xc7, 0x90, 0xdf, 0xe1, 0xde, 0x18, 0x34, 0xf2, 0x80, 0xd7, 0x66, 0x7b, 0x32, 0x7f, 0x6c, 0x8c, 0xd7, 0x55, 0x7e, 0x12, 0xac, 0x3a, 0x0f,
		0x93, 0xec, 0x05, 0xc5, 0x2e, 0x04, 0x93, 0xef, 0x31, 0xa1, 0x2d, 0x3d, 0x92, 0x60, 0xf7, 0x9a, 0x28, 0x9d, 0x6a, 0x37, 0x9b, 0xc7, 0x0c, 0x50, 0x84, 0x14, 0x73, 0xd1, 0xa8, 0xcc, 0x81, 0xec,
		0x58, 0x3e, 0x96, 0x45, 0xe0, 0x7b, 0x8d, 0x96, 0x70, 0x65, 0x5b, 0xa5, 0xbb, 0xcf, 0xec, 0xc6, 0xdc, 0x39, 0x66, 0x38, 0x0a, 0xd8, 0xfe, 0xcb, 0x17, 0xb6, 0xba, 0x02, 0x46, 0x9a, 0x02, 0x0a,
		0x84, 0xe1, 0x8e, 0x8f, 0x84, 0x25, 0x20, 0x70, 0xc1, 0x3e, 0x9f, 0x1f, 0x28, 0x9b, 0xe5, 0x4f, 0xbc, 0x48, 0x14, 0x57, 0x77, 0x8f, 0x61, 0x60, 0x15, 0xe1, 0x32, 0x7a, 0x02, 0xb1, 0x40, 0xf1,
		0x50, 0x5e, 0xb3, 0x09, 0x32, 0x6d, 0x68, 0x37, 0x8f, 0x83, 0x74, 0x59, 0x5c, 0x84, 0x9d, 0x84, 0xf4, 0xc3, 0x33, 0xec, 0x44, 0x23, 0x88, 0x51, 0x43, 0xcb, 0x47, 0xbd, 0x71, 0xc5, 0xed, 0xae,
		0x9b, 0xe6, 0x9a, 0x2f, 0xfe, 0xce, 0xb1, 0xbe, 0xc9, 0xde, 0x24, 0x4f, 0xbe, 0x15, 0x99, 0x2b, 0x11, 0xb7, 0x7c, 0x04, 0x0f, 0x12, 0xbd, 0x8f, 0x6a, 0x97, 0x5a, 0x44, 0xa0, 0xf9, 0x0c, 0x29,
		0xa9, 0xab, 0xc3, 0xd4, 0xd8, 0x93, 0x92, 0x72, 0x84, 0xc5, 0x87, 0x54, 0xcc, 0xe2, 0x94, 0x52, 0x9f, 0x86, 0x14, 0xdc, 0xd2, 0xab, 0xa9, 0x91, 0x92, 0x5f, 0xed, 0xc4, 0xae, 0x74, 0xff, 0xac,
		0x6e, 0x33, 0x3b, 0x93, 0xeb, 0x4a, 0xff, 0x04, 0x79, 0xda, 0x9a, 0x41, 0x0e, 0x44, 0x50, 0xe0, 0xdd, 0x7a, 0xe4, 0xc6, 0xe2, 0x91, 0x09, 0x00, 0x57, 0x5d, 0xa4, 0x01, 0xfc, 0x07, 0x05, 0x9f,
		0x64, 0x5e, 0x8b, 0x7e, 0x9b, 0xfd, 0xef, 0x33, 0x94, 0x30, 0x54, 0xff, 0x84, 0x01, 0x14, 0x93, 0xc2, 0x7b, 0x34, 0x29, 0xea, 0xed, 0xb4, 0xed, 0x53, 0x76, 0x44, 0x1a, 0x77, 0xed, 0x43, 0x85,
		0x1a, 0xd7, 0x7f, 0x16, 0xf5, 0x41, 0xdf, 0xd2, 0x69, 0xd5, 0x0d, 0x6a, 0x5f, 0x14, 0xfb, 0x0a, 0xab, 0x1c, 0xbb, 0x4c, 0x15, 0x50, 0xbe, 0x97, 0xf7, 0xab, 0x40, 0x66, 0x19, 0x3c, 0x4c, 0xaa,
		0x77, 0x3d, 0xad, 0x38, 0x01, 0x4b, 0xd2, 0x09, 0x2f, 0xa7, 0x55, 0xc8, 0x24, 0xbb, 0x5e, 0x54, 0xc4, 0xf3, 0x6f, 0xfd, 0xa9, 0xfc, 0xea, 0x70, 0xb9, 0xc6, 0xe6, 0x93, 0xe1, 0x48, 0xc1, 0x51
	}
},
{
	// IEEE 1619 - Vector 11

	{ 0x27, 0x18, 0x28, 0x18, 0x28, 0x45, 0x90, 0x45, 0x23, 0x53, 0x60, 0x28, 0x74, 0x71, 0x35, 0x26, 0x62, 0x49, 0x77, 0x57, 0x24, 0x70, 0x93, 0x69, 0x99, 0x59, 0x57, 0x49, 0x66, 0x96, 0x76, 0x27 },
	{ 0x31, 0x41, 0x59, 0x26, 0x53, 0x58, 0x97, 0x93, 0x23, 0x84, 0x62, 0x64, 0x33, 0x83, 0x27, 0x95, 0x02, 0x88, 0x41, 0x97, 0x16, 0x93, 0x99, 0x37, 0x51, 0x05, 0x82, 0x09, 0x74, 0x94, 0x45, 0x92 },
	{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff },
	0,
	{
		0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
		0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
		0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
		0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
		0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
		0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
		0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
		0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
		0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
		0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
		0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
		0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
		0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
		0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
		0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
		0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
	},
	{
		0x77, 0xa3, 0x12, 0x51, 0x61, 0x8a, 0x15, 0xe6, 0xb9, 0x2d, 0x1d, 0x66, 0xdf, 0xfe, 0x7b, 0x50, 0xb5, 0x0b, 0xad, 0x55, 0x23, 0x05, 0xba, 0x02, 0x17, 0xa6, 0x10, 0x68, 0x8e, 0xff, 0x7e, 0x11,
		0xe1, 0xd0, 0x22, 0x54, 0x38, 0xe0, 0x93, 0x24, 0x2d, 0x6d, 0xb2, 0x74, 0xfd, 0xe8, 0x01, 0xd4, 0xca, 0xe0, 0x6f, 0x20, 0x92, 0xc7, 0x28, 0xb2, 0x47, 0x85, 0x59, 0xdf, 0x58, 0xe8, 0x37, 0xc2,
		0x46, 0x9e, 0xe4, 0xa4, 0xfa, 0x79, 0x4e, 0x4b, 0xbc, 0x7f, 0x39, 0xbc, 0x02, 0x6e, 0x3c, 0xb7, 0x2c, 0x33, 0xb0, 0x88, 0x8f, 0x25, 0xb4, 0xac, 0xf5, 0x6a, 0x2a, 0x98, 0x04, 0xf1, 0xce, 0x6d,
		0x3d, 0x6e, 0x1d, 0xc6, 0xca, 0x18, 0x1d, 0x4b, 0x54, 0x61, 0x79, 0xd5, 0x55, 0x44, 0xaa, 0x77, 0x60, 0xc4, 0x0d, 0x06, 0x74, 0x15, 0x39, 0xc7, 0xe3, 0xcd, 0x9d, 0x2f, 0x66, 0x50, 0xb2, 0x01,
		0x3f, 0xd0, 0xee, 0xb8, 0xc2, 0xb8, 0xe3, 0xd8, 0xd2, 0x40, 0xcc, 0xae, 0x2d, 0x4c, 0x98, 0x32, 0x0a, 0x74, 0x42, 0xe1, 0xc8, 0xd7, 0x5a, 0x42, 0xd6, 0xe6, 0xcf, 0xa4, 0xc2, 0xec, 0xa1, 0x79,
		0x8d, 0x15, 0x8c, 0x7a, 0xec, 0xdf, 0x82, 0x49, 0x0f, 0x24, 0xbb, 0x9b, 0x38, 0xe1, 0x08, 0xbc, 0xda, 0x12, 0xc3, 0xfa, 0xf9, 0xa2, 0x11, 0x41, 0xc3, 0x61, 0x3b, 0x58, 0x36, 0x7f, 0x92, 0x2a,
		0xaa, 0x26, 0xcd, 0x22, 0xf2, 0x3d, 0x70, 0x8d, 0xae, 0x69, 0x9a, 0xd7, 0xcb, 0x40, 0xa8, 0xad, 0x0b, 0x6e, 0x27, 0x84, 0x97, 0x3d, 0xcb, 0x60, 0x56, 0x84, 0xc0, 0x8b, 0x8d, 0x69, 0x98, 0xc6,
		0x9a, 0xac, 0x04, 0x99, 0x21, 0x87, 0x1e, 0xbb, 0x65, 0x30, 0x1a, 0x46, 0x19, 0xca, 0x80, 0xec, 0xb4, 0x85, 0xa3, 0x1d, 0x74, 0x42, 0x23, 0xce, 0x8d, 0xdc, 0x23, 0x94, 0x82, 0x8d, 0x6a, 0x80,
		0x47, 0x0c, 0x09, 0x2f, 0x5b, 0xa4, 0x13, 0xc3, 0x37, 0x8f, 0xa6, 0x05, 0x42, 0x55, 0xc6, 0xf9, 0xdf, 0x44, 0x95, 0x86, 0x2b, 0xbb, 0x32, 0x87, 0x68, 0x1f, 0x93, 0x1b, 0x68, 0x7c, 0x88, 0x8a,
		0xbf, 0x84, 0x4d, 0xfc, 0x8f, 0xc2, 0x83, 0x31, 0xe5, 0x79, 0x92, 0x8c, 0xd1, 0x2b, 0xd2, 0x39, 0x0a, 0xe1, 0x23, 0xcf, 0x03, 0x81, 0x8d, 0x14, 0xde, 0xdd, 0xe5, 0xc0, 0xc2, 0x4c, 0x8a, 0xb0,
		0x18, 0xbf, 0xca, 0x75, 0xca, 0x09, 0x6f, 0x2d, 0x53, 0x1f, 0x3d, 0x16, 0x19, 0xe7, 0x85, 0xf1, 0xad, 0xa4, 0x37, 0xca, 0xb9, 0x2e, 0x98, 0x05, 0x58, 0xb3, 0xdc, 0xe1, 0x47, 0x4a, 0xfb, 0x75,
		0xbf, 0xed, 0xbf, 0x8f, 0xf5, 0x4c, 0xb2, 0x61, 0x8e, 0x02, 0x44, 0xc9, 0xac, 0x0d, 0x3c, 0x66, 0xfb, 0x51, 0x59, 0x8c, 0xd2, 0xdb, 0x11, 0xf9, 0xbe, 0x39, 0x79, 0x1a, 0xbe, 0x44, 0x7c, 0x63,
		0x09, 0x4f, 0x7c, 0x45, 0x3b, 0x7f, 0xf8, 0x7c, 0xb5, 0xbb, 0x36, 0xb7, 0xc7, 0x9e, 0xfb, 0x08, 0x72, 0xd1, 0x70, 0x58, 0xb8, 0x3b, 0x15, 0xab, 0x08, 0x66, 0xad, 0x8a, 0x58, 0x65, 0x6c, 0x5a,
		0x7e, 0x20, 0xdb, 0xdf, 0x30, 0x8b, 0x24, 0x61, 0xd9, 0x7c, 0x0e, 0xc0, 0x02, 0x4a, 0x27, 0x15, 0x05, 0x52, 0x49, 0xcf, 0x3b, 0x47, 0x8d, 0xdd, 0x47, 0x40, 0xde, 0x65, 0x4f, 0x75, 0xca, 0x68,
		0x6e, 0x0d, 0x73, 0x45, 0xc6, 0x9e, 0xd5, 0x0c, 0xdc, 0x2a, 0x8b, 0x33, 0x2b, 0x1f, 0x88, 0x24, 0x10, 0x8a, 0xc9, 0x37, 0xeb, 0x05, 0x05, 0x85, 0x60, 0x8e, 0xe7, 0x34, 0x09, 0x7f, 0xc0, 0x90,
		0x54, 0xfb, 0xff, 0x89, 0xee, 0xae, 0xea, 0x79, 0x1f, 0x4a, 0x7a, 0xb1, 0xf9, 0x86, 0x82, 0x94, 0xa4, 0xf9, 0xe2, 0x7b, 0x42, 0xaf, 0x81, 0x00, 0xcb, 0x9d, 0x59, 0xce, 0xf9, 0x64, 0x58, 0x03
	}
},
{
	// IEEE 1619 - Vector 12

	{ 0x27, 0x18, 0x28, 0x18, 0x28, 0x45, 0x90, 0x45, 0x23, 0x53, 0x60, 0x28, 0x74, 0x71, 0x35, 0x26, 0x62, 0x49, 0x77, 0x57, 0x24, 0x70, 0x93, 0x69, 0x99, 0x59, 0x57, 0x49, 0x66, 0x96, 0x76, 0x27 },
	{ 0x31, 0x41, 0x59, 0x26, 0x53, 0x58, 0x97, 0x93, 0x23, 0x84, 0x62, 0x64, 0x33, 0x83, 0x27, 0x95, 0x02, 0x88, 0x41, 0x97, 0x16, 0x93, 0x99, 0x37, 0x51, 0x05, 0x82, 0x09, 0x74, 0x94, 0x45, 0x92 },
	{ 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff },
	0,
	{
		0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
		0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
		0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
		0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
		0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
		0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
		0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
		0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
		0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
		0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
		0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
		0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
		0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
		0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
		0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
		0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
	},
	{
		0xe3, 0x87, 0xaa, 0xa5, 0x8b, 0xa4, 0x83, 0xaf, 0xa7, 0xe8, 0xeb, 0x46, 0x97, 0x78, 0x31, 0x7e, 0xcf, 0x4c, 0xf5, 0x73, 0xaa, 0x9d, 0x4e, 0xac, 0x23, 0xf2, 0xcd, 0xf9, 0x14, 0xe4, 0xe2, 0x00,
		0xa8, 0xb4, 0x90, 0xe4, 0x2e, 0xe6, 0x46, 0x80, 0x2d, 0xc6, 0xee, 0x2b, 0x47, 0x1b, 0x27, 0x81, 0x95, 0xd6, 0x09, 0x18, 0xec, 0xec, 0xb4, 0x4b, 0xf7, 0x99, 0x66, 0xf8, 0x3f, 0xab, 0xa0, 0x49,
		0x92, 0x98, 0xeb, 0xc6, 0x99, 0xc0, 0xc8, 0x63, 0x47, 0x15, 0xa3, 0x20, 0xbb, 0x4f, 0x07, 0x5d, 0x62, 0x2e, 0x74, 0xc8, 0xc9, 0x32, 0x00, 0x4f, 0x25, 0xb4, 0x1e, 0x36, 0x10, 0x25, 0xb5, 0xa8,
		0x78, 0x15, 0x39, 0x1f, 0x61, 0x08, 0xfc, 0x4a, 0xfa, 0x6a, 0x05, 0xd9, 0x30, 0x3c, 0x6b, 0xa6, 0x8a, 0x12, 0x8a, 0x55, 0x70, 0x5d, 0x41, 0x59, 0x85, 0x83, 0x2f, 0xde, 0xaa, 0xe6, 0xc8, 0xe1,
		0x91, 0x10, 0xe8, 0x4d, 0x1b, 0x1f, 0x19, 0x9a, 0x26, 0x92, 0x11, 0x9e, 0xdc, 0x96, 0x13, 0x26, 0x58, 0xf0, 0x9d, 0xa7, 0xc6, 0x23, 0xef, 0xce, 0xc7, 0x12, 0x53, 0x7a, 0x3d, 0x94, 0xc0, 0xbf,
		0x5d, 0x7e, 0x35, 0x2e, 0xc9, 0x4a, 0xe5, 0x79, 0x7f, 0xdb, 0x37, 0x7d, 0xc1, 0x55, 0x11, 0x50, 0x72, 0x1a, 0xdf, 0x15, 0xbd, 0x26, 0xa8, 0xef, 0xc2, 0xfc, 0xaa, 0xd5, 0x68, 0x81, 0xfa, 0x9e,
		0x62, 0x46, 0x2c, 0x28, 0xf3, 0x0a, 0xe1, 0xce, 0xac, 0xa9, 0x3c, 0x34, 0x5c, 0xf2, 0x43, 0xb7, 0x3f, 0x54, 0x2e, 0x20, 0x74, 0xa7, 0x05, 0xbd, 0x26, 0x43, 0xbb, 0x9f, 0x7c, 0xc7, 0x9b, 0xb6,
		0xe7, 0x09, 0x1e, 0xa6, 0xe2, 0x32, 0xdf, 0x0f, 0x9a, 0xd0, 0xd6, 0xcf, 0x50, 0x23, 0x27, 0x87, 0x6d, 0x82, 0x20, 0x7a, 0xbf, 0x21, 0x15, 0xcd, 0xac, 0xf6, 0xd5, 0xa4, 0x8f, 0x6c, 0x18, 0x79,
		0xa6, 0x5b, 0x11, 0x5f, 0x0f, 0x8b, 0x3c, 0xb3, 0xc5, 0x9d, 0x15, 0xdd, 0x8c, 0x76, 0x9b, 0xc0, 0x14, 0x79, 0x5a, 0x18, 0x37, 0xf3, 0x90, 0x1b, 0x58, 0x45, 0xeb, 0x49, 0x1a, 0xdf, 0xef, 0xe0,
		0x97, 0xb1, 0xfa, 0x30, 0xa1, 0x2f, 0xc1, 0xf6, 0x5b, 0xa2, 0x29, 0x05, 0x03, 0x15, 0x39, 0x97, 0x1a, 0x10, 0xf2, 0xf3, 0x6c, 0x32, 0x1b, 0xb5, 0x13, 0x31, 0xcd, 0xef, 0xb3, 0x9e, 0x39, 0x64,
		0xc7, 0xef, 0x07, 0x99, 0x94, 0xf5, 0xb6, 0x9b, 0x2e, 0xdd, 0x83, 0xa7, 0x1e, 0xf5, 0x49, 0x97, 0x1e, 0xe9, 0x3f, 0x44, 0xea, 0xc3, 0x93, 0x8f, 0xcd, 0xd6, 0x1d, 0x01, 0xfa, 0x71, 0x79, 0x9d,
		0xa3, 0xa8, 0x09, 0x1c, 0x4c, 0x48, 0xaa, 0x9e, 0xd2, 0x63, 0xff, 0x07, 0x49, 0xdf, 0x95, 0xd4, 0x4f, 0xef, 0x6a, 0x0b, 0xb5, 0x78, 0xec, 0x69, 0x45, 0x6a, 0xa5, 0x40, 0x8a, 0xe3, 0x2c, 0x7a,
		0xf0, 0x8a, 0xd7, 0xba, 0x89, 0x21, 0x28, 0x7e, 0x3b, 0xbe, 0xe3, 0x1b, 0x76, 0x7b, 0xe0, 0x6a, 0x0e, 0x70, 0x5c, 0x86, 0x4a, 0x76, 0x91, 0x37, 0xdf, 0x28, 0x29, 0x22, 0x83, 0xea, 0x81, 0xa2,
		0x48, 0x02, 0x41, 0xb4, 0x4d, 0x99, 0x21, 0xcd, 0xbe, 0xc1, 0xbc, 0x28, 0xdc, 0x1f, 0xda, 0x11, 0x4b, 0xd8, 0xe5, 0x21, 0x7a, 0xc9, 0xd8, 0xeb, 0xaf, 0xa7, 0x20, 0xe9, 0xda, 0x4f, 0x9a, 0xce,
		0x23, 0x1c, 0xc9, 0x49, 0xe5, 0xb9, 0x6f, 0xe7, 0x6f, 0xfc, 0x21, 0x06, 0x3f, 0xdd, 0xc8, 0x3a, 0x6b, 0x86, 0x79, 0xc0, 0x0d, 0x35, 0xe0, 0x95, 0x76, 0xa8, 0x75, 0x30, 0x5b, 0xed, 0x5f, 0x36,
		0xed, 0x24, 0x2c, 0x89, 0x00, 0xdd, 0x1f, 0xa9, 0x65, 0xbc, 0x95, 0x0d, 0xfc, 0xe0, 0x9b, 0x13, 0x22, 0x63, 0xa1, 0xee, 0xf5, 0x2d, 0xd6, 0x88, 0x8c, 0x30, 0x9f, 0x5a, 0x7d, 0x71, 0x28, 0x26
	}
},
{
	// IEEE 1619 - Vector 13

	{ 0x27, 0x18, 0x28, 0x18, 0x28, 0x45, 0x90, 0x45, 0x23, 0x53, 0x60, 0x28, 0x74, 0x71, 0x35, 0x26, 0x62, 0x49, 0x77, 0x57, 0x24, 0x70, 0x93, 0x69, 0x99, 0x59, 0x57, 0x49, 0x66, 0x96, 0x76, 0x27 },
	{ 0x31, 0x41, 0x59, 0x26, 0x53, 0x58, 0x97, 0x93, 0x23, 0x84, 0x62, 0x64, 0x33, 0x83, 0x27, 0x95, 0x02, 0x88, 0x41, 0x97, 0x16, 0x93, 0x99, 0x37, 0x51, 0x05, 0x82, 0x09, 0x74, 0x94, 0x45, 0x92 },
	{ 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff },
	0,
	{
		0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
		0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
		0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
		0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
		0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
		0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
		0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
		0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
		0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
		0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
		0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
		0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
		0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
		0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
		0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
		0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
	},
	{
		0xbf, 0x53, 0xd2, 0xda, 0xde, 0x78, 0xe8, 0x22, 0xa4, 0xd9, 0x49, 0xa9, 0xbc, 0x67, 0x66, 0xb0, 0x1b, 0x06, 0xa8, 0xef, 0x70, 0xd2, 0x67, 0x48, 0xc6, 0xa7, 0xfc, 0x36, 0xd8, 0x0a, 0xe4, 0xc5,
		0x52, 0x0f, 0x7c, 0x4a, 0xb0, 0xac, 0x85, 0x44, 0x42, 0x4f, 0xa4, 0x05, 0x16, 0x2f, 0xef, 0x5a, 0x6b, 0x7f, 0x22, 0x94, 0x98, 0x06, 0x36, 0x18, 0xd3, 0x9f, 0x00, 0x03, 0xcb, 0x5f, 0xb8, 0xd1,
		0xc8, 0x6b, 0x64, 0x34, 0x97, 0xda, 0x1f, 0xf9, 0x45, 0xc8, 0xd3, 0xbe, 0xde, 0xca, 0x4f, 0x47, 0x97, 0x02, 0xa7, 0xa7, 0x35, 0xf0, 0x43, 0xdd, 0xb1, 0xd6, 0xaa, 0xad, 0xe3, 0xc4, 0xa0, 0xac,
		0x7c, 0xa7, 0xf3, 0xfa, 0x52, 0x79, 0xbe, 0xf5, 0x6f, 0x82, 0xcd, 0x7a, 0x2f, 0x38, 0x67, 0x2e, 0x82, 0x48, 0x14, 0xe1, 0x07, 0x00, 0x30, 0x0a, 0x05, 0x5e, 0x16, 0x30, 0xb8, 0xf1, 0xcb, 0x0e,
		0x91, 0x9f, 0x5e, 0x94, 0x20, 0x10, 0xa4, 0x16, 0xe2, 0xbf, 0x48, 0xcb, 0x46, 0x99, 0x3d, 0x3c, 0xb6, 0xa5, 0x1c, 0x19, 0xba, 0xcf, 0x86, 0x47, 0x85, 0xa0, 0x0b, 0xc2, 0xec, 0xff, 0x15, 0xd3,
		0x50, 0x87, 0x5b, 0x24, 0x6e, 0xd5, 0x3e, 0x68, 0xbe, 0x6f, 0x55, 0xbd, 0x7e, 0x05, 0xcf, 0xc2, 0xb2, 0xed, 0x64, 0x32, 0x19, 0x8a, 0x64, 0x44, 0xb6, 0xd8, 0xc2, 0x47, 0xfa, 0xb9, 0x41, 0xf5,
		0x69, 0x76, 0x8b, 0x5c, 0x42, 0x93, 0x66, 0xf1, 0xd3, 0xf0, 0x0f, 0x03, 0x45, 0xb9, 0x61, 0x23, 0xd5, 0x62, 0x04, 0xc0, 0x1c, 0x63, 0xb2, 0x2c, 0xe7, 0x8b, 0xaf, 0x11, 0x6e, 0x52, 0x5e, 0xd9,
		0x0f, 0xde, 0xa3, 0x9f, 0xa4, 0x69, 0x49, 0x4d, 0x38, 0x66, 0xc3, 0x1e, 0x05, 0xf2, 0x95, 0xff, 0x21, 0xfe, 0xa8, 0xd4, 0xe6, 0xe1, 0x3d, 0x67, 0xe4, 0x7c, 0xe7, 0x22, 0xe9, 0x69, 0x8a, 0x1c,
		0x10, 0x48, 0xd6, 0x8e, 0xbc, 0xde, 0x76, 0xb8, 0x6f, 0xcf, 0x97, 0x6e, 0xab, 0x8a, 0xa9, 0x79, 0x02, 0x68, 0xb7, 0x06, 0x8e, 0x01, 0x7a, 0x8b, 0x9b, 0x74, 0x94, 0x09, 0x51, 0x4f, 0x10, 0x53,
		0x02, 0x7f, 0xd1, 0x6c, 0x37, 0x86, 0xea, 0x1b, 0xac, 0x5f, 0x15, 0xcb, 0x79, 0x71, 0x1e, 0xe2, 0xab, 0xe8, 0x2f, 0x5c, 0xf8, 0xb1, 0x3a, 0xe7, 0x30, 0x30, 0xef, 0x5b, 0x9e, 0x44, 0x57, 0xe7,
		0x5d, 0x13, 0x04, 0xf9, 0x88, 0xd6, 0x2d, 0xd6, 0xfc, 0x4b, 0x94, 0xed, 0x38, 0xba, 0x83, 0x1d, 0xa4, 0xb7, 0x63, 0x49, 0x71, 0xb6, 0xcd, 0x8e, 0xc3, 0x25, 0xd9, 0xc6, 0x1c, 0x00, 0xf1, 0xdf,
		0x73, 0x62, 0x7e, 0xd3, 0x74, 0x5a, 0x5e, 0x84, 0x89, 0xf3, 0xa9, 0x5c, 0x69, 0x63, 0x9c, 0x32, 0xcd, 0x6e, 0x1d, 0x53, 0x7a, 0x85, 0xf7, 0x5c, 0xc8, 0x44, 0x72, 0x6e, 0x8a, 0x72, 0xfc, 0x00,
		0x77, 0xad, 0x22, 0x00, 0x0f, 0x1d, 0x50, 0x78, 0xf6, 0xb8, 0x66, 0x31, 0x8c, 0x66, 0x8f, 0x1a, 0xd0, 0x3d, 0x5a, 0x5f, 0xce, 0xd5, 0x21, 0x9f, 0x2e, 0xab, 0xbd, 0x0a, 0xa5, 0xc0, 0xf4, 0x60,
		0xd1, 0x83, 0xf0, 0x44, 0x04, 0xa0, 0xd6, 0xf4, 0x69, 0x55, 0x8e, 0x81, 0xfa, 0xb2, 0x4a, 0x16, 0x79, 0x05, 0xab, 0x4c, 0x78, 0x78, 0x50, 0x2a, 0xd3, 0xe3, 0x8f, 0xdb, 0xe6, 0x2a, 0x41, 0x55,
		0x6c, 0xec, 0x37, 0x32, 0x57, 0x59, 0x53, 0x3c, 0xe8, 0xf2, 0x5f, 0x36, 0x7c, 0x87, 0xbb, 0x55, 0x78, 0xd6, 0x67, 0xae, 0x93, 0xf9, 0xe2, 0xfd, 0x99, 0xbc, 0xbc, 0x5f, 0x2f, 0xbb, 0xa8, 0x8c,
		0xf6, 0x51, 0x61, 0x39, 0x42, 0x0f, 0xcf, 0xf3, 0xb7, 0x36, 0x1d, 0x86, 0x32, 0x2c, 0x4b, 0xd8, 0x4c, 0x82, 0xf3, 0x35, 0xab, 0xb1, 0x52, 0xc4, 0xa9, 0x34, 0x11, 0x37, 0x3a, 0xaa, 0x82, 0x20
	}
},
{
	// IEEE 1619 - Vector 14

	/* This vector must always be the last one in XTS_vectors[] because TestSectorBufEncryption() relies on it. */

	{ 0x27, 0x18, 0x28, 0x18, 0x28, 0x45, 0x90, 0x45, 0x23, 0x53, 0x60, 0x28, 0x74, 0x71, 0x35, 0x26, 0x62, 0x49, 0x77, 0x57, 0x24, 0x70, 0x93, 0x69, 0x99, 0x59, 0x57, 0x49, 0x66, 0x96, 0x76, 0x27 },
	{ 0x31, 0x41, 0x59, 0x26, 0x53, 0x58, 0x97, 0x93, 0x23, 0x84, 0x62, 0x64, 0x33, 0x83, 0x27, 0x95, 0x02, 0x88, 0x41, 0x97, 0x16, 0x93, 0x99, 0x37, 0x51, 0x05, 0x82, 0x09, 0x74, 0x94, 0x45, 0x92 },
	{ 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff },
	0,
	{
		0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
		0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
		0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
		0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
		0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
		0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
		0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
		0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
		0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
		0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
		0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
		0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
		0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
		0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
		0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
		0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
	},
	{
		0x64, 0x49, 0x7e, 0x5a, 0x83, 0x1e, 0x4a, 0x93, 0x2c, 0x09, 0xbe, 0x3e, 0x53, 0x93, 0x37, 0x6d, 0xaa, 0x59, 0x95, 0x48, 0xb8, 0x16, 0x03, 0x1d, 0x22, 0x4b, 0xbf, 0x50, 0xa8, 0x18, 0xed, 0x23,
		0x50, 0xea, 0xe7, 0xe9, 0x60, 0x87, 0xc8, 0xa0, 0xdb, 0x51, 0xad, 0x29, 0x0b, 0xd0, 0x0c, 0x1a, 0xc1, 0x62, 0x08, 0x57, 0x63, 0x5b, 0xf2, 0x46, 0xc1, 0x76, 0xab, 0x46, 0x3b, 0xe3, 0x0b, 0x80,
		0x8d, 0xa5, 0x48, 0x08, 0x1a, 0xc8, 0x47, 0xb1, 0x58, 0xe1, 0x26, 0x4b, 0xe2, 0x5b, 0xb0, 0x91, 0x0b, 0xbc, 0x92, 0x64, 0x71, 0x08, 0x08, 0x94, 0x15, 0xd4, 0x5f, 0xab, 0x1b, 0x3d, 0x26, 0x04,
		0xe8, 0xa8, 0xef, 0xf1, 0xae, 0x40, 0x20, 0xcf, 0xa3, 0x99, 0x36, 0xb6, 0x68, 0x27, 0xb2, 0x3f, 0x37, 0x1b, 0x92, 0x20, 0x0b, 0xe9, 0x02, 0x51, 0xe6, 0xd7, 0x3c, 0x5f, 0x86, 0xde, 0x5f, 0xd4,
		0xa9, 0x50, 0x78, 0x19, 0x33, 0xd7, 0x9a, 0x28, 0x27, 0x2b, 0x78, 0x2a, 0x2e, 0xc3, 0x13, 0xef, 0xdf, 0xcc, 0x06, 0x28, 0xf4, 0x3d, 0x74, 0x4c, 0x2d, 0xc2, 0xff, 0x3d, 0xcb, 0x66, 0x99, 0x9b,
		0x50, 0xc7, 0xca, 0x89, 0x5b, 0x0c, 0x64, 0x79, 0x1e, 0xea, 0xa5, 0xf2, 0x94, 0x99, 0xfb, 0x1c, 0x02, 0x6f, 0x84, 0xce, 0x5b, 0x5c, 0x72, 0xba, 0x10, 0x83, 0xcd, 0xdb, 0x5c, 0xe4, 0x54, 0x34,
		0x63, 0x16, 0x65, 0xc3, 0x33, 0xb6, 0x0b, 0x11, 0x59, 0x3f, 0xb2, 0x53, 0xc5, 0x17, 0x9a, 0x2c, 0x8d, 0xb8, 0x13, 0x78, 0x2a, 0x00, 0x48, 0x56, 0xa1, 0x65, 0x30, 0x11, 0xe9, 0x3f, 0xb6, 0xd8,
		0x76, 0xc1, 0x83, 0x66, 0xdd, 0x86, 0x83, 0xf5, 0x34, 0x12, 0xc0, 0xc1, 0x80, 0xf9, 0xc8, 0x48, 0x59, 0x2d, 0x59, 0x3f, 0x86, 0x09, 0xca, 0x73, 0x63, 0x17, 0xd3, 0x56, 0xe1, 0x3e, 0x2b, 0xff,
		0x3a, 0x9f, 0x59, 0xcd, 0x9a, 0xeb, 0x19, 0xcd, 0x48, 0x25, 0x93, 0xd8, 0xc4, 0x61, 0x28, 0xbb, 0x32, 0x42, 0x3b, 0x37, 0xa9, 0xad, 0xfb, 0x48, 0x2b, 0x99, 0x45, 0x3f, 0xbe, 0x25, 0xa4, 0x1b,
		0xf6, 0xfe, 0xb4, 0xaa, 0x0b, 0xef, 0x5e, 0xd2, 0x4b, 0xf7, 0x3c, 0x76, 0x29, 0x78, 0x02, 0x54, 0x82, 0xc1, 0x31, 0x15, 0xe4, 0x01, 0x5a, 0xac, 0x99, 0x2e, 0x56, 0x13, 0xa3, 0xb5, 0xc2, 0xf6,
		0x85, 0xb8, 0x47, 0x95, 0xcb, 0x6e, 0x9b, 0x26, 0x56, 0xd8, 0xc8, 0x81, 0x57, 0xe5, 0x2c, 0x42, 0xf9, 0x78, 0xd8, 0x63, 0x4c, 0x43, 0xd0, 0x6f, 0xea, 0x92, 0x8f, 0x28, 0x22, 0xe4, 0x65, 0xaa,
		0x65, 0x76, 0xe9, 0xbf, 0x41, 0x93, 0x84, 0x50, 0x6c, 0xc3, 0xce, 0x3c, 0x54, 0xac, 0x1a, 0x6f, 0x67, 0xdc, 0x66, 0xf3, 0xb3, 0x01, 0x91, 0xe6, 0x98, 0x38, 0x0b, 0xc9, 0x99, 0xb0, 0x5a, 0xbc,
		0xe1, 0x9d, 0xc0, 0xc6, 0xdc, 0xc2, 0xdd, 0x00, 0x1e, 0xc5, 0x35, 0xba, 0x18, 0xde, 0xb2, 0xdf, 0x1a, 0x10, 0x10, 0x23, 0x10, 0x83, 0x18, 0xc7, 0x5d, 0xc9, 0x86, 0x11, 0xa0, 0x9d, 0xc4, 0x8a,
		0x0a, 0xcd, 0xec, 0x67, 0x6f, 0xab, 0xdf, 0x22, 0x2f, 0x07, 0xe0, 0x26, 0xf0, 0x59, 0xb6, 0x72, 0xb5, 0x6e, 0x5c, 0xbc, 0x8e, 0x1d, 0x21, 0xbb, 0xd8, 0x67, 0xdd, 0x92, 0x72, 0x12, 0x05, 0x46,
		0x81, 0xd7, 0x0e, 0xa7, 0x37, 0x13, 0x4c, 0xdf, 0xce, 0x93, 0xb6, 0xf8, 0x2a, 0xe2, 0x24, 0x23, 0x27, 0x4e, 0x58, 0xa0, 0x82, 0x1c, 0xc5, 0x50, 0x2e, 0x2d, 0x0a, 0xb4, 0x58, 0x5e, 0x94, 0xde,
		0x69, 0x75, 0xbe, 0x5e, 0x0b, 0x4e, 0xfc, 0xe5, 0x1c, 0xd3, 0xe7, 0x0c, 0x25, 0xa1, 0xfb, 0xbb, 0xd6, 0x09, 0xd2, 0x73, 0xad, 0x5b, 0x0d, 0x59, 0x63, 0x1c, 0x53, 0x1f, 0x6a, 0x0a, 0x57, 0xb9
	}
} };	// XTS_TEST XTS_vectors[]


BOOL XTSAesTest (PCRYPTO_INFO ci)
{
	unsigned __int8 p[ENCRYPTION_DATA_UNIT_SIZE];
	UINT64_STRUCT dataUnitNo;
	int i;

	for (i = 0; i < XTS_TEST_COUNT; i++)
	{
		ci->ea = EAGetByName (L"AES");
		if (ci->ea == 0)
			return FALSE;

		ci->mode = XTS;

		if (EAInit (ci->ea, XTS_vectors[i].key1, ci->ks) != ERR_SUCCESS)
			return FALSE;

		if (!EAInitMode (ci, XTS_vectors[i].key2))
			return FALSE;

		memcpy (p, XTS_vectors[i].plaintext, sizeof (p));

		dataUnitNo.Value = BE64 (*((unsigned __int64 *) XTS_vectors[i].dataUnitNo));

		EncryptBufferXTS (p, sizeof (p), &dataUnitNo, XTS_vectors[i].blockNo, (unsigned char *) (ci->ks), (unsigned char *) ci->ks2, AES);

		if (memcmp (XTS_vectors[i].ciphertext, p, sizeof (p)) != 0)
			return FALSE;
	}

	return TRUE;
}


// AES ECB test vectors FIPS-197

#define AES_TEST_COUNT 1

typedef struct {
	unsigned char key[32];
	unsigned char plaintext[16];
	unsigned char ciphertext[16];
	} AES_TEST;

AES_TEST aes_ecb_vectors[AES_TEST_COUNT] = {
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,
0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,

0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0xaa,0xbb,0xcc,0xdd,0xee,0xff,

0x8e,0xa2,0xb7,0xca,0x51,0x67,0x45,0xbf,0xea,0xfc,0x49,0x90,0x4b,0x49,0x60,0x89
};

// Serpent ECB test vectors

#define SERPENT_TEST_COUNT 1

typedef struct {
	unsigned char key[32];
	unsigned char plaintext[16];
	unsigned char ciphertext[16];
	} SERPENT_TEST;

SERPENT_TEST serpent_vectors[SERPENT_TEST_COUNT] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,

0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0xde, 0x26, 0x9f, 0xf8, 0x33, 0xe4, 0x32, 0xb8, 0x5b, 0x2e, 0x88, 0xd2, 0x70, 0x1c, 0xe7, 0x5c
};

// Twofish ECB test vectors

#define TWOFISH_TEST_COUNT 1

typedef struct {
	unsigned char key[32];
	unsigned char plaintext[16];
	unsigned char ciphertext[16];
	} TWOFISH_TEST;

TWOFISH_TEST twofish_vectors[TWOFISH_TEST_COUNT] = {
0xD4, 0x3B, 0xB7, 0x55, 0x6E, 0xA3, 0x2E, 0x46, 0xF2, 0xA2, 0x82, 0xB7, 0xD4, 0x5B, 0x4E, 0x0D,
0x57, 0xFF, 0x73, 0x9D, 0x4D, 0xC9, 0x2C, 0x1B, 0xD7, 0xFC, 0x01, 0x70, 0x0C, 0xC8, 0x21, 0x6F,

0x90, 0xAF, 0xE9, 0x1B, 0xB2, 0x88, 0x54, 0x4F, 0x2C, 0x32, 0xDC, 0x23, 0x9B, 0x26, 0x35, 0xE6,
0x6C, 0xB4, 0x56, 0x1C, 0x40, 0xBF, 0x0A, 0x97, 0x05, 0x93, 0x1C, 0xB6, 0xD4, 0x08, 0xE7, 0xFA
};

// Camellia ECB test vectors
#define CAMELLIA_TEST_COUNT 2

typedef struct {
	unsigned char key[32];
	unsigned char plaintext[16];
	unsigned char ciphertext[16];
	} CAMELLIA_TEST;

CAMELLIA_TEST camellia_vectors[CAMELLIA_TEST_COUNT] = {
{
	0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0xFE, 0xDC, 0xBA, 0x98,
	0x76, 0x54, 0x32, 0x10, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
	0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0x01, 0x23, 0x45, 0x67,
	0x89, 0xAB, 0xCD, 0xEF, 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
	0x9A, 0xCC, 0x23, 0x7D, 0xFF, 0x16, 0xD7, 0x6C, 0x20, 0xEF, 0x7C, 0x91,
	0x9E, 0x3A, 0x75, 0x09
},
{
	0x2B, 0xD6, 0x45, 0x9F, 0x82, 0xC5, 0xB3, 0x00, 0x95, 0x2C, 0x49, 0x10,
	0x48, 0x81, 0xFF, 0x48, 0x2B, 0xD6, 0x45, 0x9F, 0x82, 0xC5, 0xB3, 0x00,
	0x95, 0x2C, 0x49, 0x10, 0x48, 0x81, 0xFF, 0x48, 0xE6, 0x84, 0x42, 0x17,
	0x16, 0xFC, 0x0B, 0x01, 0xAE, 0xB5, 0xC6, 0x76, 0x51, 0x20, 0xF9, 0x5F,
	0xEA, 0x02, 0x47, 0x14, 0xAD, 0x5C, 0x4D, 0x84, 0xEA, 0x02, 0x47, 0x14,
	0xAD, 0x5C, 0x4D, 0x84
}
};

// Kuznyechik ECB test vectors
#define KUZNYECHIK_TEST_COUNT 4

typedef struct {
	unsigned char key[32];
	unsigned char plaintext[16];
	unsigned char ciphertext[16];
	} KUZNYECHIK_TEST;

KUZNYECHIK_TEST kuznyechik_vectors[KUZNYECHIK_TEST_COUNT] = {
{
	0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33,
	0x44, 0x55, 0x66, 0x77, 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
	0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0x11, 0x22, 0x33, 0x44, 
    0x55, 0x66, 0x77, 0x00, 0xFF, 0xEE, 0xDD, 0xCC,	0xBB, 0xAA, 0x99, 0x88,
    0x7F, 0x67, 0x9D, 0x90, 0xBE, 0xBC, 0x24, 0x30, 0x5A, 0x46, 0x8D, 0x42,
	0xB9, 0xD4, 0xED, 0xCD
},
{
	0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33,
	0x44, 0x55, 0x66, 0x77, 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
	0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0x00, 0x11, 0x22, 0x33, 
    0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB,	0xCC, 0xEE, 0xFF, 0x0A, 
    0xB4, 0x29, 0x91, 0x2C, 0x6E, 0x00, 0x32, 0xF9,	0x28, 0x54, 0x52, 0xD7, 
    0x67, 0x18, 0xD0, 0x8B
},
{
	0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33,
	0x44, 0x55, 0x66, 0x77, 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
	0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0x11, 0x22, 0x33, 0x44, 
    0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC,	0xEE, 0xFF, 0x0A, 0x00, 
    0xF0, 0xCA, 0x33, 0x54, 0x9D, 0x24, 0x7C, 0xEE,	0xF3, 0xF5, 0xA5, 0x31, 
    0x3B, 0xD4, 0xB1, 0x57
},
{
	0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33,
	0x44, 0x55, 0x66, 0x77, 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
	0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0x22, 0x33, 0x44, 0x55, 
    0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xEE,	0xFF, 0x0A, 0x00, 0x11, 
    0xD0, 0xB0, 0x9C, 0xCD, 0xE8, 0x30, 0xB9, 0xEB,	0x3A, 0x02, 0xC4, 0xC5, 
    0xAA, 0x8A, 0xDA, 0x98
}
};


/* Test vectors from FIPS 198a, RFC 4231, RFC 2104, RFC 2202, and other sources. */

char *hmac_sha256_test_keys[] =
{
	"\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b",
	"Jefe",
	"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa",
	"\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19",
	"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa",
	"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa",
};

char *hmac_sha256_test_data[] =
{
	"Hi There",
	"what do ya want for nothing?",
	"\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd",
	"\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd",
	"Test Using Larger Than Block-Size Key - Hash Key First",
	"This is a test using a larger than block-size key and a larger than block-size data. The key needs to be hashed before being used by the HMAC algorithm.",
};

char *hmac_sha256_test_vectors[] =
{
	"\xb0\x34\x4c\x61\xd8\xdb\x38\x53\x5c\xa8\xaf\xce\xaf\x0b\xf1\x2b\x88\x1d\xc2\x00\xc9\x83\x3d\xa7\x26\xe9\x37\x6c\x2e\x32\xcf\xf7",
	"\x5b\xdc\xc1\x46\xbf\x60\x75\x4e\x6a\x04\x24\x26\x08\x95\x75\xc7\x5a\x00\x3f\x08\x9d\x27\x39\x83\x9d\xec\x58\xb9\x64\xec\x38\x43",
	"\x77\x3e\xa9\x1e\x36\x80\x0e\x46\x85\x4d\xb8\xeb\xd0\x91\x81\xa7\x29\x59\x09\x8b\x3e\xf8\xc1\x22\xd9\x63\x55\x14\xce\xd5\x65\xfe",
	"\x82\x55\x8a\x38\x9a\x44\x3c\x0e\xa4\xcc\x81\x98\x99\xf2\x08\x3a\x85\xf0\xfa\xa3\xe5\x78\xf8\x07\x7a\x2e\x3f\xf4\x67\x29\x66\x5b",
	"\x60\xe4\x31\x59\x1e\xe0\xb6\x7f\x0d\x8a\x26\xaa\xcb\xf5\xb7\x7f\x8e\x0b\xc6\x21\x37\x28\xc5\x14\x05\x46\x04\x0f\x0e\xe3\x7f\x54",
	"\x9b\x09\xff\xa7\x1b\x94\x2f\xcb\x27\x63\x5f\xbc\xd5\xb0\xe9\x44\xbf\xdc\x63\x64\x4f\x07\x13\x93\x8a\x7f\x51\x53\x5c\x3a\x35\xe2",
};

char *hmac_sha512_test_keys[] =
{
	"\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b",
	"Jefe",
	"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa",
	"\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19",
	"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa",
	"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa",
};

char *hmac_sha512_test_data[] =
{
	"Hi There",
	"what do ya want for nothing?",
	"\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd",
	"\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd",
	"Test Using Larger Than Block-Size Key - Hash Key First",
	"This is a test using a larger than block-size key and a larger than block-size data. The key needs to be hashed before being used by the HMAC algorithm.",
};

char *hmac_sha512_test_vectors[] =
{
	"\x87\xaa\x7c\xde\xa5\xef\x61\x9d\x4f\xf0\xb4\x24\x1a\x1d\x6c\xb0\x23\x79\xf4\xe2\xce\x4e\xc2\x78\x7a\xd0\xb3\x05\x45\xe1\x7c\xde\xda\xa8\x33\xb7\xd6\xb8\xa7\x02\x03\x8b\x27\x4e\xae\xa3\xf4\xe4\xbe\x9d\x91\x4e\xeb\x61\xf1\x70\x2e\x69\x6c\x20\x3a\x12\x68\x54",
	"\x16\x4b\x7a\x7b\xfc\xf8\x19\xe2\xe3\x95\xfb\xe7\x3b\x56\xe0\xa3\x87\xbd\x64\x22\x2e\x83\x1f\xd6\x10\x27\x0c\xd7\xea\x25\x05\x54\x97\x58\xbf\x75\xc0\x5a\x99\x4a\x6d\x03\x4f\x65\xf8\xf0\xe6\xfd\xca\xea\xb1\xa3\x4d\x4a\x6b\x4b\x63\x6e\x07\x0a\x38\xbc\xe7\x37",
	"\xfa\x73\xb0\x08\x9d\x56\xa2\x84\xef\xb0\xf0\x75\x6c\x89\x0b\xe9\xb1\xb5\xdb\xdd\x8e\xe8\x1a\x36\x55\xf8\x3e\x33\xb2\x27\x9d\x39\xbf\x3e\x84\x82\x79\xa7\x22\xc8\x06\xb4\x85\xa4\x7e\x67\xc8\x07\xb9\x46\xa3\x37\xbe\xe8\x94\x26\x74\x27\x88\x59\xe1\x32\x92\xfb",
	"\xb0\xba\x46\x56\x37\x45\x8c\x69\x90\xe5\xa8\xc5\xf6\x1d\x4a\xf7\xe5\x76\xd9\x7f\xf9\x4b\x87\x2d\xe7\x6f\x80\x50\x36\x1e\xe3\xdb\xa9\x1c\xa5\xc1\x1a\xa2\x5e\xb4\xd6\x79\x27\x5c\xc5\x78\x80\x63\xa5\xf1\x97\x41\x12\x0c\x4f\x2d\xe2\xad\xeb\xeb\x10\xa2\x98\xdd",
	"\x80\xb2\x42\x63\xc7\xc1\xa3\xeb\xb7\x14\x93\xc1\xdd\x7b\xe8\xb4\x9b\x46\xd1\xf4\x1b\x4a\xee\xc1\x12\x1b\x01\x37\x83\xf8\xf3\x52\x6b\x56\xd0\x37\xe0\x5f\x25\x98\xbd\x0f\xd2\x21\x5d\x6a\x1e\x52\x95\xe6\x4f\x73\xf6\x3f\x0a\xec\x8b\x91\x5a\x98\x5d\x78\x65\x98",
	"\xe3\x7b\x6a\x77\x5d\xc8\x7d\xba\xa4\xdf\xa9\xf9\x6e\x5e\x3f\xfd\xde\xbd\x71\xf8\x86\x72\x89\x86\x5d\xf5\xa3\x2d\x20\xcd\xc9\x44\xb6\x02\x2c\xac\x3c\x49\x82\xb1\x0d\x5e\xeb\x55\xc3\xe4\xde\x15\x13\x46\x76\xfb\x6d\xe0\x44\x60\x65\xc9\x74\x40\xfa\x8c\x6a\x58",
};

char *hmac_blake2s_test_keys[] =
{
	"\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b",
	"Jefe",
	"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa",
	"\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19",
	"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa",
	"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa",
};

char *hmac_blake2s_test_data[] =
{
	"Hi There",
	"what do ya want for nothing?",
	"\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd",
	"\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd",
	"Test Using Larger Than Block-Size Key - Hash Key First",
	"This is a test using a larger than block-size key and a larger than block-size data. The key needs to be hashed before being used by the HMAC algorithm.",
};

char *hmac_blake2s_test_vectors[] =
{
	"\x65\xa8\xb7\xc5\xcc\x91\x36\xd4\x24\xe8\x2c\x37\xe2\x70\x7e\x74\xe9\x13\xc0\x65\x5b\x99\xc7\x5f\x40\xed\xf3\x87\x45\x3a\x32\x60",
	"\x90\xb6\x28\x1e\x2f\x30\x38\xc9\x05\x6a\xf0\xb4\xa7\xe7\x63\xca\xe6\xfe\x5d\x9e\xb4\x38\x6a\x0e\xc9\x52\x37\x89\x0c\x10\x4f\xf0",
	"\xfc\xc4\xf5\x95\x29\x50\x2e\x34\xc3\xd8\xda\x3f\xfd\xab\x82\x96\x6a\x2c\xb6\x37\xff\x5e\x9b\xd7\x01\x13\x5c\x2e\x94\x69\xe7\x90",
	"\x46\x44\x34\xdc\xbe\xce\x09\x5d\x45\x6a\x1d\x62\xd6\xec\x56\xf8\x98\xe6\x25\xa3\x9e\x5c\x52\xbd\xf9\x4d\xaf\x11\x1b\xad\x83\xaa",
	"\xd2\x3d\x79\x39\x4f\x53\xd5\x36\xa0\x96\xe6\x51\x44\x47\xee\xaa\xbb\x05\xde\xd0\x1b\xe3\x2c\x19\x37\xda\x6a\x8f\x71\x03\xbc\x4e",
	"\xcb\x60\xf6\xa7\x91\xf1\x40\xbf\x8a\xa2\xe5\x1f\xf3\x58\xcd\xb2\xcc\x5c\x03\x33\x04\x5b\x7f\xb7\x7a\xba\x7a\xb3\xb0\xcf\xb2\x37",
};

char *hmac_whirlpool_test_key =
{
	"\x00\x11\x22\x33\x44\x55\x66\x77\x88\x99\xAA\xBB\xCC\xDD\xEE\xFF\x01\x23\x45\x67\x89\xAB\xCD\xEF\x00\x11\x22\x33\x44\x55\x66\x77\x88\x99\xAA\xBB\xCC\xDD\xEE\xFF\x01\x23\x45\x67\x89\xAB\xCD\xEF\x00\x11\x22\x33\x44\x55\x66\x77\x88\x99\xAA\xBB\xCC\xDD\xEE\xFF"
};

char *hmac_whirlpool_test_data =
{
	"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
};

char *hmac_whirlpool_test_vectors =
{
	"\x03\x91\xd2\x80\x00\xb6\x62\xbb\xb8\xe6\x23\x3e\xe8\x6c\xf2\xb2\x84\x74\x4c\x73"
	"\x8b\x58\x00\xba\x28\x12\xed\x52\x6f\xe3\x15\x3a\xb1\xba\xe7\xe2\x36\xbe\x96\x54"
	"\x49\x3f\x19\xfa\xce\xa6\x44\x1f\x60\xf5\xf0\x18\x93\x09\x11\xa5\xe5\xce\xd8\xf2"
	"\x6a\xbf\xa4\x02"
};

typedef struct _HashTestVector
{
	const char* hexInput;
	const char* hexOutput;

} HashTestVector;

typedef int (__cdecl HashFunction) (unsigned char* input, unsigned long inputLen, unsigned char* output);

unsigned char HexCharToByte (char c)
{
   if (c >= ('0') && c <= ('9'))
      return c - ('0');
   else if (c >= ('A') && c <= ('F'))
      return c - ('A') + 10;
   else if (c >= ('a') && c <= ('f'))
      return c - ('a') + 10;
   else
      return 0xFF;
}

unsigned long HexStringToByteArray(const char* hexStr, unsigned char* pbData)
{
	unsigned long count = 0;
	while (*hexStr)
	{
		*pbData++ = (HexCharToByte(hexStr[0]) << 4) | HexCharToByte(hexStr[1]);
		hexStr += 2;
		count++;
	}
	return count;
}

BOOL RunHashTest (HashFunction fn, HashTestVector* vector, BOOL bUseSSE)
{
	CRYPTOPP_ALIGN_DATA (16) unsigned char input[256];
	unsigned char output[64];
	unsigned char digest[64];
	unsigned long i = 0, inputLen, outputLen, digestLen;
	BOOL bRet = TRUE;
#if defined (DEVICE_DRIVER) && !defined (_WIN64)
	KFLOATING_SAVE floatingPointState;
	NTSTATUS saveStatus = STATUS_INVALID_PARAMETER;
	if (bUseSSE)
		saveStatus = KeSaveFloatingPointState (&floatingPointState);
#endif
	while (vector[i].hexInput && vector[i].hexOutput)
	{
		inputLen = HexStringToByteArray (vector[i].hexInput, input);
		outputLen = HexStringToByteArray (vector[i].hexOutput, output);
		digestLen = fn (input, inputLen, digest);
		if ((digestLen != outputLen) || (0 != memcmp (digest, output, digestLen)))
		{
			bRet = FALSE;
			break;
		}
		i++;
	}

#if defined (DEVICE_DRIVER) && !defined (_WIN64)
	if (NT_SUCCESS (saveStatus))
		KeRestoreFloatingPointState (&floatingPointState);
#endif

	return bRet;
}


/* https://www.streebog.net/src/trunk/examples/ */
HashTestVector Streebog512TestVectors[] = {
	/* M1 */
	{"303132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839303132", 
	 "1b54d01a4af5b9d5cc3d86d68d285462b19abc2475222f35c085122be4ba1ffa00ad30f8767b3a82384c6574f024c311e2a481332b08ef7f41797891c1646f48"
	},
	/* M2 */
	{"d1e520e2e5f2f0e82c20d1f2f0e8e1eee6e820e2edf3f6e82c20e2e5fef2fa20f120eceef0ff20f1f2f0e5ebe0ece820ede020f5f0e0e1f0fbff20efebfaeafb20c8e3eef0e5e2fb",
	"1e88e62226bfca6f9994f1f2d51569e0daf8475a3b0fe61a5300eee46d961376035fe83549ada2b8620fcd7c496ce5b33f0cb9dddc2b6460143b03dabac9fb28"
	},
	/* M3 */
	{"",
	"8e945da209aa869f0455928529bcae4679e9873ab707b55315f56ceb98bef0a7362f715528356ee83cda5f2aac4c6ad2ba3a715c1bcd81cb8e9f90bf4c1c1a8a"
	},
	/* M4 */
	{"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
	"b0fd29ac1b0df441769ff3fdb8dc564df67721d6ac06fb28ceffb7bbaa7948c6c014ac999235b58cb26fb60fb112a145d7b4ade9ae566bf2611402c552d20db7"
	},
	{NULL, NULL}
};

/* https://github.com/openssl/openssl/blob/2d0b44126763f989a4cbffbffe9d0c7518158bb7/test/evptests.txt */
HashTestVector Blake2sTestVectors[] = {
	{"", 
	 "69217a3079908094e11121d042354a7c1f55b6482ca1a51e1b250dfd1ed0eef9"
	},
	{"61",
	"4a0d129873403037c2cd9b9048203687f6233fb6738956e0349bd4320fec3e90"
	},
	{"616263",
	"508c5e8c327c14e2e1a72ba34eeb452f37458b209ed63a294d999b4c86675982"
	},
	{"6d65737361676520646967657374",
	"fa10ab775acf89b7d3c8a6e823d586f6b67bdbac4ce207fe145b7d3ac25cd28c"
	},
	{"6162636465666768696a6b6c6d6e6f707172737475767778797a",
	"bdf88eb1f86a0cdf0e840ba88fa118508369df186c7355b4b16cf79fa2710a12"
	},
	{"4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a30313233343536373839",
	"c75439ea17e1de6fa4510c335dc3d3f343e6f9e1ce2773e25b4174f1df8b119b"
	},
	{"3132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930",
	"fdaedb290a0d5af9870864fec2e090200989dc9cd53a3c092129e8535e8b4f66"
	},
	{NULL, NULL}
};

unsigned char ks_tmp[MAX_EXPANDED_KEY];

void CipherInit2(int cipher, void* key, void* ks, int key_len)
{
	switch (cipher)
	{

	case AES:
		CipherInit(cipher,key,ks);
		break;

	case SERPENT:
		CipherInit(cipher,key,ks);
		break;

	case TWOFISH:
		CipherInit(cipher,key,ks);
		break;
		
	case CAMELLIA:
		CipherInit(cipher,key,ks);
		break;
	case KUZNYECHIK:
		CipherInit(cipher, key, ks);
		break;
	default:
		/* Unknown/wrong ID */
		TC_THROW_FATAL_EXCEPTION;
	}
}


BOOL TestSectorBufEncryption (PCRYPTO_INFO ci)
{
	unsigned char buf [ENCRYPTION_DATA_UNIT_SIZE * 4];
	unsigned int i;
	wchar_t name[64];
	unsigned __int32 crc;
	UINT64_STRUCT unitNo;
	uint32 nbrUnits;
	unsigned __int64 writeOffset;
	int testCase = 0;
	int nTestsPerformed = 0;

	static CRYPTOPP_ALIGN_DATA(16) unsigned char key1[] =
	{
		0x27, 0x18, 0x28, 0x18, 0x28, 0x45, 0x90, 0x45, 0x23, 0x53, 0x60, 0x28, 0x74, 0x71, 0x35, 0x26, 0x62, 0x49, 0x77, 0x57, 0x24, 0x70, 0x93, 0x69, 0x99, 0x59, 0x57, 0x49, 0x66, 0x96, 0x76, 0x27,
		0x31, 0x41, 0x59, 0x26, 0x53, 0x58, 0x97, 0x93, 0x23, 0x84, 0x62, 0x64, 0x33, 0x83, 0x27, 0x95, 0x02, 0x88, 0x41, 0x97, 0x16, 0x93, 0x99, 0x37, 0x51, 0x05, 0x82, 0x09, 0x74, 0x94, 0x45, 0x92,
		0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13
	};
	CRYPTOPP_ALIGN_DATA(16) unsigned __int8 key2[MASTER_KEYDATA_SIZE];


	/* Encryption/decryption of data units (typically, volume data sectors) */

	nbrUnits = sizeof (buf) / ENCRYPTION_DATA_UNIT_SIZE;

	ci->mode = XTS;	// we only implement XTS

	/* The buffer can accommodate 4 data units and we'll test 4 cases by "scrolling". The data unit 0xFFFFFFFFFF
	will "move" from the start of the buffer to its end. For a 512-byte data unit, the byte offset 562949953420800
	corresponds to the data unit 0xFFFFFFFFFF. */
	for (writeOffset = 562949953420800ULL;
		writeOffset > 562949953420800ULL - nbrUnits * ENCRYPTION_DATA_UNIT_SIZE;
		writeOffset -= ENCRYPTION_DATA_UNIT_SIZE)
	{
		unitNo.Value = writeOffset / ENCRYPTION_DATA_UNIT_SIZE;

		// Test all EAs that support this mode of operation
		for (ci->ea = EAGetFirst (); ci->ea != 0; ci->ea = EAGetNext (ci->ea))
		{
			if (!EAIsModeSupported (ci->ea, ci->mode))
				continue;

			EAGetName (name, ARRAYSIZE(name), ci->ea, 0);

			if (EAInit (ci->ea, key1, ci->ks) != ERR_SUCCESS)
				return FALSE;

			for (i = 0; i < sizeof (key2); i++)
				key2[i] = (unsigned char) i;

			memcpy (key2, XTS_vectors[XTS_TEST_COUNT-1].key2, sizeof (XTS_vectors[XTS_TEST_COUNT-1].key2));

			if (!EAInitMode (ci, key2))
				return FALSE;

#ifdef _WIN64
			if (IsRamEncryptionEnabled ())
				VcProtectKeys (ci, VcGetEncryptionID (ci));
#endif

			// Each data unit will contain the same plaintext
			for (i = 0; i < nbrUnits; i++)
			{
				memcpy ((unsigned char *) buf + i * ENCRYPTION_DATA_UNIT_SIZE,
					XTS_vectors[XTS_TEST_COUNT-1].plaintext,
					ENCRYPTION_DATA_UNIT_SIZE);
			}

			EncryptDataUnits (buf, &unitNo, nbrUnits, ci);

			crc = GetCrc32 (buf, sizeof (buf));

			if (wcscmp (name, L"AES") == 0)
			{
				// Verify the ciphertext of the "moving" data unit using the IEEE test vector #14
				if (memcmp (XTS_vectors[XTS_TEST_COUNT-1].ciphertext,
					(unsigned char *) buf + testCase * ENCRYPTION_DATA_UNIT_SIZE,
					ENCRYPTION_DATA_UNIT_SIZE) != 0)
				{
					return FALSE;
				}

				// CRC of all data units in the buffer for each test case
				switch (testCase)
				{
				case 0:
					if (crc != 0x888f2990)
						return FALSE;
					nTestsPerformed++;
					break;
				case 1:
					if (crc != 0xea28ea34)
						return FALSE;
					nTestsPerformed++;
					break;
				case 2:
					if (crc != 0xe058f5a2)
						return FALSE;
					nTestsPerformed++;
					break;
				case 3:
					if (crc != 0x10473dc9)
						return FALSE;
					nTestsPerformed++;
					break;
				}
			}
			else if (wcscmp (name, L"Serpent") == 0)
			{
				switch (testCase)
				{
				case 0:
					if (crc != 0x7edfecb3)
						return FALSE;
					nTestsPerformed++;
					break;
				case 1:
					if (crc != 0x357baaaa)
						return FALSE;
					nTestsPerformed++;
					break;
				case 2:
					if (crc != 0xc7b9fca5)
						return FALSE;
					nTestsPerformed++;
					break;
				case 3:
					if (crc != 0xb5263e0c)
						return FALSE;
					nTestsPerformed++;
					break;
				}
			}
			else if (wcscmp (name, L"Twofish") == 0)
			{
				switch (testCase)
				{
				case 0:
					if (crc != 0x91525124)
						return FALSE;
					nTestsPerformed++;
					break;
				case 1:
					if (crc != 0x2895cc47)
						return FALSE;
					nTestsPerformed++;
					break;
				case 2:
					if (crc != 0x6bee346d)
						return FALSE;
					nTestsPerformed++;
					break;
				case 3:
					if (crc != 0xb1c45759)
						return FALSE;
					nTestsPerformed++;
					break;
				}
			}
			else if (wcscmp (name, L"Camellia") == 0)
			{
				switch (testCase)
				{
				case 0:
					if (crc != 0x2436badb)
						return FALSE;
					nTestsPerformed++;
					break;
				case 1:
					if (crc != 0x247d2272)
						return FALSE;
					nTestsPerformed++;
					break;
				case 2:
					if (crc != 0x72b49cde)
						return FALSE;
					nTestsPerformed++;
					break;
				case 3:
					if (crc != 0xb838d2c1)
						return FALSE;
					nTestsPerformed++;
					break;
				}
			}
			else if (wcscmp (name, L"Kuznyechik") == 0)
			{
				switch (testCase)
				{
				case 0:
					if (crc != 0x6b86e72e)
						return FALSE;
					nTestsPerformed++;
					break;
				case 1:
					if (crc != 0xa4f8637d)
						return FALSE;
					nTestsPerformed++;
					break;
				case 2:
					if (crc != 0xfd83e76d)
						return FALSE;
					nTestsPerformed++;
					break;
				case 3:
					if (crc != 0xb24fc47b)
						return FALSE;
					nTestsPerformed++;
					break;
				}
			}            
			else if (wcscmp (name, L"AES-Twofish") == 0)
			{
				switch (testCase)
				{
				case 0:
					if (crc != 0x6cea7fa2)
						return FALSE;
					nTestsPerformed++;
					break;
				case 1:
					if (crc != 0x69052c4c)
						return FALSE;
					nTestsPerformed++;
					break;
				case 2:
					if (crc != 0x88db8de5)
						return FALSE;
					nTestsPerformed++;
					break;
				case 3:
					if (crc != 0xf16fd8c5)
						return FALSE;
					nTestsPerformed++;
					break;
				}
			}
			else if (wcscmp (name, L"AES-Twofish-Serpent") == 0)
			{
				switch (testCase)
				{
				case 0:
					if (crc != 0xa2d7d82a)
						return FALSE;
					nTestsPerformed++;
					break;
				case 1:
					if (crc != 0xdbf76412)
						return FALSE;
					nTestsPerformed++;
					break;
				case 2:
					if (crc != 0xdf0ea03e)
						return FALSE;
					nTestsPerformed++;
					break;
				case 3:
					if (crc != 0xdadedff7)
						return FALSE;
					nTestsPerformed++;
					break;
				}
			}
			else if (wcscmp (name, L"Serpent-AES") == 0)
			{
				switch (testCase)
				{
				case 0:
					if (crc != 0x6dd133b3)
						return FALSE;
					nTestsPerformed++;
					break;
				case 1:
					if (crc != 0x0e5717d2)
						return FALSE;
					nTestsPerformed++;
					break;
				case 2:
					if (crc != 0x39f83cd9)
						return FALSE;
					nTestsPerformed++;
					break;
				case 3:
					if (crc != 0x8a79fa2c)
						return FALSE;
					nTestsPerformed++;
					break;
				}
			}
			else if (wcscmp (name, L"Serpent-Twofish-AES") == 0)
			{
				switch (testCase)
				{
				case 0:
					if (crc != 0xe536daf8)
						return FALSE;
					nTestsPerformed++;
					break;
				case 1:
					if (crc != 0x3ae89e7f)
						return FALSE;
					nTestsPerformed++;
					break;
				case 2:
					if (crc != 0x2cc1301a)
						return FALSE;
					nTestsPerformed++;
					break;
				case 3:
					if (crc != 0xcac7bdc7)
						return FALSE;
					nTestsPerformed++;
					break;
				}
			}
			else if (wcscmp (name, L"Twofish-Serpent") == 0)
			{
				switch (testCase)
				{
				case 0:
					if (crc != 0x2686c859)
						return FALSE;
					nTestsPerformed++;
					break;
				case 1:
					if (crc != 0x8a201780)
						return FALSE;
					nTestsPerformed++;
					break;
				case 2:
					if (crc != 0x8dd13796)
						return FALSE;
					nTestsPerformed++;
					break;
				case 3:
					if (crc != 0xe95196cb)
						return FALSE;
					nTestsPerformed++;
					break;
				}
			}
			else if (wcscmp (name, L"Camellia-Kuznyechik") == 0)
			{
				switch (testCase)
				{
				case 0:
					if (crc != 0x4ea34e89)
						return FALSE;
					nTestsPerformed++;
					break;
				case 1:
					if (crc != 0xb3ad8559)
						return FALSE;
					nTestsPerformed++;
					break;
				case 2:
					if (crc != 0xde361313)
						return FALSE;
					nTestsPerformed++;
					break;
				case 3:
					if (crc != 0x519d2bf9)
						return FALSE;
					nTestsPerformed++;
					break;
				}
			}
			else if (wcscmp (name, L"Kuznyechik-Twofish") == 0)
			{
				switch (testCase)
				{
				case 0:
					if (crc != 0x748f8631)
						return FALSE;
					nTestsPerformed++;
					break;
				case 1:
					if (crc != 0x8a4b0888)
						return FALSE;
					nTestsPerformed++;
					break;
				case 2:
					if (crc != 0xe0310188)
						return FALSE;
					nTestsPerformed++;
					break;
				case 3:
					if (crc != 0xfc2b6b45)
						return FALSE;
					nTestsPerformed++;
					break;
				}
			}
			else if (wcscmp (name, L"Camellia-Serpent") == 0)
			{
				switch (testCase)
				{
				case 0:
					if (crc != 0x10569a42)
						return FALSE;
					nTestsPerformed++;
					break;
				case 1:
					if (crc != 0x4de95152)
						return FALSE;
					nTestsPerformed++;
					break;
				case 2:
					if (crc != 0xe17b5fe7)
						return FALSE;
					nTestsPerformed++;
					break;
				case 3:
					if (crc != 0xdbf993fa)
						return FALSE;
					nTestsPerformed++;
					break;
				}
			}
			else if (wcscmp (name, L"Kuznyechik-AES") == 0)
			{
				switch (testCase)
				{
				case 0:
					if (crc != 0xc479f95d)
						return FALSE;
					nTestsPerformed++;
					break;
				case 1:
					if (crc != 0x58eaf88d)
						return FALSE;
					nTestsPerformed++;
					break;
				case 2:
					if (crc != 0xbe300cc2)
						return FALSE;
					nTestsPerformed++;
					break;
				case 3:
					if (crc != 0x9b681c2e)
						return FALSE;
					nTestsPerformed++;
					break;
				}
			}
			else if (wcscmp (name, L"Kuznyechik-Serpent-Camellia") == 0)
			{
				switch (testCase)
				{
				case 0:
					if (crc != 0x9d8ac7ee)
						return FALSE;
					nTestsPerformed++;
					break;
				case 1:
					if (crc != 0x5d7d347f)
						return FALSE;
					nTestsPerformed++;
					break;
				case 2:
					if (crc != 0x884b62ee)
						return FALSE;
					nTestsPerformed++;
					break;
				case 3:
					if (crc != 0x5c6c3997)
						return FALSE;
					nTestsPerformed++;
					break;
				}
			}

			if (crc == 0x9f5edd58)
				return FALSE;

			DecryptDataUnits (buf, &unitNo, nbrUnits, ci);

			if (GetCrc32 (buf, sizeof (buf)) != 0x9f5edd58)
				return FALSE;

			nTestsPerformed++;
		}
		testCase++;
	}

	/* Encryption/decryption of a buffer (typically, a volume header) */

	nbrUnits = sizeof (buf) / ENCRYPTION_DATA_UNIT_SIZE;

	// Test all EAs that support this mode of operation
	for (ci->ea = EAGetFirst (); ci->ea != 0; ci->ea = EAGetNext (ci->ea))
	{
		if (!EAIsModeSupported (ci->ea, ci->mode))
			continue;

		EAGetName (name, ARRAYSIZE(name), ci->ea, 0);

		if (EAInit (ci->ea, key1, ci->ks) != ERR_SUCCESS)
			return FALSE;

		memcpy (key2, XTS_vectors[XTS_TEST_COUNT-1].key2, sizeof (XTS_vectors[XTS_TEST_COUNT-1].key2));

		if (!EAInitMode (ci, key2))
			return FALSE;

		// Each data unit will contain the same plaintext
		for (i = 0; i < nbrUnits; i++)
		{
			memcpy ((unsigned char *) buf + i * ENCRYPTION_DATA_UNIT_SIZE,
				XTS_vectors[XTS_TEST_COUNT-1].plaintext,
				ENCRYPTION_DATA_UNIT_SIZE);
		}

		EncryptBuffer (buf, sizeof (buf), ci);

		crc = GetCrc32 (buf, sizeof (buf));

		if (wcscmp (name, L"AES") == 0)
		{
			if (crc != 0x33b91fab)
				return FALSE;
			nTestsPerformed++;
		}
		else if (wcscmp (name, L"Serpent") == 0)
		{
			if (crc != 0x3494d480)
				return FALSE;
			nTestsPerformed++;
		}
		else if (wcscmp (name, L"Twofish") == 0)
		{
			if (crc != 0xc4d65b46)
				return FALSE;
			nTestsPerformed++;
		}
		else if (wcscmp (name, L"Camellia") == 0)
		{
			if (crc != 0x8176b223)
				return FALSE;
			nTestsPerformed++;
		}
		else if (wcscmp (name, L"Kuznyechik") == 0)
		{
			if (crc != 0xd6d39cdb)
				return FALSE;
			nTestsPerformed++;
		}
		else if (wcscmp (name, L"AES-Twofish") == 0)
		{
			if (crc != 0x14ce7385)
				return FALSE;
			nTestsPerformed++;
		}
		else if (wcscmp (name, L"AES-Twofish-Serpent") == 0)
		{
			if (crc != 0x0ec81bf7)
				return FALSE;
			nTestsPerformed++;
		}
		else if (wcscmp (name, L"Serpent-AES") == 0)
		{
			if (crc != 0x42f919ad)
				return FALSE;
			nTestsPerformed++;
		}
		else if (wcscmp (name, L"Serpent-Twofish-AES") == 0)
		{
			if (crc != 0x208d5c58)
				return FALSE;
			nTestsPerformed++;
		}
		else if (wcscmp (name, L"Twofish-Serpent") == 0)
		{
			if (crc != 0xbe78cec1)
				return FALSE;
			nTestsPerformed++;
		}
		else if (wcscmp (name, L"Camellia-Kuznyechik") == 0)
		{
			if (crc != 0xe69d680d)
				return FALSE;
			nTestsPerformed++;
		}
		else if (wcscmp (name, L"Kuznyechik-Twofish") == 0)
		{
			if (crc != 0xe0aef0d1)
				return FALSE;
			nTestsPerformed++;
		}
		else if (wcscmp (name, L"Camellia-Serpent") == 0)
		{
			if (crc != 0x58aad727)
				return FALSE;
			nTestsPerformed++;
		}
		else if (wcscmp (name, L"Kuznyechik-AES") == 0)
		{
			if (crc != 0x4641234a)
				return FALSE;
			nTestsPerformed++;
		}
		else if (wcscmp (name, L"Kuznyechik-Serpent-Camellia") == 0)
		{
			if (crc != 0x755dad72)
				return FALSE;
			nTestsPerformed++;
		}

		if (crc == 0x9f5edd58)
			return FALSE;

		DecryptBuffer (buf, sizeof (buf), ci);

		if (GetCrc32 (buf, sizeof (buf)) != 0x9f5edd58)
			return FALSE;

		nTestsPerformed++;
	}
	return (nTestsPerformed == 150);
}

static BOOL DoAutoTestAlgorithms (void)
{
	PCRYPTO_INFO ci;
	CRYPTOPP_ALIGN_DATA(16) char key[32];
	unsigned char tmp[16];
	BOOL bFailed = FALSE;
	int i;

	ci = crypto_open ();
	if (!ci)
		return FALSE;

	memset (ci, 0, sizeof (*ci));

	/* AES */

	for (i = 0; i < AES_TEST_COUNT; i++)
	{
		int cipher = AES;
		memcpy(key, aes_ecb_vectors[i].key, 32);
		memcpy(tmp, aes_ecb_vectors[i].plaintext, 16);
		CipherInit(cipher, key, ks_tmp);

		EncipherBlock(cipher, tmp, ks_tmp);
		if (memcmp(aes_ecb_vectors[i].ciphertext, tmp, 16) != 0)
			break;

		DecipherBlock(cipher, tmp, ks_tmp);
		if (memcmp(aes_ecb_vectors[i].plaintext, tmp, 16) != 0)
			break;
	}
	if (i != AES_TEST_COUNT)
		bFailed = TRUE;

	// AES EncipherBlocks()/DecipherBlocks()
	{
		byte testData[1024];
		uint32 origCrc;
		size_t i;

		for (i = 0; i < sizeof (testData); ++i)
		{
			testData[i] = (byte) i;
		}

		origCrc = GetCrc32 (testData, sizeof (testData));

		CipherInit (AES, testData, ks_tmp);
		EncipherBlocks (AES, testData, ks_tmp, sizeof (testData) / CipherGetBlockSize (AES));

		if (GetCrc32 (testData, sizeof (testData)) != 0xb5cd5631)
			bFailed = TRUE;

		DecipherBlocks (AES, testData, ks_tmp, sizeof (testData) / CipherGetBlockSize (AES));

		if (origCrc != GetCrc32 (testData, sizeof (testData)))
			bFailed = TRUE;
	}

	/* Serpent */

	for (i = 0; i < SERPENT_TEST_COUNT; i++)
	{
		int cipher = SERPENT;
		memcpy(key, serpent_vectors[i].key, 32);
		memcpy(tmp, serpent_vectors[i].plaintext, 16);
		CipherInit(cipher, key, ks_tmp);

		EncipherBlock(cipher, tmp, ks_tmp);
		if (memcmp(serpent_vectors[i].ciphertext, tmp, 16) != 0)
			break;

		DecipherBlock(cipher, tmp, ks_tmp);
		if (memcmp(serpent_vectors[i].plaintext, tmp, 16) != 0)
			break;
	}
	if (i != SERPENT_TEST_COUNT)
		bFailed = TRUE;


	/* Twofish */

	for (i = 0; i < TWOFISH_TEST_COUNT; i++)
	{
		int cipher = TWOFISH;
		memcpy(key, twofish_vectors[i].key, 32);
		memcpy(tmp, twofish_vectors[i].plaintext, 16);
		CipherInit(cipher, key, ks_tmp);

		EncipherBlock(cipher, tmp, ks_tmp);
		if (memcmp(twofish_vectors[i].ciphertext, tmp, 16) != 0)
			break;

		DecipherBlock(cipher, tmp, ks_tmp);
		if (memcmp(twofish_vectors[i].plaintext, tmp, 16) != 0)
			break;
	}
	if (i != TWOFISH_TEST_COUNT)
		bFailed = TRUE;
	
	/* Camellia */

	for (i = 0; i < CAMELLIA_TEST_COUNT; i++)
	{
		int cipher = CAMELLIA;
		memcpy(key, camellia_vectors[i].key, 32);
		memcpy(tmp, camellia_vectors[i].plaintext, 16);
		CipherInit(cipher, key, ks_tmp);

		EncipherBlock(cipher, tmp, ks_tmp);
		if (memcmp(camellia_vectors[i].ciphertext, tmp, 16) != 0)
			break;

		DecipherBlock(cipher, tmp, ks_tmp);
		if (memcmp(camellia_vectors[i].plaintext, tmp, 16) != 0)
			break;
	}
	if (i != CAMELLIA_TEST_COUNT)
		bFailed = TRUE;

	/* Kuznyechik */

	for (i = 0; i < KUZNYECHIK_TEST_COUNT; i++)
	{
        int cipher = KUZNYECHIK;
        memcpy(key, kuznyechik_vectors[i].key, 32);
		memcpy(tmp, kuznyechik_vectors[i].plaintext, 16);
		CipherInit(cipher, key, ks_tmp);

		EncipherBlock(cipher, tmp, ks_tmp);
		if (memcmp(kuznyechik_vectors[i].ciphertext, tmp, 16) != 0)
			break;

		DecipherBlock(cipher, tmp, ks_tmp);
		if (memcmp(kuznyechik_vectors[i].plaintext, tmp, 16) != 0)
			break;
	}
	if (i != KUZNYECHIK_TEST_COUNT)
		bFailed = TRUE;

	/* PKCS #5 and HMACs */
	if (!test_pkcs5 ())
		bFailed = TRUE;

	/* CRC-32 */
	if (!crc32_selftests ())
		bFailed = TRUE;

	/* GF multiplicator */
#if 0
	if (!GfMulSelfTest ())
		bFailed = TRUE;
#endif

	/* XTS-AES */
	if (!XTSAesTest (ci))
		bFailed = TRUE;

	/* Sector and buffer related algorithms */
	if (!TestSectorBufEncryption (ci))
		bFailed = TRUE;

	crypto_close (ci);
	return !bFailed;
}


BOOL AutoTestAlgorithms (void)
{
	BOOL result = TRUE;
	BOOL hwEncryptionEnabled = IsHwEncryptionEnabled();
#if defined (_MSC_VER) && !defined (_UEFI)
	BOOL exceptionCatched = FALSE;
	__try
	{
#endif
		EnableHwEncryption (FALSE);

		if (!DoAutoTestAlgorithms())
			result = FALSE;

		EnableHwEncryption (TRUE);

		if (!DoAutoTestAlgorithms())
			result = FALSE;

		EnableHwEncryption (hwEncryptionEnabled);
#if defined (_MSC_VER) && !defined (_UEFI)
	}
    __except (EXCEPTION_EXECUTE_HANDLER)
	{
		exceptionCatched = TRUE;
	}

	if (exceptionCatched)
	{
		/* unexepected exception raised. Disable all CPU extended feature and try again */
		EnableHwEncryption (hwEncryptionEnabled);
		DisableCPUExtendedFeatures ();
		__try
		{
			result = DoAutoTestAlgorithms();
		}
	    __except (EXCEPTION_EXECUTE_HANDLER)
		{
			/* exception still occuring. Report failure. */
			result = FALSE;
		}
	}
#endif
	return result;
}

BOOL test_hmac_sha256 ()
{
	unsigned int i;
	int nTestsPerformed = 0;

	for (i = 0; i < sizeof (hmac_sha256_test_data) / sizeof(char *); i++)
	{
		char digest[1024]; /* large enough to hold digets and test vector inputs */
		size_t dataLen = strlen (hmac_sha256_test_data[i]);
		if (dataLen <= sizeof(digest))
		{
			memcpy (digest, hmac_sha256_test_data[i], dataLen);
			hmac_sha256 (hmac_sha256_test_keys[i], (int) strlen (hmac_sha256_test_keys[i]), digest, (int) dataLen);
			if (memcmp (digest, hmac_sha256_test_vectors[i], SHA256_DIGESTSIZE) != 0)
				return FALSE;
			else
				nTestsPerformed++;
		}
		else
		{
			return FALSE;
		}
	}

	return (nTestsPerformed == 6);
}

BOOL test_hmac_sha512 ()
{
	unsigned int i;
	int nTestsPerformed = 0;

	for (i = 0; i < sizeof (hmac_sha512_test_data) / sizeof(char *); i++)
	{
		char digest[1024]; /* large enough to hold digets and test vector inputs */
		size_t dataLen = strlen (hmac_sha512_test_data[i]);
		if (dataLen <= sizeof(digest))
		{
			memcpy (digest, hmac_sha512_test_data[i], dataLen );
			hmac_sha512 (hmac_sha512_test_keys[i], (int) strlen (hmac_sha512_test_keys[i]), digest, (int) dataLen);
			if (memcmp (digest, hmac_sha512_test_vectors[i], SHA512_DIGESTSIZE) != 0)
				return FALSE;
			else
				nTestsPerformed++;
		}
		else
		{
			return FALSE;
		}
	}

	return (nTestsPerformed == 6);
}

BOOL test_hmac_blake2s ()
{
	unsigned int i;
	int nTestsPerformed = 0;

	for (i = 0; i < sizeof (hmac_blake2s_test_data) / sizeof(char *); i++)
	{
		char digest[1024]; /* large enough to hold digets and test vector inputs */
		size_t dataLen = strlen (hmac_blake2s_test_data[i]);
		if (dataLen <= sizeof(digest))
		{
			memcpy (digest, hmac_blake2s_test_data[i], dataLen);
			hmac_blake2s (hmac_blake2s_test_keys[i], (int) strlen (hmac_blake2s_test_keys[i]), digest, (int) dataLen);
			if (memcmp (digest, hmac_blake2s_test_vectors[i], BLAKE2S_DIGESTSIZE) != 0)
				return FALSE;
			else
				nTestsPerformed++;
		}
		else
		{
			return FALSE;
		}
	}

	return (nTestsPerformed == 6);
}

int __cdecl Blake2sHash (unsigned char* input, unsigned long inputLen, unsigned char* output)
{
	blake2s(output, input, (size_t) inputLen);
	return BLAKE2S_DIGESTSIZE;
}

BOOL test_hmac_whirlpool ()
{
	unsigned char digest[1024]; /* large enough to hold digets and test vector inputs */

	memcpy (digest, hmac_whirlpool_test_data, strlen (hmac_whirlpool_test_data));
	hmac_whirlpool (hmac_whirlpool_test_key, 64, digest, (int) strlen (hmac_whirlpool_test_data));
	if (memcmp (digest, hmac_whirlpool_test_vectors, WHIRLPOOL_DIGESTSIZE) != 0)
		return FALSE;

	return TRUE;
}

/* http://www.tc26.ru/methods/recommendation/%D0%A2%D0%9A26%D0%90%D0%9B%D0%93.pdf */
/* https://tools.ietf.org/html/draft-smyshlyaev-gost-usage-00 */
/* https://datatracker.ietf.org/doc/rfc7836/?include_text=1 */
static const unsigned char gost3411_2012_hmac_k1[] = {
	0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
	0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
	0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
	0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f
};
static const unsigned char gost3411_2012_hmac_m1[] = {
	0x01, 0x26, 0xbd, 0xb8, 0x78, 0x00, 0xaf, 0x21,
	0x43, 0x41, 0x45, 0x65, 0x63, 0x78, 0x01, 0x00
};
static const unsigned char gost3411_2012_hmac_r1[] = {
	0xA5, 0x9B, 0xAB, 0x22, 0xEC, 0xAE, 0x19, 0xC6, 0x5F, 0xBD, 0xE6, 0xE5,
	0xF4, 0xE9, 0xF5, 0xD8, 0x54, 0x9D, 0x31, 0xF0, 0x37, 0xF9, 0xDF, 0x9B,
	0x90, 0x55, 0x00, 0xE1, 0x71, 0x92, 0x3A, 0x77, 0x3D, 0x5F, 0x15, 0x30,
	0xF2, 0xED, 0x7E, 0x96, 0x4C, 0xB2, 0xEE, 0xDC, 0x29, 0xE9, 0xAD, 0x2F,
	0x3A, 0xFE, 0x93, 0xB2, 0x81, 0x4F, 0x79, 0xF5, 0x00, 0x0F, 0xFC, 0x03,
	0x66, 0xC2, 0x51, 0xE6
};


BOOL test_hmac_streebog ()
{
	CRYPTOPP_ALIGN_DATA(16) char digest[64]; /* large enough to hold digets and test vector inputs */

	memcpy (digest, gost3411_2012_hmac_m1, sizeof (gost3411_2012_hmac_m1));
	hmac_streebog ((char*) gost3411_2012_hmac_k1, sizeof(gost3411_2012_hmac_k1), digest, (int) sizeof (gost3411_2012_hmac_m1));
	if (memcmp (digest, gost3411_2012_hmac_r1, STREEBOG_DIGESTSIZE) != 0)
		return FALSE;

	return TRUE;
}

int __cdecl StreebogHash (unsigned char* input, unsigned long inputLen, unsigned char* output)
{
	STREEBOG_CTX ctx;
	STREEBOG_init (&ctx);
	STREEBOG_add (&ctx, input, inputLen);
	STREEBOG_finalize (&ctx, output);
	return STREEBOG_DIGESTSIZE;
}

BOOL test_pkcs5 ()
{
	char dk[144];

	/* HMAC-SHA-256 tests */
	if (!test_hmac_sha256())
		return FALSE;

	/* HMAC-SHA-512 tests */
	if (!test_hmac_sha512())
		return FALSE;

	/* HMAC-BLAKE2s tests */
	if (test_hmac_blake2s() == FALSE)
		return FALSE;

	/* Blake2s hash tests */
	if (RunHashTest (Blake2sHash, Blake2sTestVectors, (HasSSE2())? TRUE : FALSE) == FALSE)
		return FALSE;

	/* HMAC-Whirlpool tests */
	if (test_hmac_whirlpool() == FALSE)
		return FALSE;

	/* HMAC-STREEBOG tests */
	if (test_hmac_streebog() == FALSE)
		return FALSE;

	/* STREEBOG hash tests */
	if (RunHashTest (StreebogHash, Streebog512TestVectors, (HasSSE2() || HasSSE41())? TRUE : FALSE) == FALSE)
		return FALSE;

	/* PKCS-5 test 1 with HMAC-SHA-256 used as the PRF (https://tools.ietf.org/html/draft-josefsson-scrypt-kdf-00) */
	derive_key_sha256 ("passwd", 6, "\x73\x61\x6C\x74", 4, 1, dk, 64);
	if (memcmp (dk, "\x55\xac\x04\x6e\x56\xe3\x08\x9f\xec\x16\x91\xc2\x25\x44\xb6\x05\xf9\x41\x85\x21\x6d\xde\x04\x65\xe6\x8b\x9d\x57\xc2\x0d\xac\xbc\x49\xca\x9c\xcc\xf1\x79\xb6\x45\x99\x16\x64\xb3\x9d\x77\xef\x31\x7c\x71\xb8\x45\xb1\xe3\x0b\xd5\x09\x11\x20\x41\xd3\xa1\x97\x83", 64) != 0)
		return FALSE;

	/* PKCS-5 test 2 with HMAC-SHA-256 used as the PRF (https://stackoverflow.com/questions/5130513/pbkdf2-hmac-sha2-test-vectors) */
	derive_key_sha256 ("password", 8, "\x73\x61\x6C\x74", 4, 2, dk, 32);
	if (memcmp (dk, "\xae\x4d\x0c\x95\xaf\x6b\x46\xd3\x2d\x0a\xdf\xf9\x28\xf0\x6d\xd0\x2a\x30\x3f\x8e\xf3\xc2\x51\xdf\xd6\xe2\xd8\x5a\x95\x47\x4c\x43", 32) != 0)
		return FALSE;

	/* PKCS-5 test 3 with HMAC-SHA-256 used as the PRF (MS CryptoAPI) */
	derive_key_sha256 ("password", 8, "\x12\x34\x56\x78", 4, 5, dk, 4);
	if (memcmp (dk, "\xf2\xa0\x4f\xb2", 4) != 0)
		return FALSE;

	/* PKCS-5 test 4 with HMAC-SHA-256 used as the PRF (MS CryptoAPI) */
	derive_key_sha256 ("password", 8, "\x12\x34\x56\x78", 4, 5, dk, 144);
	if (memcmp (dk, "\xf2\xa0\x4f\xb2\xd3\xe9\xa5\xd8\x51\x0b\x5c\x06\xdf\x70\x8e\x24\xe9\xc7\xd9\x15\x3d\x22\xcd\xde\xb8\xa6\xdb\xfd\x71\x85\xc6\x99\x32\xc0\xee\x37\x27\xf7\x24\xcf\xea\xa6\xac\x73\xa1\x4c\x4e\x52\x9b\x94\xf3\x54\x06\xfc\x04\x65\xa1\x0a\x24\xfe\xf0\x98\x1d\xa6\x22\x28\xeb\x24\x55\x74\xce\x6a\x3a\x28\xe2\x04\x3a\x59\x13\xec\x3f\xf2\xdb\xcf\x58\xdd\x53\xd9\xf9\x17\xf6\xda\x74\x06\x3c\x0b\x66\xf5\x0f\xf5\x58\xa3\x27\x52\x8c\x5b\x07\x91\xd0\x81\xeb\xb6\xbc\x30\x69\x42\x71\xf2\xd7\x18\x42\xbe\xe8\x02\x93\x70\x66\xad\x35\x65\xbc\xf7\x96\x8e\x64\xf1\xc6\x92\xda\xe0\xdc\x1f\xb5\xf4", 144) != 0)
		return FALSE;

	/* PKCS-5 test 1 with HMAC-SHA-512 used as the PRF */
	derive_key_sha512 ("password", 8, "\x12\x34\x56\x78", 4, 5, dk, 4);
	if (memcmp (dk, "\x13\x64\xae\xf8", 4) != 0)
		return FALSE;

	/* PKCS-5 test 2 with HMAC-SHA-512 used as the PRF (derives a key longer than the underlying
	hash output size and block size) */
	derive_key_sha512 ("password", 8, "\x12\x34\x56\x78", 4, 5, dk, 144);
	if (memcmp (dk, "\x13\x64\xae\xf8\x0d\xf5\x57\x6c\x30\xd5\x71\x4c\xa7\x75\x3f\xfd\x00\xe5\x25\x8b\x39\xc7\x44\x7f\xce\x23\x3d\x08\x75\xe0\x2f\x48\xd6\x30\xd7\x00\xb6\x24\xdb\xe0\x5a\xd7\x47\xef\x52\xca\xa6\x34\x83\x47\xe5\xcb\xe9\x87\xf1\x20\x59\x6a\xe6\xa9\xcf\x51\x78\xc6\xb6\x23\xa6\x74\x0d\xe8\x91\xbe\x1a\xd0\x28\xcc\xce\x16\x98\x9a\xbe\xfb\xdc\x78\xc9\xe1\x7d\x72\x67\xce\xe1\x61\x56\x5f\x96\x68\xe6\xe1\xdd\xf4\xbf\x1b\x80\xe0\x19\x1c\xf4\xc4\xd3\xdd\xd5\xd5\x57\x2d\x83\xc7\xa3\x37\x87\xf4\x4e\xe0\xf6\xd8\x6d\x65\xdc\xa0\x52\xa3\x13\xbe\x81\xfc\x30\xbe\x7d\x69\x58\x34\xb6\xdd\x41\xc6", 144) != 0)
		return FALSE;

	/* PKCS-5 test 1 with HMAC-BLAKE2s used as the PRF */
	derive_key_blake2s ("password", 8, "\x12\x34\x56\x78", 4, 5, dk, 4);
	if (memcmp (dk, "\x8d\x51\xfa\x31", 4) != 0)
		return FALSE;

	/* PKCS-5 test 2 with HMAC-BLAKE2s used as the PRF (derives a key longer than the underlying hash) */
	derive_key_blake2s ("password", 8, "\x12\x34\x56\x78", 4, 5, dk, 48);
	if (memcmp (dk, "\x8d\x51\xfa\x31\x46\x25\x37\x67\xa3\x29\x6b\x3c\x6b\xc1\x5d\xb2\xee\xe1\x6c\x28\x00\x26\xea\x08\x65\x9c\x12\xf1\x07\xde\x0d\xb9\x9b\x4f\x39\xfa\xc6\x80\x26\xb1\x8f\x8e\x48\x89\x85\x2d\x24\x2d", 48) != 0)
		return FALSE;

	/* PKCS-5 test 1 with HMAC-Whirlpool used as the PRF */
	derive_key_whirlpool ("password", 8, "\x12\x34\x56\x78", 4, 5, dk, 4);
	if (memcmp (dk, "\x50\x7c\x36\x6f", 4) != 0)
		return FALSE;

	/* PKCS-5 test 2 with HMAC-Whirlpool used as the PRF (derives a key longer than the underlying hash) */
	derive_key_whirlpool ("password", 8, "\x12\x34\x56\x78", 4, 5, dk, 96);
	if (memcmp (dk, "\x50\x7c\x36\x6f\xee\x10\x2e\x9a\xe2\x8a\xd5\x82\x72\x7d\x27\x0f\xe8\x4d\x7f\x68\x7a\xcf\xb5\xe7\x43\x67\xaa\x98\x93\x52\x2b\x09\x6e\x42\xdf\x2c\x59\x4a\x91\x6d\x7e\x10\xae\xb2\x1a\x89\x8f\xb9\x8f\xe6\x31\xa9\xd8\x9f\x98\x26\xf4\xda\xcd\x7d\x65\x65\xde\x10\x95\x91\xb4\x84\x26\xae\x43\xa1\x00\x5b\x1e\xb8\x38\x97\xa4\x1e\x4b\xd2\x65\x64\xbc\xfa\x1f\x35\x85\xdb\x4f\x97\x65\x6f\xbd\x24", 96) != 0)
		return FALSE;

	/* PKCS-5 test 1 with HMAC-STREEBOG used as the PRF */
	derive_key_streebog ("password", 8, "\x12\x34\x56\x78", 4, 5, dk, 4);
	if (memcmp (dk, "\xd0\x53\xa2\x30", 4) != 0)
		return FALSE;

	/* PKCS-5 test 2 with HMAC-STREEBOG used as the PRF (derives a key longer than the underlying hash) */
	derive_key_streebog ("password", 8, "\x12\x34\x56\x78", 4, 5, dk, 96);
	if (memcmp (dk, "\xd0\x53\xa2\x30\x6f\x45\x81\xeb\xbc\x06\x81\xc5\xe7\x53\xa8\x5d\xc7\xf1\x23\x33\x1e\xbe\x64\x2c\x3b\x0f\x26\xd7\x00\xe1\x95\xc9\x65\x26\xb1\x85\xbe\x1e\xe2\xf4\x9b\xfc\x6b\x14\x84\xda\x24\x61\xa0\x1b\x9e\x79\x5c\xee\x69\x6e\xf9\x25\xb1\x1d\xca\xa0\x31\xba\x02\x6f\x9e\x99\x0f\xdb\x25\x01\x5b\xf1\xc7\x10\x19\x53\x3b\x29\x3f\x18\x00\xd6\xfc\x85\x03\xdc\xf2\xe5\xe9\x5a\xb1\x1e\x61\xde", 96) != 0)
		return FALSE;

	return TRUE;
}
span> CRYPT_PROVIDER_SGNR* (WINAPI *WTHELPERGETPROVSIGNERFROMCHAIN)(CRYPT_PROVIDER_DATA *pProvData, DWORD idxSigner, BOOL fCounterSigner, DWORD idxCounterSigner); typedef CRYPT_PROVIDER_CERT* (WINAPI *WTHELPERGETPROVCERTFROMCHAIN)(CRYPT_PROVIDER_SGNR *pSgnr, DWORD idxCert); static WINVERIFYTRUST WinVerifyTrustFn = NULL; static WTHELPERPROVDATAFROMSTATEDATA WTHelperProvDataFromStateDataFn = NULL; static WTHELPERGETPROVSIGNERFROMCHAIN WTHelperGetProvSignerFromChainFn = NULL; static WTHELPERGETPROVCERTFROMCHAIN WTHelperGetProvCertFromChainFn = NULL; static unsigned char gpbSha1CodeSignCertFingerprint[64] = { 0x64, 0x4C, 0x59, 0x15, 0xC5, 0xD4, 0x31, 0x2A, 0x73, 0x12, 0xC4, 0xA6, 0xF2, 0x2C, 0xE8, 0x7E, 0xA8, 0x05, 0x53, 0xB5, 0x99, 0x9A, 0xF5, 0xD1, 0xBE, 0x57, 0x56, 0x3D, 0x2F, 0xCA, 0x0B, 0x2F, 0xEF, 0x57, 0xFB, 0xA0, 0x03, 0xEF, 0x66, 0x4D, 0xBF, 0xEE, 0x25, 0xBC, 0x22, 0xDD, 0x5C, 0x15, 0x47, 0xD6, 0x6F, 0x57, 0x94, 0xBB, 0x65, 0xBC, 0x5C, 0xAA, 0xE8, 0x80, 0xFB, 0xD0, 0xEF, 0x00 }; typedef HRESULT (WINAPI *SHGETKNOWNFOLDERPATH) ( _In_ REFKNOWNFOLDERID rfid, _In_ DWORD dwFlags, _In_opt_ HANDLE hToken, _Out_ PWSTR *ppszPath ); /* Windows dialog class */ #define WINDOWS_DIALOG_CLASS L"#32770" /* Custom class names */ #define TC_DLG_CLASS L"VeraCryptCustomDlg" #define TC_SPLASH_CLASS L"VeraCryptSplashDlg" /* constant used by ChangeWindowMessageFilter calls */ #ifndef MSGFLT_ADD #define MSGFLT_ADD 1 #endif /* undocumented message sent during drag-n-drop */ #ifndef WM_COPYGLOBALDATA #define WM_COPYGLOBALDATA 0x0049 #endif /* Benchmarks */ #ifndef SETUP #define BENCHMARK_MAX_ITEMS 100 #define BENCHMARK_DEFAULT_BUF_SIZE BYTES_PER_MB #define HASH_FNC_BENCHMARKS FALSE // For development purposes only. Must be FALSE when building a public release. #define PKCS5_BENCHMARKS FALSE // For development purposes only. Must be FALSE when building a public release. #if PKCS5_BENCHMARKS && HASH_FNC_BENCHMARKS #error PKCS5_BENCHMARKS and HASH_FNC_BENCHMARKS are both TRUE (at least one of them should be FALSE). #endif enum { BENCHMARK_TYPE_ENCRYPTION = 0, BENCHMARK_TYPE_PRF, BENCHMARK_TYPE_HASH }; enum { BENCHMARK_SORT_BY_NAME = 0, BENCHMARK_SORT_BY_SPEED }; typedef struct { int id; wchar_t name[100]; unsigned __int64 encSpeed; unsigned __int64 decSpeed; unsigned __int64 meanBytesPerSec; } BENCHMARK_REC; BENCHMARK_REC benchmarkTable [BENCHMARK_MAX_ITEMS]; int benchmarkTotalItems = 0; int benchmarkBufferSize = BENCHMARK_DEFAULT_BUF_SIZE; int benchmarkLastBufferSize = BENCHMARK_DEFAULT_BUF_SIZE; int benchmarkSortMethod = BENCHMARK_SORT_BY_SPEED; LARGE_INTEGER benchmarkPerformanceFrequency; int benchmarkType = BENCHMARK_TYPE_ENCRYPTION; int benchmarkPim = -1; BOOL benchmarkPreBoot = FALSE; BOOL benchmarkGPT = FALSE; #endif // #ifndef SETUP typedef struct { void *strings; BOOL bold; } MULTI_CHOICE_DLGPROC_PARAMS; void InitGlobalLocks () { InitializeCriticalSection (&csWNetCalls); InitializeCriticalSection (&csMountableDevices); InitializeCriticalSection (&csVolumeIdCandidates); InitializeCriticalSection (&csSecureDesktop); } void FinalizeGlobalLocks () { DeleteCriticalSection (&csWNetCalls); DeleteCriticalSection (&csMountableDevices); DeleteCriticalSection (&csVolumeIdCandidates); DeleteCriticalSection (&csSecureDesktop); } void cleanup () { burn (&CmdTokenPin, sizeof (CmdTokenPin)); /* Cleanup the GDI fonts */ if (hFixedFont != NULL) DeleteObject (hFixedFont); if (hFixedDigitFont != NULL) DeleteObject (hFixedDigitFont); if (hBoldFont != NULL) DeleteObject (hBoldFont); if (hTitleFont != NULL) DeleteObject (hTitleFont); if (hUserFont != NULL) DeleteObject (hUserFont); if (hUserUnderlineFont != NULL) DeleteObject (hUserUnderlineFont); if (hUserBoldFont != NULL) DeleteObject (hUserBoldFont); if (hUserUnderlineBoldFont != NULL) DeleteObject (hUserUnderlineBoldFont); /* Cleanup our dialog class */ if (hDlgClass) UnregisterClassW (TC_DLG_CLASS, hInst); if (hSplashClass) UnregisterClassW (TC_SPLASH_CLASS, hInst); /* Close the device driver handle */ if (hDriver != INVALID_HANDLE_VALUE) { // Unload driver mode if possible (non-install mode) if (IsNonInstallMode ()) { // If a dismount was forced in the lifetime of the driver, Windows may later prevent it to be loaded again from // the same path. Therefore, the driver will not be unloaded even though it was loaded in non-install mode. int driverUnloadDisabled; DWORD dwResult; if (!DeviceIoControl (hDriver, TC_IOCTL_IS_DRIVER_UNLOAD_DISABLED, NULL, 0, &driverUnloadDisabled, sizeof (driverUnloadDisabled), &dwResult, NULL)) driverUnloadDisabled = 0; if (!driverUnloadDisabled) DriverUnload (); else { CloseHandle (hDriver); hDriver = INVALID_HANDLE_VALUE; } } else { CloseHandle (hDriver); hDriver = INVALID_HANDLE_VALUE; } } if (ConfigBuffer != NULL) { free (ConfigBuffer); ConfigBuffer = NULL; } CoUninitialize (); CloseSysEncMutex (); #ifndef SETUP try { if (SecurityToken::IsInitialized()) SecurityToken::CloseLibrary(); } catch (...) { } EncryptionThreadPoolStop(); #endif FinalizeGlobalLocks (); } void LowerCaseCopy (wchar_t *lpszDest, const wchar_t *lpszSource) { size_t i = wcslen (lpszSource) + 1; lpszDest[i - 1] = 0; while (--i > 0) { lpszDest[i - 1] = (wchar_t) towlower (lpszSource[i - 1]); } } void UpperCaseCopy (wchar_t *lpszDest, size_t cbDest, const wchar_t *lpszSource) { if (lpszDest && cbDest) { size_t i = wcslen (lpszSource); if (i >= cbDest) i = cbDest - 1; lpszDest[i] = 0; i++; while (--i > 0) { lpszDest[i - 1] = (wchar_t) towupper (lpszSource[i - 1]); } } } std::wstring ToUpperCase (const std::wstring &str) { wstring u; foreach (wchar_t c, str) { u += (wchar_t) towupper (c); } return u; } size_t TrimWhiteSpace(wchar_t *str) { wchar_t *end, *ptr = str; size_t out_size; if(!str || *str == 0) return 0; // Trim leading space while(iswspace(*ptr)) ptr++; if(*ptr == 0) // All spaces? { *str = 0; return 0; } // Trim trailing space end = str + wcslen(str) - 1; while(end > ptr && iswspace(*end)) end--; end++; // Set output size to trimmed string length out_size = (end - ptr); // Copy trimmed string and add null terminator wmemmove(str, ptr, out_size); str[out_size] = 0; return out_size; } BOOL IsNullTerminateString (const wchar_t* str, size_t cbSize) { if (str && cbSize) { for (size_t i = 0; i < cbSize; i++) { if (str[i] == 0) return TRUE; } } return FALSE; } // check the validity of a file name BOOL IsValidFileName(const wchar_t* str) { static wchar_t invalidChars[9] = {L'<', L'>', L':', L'"', L'/', L'\\', L'|', L'?', L'*'}; wchar_t c; int i; BOOL bNotDotOnly = FALSE; while ((c = *str)) { if (c != L'.') bNotDotOnly = TRUE; for (i= 0; i < ARRAYSIZE(invalidChars); i++) if (c == invalidChars[i]) return FALSE; str++; } return bNotDotOnly; } BOOL IsVolumeDeviceHosted (const wchar_t *lpszDiskFile) { return wcsstr (lpszDiskFile, L"\\Device\\") == lpszDiskFile || wcsstr (lpszDiskFile, L"\\DEVICE\\") == lpszDiskFile; } void CreateFullVolumePath (wchar_t *lpszDiskFile, size_t cbDiskFile, const wchar_t *lpszFileName, BOOL * bDevice) { UpperCaseCopy (lpszDiskFile, cbDiskFile, lpszFileName); *bDevice = FALSE; if (wmemcmp (lpszDiskFile, L"\\DEVICE", 7) == 0) { *bDevice = TRUE; } StringCbCopyW (lpszDiskFile, cbDiskFile, lpszFileName); #if _DEBUG OutputDebugString (L"CreateFullVolumePath: "); OutputDebugString (lpszDiskFile); OutputDebugString (L"\n"); #endif } int FakeDosNameForDevice (const wchar_t *lpszDiskFile , wchar_t *lpszDosDevice , size_t cbDosDevice, wchar_t *lpszCFDevice , size_t cbCFDevice, BOOL bNameOnly) { BOOL bDosLinkCreated = TRUE; StringCbPrintfW (lpszDosDevice, cbDosDevice,L"veracrypt%lu", GetCurrentProcessId ()); if (bNameOnly == FALSE) bDosLinkCreated = DefineDosDevice (DDD_RAW_TARGET_PATH, lpszDosDevice, lpszDiskFile); if (bDosLinkCreated == FALSE) return ERR_OS_ERROR; else StringCbPrintfW (lpszCFDevice, cbCFDevice,L"\\\\.\\%s", lpszDosDevice); return 0; } int RemoveFakeDosName (wchar_t *lpszDiskFile, wchar_t *lpszDosDevice) { BOOL bDosLinkRemoved = DefineDosDevice (DDD_RAW_TARGET_PATH | DDD_EXACT_MATCH_ON_REMOVE | DDD_REMOVE_DEFINITION, lpszDosDevice, lpszDiskFile); if (bDosLinkRemoved == FALSE) { return ERR_OS_ERROR; } return 0; } void AbortProcessDirect (wchar_t *abortMsg) { // Note that this function also causes localcleanup() to be called (see atexit()) MessageBeep (MB_ICONEXCLAMATION); MessageBoxW (NULL, abortMsg, lpszTitle, ICON_HAND); FREE_DLL (hRichEditDll); FREE_DLL (hComctl32Dll); FREE_DLL (hSetupDll); FREE_DLL (hShlwapiDll); FREE_DLL (hProfApiDll); FREE_DLL (hUsp10Dll); FREE_DLL (hCryptSpDll); FREE_DLL (hUXThemeDll); FREE_DLL (hUserenvDll); FREE_DLL (hRsaenhDll); FREE_DLL (himm32dll); FREE_DLL (hMSCTFdll); FREE_DLL (hfltlibdll); FREE_DLL (hframedyndll); FREE_DLL (hpsapidll); FREE_DLL (hsecur32dll); FREE_DLL (hnetapi32dll); FREE_DLL (hauthzdll); FREE_DLL (hxmllitedll); FREE_DLL (hmprdll); FREE_DLL (hsppdll); FREE_DLL (vssapidll); FREE_DLL (hvsstracedll); FREE_DLL (hCryptSpDll); FREE_DLL (hcfgmgr32dll); FREE_DLL (hdevobjdll); FREE_DLL (hpowrprofdll); FREE_DLL (hsspiclidll); FREE_DLL (hcryptbasedll); FREE_DLL (hdwmapidll); FREE_DLL (hmsasn1dll); FREE_DLL (hcrypt32dll); FREE_DLL (hbcryptdll); FREE_DLL (hbcryptprimitivesdll); FREE_DLL (hMsls31); FREE_DLL (hntmartadll); FREE_DLL (hwinscarddll); FREE_DLL (hmsvcrtdll); exit (1); } void AbortProcess (char *stringId) { // Note that this function also causes localcleanup() to be called (see atexit()) AbortProcessDirect (GetString (stringId)); } void AbortProcessSilent (void) { FREE_DLL (hRichEditDll); FREE_DLL (hComctl32Dll); FREE_DLL (hSetupDll); FREE_DLL (hShlwapiDll); FREE_DLL (hProfApiDll); FREE_DLL (hUsp10Dll); FREE_DLL (hCryptSpDll); FREE_DLL (hUXThemeDll); FREE_DLL (hUserenvDll); FREE_DLL (hRsaenhDll); FREE_DLL (himm32dll); FREE_DLL (hMSCTFdll); FREE_DLL (hfltlibdll); FREE_DLL (hframedyndll); FREE_DLL (hpsapidll); FREE_DLL (hsecur32dll); FREE_DLL (hnetapi32dll); FREE_DLL (hauthzdll); FREE_DLL (hxmllitedll); FREE_DLL (hmprdll); FREE_DLL (hsppdll); FREE_DLL (vssapidll); FREE_DLL (hvsstracedll); FREE_DLL (hCryptSpDll); FREE_DLL (hcfgmgr32dll); FREE_DLL (hdevobjdll); FREE_DLL (hpowrprofdll); FREE_DLL (hsspiclidll); FREE_DLL (hcryptbasedll); FREE_DLL (hdwmapidll); FREE_DLL (hmsasn1dll); FREE_DLL (hcrypt32dll); FREE_DLL (hbcryptdll); FREE_DLL (hbcryptprimitivesdll); FREE_DLL (hMsls31); FREE_DLL (hntmartadll); FREE_DLL (hwinscarddll); FREE_DLL (hmsvcrtdll); // Note that this function also causes localcleanup() to be called (see atexit()) exit (1); } #pragma warning(push) #pragma warning(disable:4702) void *err_malloc (size_t size) { void *z = (void *) TCalloc (size); if (z) return z; AbortProcess ("OUTOFMEMORY"); return 0; } #pragma warning(pop) char *err_strdup (char *lpszText) { size_t j = (strlen (lpszText) + 1) * sizeof (char); char *z = (char *) err_malloc (j); memmove (z, lpszText, j); return z; } BOOL IsDiskReadError (DWORD error) { return (error == ERROR_CRC || error == ERROR_IO_DEVICE || error == ERROR_BAD_CLUSTERS || error == ERROR_SECTOR_NOT_FOUND || error == ERROR_READ_FAULT || error == ERROR_INVALID_FUNCTION // I/O error may be reported as ERROR_INVALID_FUNCTION by buggy chipset drivers || error == ERROR_SEM_TIMEOUT); // I/O operation timeout may be reported as ERROR_SEM_TIMEOUT } BOOL IsDiskWriteError (DWORD error) { return (error == ERROR_IO_DEVICE || error == ERROR_BAD_CLUSTERS || error == ERROR_SECTOR_NOT_FOUND || error == ERROR_WRITE_FAULT || error == ERROR_INVALID_FUNCTION // I/O error may be reported as ERROR_INVALID_FUNCTION by buggy chipset drivers || error == ERROR_SEM_TIMEOUT); // I/O operation timeout may be reported as ERROR_SEM_TIMEOUT } BOOL IsDiskError (DWORD error) { return IsDiskReadError (error) || IsDiskWriteError (error); } DWORD handleWin32Error (HWND hwndDlg, const char* srcPos) { PWSTR lpMsgBuf; DWORD dwError = GetLastError (); wchar_t szErrorValue[32]; wchar_t* pszDesc; if (Silent || dwError == 0 || dwError == ERROR_INVALID_WINDOW_HANDLE) return dwError; // Access denied if (dwError == ERROR_ACCESS_DENIED && !IsAdmin ()) { ErrorDirect ( AppendSrcPos (GetString ("ERR_ACCESS_DENIED"), srcPos).c_str (), hwndDlg); SetLastError (dwError); // Preserve the original error code return dwError; } FormatMessageW ( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, dwError, MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT), /* Default language */ (PWSTR) &lpMsgBuf, 0, NULL ); if (lpMsgBuf) pszDesc = (wchar_t*) lpMsgBuf; else { StringCchPrintfW (szErrorValue, ARRAYSIZE (szErrorValue), L"Error 0x%.8X", dwError); pszDesc = szErrorValue; } MessageBoxW (hwndDlg, AppendSrcPos (pszDesc, srcPos).c_str (), lpszTitle, ICON_HAND); if (lpMsgBuf) LocalFree (lpMsgBuf); // User-friendly hardware error explanation if (IsDiskError (dwError)) Error ("ERR_HARDWARE_ERROR", hwndDlg); // Device not ready if (dwError == ERROR_NOT_READY) HandleDriveNotReadyError(hwndDlg); SetLastError (dwError); // Preserve the original error code return dwError; } BOOL translateWin32Error (wchar_t *lpszMsgBuf, int nWSizeOfBuf) { DWORD dwError = GetLastError (); if (FormatMessageW (FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, dwError, MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT), /* Default language */ lpszMsgBuf, nWSizeOfBuf, NULL)) { SetLastError (dwError); // Preserve the original error code return TRUE; } SetLastError (dwError); // Preserve the original error code return FALSE; } // If the user has a non-default screen DPI, all absolute font sizes must be // converted using this function. int CompensateDPIFont (int val) { if (ScreenDPI == USER_DEFAULT_SCREEN_DPI) return val; else { double tmpVal = (double) val * DPIScaleFactorY * DlgAspectRatio * 0.999; if (tmpVal > 0) return (int) floor(tmpVal); else return (int) ceil(tmpVal); } } // If the user has a non-default screen DPI, some screen coordinates and sizes must // be converted using this function int CompensateXDPI (int val) { if (ScreenDPI == USER_DEFAULT_SCREEN_DPI) return val; else { double tmpVal = (double) val * DPIScaleFactorX; if (tmpVal > 0) return (int) floor(tmpVal); else return (int) ceil(tmpVal); } } // If the user has a non-default screen DPI, some screen coordinates and sizes must // be converted using this function int CompensateYDPI (int val) { if (ScreenDPI == USER_DEFAULT_SCREEN_DPI) return val; else { double tmpVal = (double) val * DPIScaleFactorY; if (tmpVal > 0) return (int) floor(tmpVal); else return (int) ceil(tmpVal); } } int GetTextGfxWidth (HWND hwndDlgItem, const wchar_t *text, HFONT hFont) { SIZE sizes; TEXTMETRIC textMetrics; HDC hdc = GetDC (hwndDlgItem); SelectObject(hdc, (HGDIOBJ) hFont); GetTextExtentPoint32W (hdc, text, (int) wcslen (text), &sizes); GetTextMetrics(hdc, &textMetrics); // Necessary for non-TrueType raster fonts (tmOverhang) ReleaseDC (hwndDlgItem, hdc); return ((int) sizes.cx - (int) textMetrics.tmOverhang); } int GetTextGfxHeight (HWND hwndDlgItem, const wchar_t *text, HFONT hFont) { SIZE sizes; HDC hdc = GetDC (hwndDlgItem); SelectObject(hdc, (HGDIOBJ) hFont); GetTextExtentPoint32W (hdc, text, (int) wcslen (text), &sizes); ReleaseDC (hwndDlgItem, hdc); return ((int) sizes.cy); } std::wstring FitPathInGfxWidth (HWND hwnd, HFONT hFont, LONG width, const std::wstring &path) { wstring newPath; RECT rect; rect.left = 0; rect.top = 0; rect.right = width; rect.bottom = LONG_MAX; HDC hdc = GetDC (hwnd); SelectObject (hdc, (HGDIOBJ) hFont); wchar_t pathBuf[TC_MAX_PATH]; StringCchCopyW (pathBuf, ARRAYSIZE (pathBuf), path.c_str()); if (DrawText (hdc, pathBuf, (int) path.size(), &rect, DT_CALCRECT | DT_MODIFYSTRING | DT_PATH_ELLIPSIS | DT_SINGLELINE) != 0) newPath = pathBuf; ReleaseDC (hwnd, hdc); return newPath; } static LRESULT CALLBACK HyperlinkProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { WNDPROC wp = (WNDPROC) GetWindowLongPtrW (hwnd, GWLP_USERDATA); switch (message) { case WM_SETCURSOR: if (!bHyperLinkBeingTracked) { TRACKMOUSEEVENT trackMouseEvent; trackMouseEvent.cbSize = sizeof(trackMouseEvent); trackMouseEvent.dwFlags = TME_LEAVE; trackMouseEvent.hwndTrack = hwnd; bHyperLinkBeingTracked = TrackMouseEvent(&trackMouseEvent); HandCursor(); } return 0; case WM_MOUSELEAVE: bHyperLinkBeingTracked = FALSE; NormalCursor(); return 0; } return CallWindowProcW (wp, hwnd, message, wParam, lParam); } BOOL ToHyperlink (HWND hwndDlg, UINT ctrlId) { return ToCustHyperlink (hwndDlg, ctrlId, hUserUnderlineFont); } BOOL ToCustHyperlink (HWND hwndDlg, UINT ctrlId, HFONT hFont) { HWND hwndCtrl = GetDlgItem (hwndDlg, ctrlId); SendMessageW (hwndCtrl, WM_SETFONT, (WPARAM) hFont, 0); SetWindowLongPtrW (hwndCtrl, GWLP_USERDATA, (LONG_PTR) GetWindowLongPtrW (hwndCtrl, GWLP_WNDPROC)); SetWindowLongPtrW (hwndCtrl, GWLP_WNDPROC, (LONG_PTR) HyperlinkProc); // Resize the field according to its actual size in pixels and move it if centered or right-aligned. // This should be done again if the link text changes. AccommodateTextField (hwndDlg, ctrlId, TRUE, hFont); return TRUE; } // Resizes a text field according to its actual width and height in pixels (font size is taken into account) and moves // it accordingly if the field is centered or right-aligned. Should be used on all hyperlinks upon dialog init // after localization (bFirstUpdate should be TRUE) and later whenever a hyperlink text changes (bFirstUpdate // must be FALSE). void AccommodateTextField (HWND hwndDlg, UINT ctrlId, BOOL bFirstUpdate, HFONT hFont) { RECT rec, wrec, trec; HWND hwndCtrl = GetDlgItem (hwndDlg, ctrlId); int width, origWidth, height, origHeight; int horizSubOffset, vertSubOffset, vertOffset, alignPosDiff = 0; wchar_t text [MAX_URL_LENGTH]; WINDOWINFO windowInfo; BOOL bBorderlessWindow = !(GetWindowLongPtrW (hwndDlg, GWL_STYLE) & (WS_BORDER | WS_DLGFRAME)); // Resize the field according to its length and font size and move if centered or right-aligned GetWindowTextW (hwndCtrl, text, sizeof (text) / sizeof (wchar_t)); width = GetTextGfxWidth (hwndCtrl, text, hFont); height = GetTextGfxHeight (hwndCtrl, text, hFont); GetClientRect (hwndCtrl, &rec); origWidth = rec.right; origHeight = rec.bottom; if (width >= 0 && (!bFirstUpdate || origWidth > width)) // The original width of the field is the maximum allowed size { horizSubOffset = origWidth - width; vertSubOffset = origHeight - height; // Window coords GetWindowRect(hwndDlg, &wrec); GetClientRect(hwndDlg, &trec); // Vertical "title bar" offset vertOffset = wrec.bottom - wrec.top - trec.bottom - (bBorderlessWindow ? 0 : GetSystemMetrics(SM_CYFIXEDFRAME)); // Text field coords GetWindowRect(hwndCtrl, &rec); // Alignment offset windowInfo.cbSize = sizeof(windowInfo); GetWindowInfo (hwndCtrl, &windowInfo); if (windowInfo.dwStyle & SS_CENTER) alignPosDiff = horizSubOffset / 2; else if (windowInfo.dwStyle & SS_RIGHT) alignPosDiff = horizSubOffset; // Resize/move if (alignPosDiff > 0) { // Resize and move the text field MoveWindow (hwndCtrl, rec.left - wrec.left - (bBorderlessWindow ? 0 : GetSystemMetrics(SM_CXFIXEDFRAME)) + alignPosDiff, rec.top - wrec.top - vertOffset, origWidth - horizSubOffset, origHeight - vertSubOffset, TRUE); } else { // Resize the text field SetWindowPos (hwndCtrl, 0, 0, 0, origWidth - horizSubOffset, origHeight - vertSubOffset, SWP_NOMOVE | SWP_NOZORDER); } SetWindowPos (hwndCtrl, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); InvalidateRect (hwndCtrl, NULL, TRUE); } } // Note that the user can still close the window by right-clicking its taskbar icon and selecting 'Close window', or by pressing Alt-F4, or using the Task Manager. void DisableCloseButton (HWND hwndDlg) { EnableMenuItem (GetSystemMenu (hwndDlg, FALSE), SC_CLOSE, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED); } void EnableCloseButton (HWND hwndDlg) { EnableMenuItem (GetSystemMenu (hwndDlg, FALSE), SC_CLOSE, MF_BYCOMMAND | MF_ENABLED); } // Protects an input field from having its content updated by a Paste action (call ToBootPwdField() to use this). static LRESULT CALLBACK BootPwdFieldProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { WNDPROC wp = (WNDPROC) GetWindowLongPtrW (hwnd, GWLP_USERDATA); switch (message) { case WM_PASTE: return 1; } return CallWindowProcW (wp, hwnd, message, wParam, lParam); } // Protects an input field from having its content updated by a Paste action. Used for pre-boot password // input fields (only the US keyboard layout is supported in pre-boot environment so we must prevent the // user from pasting a password typed using a non-US keyboard layout). void ToBootPwdField (HWND hwndDlg, UINT ctrlId) { HWND hwndCtrl = GetDlgItem (hwndDlg, ctrlId); WNDPROC originalwp = (WNDPROC) GetWindowLongPtrW (hwndCtrl, GWLP_USERDATA); SendMessage (hwndCtrl, EM_LIMITTEXT, MAX_LEGACY_PASSWORD, 0); // if ToNormalPwdField has been called before, GWLP_USERDATA already contains original WNDPROC if (!originalwp) { SetWindowLongPtrW (hwndCtrl, GWLP_USERDATA, (LONG_PTR) GetWindowLongPtrW (hwndCtrl, GWLP_WNDPROC)); } SetWindowLongPtrW (hwndCtrl, GWLP_WNDPROC, (LONG_PTR) BootPwdFieldProc); } // Ensures that a warning is displayed when user is pasting a password longer than the maximum // length which is set to 64 characters static LRESULT CALLBACK NormalPwdFieldProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { WNDPROC wp = (WNDPROC) GetWindowLongPtrW (hwnd, GWLP_USERDATA); switch (message) { case WM_PASTE: { bool bBlock = false; if (OpenClipboard (NULL)) { HANDLE h = GetClipboardData (CF_UNICODETEXT); if (h) { wchar_t *pchData = (wchar_t*)GlobalLock(h); int txtlen = 0; int dwMaxPassLen = bUseLegacyMaxPasswordLength? MAX_LEGACY_PASSWORD : MAX_PASSWORD; while (*pchData) { if (*pchData == '\r' || *pchData == '\n') break; else { txtlen++; pchData++; } } if (txtlen) { int curLen = GetWindowTextLength (hwnd); if (curLen == dwMaxPassLen) { EDITBALLOONTIP ebt; ebt.cbStruct = sizeof( EDITBALLOONTIP ); ebt.pszText = GetString ("PASSWORD_MAXLENGTH_REACHED"); ebt.pszTitle = lpszTitle; ebt.ttiIcon = TTI_ERROR_LARGE; // tooltip warning icon SendMessage(hwnd, EM_SHOWBALLOONTIP, 0, (LPARAM)&ebt); MessageBeep (0xFFFFFFFF); bBlock = true; } else if ((txtlen + curLen) > dwMaxPassLen) { EDITBALLOONTIP ebt; ebt.cbStruct = sizeof( EDITBALLOONTIP ); ebt.pszText = GetString ("PASSWORD_PASTED_TRUNCATED"); ebt.pszTitle = lpszTitle; ebt.ttiIcon = TTI_WARNING_LARGE; // tooltip warning icon SendMessage(hwnd, EM_SHOWBALLOONTIP, 0, (LPARAM)&ebt); MessageBeep (0xFFFFFFFF); } else SendMessage(hwnd, EM_HIDEBALLOONTIP, 0, 0); } GlobalUnlock(h); } CloseClipboard (); } if (bBlock) return FALSE; } break; case WM_CHAR: { DWORD dwStartPos = 0, dwEndPos = 0; short vk = VkKeyScanW ((WCHAR) wParam); BYTE vkCode = LOBYTE (vk); BYTE vkState = HIBYTE (vk); bool ctrlPressed = (vkState & 2) && !(vkState & 4); int dwMaxPassLen = bUseLegacyMaxPasswordLength? MAX_LEGACY_PASSWORD : MAX_PASSWORD; // check if there is a selected text SendMessage (hwnd, EM_GETSEL, (WPARAM) &dwStartPos, (LPARAM) &dwEndPos); if ((dwStartPos == dwEndPos) && (vkCode != VK_DELETE) && (vkCode != VK_BACK) && !ctrlPressed && (GetWindowTextLength (hwnd) == dwMaxPassLen)) { EDITBALLOONTIP ebt; ebt.cbStruct = sizeof( EDITBALLOONTIP ); ebt.pszText = GetString ("PASSWORD_MAXLENGTH_REACHED"); ebt.pszTitle = lpszTitle; ebt.ttiIcon = TTI_ERROR_LARGE; // tooltip warning icon SendMessage(hwnd, EM_SHOWBALLOONTIP, 0, (LPARAM)&ebt); MessageBeep (0xFFFFFFFF); } else SendMessage(hwnd, EM_HIDEBALLOONTIP, 0, 0); } break; } return CallWindowProcW (wp, hwnd, message, wParam, lParam); } void ToNormalPwdField (HWND hwndDlg, UINT ctrlId) { HWND hwndCtrl = GetDlgItem (hwndDlg, ctrlId); WNDPROC originalwp = (WNDPROC) GetWindowLongPtrW (hwndCtrl, GWLP_USERDATA); DWORD dwMaxPassLen = bUseLegacyMaxPasswordLength? MAX_LEGACY_PASSWORD : MAX_PASSWORD; SendMessage (hwndCtrl, EM_LIMITTEXT, dwMaxPassLen, 0); // only change WNDPROC if not changed already if (!originalwp) { SetWindowLongPtrW (hwndCtrl, GWLP_USERDATA, (LONG_PTR) GetWindowLongPtrW (hwndCtrl, GWLP_WNDPROC)); SetWindowLongPtrW (hwndCtrl, GWLP_WNDPROC, (LONG_PTR) NormalPwdFieldProc); } } // This function currently serves the following purposes: // - Determines scaling factors for current screen DPI and GUI aspect ratio. // - Determines how Windows skews the GUI aspect ratio (which happens when the user has a non-default DPI). // The determined values must be used when performing some GUI operations and calculations. BOOL CALLBACK AuxiliaryDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) { switch (msg) { case WM_INITDIALOG: { HDC hDC = GetDC (hwndDlg); if (hDC) { ScreenDPI = GetDeviceCaps (hDC, LOGPIXELSY); ReleaseDC (hwndDlg, hDC); } DPIScaleFactorX = 1; DPIScaleFactorY = 1; DlgAspectRatio = 1; if (ScreenDPI != USER_DEFAULT_SCREEN_DPI) { // Windows skews the GUI aspect ratio if the user has a non-default DPI. Hence, working with // actual screen DPI is redundant and leads to incorrect results. What really matters here is // how Windows actually renders our GUI. This is determined by comparing the expected and current // sizes of a hidden calibration text field. RECT trec; trec.right = 0; trec.bottom = 0; GetClientRect (GetDlgItem (hwndDlg, IDC_ASPECT_RATIO_CALIBRATION_BOX), &trec); if (trec.right != 0 && trec.bottom != 0) { // The size of the 282x282 IDC_ASPECT_RATIO_CALIBRATION_BOX rendered at the default DPI (96) is 423x458 DPIScaleFactorX = (double) trec.right / 423; DPIScaleFactorY = (double) trec.bottom / 458; DlgAspectRatio = DPIScaleFactorX / DPIScaleFactorY; } } EndDialog (hwndDlg, 0); return 1; } case WM_CLOSE: EndDialog (hwndDlg, 0); return 1; } return 0; } /* Except in response to the WM_INITDIALOG message, the dialog box procedure should return nonzero if it processes the message, and zero if it does not. - see DialogProc */ BOOL CALLBACK AboutDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) { WORD lw = LOWORD (wParam); static HBITMAP hbmTextualLogoBitmapRescaled = NULL; switch (msg) { case WM_INITDIALOG: { wchar_t szTmp[100]; RECT rec; LocalizeDialog (hwndDlg, "IDD_ABOUT_DLG"); // Hyperlink SetWindowText (GetDlgItem (hwndDlg, IDC_HOMEPAGE), L"www.idrix.fr"); ToHyperlink (hwndDlg, IDC_HOMEPAGE); // Logo area background (must not keep aspect ratio; must retain Windows-imposed distortion) GetClientRect (GetDlgItem (hwndDlg, IDC_ABOUT_LOGO_AREA), &rec); SetWindowPos (GetDlgItem (hwndDlg, IDC_ABOUT_BKG), HWND_TOP, 0, 0, rec.right, rec.bottom, SWP_NOMOVE); // Resize the logo bitmap if the user has a non-default DPI if (ScreenDPI != USER_DEFAULT_SCREEN_DPI) { // Logo (must recreate and keep the original aspect ratio as Windows distorts it) hbmTextualLogoBitmapRescaled = RenderBitmap (MAKEINTRESOURCE (IDB_TEXTUAL_LOGO_288DPI), GetDlgItem (hwndDlg, IDC_TEXTUAL_LOGO_IMG), 0, 0, 0, 0, FALSE, TRUE); SetWindowPos (GetDlgItem (hwndDlg, IDC_ABOUT_BKG), HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); } // Version SendMessage (GetDlgItem (hwndDlg, IDT_ABOUT_VERSION), WM_SETFONT, (WPARAM) hUserBoldFont, 0); StringCbPrintfW (szTmp, sizeof(szTmp), L"VeraCrypt %s", _T(VERSION_STRING) _T(VERSION_STRING_SUFFIX)); #ifdef _WIN64 StringCbCatW (szTmp, sizeof(szTmp), L" (64-bit)"); #else StringCbCatW (szTmp, sizeof(szTmp), L" (32-bit)"); #endif #if (defined(_DEBUG) || defined(DEBUG)) StringCbCatW (szTmp, sizeof(szTmp), L" (debug)"); #endif SetDlgItemText (hwndDlg, IDT_ABOUT_VERSION, szTmp); SetDlgItemText (hwndDlg, IDT_ABOUT_RELEASE, TC_STR_RELEASED_BY); // Credits SendMessage (GetDlgItem (hwndDlg, IDC_ABOUT_CREDITS), WM_SETFONT, (WPARAM) hUserFont, (LPARAM) 0); SendMessage (hwndDlg, WM_APP, 0, 0); return 1; } case WM_APP: SetWindowText (GetDlgItem (hwndDlg, IDC_ABOUT_CREDITS), L"Based on TrueCrypt 7.1a, freely available at http://www.truecrypt.org/ .\r\n\r\n" L"Portions of this software:\r\n" L"Copyright \xA9 2013-2019 IDRIX. All rights reserved.\r\n" L"Copyright \xA9 2003-2012 TrueCrypt Developers Association. All Rights Reserved.\r\n" L"Copyright \xA9 1998-2000 Paul Le Roux. All Rights Reserved.\r\n" L"Copyright \xA9 1998-2008 Brian Gladman. All Rights Reserved.\r\n" L"Copyright \xA9 1995-2017 Jean-loup Gailly and Mark Adler.\r\n" L"Copyright \xA9 2016 Disk Cryptography Services for EFI (DCS), Alex Kolotnikov.\r\n" L"Copyright \xA9 1999-2017 Dieter Baron and Thomas Klausner.\r\n" L"Copyright \xA9 2013, Alexey Degtyarev. All rights reserved.\r\n" L"Copyright \xA9 1999-2016 Jack Lloyd. All rights reserved.\r\n" L"Copyright \xA9 2013-2018 Stephan Mueller <smueller@chronox.de>\r\n\r\n" L"This software as a whole:\r\n" L"Copyright \xA9 2013-2019 IDRIX. All rights reserved.\r\n\r\n" L"An IDRIX Release"); return 1; case WM_COMMAND: if (lw == IDOK || lw == IDCANCEL) { PostMessage (hwndDlg, WM_CLOSE, 0, 0); return 1; } if (lw == IDC_HOMEPAGE) { Applink ("main"); return 1; } // Disallow modification of credits if (HIWORD (wParam) == EN_UPDATE) { SendMessage (hwndDlg, WM_APP, 0, 0); return 1; } return 0; case WM_CLOSE: /* Delete buffered bitmaps (if any) */ if (hbmTextualLogoBitmapRescaled != NULL) { DeleteObject ((HGDIOBJ) hbmTextualLogoBitmapRescaled); hbmTextualLogoBitmapRescaled = NULL; } EndDialog (hwndDlg, 0); return 1; } return 0; } static HWND StaticModelessWaitDlgHandle = NULL; // Call DisplayStaticModelessWaitDlg() to open this dialog and CloseStaticModelessWaitDlg() to close it. static BOOL CALLBACK StaticModelessWaitDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) { WORD lw = LOWORD (wParam); switch (msg) { case WM_INITDIALOG: { LocalizeDialog (hwndDlg, NULL); return 0; } case WM_COMMAND: if (lw == IDOK || lw == IDCANCEL) return 1; return 0; case WM_CLOSE: StaticModelessWaitDlgHandle = NULL; EndDialog (hwndDlg, 0); return 1; } return 0; } // Opens a dialog window saying "Please wait..." which is not modal and does not need any GUI refresh after initialization. void DisplayStaticModelessWaitDlg (HWND parent) { if (StaticModelessWaitDlgHandle != NULL) return; // Already shown StaticModelessWaitDlgHandle = CreateDialogParamW (hInst, MAKEINTRESOURCEW (IDD_STATIC_MODELESS_WAIT_DLG), parent, (DLGPROC) StaticModelessWaitDlgProc, (LPARAM) 0); ShowWindow (StaticModelessWaitDlgHandle, SW_SHOWNORMAL); // Allow synchronous use with the GUI being instantly and fully rendered ProcessPaintMessages (StaticModelessWaitDlgHandle, 500); } void CloseStaticModelessWaitDlg (void) { if (StaticModelessWaitDlgHandle == NULL) return; // Not shown DestroyWindow (StaticModelessWaitDlgHandle); } BOOL IsButtonChecked (HWND hButton) { if (SendMessage (hButton, BM_GETCHECK, 0, 0) == BST_CHECKED) return TRUE; else return FALSE; } void CheckButton (HWND hButton) { SendMessage (hButton, BM_SETCHECK, BST_CHECKED, 0); } void LeftPadString (wchar_t *szTmp, int len, int targetLen, wchar_t filler) { int i; if (targetLen <= len) return; for (i = targetLen-1; i >= (targetLen-len); i--) szTmp [i] = szTmp [i-(targetLen-len)]; wmemset (szTmp, filler, targetLen-len); szTmp [targetLen] = 0; } /* InitDialog - initialize the applications main dialog, this function should be called only once in the dialogs WM_INITDIALOG message handler */ void InitDialog (HWND hwndDlg) { NONCLIENTMETRICSW metric; static BOOL aboutMenuAppended = FALSE; int nHeight; LOGFONTW lf; HMENU hMenu; Font *font; /* Fonts */ memset (&lf, 0, sizeof(lf)); // Normal font = GetFont ("font_normal"); metric.cbSize = sizeof (metric); SystemParametersInfoW (SPI_GETNONCLIENTMETRICS, sizeof(metric), &metric, 0); WindowTitleBarFont = CreateFontIndirectW (&metric.lfCaptionFont); metric.lfMessageFont.lfHeight = CompensateDPIFont (!font ? -11 : -font->Size); metric.lfMessageFont.lfWidth = 0; if (font && wcscmp (font->FaceName, L"default") != 0) { StringCbCopyW ((WCHAR *)metric.lfMessageFont.lfFaceName, sizeof (metric.lfMessageFont.lfFaceName), font->FaceName); } else if (IsOSAtLeast (WIN_VISTA)) { // Vista's new default font (size and spacing) breaks compatibility with Windows 2k/XP applications. // Force use of Tahoma (as Microsoft does in many dialogs) until a native Vista look is implemented. StringCbCopyW ((WCHAR *)metric.lfMessageFont.lfFaceName, sizeof (metric.lfMessageFont.lfFaceName), L"Tahoma"); } hUserFont = CreateFontIndirectW (&metric.lfMessageFont); metric.lfMessageFont.lfUnderline = TRUE; hUserUnderlineFont = CreateFontIndirectW (&metric.lfMessageFont); metric.lfMessageFont.lfUnderline = FALSE; metric.lfMessageFont.lfWeight = FW_BOLD; hUserBoldFont = CreateFontIndirectW (&metric.lfMessageFont); metric.lfMessageFont.lfUnderline = TRUE; metric.lfMessageFont.lfWeight = FW_BOLD; hUserUnderlineBoldFont = CreateFontIndirectW (&metric.lfMessageFont); // Fixed-size (hexadecimal digits) nHeight = CompensateDPIFont (-12); lf.lfHeight = nHeight; lf.lfWidth = 0; lf.lfEscapement = 0; lf.lfOrientation = 0; lf.lfWeight = FW_NORMAL; lf.lfItalic = FALSE; lf.lfUnderline = FALSE; lf.lfStrikeOut = FALSE; lf.lfCharSet = DEFAULT_CHARSET; lf.lfOutPrecision = OUT_DEFAULT_PRECIS; lf.lfClipPrecision = CLIP_DEFAULT_PRECIS; lf.lfQuality = PROOF_QUALITY; lf.lfPitchAndFamily = FF_DONTCARE; StringCbCopyW (lf.lfFaceName, sizeof(lf.lfFaceName), L"Courier New"); hFixedDigitFont = CreateFontIndirectW (&lf); if (hFixedDigitFont == NULL) { handleWin32Error (hwndDlg, SRC_POS); AbortProcess ("NOFONT"); } // Bold font = GetFont ("font_bold"); nHeight = CompensateDPIFont (!font ? -13 : -font->Size); lf.lfHeight = nHeight; lf.lfWeight = FW_BLACK; StringCbCopyW (lf.lfFaceName, sizeof(lf.lfFaceName), !font ? L"Arial" : font->FaceName); hBoldFont = CreateFontIndirectW (&lf); if (hBoldFont == NULL) { handleWin32Error (hwndDlg, SRC_POS); AbortProcess ("NOFONT"); } // Title font = GetFont ("font_title"); nHeight = CompensateDPIFont (!font ? -21 : -font->Size); lf.lfHeight = nHeight; lf.lfWeight = FW_REGULAR; StringCbCopyW (lf.lfFaceName, sizeof(lf.lfFaceName),!font ? L"Times New Roman" : font->FaceName); hTitleFont = CreateFontIndirectW (&lf); if (hTitleFont == NULL) { handleWin32Error (hwndDlg, SRC_POS); AbortProcess ("NOFONT"); } // Fixed-size font = GetFont ("font_fixed"); nHeight = CompensateDPIFont (!font ? -12 : -font->Size); lf.lfHeight = nHeight; lf.lfWidth = 0; lf.lfEscapement = 0; lf.lfOrientation = 0; lf.lfWeight = FW_NORMAL; lf.lfItalic = FALSE; lf.lfUnderline = FALSE; lf.lfStrikeOut = FALSE; lf.lfCharSet = DEFAULT_CHARSET; lf.lfOutPrecision = OUT_DEFAULT_PRECIS; lf.lfClipPrecision = CLIP_DEFAULT_PRECIS; lf.lfQuality = PROOF_QUALITY; lf.lfPitchAndFamily = FF_DONTCARE; StringCbCopyW (lf.lfFaceName, sizeof(lf.lfFaceName),!font ? L"Lucida Console" : font->FaceName); hFixedFont = CreateFontIndirectW (&lf); if (hFixedFont == NULL) { handleWin32Error (hwndDlg, SRC_POS); AbortProcess ("NOFONT"); } if (!aboutMenuAppended) { hMenu = GetSystemMenu (hwndDlg, FALSE); AppendMenu (hMenu, MF_SEPARATOR, 0, L""); AppendMenuW (hMenu, MF_ENABLED | MF_STRING, IDC_ABOUT, GetString ("ABOUTBOX")); aboutMenuAppended = TRUE; } } // The parameter maxMessagesToProcess prevents endless processing of paint messages void ProcessPaintMessages (HWND hwnd, int maxMessagesToProcess) { MSG paintMsg; int msgCounter = maxMessagesToProcess; while (PeekMessageW (&paintMsg, hwnd, 0, 0, PM_REMOVE | PM_QS_PAINT) != 0 && msgCounter-- > 0) { DispatchMessageW (&paintMsg); } } HDC CreateMemBitmap (HINSTANCE hInstance, HWND hwnd, wchar_t *resource) { HBITMAP picture = LoadBitmap (hInstance, resource); HDC viewDC = GetDC (hwnd), dcMem; dcMem = CreateCompatibleDC (viewDC); SetMapMode (dcMem, MM_TEXT); SelectObject (dcMem, picture); DeleteObject (picture); ReleaseDC (hwnd, viewDC); return dcMem; } /* Renders the specified bitmap at the specified location and stretches it to fit (anti-aliasing is applied). If bDirectRender is FALSE and both nWidth and nHeight are zero, the width and height of hwndDest are retrieved and adjusted according to screen DPI (the width and height of the resultant image are adjusted the same way); furthermore, if bKeepAspectRatio is TRUE, the smaller DPI factor of the two (i.e. horiz. or vert.) is used both for horiz. and vert. scaling (note that the overall GUI aspect ratio changes irregularly in both directions depending on the DPI). If bDirectRender is TRUE, bKeepAspectRatio is ignored. This function returns a handle to the scaled bitmap. When the bitmap is no longer needed, it should be deleted by calling DeleteObject() with the handle passed as the parameter. Known Windows issues: - For some reason, anti-aliasing is not applied if the source bitmap contains less than 16K pixels. - Windows 2000 may produce slightly inaccurate colors even when source, buffer, and target are 24-bit true color. */ HBITMAP RenderBitmap (wchar_t *resource, HWND hwndDest, int x, int y, int nWidth, int nHeight, BOOL bDirectRender, BOOL bKeepAspectRatio) { LRESULT lResult = 0; HDC hdcSrc = CreateMemBitmap (hInst, hwndDest, resource); if (!hdcSrc) return NULL; HGDIOBJ picture = GetCurrentObject (hdcSrc, OBJ_BITMAP); HBITMAP hbmpRescaled = NULL; BITMAP bitmap; HDC hdcRescaled; if (!bDirectRender && nWidth == 0 && nHeight == 0) { RECT rec; GetClientRect (hwndDest, &rec); if (bKeepAspectRatio) { if (DlgAspectRatio > 1) { // Do not fix this, it's correct. We use the Y scale factor intentionally for both // directions to maintain aspect ratio (see above for more info). nWidth = CompensateYDPI (rec.right); nHeight = CompensateYDPI (rec.bottom); } else { // Do not fix this, it's correct. We use the X scale factor intentionally for both // directions to maintain aspect ratio (see above for more info). nWidth = CompensateXDPI (rec.right); nHeight = CompensateXDPI (rec.bottom); } } else { nWidth = CompensateXDPI (rec.right); nHeight = CompensateYDPI (rec.bottom); } } GetObject (picture, sizeof (BITMAP), &bitmap); hdcRescaled = CreateCompatibleDC (hdcSrc); if (hdcRescaled) { hbmpRescaled = CreateCompatibleBitmap (hdcSrc, nWidth, nHeight); SelectObject (hdcRescaled, hbmpRescaled); /* Anti-aliasing mode (HALFTONE is the only anti-aliasing algorithm natively supported by Windows 2000. TODO: GDI+ offers higher quality -- InterpolationModeHighQualityBicubic) */ SetStretchBltMode (hdcRescaled, HALFTONE); StretchBlt (hdcRescaled, 0, 0, nWidth, nHeight, hdcSrc, 0, 0, bitmap.bmWidth, bitmap.bmHeight, SRCCOPY); DeleteDC (hdcSrc); if (bDirectRender) { HDC hdcDest = GetDC (hwndDest); if (hdcDest) { BitBlt (hdcDest, x, y, nWidth, nHeight, hdcRescaled, 0, 0, SRCCOPY); ReleaseDC (hwndDest, hdcDest); } } else { lResult = SendMessage (hwndDest, (UINT) STM_SETIMAGE, (WPARAM) IMAGE_BITMAP, (LPARAM) (HANDLE) hbmpRescaled); } if ((HGDIOBJ) lResult != NULL && (HGDIOBJ) lResult != (HGDIOBJ) hbmpRescaled) DeleteObject ((HGDIOBJ) lResult); DeleteDC (hdcRescaled); } return hbmpRescaled; } LRESULT CALLBACK RedTick (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { if (uMsg == WM_CREATE) { } else if (uMsg == WM_DESTROY) { } else if (uMsg == WM_TIMER) { } else if (uMsg == WM_PAINT) { PAINTSTRUCT tmp; HPEN hPen; HDC hDC; BOOL bEndPaint; RECT Rect; if (GetUpdateRect (hwnd, NULL, FALSE)) { hDC = BeginPaint (hwnd, &tmp); bEndPaint = TRUE; if (hDC == NULL) return DefWindowProcW (hwnd, uMsg, wParam, lParam); } else { hDC = GetDC (hwnd); bEndPaint = FALSE; } GetClientRect (hwnd, &Rect); hPen = CreatePen (PS_SOLID, 2, RGB (0, 255, 0)); if (hPen != NULL) { HGDIOBJ hObj = SelectObject (hDC, hPen); WORD bx = LOWORD (GetDialogBaseUnits ()); WORD by = HIWORD (GetDialogBaseUnits ()); MoveToEx (hDC, (Rect.right - Rect.left) / 2, Rect.bottom, NULL); LineTo (hDC, Rect.right, Rect.top); MoveToEx (hDC, (Rect.right - Rect.left) / 2, Rect.bottom, NULL); LineTo (hDC, (3 * bx) / 4, (2 * by) / 8); SelectObject (hDC, hObj); DeleteObject (hPen); } if (bEndPaint) EndPaint (hwnd, &tmp); else ReleaseDC (hwnd, hDC); return TRUE; } return DefWindowProcW (hwnd, uMsg, wParam, lParam); } BOOL RegisterRedTick (HINSTANCE hInstance) { WNDCLASSW wc; ULONG rc; memset(&wc, 0 , sizeof wc); wc.style = CS_HREDRAW | CS_VREDRAW; wc.cbClsExtra = 0; wc.cbWndExtra = 4; wc.hInstance = hInstance; wc.hIcon = LoadIcon (NULL, IDI_APPLICATION); wc.hCursor = NULL; wc.hbrBackground = (HBRUSH) GetStockObject (LTGRAY_BRUSH); wc.lpszClassName = L"VCREDTICK"; wc.lpfnWndProc = &RedTick; rc = (ULONG) RegisterClassW (&wc); return rc == 0 ? FALSE : TRUE; } BOOL UnregisterRedTick (HINSTANCE hInstance) { return UnregisterClassW (L"VCREDTICK", hInstance); } LRESULT CALLBACK SplashDlgProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { return DefDlgProcW (hwnd, uMsg, wParam, lParam); } static int g_waitCursorCounter = 0; void WaitCursor () { static HCURSOR hcWait = NULL; if (hcWait == NULL) hcWait = LoadCursor (NULL, IDC_WAIT); if ((g_waitCursorCounter == 0) || (hCursor != hcWait)) { if (!Silent) SetCursor (hcWait); hCursor = hcWait; } g_waitCursorCounter++; } void NormalCursor () { static HCURSOR hcArrow = NULL; if (hcArrow == NULL) hcArrow = LoadCursor (NULL, IDC_ARROW); if (g_waitCursorCounter > 0) g_waitCursorCounter--; if (g_waitCursorCounter == 0) { if (!Silent) SetCursor (hcArrow); hCursor = NULL; } } void ArrowWaitCursor () { static HCURSOR hcArrowWait = NULL; if (hcArrowWait == NULL) hcArrowWait = LoadCursor (NULL, IDC_APPSTARTING); if ((g_waitCursorCounter == 0) || (hCursor != hcArrowWait)) { if (!Silent) SetCursor (hcArrowWait); hCursor = hcArrowWait; } g_waitCursorCounter++; } void HandCursor () { static HCURSOR hcHand = NULL; if (hcHand == NULL) hcHand = LoadCursor (NULL, IDC_HAND); SetCursor (hcHand); hCursor = hcHand; } void AddComboPair (HWND hComboBox, const wchar_t *lpszItem, int value) { LPARAM nIndex; nIndex = SendMessage (hComboBox, CB_ADDSTRING, 0, (LPARAM) lpszItem); nIndex = SendMessage (hComboBox, CB_SETITEMDATA, nIndex, (LPARAM) value); } void SelectAlgo (HWND hComboBox, int *algo_id) { LPARAM nCount = SendMessage (hComboBox, CB_GETCOUNT, 0, 0); LPARAM x, i; for (i = 0; i < nCount; i++) { x = SendMessage (hComboBox, CB_GETITEMDATA, i, 0); if (x == (LPARAM) *algo_id) { SendMessage (hComboBox, CB_SETCURSEL, i, 0); return; } } /* Something went wrong ; couldn't find the requested algo id so we drop back to a default */ *algo_id = (int) SendMessage (hComboBox, CB_GETITEMDATA, 0, 0); SendMessage (hComboBox, CB_SETCURSEL, 0, 0); } void PopulateWipeModeCombo (HWND hComboBox, BOOL bNA, BOOL bInPlaceEncryption, BOOL bHeaderWipe) { if (bNA) { AddComboPair (hComboBox, GetString ("NOT_APPLICABLE_OR_NOT_AVAILABLE"), TC_WIPE_NONE); } else { if (!bHeaderWipe) { AddComboPair (hComboBox, GetString ("WIPE_MODE_NONE"), TC_WIPE_NONE); } AddComboPair (hComboBox, GetString ("WIPE_MODE_1_RAND"), TC_WIPE_1_RAND); AddComboPair (hComboBox, GetString ("WIPE_MODE_3_DOD_5220"), TC_WIPE_3_DOD_5220); AddComboPair (hComboBox, GetString ("WIPE_MODE_7_DOD_5220"), TC_WIPE_7_DOD_5220); AddComboPair (hComboBox, GetString ("WIPE_MODE_35_GUTMANN"), TC_WIPE_35_GUTMANN); if (bHeaderWipe) AddComboPair (hComboBox, GetString ("WIPE_MODE_256"), TC_WIPE_256); // paranoid wipe for volume header } } wchar_t *GetWipeModeName (WipeAlgorithmId modeId) { switch (modeId) { case TC_WIPE_NONE: return GetString ("WIPE_MODE_NONE"); case TC_WIPE_1_RAND: return GetString ("WIPE_MODE_1_RAND"); case TC_WIPE_3_DOD_5220: return GetString ("WIPE_MODE_3_DOD_5220"); case TC_WIPE_7_DOD_5220: return GetString ("WIPE_MODE_7_DOD_5220"); case TC_WIPE_35_GUTMANN: return GetString ("WIPE_MODE_35_GUTMANN"); case TC_WIPE_256: return GetString ("WIPE_MODE_256"); default: return GetString ("NOT_APPLICABLE_OR_NOT_AVAILABLE"); } } wchar_t *GetPathType (const wchar_t *path, BOOL bUpperCase, BOOL *bIsPartition) { if (wcsstr (path, L"Partition") && wcsstr (path, L"Partition0") == NULL) { *bIsPartition = TRUE; return GetString (bUpperCase ? "PARTITION_UPPER_CASE" : "PARTITION_LOWER_CASE"); } else if (wcsstr (path, L"HarddiskVolume")) { *bIsPartition = TRUE; return GetString (bUpperCase ? "VOLUME_UPPER_CASE" : "VOLUME_LOWER_CASE"); } *bIsPartition = FALSE; return GetString (bUpperCase ? "DEVICE_UPPER_CASE" : "DEVICE_LOWER_CASE"); } LRESULT CALLBACK CustomDlgProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { if (uMsg == WM_SETCURSOR && hCursor != NULL) { SetCursor (hCursor); return TRUE; } return DefDlgProcW (hwnd, uMsg, wParam, lParam); } /* static BOOL IsReturnAddress (DWORD64 address) { static size_t codeEnd = 0; byte *sp = (byte *) address; if (codeEnd == 0) { MEMORY_BASIC_INFORMATION mi; if (VirtualQuery ((LPCVOID) 0x401000, &mi, sizeof (mi)) >= sizeof (mi)) codeEnd = (size_t) mi.BaseAddress + mi.RegionSize; } if (address < 0x401000 + 8 || address > codeEnd) return FALSE; return sp[-5] == 0xe8 // call ADDR || (sp[-6] == 0xff && sp[-5] == 0x15) // call [ADDR] || (sp[-2] == 0xff && (sp[-1] & 0xf0) == 0xd0); // call REG } */ typedef struct { EXCEPTION_POINTERS *ExceptionPointers; HANDLE ExceptionThread; } ExceptionHandlerThreadArgs; void ExceptionHandlerThread (void *threadArg) { ExceptionHandlerThreadArgs *args = (ExceptionHandlerThreadArgs *) threadArg; EXCEPTION_POINTERS *ep = args->ExceptionPointers; //DWORD addr; DWORD exCode = ep->ExceptionRecord->ExceptionCode; // SYSTEM_INFO si; // wchar_t msg[8192]; // char modPath[MAX_PATH]; // int crc = 0; // char url[MAX_URL_LENGTH]; // char lpack[128]; // stringstream callStack; // addr = (DWORD) ep->ExceptionRecord->ExceptionAddress; // PDWORD sp = (PDWORD) ep->ContextRecord->Esp; // int frameNumber = 0; switch (exCode) { case STATUS_IN_PAGE_ERROR: case 0xeedfade: // Exception not caused by VeraCrypt MessageBoxW (0, GetString ("EXCEPTION_REPORT_EXT"), GetString ("EXCEPTION_REPORT_TITLE"), MB_ICONERROR | MB_OK | MB_SETFOREGROUND | MB_TOPMOST); return; } // Call stack /* HMODULE dbgDll = LoadLibrary ("dbghelp.dll"); if (dbgDll) { typedef DWORD (__stdcall *SymGetOptions_t) (); typedef DWORD (__stdcall *SymSetOptions_t) (DWORD SymOptions); typedef BOOL (__stdcall *SymInitialize_t) (HANDLE hProcess, PCSTR UserSearchPath, BOOL fInvadeProcess); typedef BOOL (__stdcall *StackWalk64_t) (DWORD MachineType, HANDLE hProcess, HANDLE hThread, LPSTACKFRAME64 StackFrame, PVOID ContextRecord, PREAD_PROCESS_MEMORY_ROUTINE64 ReadMemoryRoutine, PFUNCTION_TABLE_ACCESS_ROUTINE64 FunctionTableAccessRoutine, PGET_MODULE_BASE_ROUTINE64 GetModuleBaseRoutine, PTRANSLATE_ADDRESS_ROUTINE64 TranslateAddress); typedef BOOL (__stdcall * SymFromAddr_t) (HANDLE hProcess, DWORD64 Address, PDWORD64 Displacement, PSYMBOL_INFO Symbol); SymGetOptions_t DbgHelpSymGetOptions = (SymGetOptions_t) GetProcAddress (dbgDll, "SymGetOptions"); SymSetOptions_t DbgHelpSymSetOptions = (SymSetOptions_t) GetProcAddress (dbgDll, "SymSetOptions"); SymInitialize_t DbgHelpSymInitialize = (SymInitialize_t) GetProcAddress (dbgDll, "SymInitialize"); PFUNCTION_TABLE_ACCESS_ROUTINE64 DbgHelpSymFunctionTableAccess64 = (PFUNCTION_TABLE_ACCESS_ROUTINE64) GetProcAddress (dbgDll, "SymFunctionTableAccess64"); PGET_MODULE_BASE_ROUTINE64 DbgHelpSymGetModuleBase64 = (PGET_MODULE_BASE_ROUTINE64) GetProcAddress (dbgDll, "SymGetModuleBase64"); StackWalk64_t DbgHelpStackWalk64 = (StackWalk64_t) GetProcAddress (dbgDll, "StackWalk64"); SymFromAddr_t DbgHelpSymFromAddr = (SymFromAddr_t) GetProcAddress (dbgDll, "SymFromAddr"); if (DbgHelpSymGetOptions && DbgHelpSymSetOptions && DbgHelpSymInitialize && DbgHelpSymFunctionTableAccess64 && DbgHelpSymGetModuleBase64 && DbgHelpStackWalk64 && DbgHelpSymFromAddr) { DbgHelpSymSetOptions (DbgHelpSymGetOptions() | SYMOPT_DEFERRED_LOADS | SYMOPT_ALLOW_ABSOLUTE_SYMBOLS | SYMOPT_NO_CPP); if (DbgHelpSymInitialize (GetCurrentProcess(), NULL, TRUE)) { STACKFRAME64 frame; memset (&frame, 0, sizeof (frame)); frame.AddrPC.Offset = ep->ContextRecord->Eip; frame.AddrPC.Mode = AddrModeFlat; frame.AddrStack.Offset = ep->ContextRecord->Esp; frame.AddrStack.Mode = AddrModeFlat; frame.AddrFrame.Offset = ep->ContextRecord->Ebp; frame.AddrFrame.Mode = AddrModeFlat; string lastSymbol; while (frameNumber < 32 && DbgHelpStackWalk64 (IMAGE_FILE_MACHINE_I386, GetCurrentProcess(), args->ExceptionThread, &frame, ep->ContextRecord, NULL, DbgHelpSymFunctionTableAccess64, DbgHelpSymGetModuleBase64, NULL)) { if (!frame.AddrPC.Offset) continue; ULONG64 symbolBuffer[(sizeof (SYMBOL_INFO) + MAX_SYM_NAME * sizeof (TCHAR) + sizeof (ULONG64) - 1) / sizeof (ULONG64)]; memset (symbolBuffer, 0, sizeof (symbolBuffer)); PSYMBOL_INFO symbol = (PSYMBOL_INFO) symbolBuffer; symbol->SizeOfStruct = sizeof (SYMBOL_INFO); symbol->MaxNameLen = MAX_SYM_NAME; if (DbgHelpSymFromAddr (GetCurrentProcess(), frame.AddrPC.Offset, NULL, symbol) && symbol->NameLen > 0) { for (size_t i = 0; i < symbol->NameLen; ++i) { if (!isalnum (symbol->Name[i])) symbol->Name[i] = '_'; } if (symbol->Name != lastSymbol) callStack << "&st" << frameNumber++ << "=" << symbol->Name; lastSymbol = symbol->Name; } else if (frameNumber == 0 || IsReturnAddress (frame.AddrPC.Offset)) { callStack << "&st" << frameNumber++ << "=0x" << hex << frame.AddrPC.Offset << dec; } } } } } // StackWalk64() may fail due to missing frame pointers list <DWORD> retAddrs; if (frameNumber == 0) retAddrs.push_back (ep->ContextRecord->Eip); retAddrs.push_back (0); MEMORY_BASIC_INFORMATION mi; VirtualQuery (sp, &mi, sizeof (mi)); PDWORD stackTop = (PDWORD)((byte *) mi.BaseAddress + mi.RegionSize); int i = 0; while (retAddrs.size() < 16 && &sp[i] < stackTop) { if (IsReturnAddress (sp[i])) { bool duplicate = false; foreach (DWORD prevAddr, retAddrs) { if (sp[i] == prevAddr) { duplicate = true; break; } } if (!duplicate) retAddrs.push_back (sp[i]); } i++; } if (retAddrs.size() > 1) { foreach (DWORD addr, retAddrs) { callStack << "&st" << frameNumber++ << "=0x" << hex << addr << dec; } } // Checksum of the module if (GetModuleFileName (NULL, modPath, sizeof (modPath))) { HANDLE h = CreateFile (modPath, FILE_READ_DATA | FILE_READ_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); if (h != INVALID_HANDLE_VALUE) { BY_HANDLE_FILE_INFORMATION fi; if (GetFileInformationByHandle (h, &fi)) { char *buf = (char *) malloc (fi.nFileSizeLow); if (buf) { DWORD bytesRead; if (ReadFile (h, buf, fi.nFileSizeLow, &bytesRead, NULL) && bytesRead == fi.nFileSizeLow) crc = GetCrc32 ((unsigned char *) buf, fi.nFileSizeLow); free (buf); } } CloseHandle (h); } } GetSystemInfo (&si); if (LocalizationActive) sprintf_s (lpack, sizeof (lpack), "&langpack=%s_%s", GetPreferredLangId (), GetActiveLangPackVersion ()); else lpack[0] = 0; sprintf (url, TC_APPLINK_SECURE "&dest=err-report%s&os=%s&osver=%d.%d.%d&arch=%s&cpus=%d&app=%s&cksum=%x&dlg=%s&err=%x&addr=%x" , lpack , GetWindowsEdition().c_str() , CurrentOSMajor , CurrentOSMinor , CurrentOSServicePack , Is64BitOs () ? "x64" : "x86" , si.dwNumberOfProcessors #ifdef TCMOUNT ,"main" #endif #ifdef VOLFORMAT ,"format" #endif #ifdef SETUP ,"setup" #endif , crc , LastDialogId ? LastDialogId : "-" , exCode , addr); string urlStr = url + callStack.str(); _snwprintf (msg, array_capacity (msg), GetString ("EXCEPTION_REPORT"), urlStr.c_str()); if (IDYES == MessageBoxW (0, msg, GetString ("EXCEPTION_REPORT_TITLE"), MB_ICONERROR | MB_YESNO | MB_DEFBUTTON1)) ShellExecute (NULL, "open", urlStr.c_str(), NULL, NULL, SW_SHOWNORMAL); else */ UnhandledExceptionFilter (ep); } LONG __stdcall ExceptionHandler (EXCEPTION_POINTERS *ep) { SetUnhandledExceptionFilter (NULL); if (SystemFileSelectorCallPending && SystemFileSelectorCallerThreadId == GetCurrentThreadId()) { MessageBoxW (NULL, GetString ("EXCEPTION_REPORT_EXT_FILESEL"), GetString ("EXCEPTION_REPORT_TITLE"), MB_ICONERROR | MB_OK | MB_SETFOREGROUND | MB_TOPMOST); UnhandledExceptionFilter (ep); return EXCEPTION_EXECUTE_HANDLER; } ExceptionHandlerThreadArgs args; args.ExceptionPointers = ep; args.ExceptionThread = GetCurrentThread(); WaitForSingleObject ((HANDLE) _beginthread (ExceptionHandlerThread, 0, &args), INFINITE); return EXCEPTION_EXECUTE_HANDLER; } void InvalidParameterHandler (const wchar_t *expression, const wchar_t *function, const wchar_t *file, unsigned int line, uintptr_t reserved) { TC_THROW_FATAL_EXCEPTION; } static LRESULT CALLBACK NonInstallUacWndProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { return DefWindowProcW (hWnd, message, wParam, lParam); } BOOL LaunchElevatedProcess (HWND hwndDlg, const wchar_t* szModPath, const wchar_t* args) { wchar_t newCmdLine[4096]; WNDCLASSEXW wcex; HWND hWnd; memset (&wcex, 0, sizeof (wcex)); wcex.cbSize = sizeof(WNDCLASSEX); wcex.lpfnWndProc = (WNDPROC) NonInstallUacWndProc; wcex.hInstance = hInst; wcex.lpszClassName = L"VeraCrypt"; RegisterClassExW (&wcex); // A small transparent window is necessary to bring the new instance to foreground hWnd = CreateWindowExW (WS_EX_TOOLWINDOW | WS_EX_LAYERED, L"VeraCrypt", L"VeraCrypt", 0, GetSystemMetrics (SM_CXSCREEN)/2, GetSystemMetrics (SM_CYSCREEN)/2, 1, 1, NULL, NULL, hInst, NULL); SetLayeredWindowAttributes (hWnd, 0, 0, LWA_ALPHA); ShowWindow (hWnd, SW_SHOWNORMAL); StringCbCopyW (newCmdLine, sizeof(newCmdLine), L"/q UAC "); StringCbCatW (newCmdLine, sizeof (newCmdLine), args); if ((int)ShellExecuteW (hWnd, L"runas", szModPath, newCmdLine, NULL, SW_SHOWNORMAL) <= 32) { if (hwndDlg) handleWin32Error (hwndDlg, SRC_POS); return FALSE; } else { Sleep (2000); return TRUE; } } // Mutex handling to prevent multiple instances of the wizard or main app from dealing with system encryption. // Returns TRUE if the mutex is (or had been) successfully acquired (otherwise FALSE). BOOL CreateSysEncMutex (void) { return TCCreateMutex (&hSysEncMutex, TC_MUTEX_NAME_SYSENC); } BOOL InstanceHasSysEncMutex (void) { return (hSysEncMutex != NULL); } // Mutex handling to prevent multiple instances of the wizard from dealing with system encryption void CloseSysEncMutex (void) { TCCloseMutex (&hSysEncMutex); } // Returns TRUE if the mutex is (or had been) successfully acquired (otherwise FALSE). BOOL CreateNonSysInplaceEncMutex (void) { return TCCreateMutex (&hNonSysInplaceEncMutex, TC_MUTEX_NAME_NONSYS_INPLACE_ENC); } BOOL InstanceHasNonSysInplaceEncMutex (void) { return (hNonSysInplaceEncMutex != NULL); } void CloseNonSysInplaceEncMutex (void) { TCCloseMutex (&hNonSysInplaceEncMutex); } // Returns TRUE if another instance of the wizard is preparing, resuming or performing non-system in-place encryption BOOL NonSysInplaceEncInProgressElsewhere (void) { return (!InstanceHasNonSysInplaceEncMutex () && MutexExistsOnSystem (TC_MUTEX_NAME_NONSYS_INPLACE_ENC)); } // Mutex handling to prevent multiple instances of the wizard or main app from trying to install // or register the driver or from trying to launch it in portable mode at the same time. // Returns TRUE if the mutex is (or had been) successfully acquired (otherwise FALSE). BOOL CreateDriverSetupMutex (void) { return TCCreateMutex (&hDriverSetupMutex, TC_MUTEX_NAME_DRIVER_SETUP); } void CloseDriverSetupMutex (void) { TCCloseMutex (&hDriverSetupMutex); } BOOL CreateAppSetupMutex (void) { return TCCreateMutex (&hAppSetupMutex, TC_MUTEX_NAME_APP_SETUP); } void CloseAppSetupMutex (void) { TCCloseMutex (&hAppSetupMutex); } BOOL IsTrueCryptInstallerRunning (void) { return (MutexExistsOnSystem (TC_MUTEX_NAME_APP_SETUP)); } // Returns TRUE if the mutex is (or had been) successfully acquired (otherwise FALSE). BOOL TCCreateMutex (volatile HANDLE *hMutex, wchar_t *name) { if (*hMutex != NULL) return TRUE; // This instance already has the mutex *hMutex = CreateMutex (NULL, TRUE, name); if (*hMutex == NULL) { // In multi-user configurations, the OS returns "Access is denied" here when a user attempts // to acquire the mutex if another user already has. However, on Vista, "Access is denied" is // returned also if the mutex is owned by a process with admin rights while we have none. return FALSE; } if (GetLastError () == ERROR_ALREADY_EXISTS) { ReleaseMutex (*hMutex); CloseHandle (*hMutex); *hMutex = NULL; return FALSE; } return TRUE; } void TCCloseMutex (volatile HANDLE *hMutex) { if (*hMutex != NULL) { if (ReleaseMutex (*hMutex) && CloseHandle (*hMutex)) *hMutex = NULL; } } // Returns TRUE if a process running on the system has the specified mutex (otherwise FALSE). BOOL MutexExistsOnSystem (wchar_t *name) { if (name[0] == 0) return FALSE; HANDLE hMutex = OpenMutex (MUTEX_ALL_ACCESS, FALSE, name); if (hMutex == NULL) { if (GetLastError () == ERROR_FILE_NOT_FOUND) return FALSE; if (GetLastError () == ERROR_ACCESS_DENIED) // On Vista, this is returned if the owner of the mutex is elevated while we are not return TRUE; // The call failed and it is not certain whether the mutex exists or not return FALSE; } CloseHandle (hMutex); return TRUE; } uint32 ReadDriverConfigurationFlags () { DWORD configMap; if (!ReadLocalMachineRegistryDword (L"SYSTEM\\CurrentControlSet\\Services\\veracrypt", TC_DRIVER_CONFIG_REG_VALUE_NAME, &configMap)) configMap = 0; return configMap; } uint32 ReadEncryptionThreadPoolFreeCpuCountLimit () { DWORD count; if (!ReadLocalMachineRegistryDword (L"SYSTEM\\CurrentControlSet\\Services\\veracrypt", TC_ENCRYPTION_FREE_CPU_COUNT_REG_VALUE_NAME, &count)) count = 0; return count; } BOOL LoadSysEncSettings () { BOOL status = TRUE; DWORD size = 0; char *sysEncCfgFileBuf = LoadFile (GetConfigPath (TC_APPD_FILENAME_SYSTEM_ENCRYPTION), &size); char *xml = sysEncCfgFileBuf; char paramName[100], paramVal[MAX_PATH]; // Defaults int newSystemEncryptionStatus = SYSENC_STATUS_NONE; WipeAlgorithmId newnWipeMode = TC_WIPE_NONE; if (!FileExists (GetConfigPath (TC_APPD_FILENAME_SYSTEM_ENCRYPTION))) { SystemEncryptionStatus = newSystemEncryptionStatus; nWipeMode = newnWipeMode; } if (xml == NULL) { return FALSE; } while (xml = XmlFindElement (xml, "config")) { XmlGetAttributeText (xml, "key", paramName, sizeof (paramName)); XmlGetNodeText (xml, paramVal, sizeof (paramVal)); if (strcmp (paramName, "SystemEncryptionStatus") == 0) { newSystemEncryptionStatus = atoi (paramVal); } else if (strcmp (paramName, "WipeMode") == 0) { newnWipeMode = (WipeAlgorithmId) atoi (paramVal); } xml++; } SystemEncryptionStatus = newSystemEncryptionStatus; nWipeMode = newnWipeMode; free (sysEncCfgFileBuf); return status; } // Returns the number of partitions where non-system in-place encryption is progress or had been in progress // but was interrupted. In addition, via the passed pointer, returns the last selected wipe algorithm ID. int LoadNonSysInPlaceEncSettings (WipeAlgorithmId *wipeAlgorithm) { char *fileBuf = NULL; char *fileBuf2 = NULL; DWORD size, size2; int count; *wipeAlgorithm = TC_WIPE_NONE; if (!FileExists (GetConfigPath (TC_APPD_FILENAME_NONSYS_INPLACE_ENC))) return 0; if ((fileBuf = LoadFile (GetConfigPath (TC_APPD_FILENAME_NONSYS_INPLACE_ENC), &size)) == NULL) return 0; if (FileExists (GetConfigPath (TC_APPD_FILENAME_NONSYS_INPLACE_ENC_WIPE))) { if ((fileBuf2 = LoadFile (GetConfigPath (TC_APPD_FILENAME_NONSYS_INPLACE_ENC_WIPE), &size2)) != NULL) *wipeAlgorithm = (WipeAlgorithmId) atoi (fileBuf2); } count = atoi (fileBuf); if (fileBuf != NULL) TCfree (fileBuf); if (fileBuf2 != NULL) TCfree (fileBuf2); return (count); } void RemoveNonSysInPlaceEncNotifications (void) { if (FileExists (GetConfigPath (TC_APPD_FILENAME_NONSYS_INPLACE_ENC))) _wremove (GetConfigPath (TC_APPD_FILENAME_NONSYS_INPLACE_ENC)); if (FileExists (GetConfigPath (TC_APPD_FILENAME_NONSYS_INPLACE_ENC_WIPE))) _wremove (GetConfigPath (TC_APPD_FILENAME_NONSYS_INPLACE_ENC_WIPE)); if (!IsNonInstallMode () && SystemEncryptionStatus == SYSENC_STATUS_NONE) ManageStartupSeqWiz (TRUE, L""); } void SavePostInstallTasksSettings (int command) { FILE *f = NULL; if (IsNonInstallMode() && command != TC_POST_INSTALL_CFG_REMOVE_ALL) return; switch (command) { case TC_POST_INSTALL_CFG_REMOVE_ALL: _wremove (GetConfigPath (TC_APPD_FILENAME_POST_INSTALL_TASK_TUTORIAL)); _wremove (GetConfigPath (TC_APPD_FILENAME_POST_INSTALL_TASK_RELEASE_NOTES)); _wremove (GetConfigPath (TC_APPD_FILENAME_POST_INSTALL_TASK_RESCUE_DISK)); break; case TC_POST_INSTALL_CFG_TUTORIAL: f = _wfopen (GetConfigPath (TC_APPD_FILENAME_POST_INSTALL_TASK_TUTORIAL), L"w"); break; case TC_POST_INSTALL_CFG_RELEASE_NOTES: f = _wfopen (GetConfigPath (TC_APPD_FILENAME_POST_INSTALL_TASK_RELEASE_NOTES), L"w"); break; case TC_POST_INSTALL_CFG_RESCUE_DISK: f = _wfopen (GetConfigPath (TC_APPD_FILENAME_POST_INSTALL_TASK_RESCUE_DISK), L"w"); break; default: return; } if (f == NULL) return; if (fputws (L"1", f) < 0) { // Error fclose (f); return; } TCFlushFile (f); fclose (f); } void DoPostInstallTasks (HWND hwndDlg) { BOOL bDone = FALSE; if (FileExists (GetConfigPath (TC_APPD_FILENAME_POST_INSTALL_TASK_TUTORIAL))) { if (AskYesNo ("AFTER_INSTALL_TUTORIAL", hwndDlg) == IDYES) Applink ("beginnerstutorial"); bDone = TRUE; } if (FileExists (GetConfigPath (TC_APPD_FILENAME_POST_INSTALL_TASK_RELEASE_NOTES))) { if (AskYesNo ("AFTER_UPGRADE_RELEASE_NOTES", hwndDlg) == IDYES) Applink ("releasenotes"); bDone = TRUE; } if (FileExists (GetConfigPath (TC_APPD_FILENAME_POST_INSTALL_TASK_RESCUE_DISK))) { if (AskYesNo ("AFTER_UPGRADE_RESCUE_DISK", hwndDlg) == IDYES) PostMessage (hwndDlg, VC_APPMSG_CREATE_RESCUE_DISK, 0, 0); bDone = TRUE; } if (bDone) SavePostInstallTasksSettings (TC_POST_INSTALL_CFG_REMOVE_ALL); } /* * Use RtlGetVersion to get Windows version because GetVersionEx is affected by application manifestation. */ typedef NTSTATUS (WINAPI* RtlGetVersionPtr)(PRTL_OSVERSIONINFOW); static BOOL GetWindowsVersion(LPOSVERSIONINFOW lpVersionInformation) { BOOL bRet = FALSE; RtlGetVersionPtr RtlGetVersionFn = (RtlGetVersionPtr) GetProcAddress(GetModuleHandle (L"ntdll.dll"), "RtlGetVersion"); if (RtlGetVersionFn != NULL) { if (ERROR_SUCCESS == RtlGetVersionFn (lpVersionInformation)) bRet = TRUE; } if (!bRet) bRet = GetVersionExW (lpVersionInformation); return bRet; } void InitOSVersionInfo () { OSVERSIONINFOEXW os; os.dwOSVersionInfoSize = sizeof (OSVERSIONINFOEXW); if (GetWindowsVersion ((LPOSVERSIONINFOW) &os) == FALSE) AbortProcess ("NO_OS_VER"); CurrentOSMajor = os.dwMajorVersion; CurrentOSMinor = os.dwMinorVersion; CurrentOSServicePack = os.wServicePackMajor; CurrentOSBuildNumber = os.dwBuildNumber; if (os.dwPlatformId == VER_PLATFORM_WIN32_NT && CurrentOSMajor == 5 && CurrentOSMinor == 0) nCurrentOS = WIN_2000; else if (os.dwPlatformId == VER_PLATFORM_WIN32_NT && CurrentOSMajor == 5 && CurrentOSMinor == 1) nCurrentOS = WIN_XP; else if (os.dwPlatformId == VER_PLATFORM_WIN32_NT && CurrentOSMajor == 5 && CurrentOSMinor == 2) { if (os.wProductType == VER_NT_SERVER || os.wProductType == VER_NT_DOMAIN_CONTROLLER) nCurrentOS = WIN_SERVER_2003; else nCurrentOS = WIN_XP64; } else if (os.dwPlatformId == VER_PLATFORM_WIN32_NT && CurrentOSMajor == 6 && CurrentOSMinor == 0) { if (os.wProductType != VER_NT_WORKSTATION) nCurrentOS = WIN_SERVER_2008; else nCurrentOS = WIN_VISTA; } else if (os.dwPlatformId == VER_PLATFORM_WIN32_NT && CurrentOSMajor == 6 && CurrentOSMinor == 1) nCurrentOS = ((os.wProductType != VER_NT_WORKSTATION) ? WIN_SERVER_2008_R2 : WIN_7); else if (os.dwPlatformId == VER_PLATFORM_WIN32_NT && CurrentOSMajor == 6 && CurrentOSMinor == 2) nCurrentOS = ((os.wProductType != VER_NT_WORKSTATION) ? WIN_SERVER_2012 : WIN_8); else if (os.dwPlatformId == VER_PLATFORM_WIN32_NT && CurrentOSMajor == 6 && CurrentOSMinor == 3) nCurrentOS = ((os.wProductType != VER_NT_WORKSTATION) ? WIN_SERVER_2012_R2 : WIN_8_1); else if (os.dwPlatformId == VER_PLATFORM_WIN32_NT && CurrentOSMajor == 10 && CurrentOSMinor == 0) nCurrentOS = ((os.wProductType != VER_NT_WORKSTATION) ? WIN_SERVER_2016 : WIN_10); else if (os.dwPlatformId == VER_PLATFORM_WIN32_NT && CurrentOSMajor == 4) nCurrentOS = WIN_NT4; else if (os.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS && os.dwMajorVersion == 4 && os.dwMinorVersion == 0) nCurrentOS = WIN_95; else if (os.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS && os.dwMajorVersion == 4 && os.dwMinorVersion == 10) nCurrentOS = WIN_98; else if (os.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS && os.dwMajorVersion == 4 && os.dwMinorVersion == 90) nCurrentOS = WIN_ME; else if (os.dwPlatformId == VER_PLATFORM_WIN32s) nCurrentOS = WIN_31; else nCurrentOS = WIN_UNKNOWN; } static void LoadSystemDll (LPCTSTR szModuleName, HMODULE *pHandle, BOOL bIgnoreError, const char* srcPos) { wchar_t dllPath[MAX_PATH]; /* Load dll explictely from System32 to avoid Dll hijacking attacks*/ if (!GetSystemDirectory(dllPath, MAX_PATH)) StringCbCopyW(dllPath, sizeof(dllPath), L"C:\\Windows\\System32"); StringCbCatW(dllPath, sizeof(dllPath), L"\\"); StringCbCatW(dllPath, sizeof(dllPath), szModuleName); if (((*pHandle = LoadLibrary(dllPath)) == NULL) && !bIgnoreError) { // This error is fatal handleWin32Error (NULL, srcPos); AbortProcess ("INIT_DLL"); } } /* InitApp - initialize the application, this function is called once in the applications WinMain function, but before the main dialog has been created */ void InitApp (HINSTANCE hInstance, wchar_t *lpszCommandLine) { WNDCLASSW wc; char langId[6]; InitCommonControlsPtr InitCommonControlsFn = NULL; wchar_t modPath[MAX_PATH]; /* Protect this process memory from being accessed by non-admin users */ EnableProcessProtection (); GetModuleFileNameW (NULL, modPath, ARRAYSIZE (modPath)); /* remove current directory from dll search path */ SetDllDirectoryFn = (SetDllDirectoryPtr) GetProcAddress (GetModuleHandle(L"kernel32.dll"), "SetDllDirectoryW"); SetSearchPathModeFn = (SetSearchPathModePtr) GetProcAddress (GetModuleHandle(L"kernel32.dll"), "SetSearchPathMode"); SetDefaultDllDirectoriesFn = (SetDefaultDllDirectoriesPtr) GetProcAddress (GetModuleHandle(L"kernel32.dll"), "SetDefaultDllDirectories"); if (SetDllDirectoryFn) SetDllDirectoryFn (L""); if (SetSearchPathModeFn) SetSearchPathModeFn (BASE_SEARCH_PATH_ENABLE_SAFE_SEARCHMODE | BASE_SEARCH_PATH_PERMANENT); if (SetDefaultDllDirectoriesFn) SetDefaultDllDirectoriesFn (LOAD_LIBRARY_SEARCH_SYSTEM32); InitOSVersionInfo(); VirtualLock (&CmdTokenPin, sizeof (CmdTokenPin)); InitGlobalLocks (); LoadSystemDll (L"msvcrt.dll", &hmsvcrtdll, TRUE, SRC_POS); LoadSystemDll (L"ntmarta.dll", &hntmartadll, TRUE, SRC_POS); LoadSystemDll (L"MPR.DLL", &hmprdll, TRUE, SRC_POS); #ifdef SETUP if (IsOSAtLeast (WIN_7)) { LoadSystemDll (L"ProfApi.DLL", &hProfApiDll, TRUE, SRC_POS); LoadSystemDll (L"cryptbase.dll", &hcryptbasedll, TRUE, SRC_POS); LoadSystemDll (L"sspicli.dll", &hsspiclidll, TRUE, SRC_POS); } #endif LoadSystemDll (L"psapi.dll", &hpsapidll, TRUE, SRC_POS); LoadSystemDll (L"secur32.dll", &hsecur32dll, TRUE, SRC_POS); LoadSystemDll (L"msasn1.dll", &hmsasn1dll, TRUE, SRC_POS); LoadSystemDll (L"Usp10.DLL", &hUsp10Dll, TRUE, SRC_POS); if (IsOSAtLeast (WIN_7)) LoadSystemDll (L"dwmapi.dll", &hdwmapidll, TRUE, SRC_POS); LoadSystemDll (L"UXTheme.dll", &hUXThemeDll, TRUE, SRC_POS); LoadSystemDll (L"msls31.dll", &hMsls31, TRUE, SRC_POS); LoadSystemDll (L"SETUPAPI.DLL", &hSetupDll, FALSE, SRC_POS); LoadSystemDll (L"SHLWAPI.DLL", &hShlwapiDll, FALSE, SRC_POS); LoadSystemDll (L"userenv.dll", &hUserenvDll, TRUE, SRC_POS); LoadSystemDll (L"rsaenh.dll", &hRsaenhDll, TRUE, SRC_POS); #ifdef SETUP if (nCurrentOS < WIN_7) { if (nCurrentOS == WIN_XP) { LoadSystemDll (L"imm32.dll", &himm32dll, TRUE, SRC_POS); LoadSystemDll (L"MSCTF.dll", &hMSCTFdll, TRUE, SRC_POS); LoadSystemDll (L"fltlib.dll", &hfltlibdll, TRUE, SRC_POS); LoadSystemDll (L"wbem\\framedyn.dll", &hframedyndll, TRUE, SRC_POS); } if (IsOSAtLeast (WIN_VISTA)) { LoadSystemDll (L"netapi32.dll", &hnetapi32dll, TRUE, SRC_POS); LoadSystemDll (L"authz.dll", &hauthzdll, TRUE, SRC_POS); LoadSystemDll (L"xmllite.dll", &hxmllitedll, TRUE, SRC_POS); } } if (IsOSAtLeast (WIN_VISTA)) { LoadSystemDll (L"atl.dll", &hsppdll, TRUE, SRC_POS); LoadSystemDll (L"vsstrace.dll", &hvsstracedll, TRUE, SRC_POS); LoadSystemDll (L"vssapi.dll", &vssapidll, TRUE, SRC_POS); LoadSystemDll (L"spp.dll", &hsppdll, TRUE, SRC_POS); } #endif LoadSystemDll (L"crypt32.dll", &hcrypt32dll, TRUE, SRC_POS); if (IsOSAtLeast (WIN_7)) { LoadSystemDll (L"CryptSP.dll", &hCryptSpDll, TRUE, SRC_POS); LoadSystemDll (L"cfgmgr32.dll", &hcfgmgr32dll, TRUE, SRC_POS); LoadSystemDll (L"devobj.dll", &hdevobjdll, TRUE, SRC_POS); LoadSystemDll (L"powrprof.dll", &hpowrprofdll, TRUE, SRC_POS); LoadSystemDll (L"bcrypt.dll", &hbcryptdll, TRUE, SRC_POS); LoadSystemDll (L"bcryptprimitives.dll", &hbcryptprimitivesdll, TRUE, SRC_POS); } #ifndef SETUP LoadSystemDll (L"WINSCARD.DLL", &hwinscarddll, TRUE, SRC_POS); #endif LoadSystemDll (L"COMCTL32.DLL", &hComctl32Dll, FALSE, SRC_POS); // call InitCommonControls function InitCommonControlsFn = (InitCommonControlsPtr) GetProcAddress (hComctl32Dll, "InitCommonControls"); ImageList_AddFn = (ImageList_AddPtr) GetProcAddress (hComctl32Dll, "ImageList_Add"); ImageList_CreateFn = (ImageList_CreatePtr) GetProcAddress (hComctl32Dll, "ImageList_Create"); if (InitCommonControlsFn && ImageList_AddFn && ImageList_CreateFn) { InitCommonControlsFn(); } else AbortProcess ("INIT_DLL"); LoadSystemDll (L"Riched20.dll", &hRichEditDll, FALSE, SRC_POS); #if !defined(SETUP) if (!VerifyModuleSignature (modPath)) AbortProcess ("DIST_PACKAGE_CORRUPTED"); #endif // Get SetupAPI functions pointers SetupCloseInfFileFn = (SetupCloseInfFilePtr) GetProcAddress (hSetupDll, "SetupCloseInfFile"); SetupDiOpenClassRegKeyFn = (SetupDiOpenClassRegKeyPtr) GetProcAddress (hSetupDll, "SetupDiOpenClassRegKey"); SetupInstallFromInfSectionWFn = (SetupInstallFromInfSectionWPtr) GetProcAddress (hSetupDll, "SetupInstallFromInfSectionW"); SetupOpenInfFileWFn = (SetupOpenInfFileWPtr) GetProcAddress (hSetupDll, "SetupOpenInfFileW"); if (!SetupCloseInfFileFn || !SetupDiOpenClassRegKeyFn || !SetupInstallFromInfSectionWFn || !SetupOpenInfFileWFn) AbortProcess ("INIT_DLL"); // Get SHDeleteKeyW function pointer SHDeleteKeyWFn = (SHDeleteKeyWPtr) GetProcAddress (hShlwapiDll, "SHDeleteKeyW"); SHStrDupWFn = (SHStrDupWPtr) GetProcAddress (hShlwapiDll, "SHStrDupW"); if (!SHDeleteKeyWFn || !SHStrDupWFn) AbortProcess ("INIT_DLL"); if (IsOSAtLeast (WIN_VISTA)) { /* Get ChangeWindowMessageFilter used to enable some messages bypasss UIPI (User Interface Privilege Isolation) */ ChangeWindowMessageFilterFn = (ChangeWindowMessageFilterPtr) GetProcAddress (GetModuleHandle (L"user32.dll"), "ChangeWindowMessageFilter"); #ifndef SETUP /* enable drag-n-drop when we are running elevated */ AllowMessageInUIPI (WM_DROPFILES); AllowMessageInUIPI (WM_COPYDATA); AllowMessageInUIPI (WM_COPYGLOBALDATA); #endif } /* Save the instance handle for later */ hInst = hInstance; SetErrorMode (SetErrorMode (0) | SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX); CoInitialize (NULL); #ifndef SETUP // Application ID typedef HRESULT (WINAPI *SetAppId_t) (PCWSTR appID); SetAppId_t setAppId = (SetAppId_t) GetProcAddress (GetModuleHandle (L"shell32.dll"), "SetCurrentProcessExplicitAppUserModelID"); if (setAppId) setAppId (TC_APPLICATION_ID); #endif // Language langId[0] = 0; SetPreferredLangId (ConfigReadString ("Language", "", langId, sizeof (langId))); #ifndef SETUP if (langId[0] == 0) { // check if user selected a language during installation WCHAR uiLang[6]; ReadRegistryString (L"Software\\VeraCrypt", L"SetupUILanguage", L"", uiLang, sizeof (uiLang)); if (0 < WideCharToMultiByte (CP_ACP, 0, uiLang, -1, langId, sizeof (langId), NULL, NULL)) { SetPreferredLangId (langId); bLanguageSetInSetup = TRUE; } } #ifndef VCEXPANDER // delete the registry key created by the installer (if any) DeleteRegistryKey (HKEY_CURRENT_USER, L"Software\\VeraCrypt"); #endif #endif if (langId[0] == 0) { if (IsNonInstallMode ()) { // only support automatic use of a language file in portable mode // this is achieved by placing a unique language XML file in the same // place as portable VeraCrypt binaries. DialogBoxParamW (hInst, MAKEINTRESOURCEW (IDD_LANGUAGE), NULL, (DLGPROC) LanguageDlgProc, (LPARAM) 1); } else { // when installed, force using English as default language SetPreferredLangId ("en"); } } LoadLanguageFile (); #ifndef SETUP // UAC elevation moniker cannot be used in portable mode. // A new instance of the application must be created with elevated privileges. if (IsNonInstallMode () && !IsAdmin () && IsUacSupported ()) { if (wcsstr (lpszCommandLine, L"/q UAC ") == lpszCommandLine) { Error ("UAC_INIT_ERROR", NULL); exit (1); } if (LaunchElevatedProcess (NULL, modPath, lpszCommandLine)) exit (0); else exit (1); } #endif SetUnhandledExceptionFilter (ExceptionHandler); _set_invalid_parameter_handler (InvalidParameterHandler); RemoteSession = GetSystemMetrics (SM_REMOTESESSION) != 0; // OS version check if (CurrentOSMajor < 5) { MessageBoxW (NULL, GetString ("UNSUPPORTED_OS"), lpszTitle, MB_ICONSTOP); exit (1); } else { // Service pack check & warnings about critical MS issues switch (nCurrentOS) { case WIN_2000: if (CurrentOSServicePack < 3) Warning ("LARGE_IDE_WARNING_2K", NULL); else { DWORD val = 0, size = sizeof(val); HKEY hkey; if (RegOpenKeyExW (HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Services\\Atapi\\Parameters", 0, KEY_READ, &hkey) == ERROR_SUCCESS) { if (RegQueryValueExW (hkey, L"EnableBigLba", 0, 0, (LPBYTE) &val, &size) != ERROR_SUCCESS || val != 1) { Warning ("LARGE_IDE_WARNING_2K_REGISTRY", NULL); } RegCloseKey (hkey); } } break; case WIN_XP: if (CurrentOSServicePack < 1) { HKEY k; // PE environment does not report version of SP if (RegOpenKeyExW (HKEY_LOCAL_MACHINE, L"System\\CurrentControlSet\\Control\\minint", 0, KEY_READ, &k) != ERROR_SUCCESS) Warning ("LARGE_IDE_WARNING_XP", NULL); else RegCloseKey (k); } break; } } /* Get the attributes for the standard dialog class */ if ((GetClassInfoW (hInst, WINDOWS_DIALOG_CLASS, &wc)) == 0) { handleWin32Error (NULL, SRC_POS); AbortProcess ("INIT_REGISTER"); } #ifndef SETUP wc.hIcon = LoadIcon (hInstance, MAKEINTRESOURCE (IDI_TRUECRYPT_ICON)); #else #include "../setup/resource.h" wc.hIcon = LoadIcon (hInstance, MAKEINTRESOURCE (IDI_SETUP)); #endif wc.lpszClassName = TC_DLG_CLASS; wc.lpfnWndProc = &CustomDlgProc; wc.hCursor = LoadCursor (NULL, IDC_ARROW); wc.cbWndExtra = DLGWINDOWEXTRA; hDlgClass = RegisterClassW (&wc); if (hDlgClass == 0) { handleWin32Error (NULL, SRC_POS); AbortProcess ("INIT_REGISTER"); } wc.lpszClassName = TC_SPLASH_CLASS; wc.lpfnWndProc = &SplashDlgProc; wc.hCursor = LoadCursor (NULL, IDC_ARROW); wc.cbWndExtra = DLGWINDOWEXTRA; hSplashClass = RegisterClassW (&wc); if (hSplashClass == 0) { handleWin32Error (NULL, SRC_POS); AbortProcess ("INIT_REGISTER"); } // DPI and GUI aspect ratio DialogBoxParamW (hInst, MAKEINTRESOURCEW (IDD_AUXILIARY_DLG), NULL, (DLGPROC) AuxiliaryDlgProc, (LPARAM) 1); InitHelpFileName (); #ifndef SETUP #ifdef _WIN64 if (IsOSAtLeast (WIN_7)) { EnableRamEncryption ((ReadDriverConfigurationFlags() & VC_DRIVER_CONFIG_ENABLE_RAM_ENCRYPTION) ? TRUE : FALSE); if (IsRamEncryptionEnabled()) { if (!InitializeSecurityParameters(GetAppRandomSeed)) AbortProcess("OUTOFMEMORY"); } } #endif if (!EncryptionThreadPoolStart (ReadEncryptionThreadPoolFreeCpuCountLimit())) { handleWin32Error (NULL, SRC_POS); FREE_DLL (hRichEditDll); FREE_DLL (hComctl32Dll); FREE_DLL (hSetupDll); FREE_DLL (hShlwapiDll); FREE_DLL (hProfApiDll); FREE_DLL (hUsp10Dll); FREE_DLL (hCryptSpDll); FREE_DLL (hUXThemeDll); FREE_DLL (hUserenvDll); FREE_DLL (hRsaenhDll); FREE_DLL (himm32dll); FREE_DLL (hMSCTFdll); FREE_DLL (hfltlibdll); FREE_DLL (hframedyndll); FREE_DLL (hpsapidll); FREE_DLL (hsecur32dll); FREE_DLL (hnetapi32dll); FREE_DLL (hauthzdll); FREE_DLL (hxmllitedll); FREE_DLL (hmprdll); FREE_DLL (hsppdll); FREE_DLL (vssapidll); FREE_DLL (hvsstracedll); FREE_DLL (hCryptSpDll); FREE_DLL (hcfgmgr32dll); FREE_DLL (hdevobjdll); FREE_DLL (hpowrprofdll); FREE_DLL (hsspiclidll); FREE_DLL (hcryptbasedll); FREE_DLL (hdwmapidll); FREE_DLL (hmsasn1dll); FREE_DLL (hcrypt32dll); FREE_DLL (hbcryptdll); FREE_DLL (hbcryptprimitivesdll); FREE_DLL (hMsls31); FREE_DLL (hntmartadll); FREE_DLL (hwinscarddll); FREE_DLL (hmsvcrtdll); exit (1); } #endif } void FinalizeApp (void) { FREE_DLL (hRichEditDll); FREE_DLL (hComctl32Dll); FREE_DLL (hSetupDll); FREE_DLL (hShlwapiDll); FREE_DLL (hProfApiDll); FREE_DLL (hUsp10Dll); FREE_DLL (hCryptSpDll); FREE_DLL (hUXThemeDll); FREE_DLL (hUserenvDll); FREE_DLL (hRsaenhDll); FREE_DLL (himm32dll); FREE_DLL (hMSCTFdll); FREE_DLL (hfltlibdll); FREE_DLL (hframedyndll); FREE_DLL (hpsapidll); FREE_DLL (hsecur32dll); FREE_DLL (hnetapi32dll); FREE_DLL (hauthzdll); FREE_DLL (hxmllitedll); FREE_DLL (hmprdll); FREE_DLL (hsppdll); FREE_DLL (vssapidll); FREE_DLL (hvsstracedll); FREE_DLL (hCryptSpDll); FREE_DLL (hcfgmgr32dll); FREE_DLL (hdevobjdll); FREE_DLL (hpowrprofdll); FREE_DLL (hsspiclidll); FREE_DLL (hcryptbasedll); FREE_DLL (hdwmapidll); FREE_DLL (hmsasn1dll); FREE_DLL (hcrypt32dll); FREE_DLL (hbcryptdll); FREE_DLL (hbcryptprimitivesdll); FREE_DLL (hMsls31); FREE_DLL (hntmartadll); FREE_DLL (hwinscarddll); FREE_DLL (hmsvcrtdll); } void InitHelpFileName (void) { wchar_t *lpszTmp; GetModuleFileNameW (NULL, szHelpFile, ARRAYSIZE (szHelpFile)); lpszTmp = wcsrchr (szHelpFile, L'\\'); if (lpszTmp) { wchar_t szTemp[TC_MAX_PATH]; ++lpszTmp; *lpszTmp = 0; // add null terminating character to prepare for append operations // Primary file name if (strcmp (GetPreferredLangId(), "en") == 0 || strlen(GetPreferredLangId()) == 0) { StringCbCatW (szHelpFile, sizeof(szHelpFile), L"docs\\VeraCrypt User Guide.chm"); } else { StringCbPrintfW (szTemp, sizeof(szTemp), L"docs\\VeraCrypt User Guide.%S.chm", GetPreferredLangId()); StringCbCatW (szHelpFile, sizeof(szHelpFile), szTemp); } // Secondary file name (used when localized documentation is not found). GetModuleFileNameW (NULL, szHelpFile2, ARRAYSIZE (szHelpFile2)); lpszTmp = wcsrchr (szHelpFile2, L'\\'); if (lpszTmp) { ++lpszTmp; *lpszTmp = 0; StringCbCatW (szHelpFile2, sizeof(szHelpFile2), L"docs\\VeraCrypt User Guide.chm"); } } } #ifndef SETUP BOOL OpenDevice (const wchar_t *lpszPath, OPEN_TEST_STRUCT *driver, BOOL detectFilesystem, BOOL computeVolumeIDs) { DWORD dwResult; BOOL bResult; wchar_t wszFileName[TC_MAX_PATH]; StringCbCopyW (wszFileName, sizeof(wszFileName), lpszPath); memset (driver, 0, sizeof (OPEN_TEST_STRUCT)); memcpy (driver->wszFileName, wszFileName, sizeof (wszFileName)); driver->bDetectTCBootLoader = FALSE; driver->DetectFilesystem = detectFilesystem; driver->bComputeVolumeIDs = computeVolumeIDs; bResult = DeviceIoControl (hDriver, TC_IOCTL_OPEN_TEST, driver, sizeof (OPEN_TEST_STRUCT), driver, sizeof (OPEN_TEST_STRUCT), &dwResult, NULL); // check variable driver if ( bResult && ( (driver->bDetectTCBootLoader != TRUE && driver->bDetectTCBootLoader != FALSE) || (driver->TCBootLoaderDetected != TRUE && driver->TCBootLoaderDetected != FALSE) || (driver->DetectFilesystem != TRUE && driver->DetectFilesystem != FALSE) || (driver->FilesystemDetected != TRUE && driver->FilesystemDetected != FALSE) || (wcscmp (wszFileName, driver->wszFileName)) ) ) { return FALSE; } if (bResult == FALSE) { dwResult = GetLastError (); if (dwResult == ERROR_SHARING_VIOLATION || dwResult == ERROR_NOT_READY) { driver->TCBootLoaderDetected = FALSE; driver->FilesystemDetected = FALSE; memset (driver->VolumeIDComputed, 0, sizeof (driver->VolumeIDComputed)); return TRUE; } else return FALSE; } return TRUE; } #endif // Tells the driver that it's running in portable mode void NotifyDriverOfPortableMode (void) { if (hDriver != INVALID_HANDLE_VALUE) { DWORD dwResult; DeviceIoControl (hDriver, TC_IOCTL_SET_PORTABLE_MODE_STATUS, NULL, 0, NULL, 0, &dwResult, NULL); } } BOOL GetDriveLabel (int driveNo, wchar_t *label, int labelSize) { DWORD fileSystemFlags; wchar_t root[] = { L'A' + (wchar_t) driveNo, L':', L'\\', 0 }; return GetVolumeInformationW (root, label, labelSize / 2, NULL, NULL, &fileSystemFlags, NULL, 0); } #ifndef SETUP /* Stores the device path of the system partition in SysPartitionDevicePath and the device path of the system drive in SysDriveDevicePath. IMPORTANT: As this may take a very long time if called for the first time, it should be called only before performing a dangerous operation (such as header backup restore or formatting a supposedly non-system device) never at WM_INITDIALOG or any other GUI events -- instead call IsSystemDevicePath (path, hwndDlg, FALSE) for very fast preliminary GUI checks; also note that right after the "Select Device" dialog exits with an OK return code, you can use the global flags bSysPartitionSelected and bSysDriveSelected to see if the user selected the system partition/device. After this function completes successfully, the results are cached for the rest of the session and repeated executions complete very fast. Returns TRUE if successful (otherwise FALSE). */ BOOL GetSysDevicePaths (HWND hwndDlg) { if (!bCachedSysDevicePathsValid || wcslen (SysPartitionDevicePath) <= 1 || wcslen (SysDriveDevicePath) <= 1) { foreach (const HostDevice &device, GetAvailableHostDevices (false, true)) { if (device.ContainsSystem) StringCchCopyW (device.IsPartition ? SysPartitionDevicePath : SysDriveDevicePath, TC_MAX_PATH, device.Path.c_str()); } if (IsOSAtLeast (WIN_7)) { // Find extra boot partition foreach (const HostDevice &drive, GetAvailableHostDevices (false, false)) { if (drive.ContainsSystem) { foreach (const HostDevice &sysDrivePartition, drive.Partitions) { if (sysDrivePartition.Bootable) { if (sysDrivePartition.Size <= TC_MAX_EXTRA_BOOT_PARTITION_SIZE) ExtraBootPartitionDevicePath = sysDrivePartition.Path; break; } } break; } } } bCachedSysDevicePathsValid = 1; } return (bCachedSysDevicePathsValid && wcslen (SysPartitionDevicePath) > 1 && wcslen (SysDriveDevicePath) > 1); } /* Determines whether the device path is the path of the system partition or of the system drive (or neither). If bReliableRequired is TRUE, very fast execution is guaranteed, but the results cannot be relied upon. If it's FALSE and the function is called for the first time, execution may take up to one minute but the results are reliable. IMPORTANT: As the execution may take a very long time if called for the first time with bReliableRequired set to TRUE, it should be called with bReliableRequired set to TRUE only before performing a dangerous operation (such as header backup restore or formatting a supposedly non-system device) never at WM_INITDIALOG or any other GUI events (use IsSystemDevicePath(path, hwndDlg, FALSE) for fast preliminary GUI checks; also note that right after the "Select Device" dialog exits with an OK return code, you can use the global flags bSysPartitionSelected and bSysDriveSelected to see if the user selected the system partition/device). After this function completes successfully, the results are cached for the rest of the session, bReliableRequired is ignored (TRUE implied), repeated executions complete very fast, and the results are always reliable. Return codes: 1 - it is the system partition path (e.g. \Device\Harddisk0\Partition1) 2 - it is the system drive path (e.g. \Device\Harddisk0\Partition0) 3 - it is the extra boot partition path 0 - it's not the system partition/drive path -1 - the result can't be determined, isn't reliable, or there was an error. */ int IsSystemDevicePath (const wchar_t *path, HWND hwndDlg, BOOL bReliableRequired) { if (!bCachedSysDevicePathsValid && bReliableRequired) { if (!GetSysDevicePaths (hwndDlg)) return -1; } if (wcslen (SysPartitionDevicePath) <= 1 || wcslen (SysDriveDevicePath) <= 1) return -1; if (!path) return -1; if (wcsncmp (path, SysPartitionDevicePath, max (wcslen(path), wcslen(SysPartitionDevicePath))) == 0) return 1; else if (wcsncmp (path, SysDriveDevicePath, max (wcslen(path), wcslen(SysDriveDevicePath))) == 0) return 2; else if (ExtraBootPartitionDevicePath == path) return 3; return 0; } /* Determines whether the path points to a non-system partition on the system drive. IMPORTANT: As this may take a very long time if called for the first time, it should be called only before performing a dangerous operation, never at WM_INITDIALOG or any other GUI events. Return codes: 0 - it isn't a non-system partition on the system drive 1 - it's a non-system partition on the system drive -1 - the result can't be determined, isn't reliable, or there was an error. */ int IsNonSysPartitionOnSysDrive (const wchar_t *path) { wchar_t tmpPath [TC_MAX_PATH + 1]; int pos; if (!GetSysDevicePaths (MainDlg)) return -1; if (wcslen (SysPartitionDevicePath) <= 1 || wcslen (SysDriveDevicePath) <= 1) return -1; if (wcsncmp (path, SysPartitionDevicePath, max (wcslen(path), wcslen(SysPartitionDevicePath))) == 0 || wcsncmp (path, SysDriveDevicePath, max (wcslen(path), wcslen(SysDriveDevicePath))) == 0) { // It is the system partition/drive path (it isn't a non-system partition) return 0; } memset (tmpPath, 0, sizeof (tmpPath)); wcsncpy (tmpPath, path, ARRAYSIZE (tmpPath) - 1); pos = (int) FindString ((const char*) tmpPath, (const char*) L"Partition", (int) wcslen (tmpPath) * 2, (int) wcslen (L"Partition") * 2, 0); if (pos < 0) return -1; pos /= 2; pos += (int) strlen ("Partition"); if (pos + 1 > ARRAYSIZE (tmpPath) - 1) return -1; tmpPath [pos] = L'0'; tmpPath [pos + 1] = 0; if (wcsncmp (tmpPath, SysDriveDevicePath, max (wcslen(tmpPath), wcslen(SysDriveDevicePath))) == 0) { // It is a non-system partition on the system drive return 1; } else { // The partition is not on the system drive return 0; } } #endif //!SETUP wstring GetSysEncryptionPretestInfo2String (void) { // This huge string is divided into smaller portions to make it easier for translators to // re-translate it when a minor modification is made to it (the whole huge string will not be // reverted to English, so they will have to translate only a small portion of it). return (wstring (L"\n") + GetString ("SYS_ENCRYPTION_PRETEST_INFO2_PORTION_1") + GetString ("SYS_ENCRYPTION_PRETEST_INFO2_PORTION_2") + GetString ("SYS_ENCRYPTION_PRETEST_INFO2_PORTION_3") + GetString ("SYS_ENCRYPTION_PRETEST_INFO2_PORTION_4")); } wstring GetRescueDiskHelpString (void) { // This huge string is divided into smaller portions to make it easier for translators to // re-translate it when a minor modification is made to it (the whole huge string will not be // reverted to English, so they will have to translate only a small portion of it). return (wstring ( GetString ("RESCUE_DISK_HELP_PORTION_1")) + GetString ("RESCUE_DISK_HELP_PORTION_2") + GetString ("RESCUE_DISK_HELP_PORTION_3") + GetString ("RESCUE_DISK_HELP_PORTION_4") + GetString ("RESCUE_DISK_HELP_PORTION_5") + GetString ("RESCUE_DISK_HELP_PORTION_6") + GetString ("RESCUE_DISK_HELP_PORTION_7") + GetString ("RESCUE_DISK_HELP_PORTION_8") + GetString ("RESCUE_DISK_HELP_PORTION_9")); } wstring GetDecoyOsInstructionsString (void) { // This huge string is divided into smaller portions to make it easier for translators to // re-translate it when a minor modification is made to it (the whole huge string will not be // reverted to English, so they will have to translate only a small portion of it). return (wstring ( GetString ("DECOY_OS_INSTRUCTIONS_PORTION_1")) + GetString ("DECOY_OS_INSTRUCTIONS_PORTION_2") + GetString ("DECOY_OS_INSTRUCTIONS_PORTION_3") + GetString ("DECOY_OS_INSTRUCTIONS_PORTION_4") + GetString ("DECOY_OS_INSTRUCTIONS_PORTION_5") + GetString ("DECOY_OS_INSTRUCTIONS_PORTION_6") + GetString ("DECOY_OS_INSTRUCTIONS_PORTION_7") + GetString ("DECOY_OS_INSTRUCTIONS_PORTION_8") + GetString ("DECOY_OS_INSTRUCTIONS_PORTION_9") + GetString ("DECOY_OS_INSTRUCTIONS_PORTION_10") + GetString ("DECOY_OS_INSTRUCTIONS_PORTION_11") + GetString ("DECOY_OS_INSTRUCTIONS_PORTION_12") + GetString ("DECOY_OS_INSTRUCTIONS_PORTION_13") + GetString ("DECOY_OS_INSTRUCTIONS_PORTION_14") + GetString ("DECOY_OS_INSTRUCTIONS_PORTION_15") + GetString ("DECOY_OS_INSTRUCTIONS_PORTION_16") + GetString ("DECOY_OS_INSTRUCTIONS_PORTION_17") + GetString ("DECOY_OS_INSTRUCTIONS_PORTION_18")); } struct _TEXT_EDIT_DIALOG_PARAM { BOOL ReadOnly; std::string& Text; const WCHAR* Title; _TEXT_EDIT_DIALOG_PARAM(BOOL _readOnly, const WCHAR* title, std::string& _text) : Title(title), Text(_text), ReadOnly(_readOnly) {} _TEXT_EDIT_DIALOG_PARAM& operator=( const _TEXT_EDIT_DIALOG_PARAM& other) { ReadOnly = other.ReadOnly; Text = other.Text; Title = other.Title; return *this; } }; typedef struct _TEXT_EDIT_DIALOG_PARAM TEXT_INFO_DIALOG_PARAM,*TEXT_INFO_DIALOG_PARAM_PTR; INT_PTR TextEditDialogBox (BOOL readOnly, HWND parent, const WCHAR* Title, std::string& text) { TEXT_INFO_DIALOG_PARAM pm(readOnly, Title, text); return DialogBoxParamW (hInst, MAKEINTRESOURCEW (IDD_TEXT_EDIT_DLG), parent, (DLGPROC) TextEditDlgProc, (LPARAM) &pm); } BOOL CALLBACK TextEditDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) { WORD lw = LOWORD (wParam); static int nID = 0; static TEXT_INFO_DIALOG_PARAM_PTR prm; switch (msg) { case WM_INITDIALOG: { prm = (TEXT_INFO_DIALOG_PARAM_PTR)lParam; // increase size limit of rich edit control SendMessage(GetDlgItem (hwndDlg, IDC_INFO_BOX_TEXT), EM_EXLIMITTEXT, 0, -1); SetWindowTextW (hwndDlg, prm->Title); // Left margin for rich edit text field SendMessage (GetDlgItem (hwndDlg, IDC_INFO_BOX_TEXT), EM_SETMARGINS, (WPARAM) EC_LEFTMARGIN, (LPARAM) CompensateXDPI (4)); if (prm->ReadOnly) { // switch rich edit control to ReadOnly SendMessage(GetDlgItem (hwndDlg, IDC_INFO_BOX_TEXT), ES_READONLY, TRUE, 0); // hide cancel button ShowWindow(GetDlgItem(hwndDlg, IDCANCEL), SW_HIDE); } SendMessage (hwndDlg, TC_APPMSG_LOAD_TEXT_BOX_CONTENT, 0, 0); } return 0; case WM_COMMAND: if (lw == IDOK ) { if (!prm->ReadOnly) { prm->Text.resize(GetWindowTextLengthA (GetDlgItem (hwndDlg, IDC_INFO_BOX_TEXT)) + 1); GetWindowTextA (GetDlgItem (hwndDlg, IDC_INFO_BOX_TEXT), &(prm->Text)[0], (int) prm->Text.size()); } NormalCursor (); EndDialog (hwndDlg, IDOK); return 1; } if (lw == IDCANCEL ) { NormalCursor (); EndDialog (hwndDlg, IDCANCEL); return 1; } return 0; case TC_APPMSG_LOAD_TEXT_BOX_CONTENT: { SetWindowTextA (GetDlgItem (hwndDlg, IDC_INFO_BOX_TEXT), prm->Text.c_str()); } return 0; case WM_CLOSE: NormalCursor (); EndDialog (hwndDlg, 0); return 1; } return 0; } INT_PTR TextInfoDialogBox (int nID) { return DialogBoxParamW (hInst, MAKEINTRESOURCEW (IDD_TEXT_INFO_DIALOG_BOX_DLG), MainDlg, (DLGPROC) TextInfoDialogBoxDlgProc, (LPARAM) nID); } BOOL CALLBACK TextInfoDialogBoxDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) { WORD lw = LOWORD (wParam); static int nID = 0; switch (msg) { case WM_INITDIALOG: { nID = (int) lParam; // increase size limit of rich edit control SendMessage(GetDlgItem (hwndDlg, IDC_INFO_BOX_TEXT), EM_EXLIMITTEXT, 0, -1); // Left margin for rich edit text field SendMessage (GetDlgItem (hwndDlg, IDC_INFO_BOX_TEXT), EM_SETMARGINS, (WPARAM) EC_LEFTMARGIN, (LPARAM) CompensateXDPI (4)); ShowWindow(GetDlgItem(hwndDlg, IDC_PRINT), SW_HIDE); switch (nID) { case TC_TBXID_LEGAL_NOTICES: LocalizeDialog (hwndDlg, "LEGAL_NOTICES_DLG_TITLE"); break; case TC_TBXID_SYS_ENCRYPTION_PRETEST: LocalizeDialog (hwndDlg, NULL); ShowWindow(GetDlgItem(hwndDlg, IDC_PRINT), SW_SHOW); break; case TC_TBXID_SYS_ENC_RESCUE_DISK: LocalizeDialog (hwndDlg, NULL); ShowWindow(GetDlgItem(hwndDlg, IDC_PRINT), SW_SHOW); break; case TC_TBXID_DECOY_OS_INSTRUCTIONS: LocalizeDialog (hwndDlg, NULL); ShowWindow(GetDlgItem(hwndDlg, IDC_PRINT), SW_SHOW); break; case TC_TBXID_EXTRA_BOOT_PARTITION_REMOVAL_INSTRUCTIONS: LocalizeDialog (hwndDlg, NULL); ShowWindow(GetDlgItem(hwndDlg, IDC_PRINT), SW_SHOW); break; } SendMessage (hwndDlg, TC_APPMSG_LOAD_TEXT_BOX_CONTENT, 0, 0); } return 0; case WM_COMMAND: if (lw == IDOK || lw == IDCANCEL) { NormalCursor (); EndDialog (hwndDlg, 0); return 1; } if (lw == IDC_PRINT) { switch (nID) { case TC_TBXID_SYS_ENCRYPTION_PRETEST: PrintHardCopyTextUTF16 ((wchar_t *) GetSysEncryptionPretestInfo2String ().c_str(), L"Pre-Boot Troubleshooting", GetSysEncryptionPretestInfo2String ().length () * 2); break; case TC_TBXID_SYS_ENC_RESCUE_DISK: PrintHardCopyTextUTF16 ((wchar_t *) GetRescueDiskHelpString ().c_str(), L"VeraCrypt Rescue Disk Help", GetRescueDiskHelpString ().length () * 2); break; case TC_TBXID_DECOY_OS_INSTRUCTIONS: PrintHardCopyTextUTF16 ((wchar_t *) GetDecoyOsInstructionsString ().c_str(), L"How to Create Decoy OS", GetDecoyOsInstructionsString ().length () * 2); break; case TC_TBXID_EXTRA_BOOT_PARTITION_REMOVAL_INSTRUCTIONS: PrintHardCopyTextUTF16 (GetString ("EXTRA_BOOT_PARTITION_REMOVAL_INSTRUCTIONS"), L"How to Remove Extra Boot Partition", wcslen (GetString ("EXTRA_BOOT_PARTITION_REMOVAL_INSTRUCTIONS")) * 2); break; } return 1; } return 0; case TC_APPMSG_LOAD_TEXT_BOX_CONTENT: { char *r = NULL; switch (nID) { case TC_TBXID_LEGAL_NOTICES: LocalizeDialog (hwndDlg, "LEGAL_NOTICES_DLG_TITLE"); r = GetLegalNotices (); if (r != NULL) { SETTEXTEX TextInfo = {0}; TextInfo.flags = ST_SELECTION; TextInfo.codepage = CP_ACP; SendMessage(GetDlgItem (hwndDlg, IDC_INFO_BOX_TEXT), EM_SETTEXTEX, (WPARAM)&TextInfo, (LPARAM)r); free (r); } break; case TC_TBXID_SYS_ENCRYPTION_PRETEST: LocalizeDialog (hwndDlg, NULL); SetWindowTextW (GetDlgItem (hwndDlg, IDC_INFO_BOX_TEXT), (wchar_t *) GetSysEncryptionPretestInfo2String ().c_str()); break; case TC_TBXID_SYS_ENC_RESCUE_DISK: LocalizeDialog (hwndDlg, NULL); SetWindowTextW (GetDlgItem (hwndDlg, IDC_INFO_BOX_TEXT), (wchar_t *) GetRescueDiskHelpString ().c_str()); break; case TC_TBXID_DECOY_OS_INSTRUCTIONS: LocalizeDialog (hwndDlg, NULL); SetWindowTextW (GetDlgItem (hwndDlg, IDC_INFO_BOX_TEXT), (wchar_t *) GetDecoyOsInstructionsString ().c_str()); break; case TC_TBXID_EXTRA_BOOT_PARTITION_REMOVAL_INSTRUCTIONS: LocalizeDialog (hwndDlg, NULL); SetWindowTextW (GetDlgItem (hwndDlg, IDC_INFO_BOX_TEXT), GetString ("EXTRA_BOOT_PARTITION_REMOVAL_INSTRUCTIONS")); break; } } return 1; case WM_CLOSE: NormalCursor (); EndDialog (hwndDlg, 0); return 1; } return 0; } char * GetLegalNotices () { static char *resource; static DWORD size; char *buf = NULL; if (resource == NULL) resource = (char *) MapResource (L"Text", IDR_LICENSE, &size); if (resource != NULL) { buf = (char *) malloc (size + 1); if (buf != NULL) { memcpy (buf, resource, size); buf[size] = 0; } } return buf; } #ifndef SETUP BOOL CALLBACK RawDevicesDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) { static wchar_t *lpszFileName; // This is actually a pointer to a GLOBAL array static vector <HostDevice> devices; static map <int, HostDevice> itemToDeviceMap; WORD lw = LOWORD (wParam); switch (msg) { case WM_INITDIALOG: { LVCOLUMNW LvCol; HWND hList = GetDlgItem (hwndDlg, IDC_DEVICELIST); RawDevicesDlgParam* pDlgParam = (RawDevicesDlgParam *) lParam; LocalizeDialog (hwndDlg, "IDD_RAWDEVICES_DLG"); SendMessage (hList,LVM_SETEXTENDEDLISTVIEWSTYLE,0, LVS_EX_FULLROWSELECT|LVS_EX_HEADERDRAGDROP|LVS_EX_TWOCLICKACTIVATE|LVS_EX_LABELTIP ); memset (&LvCol,0,sizeof(LvCol)); LvCol.mask = LVCF_TEXT|LVCF_WIDTH|LVCF_SUBITEM|LVCF_FMT; LvCol.pszText = GetString ("DEVICE"); LvCol.cx = CompensateXDPI (186); LvCol.fmt = LVCFMT_LEFT; SendMessage (hList,LVM_INSERTCOLUMNW,0,(LPARAM)&LvCol); LvCol.pszText = GetString ("DRIVE"); LvCol.cx = CompensateXDPI (38); LvCol.fmt = LVCFMT_LEFT; SendMessage (hList,LVM_INSERTCOLUMNW,1,(LPARAM)&LvCol); LvCol.pszText = GetString ("SIZE"); LvCol.cx = CompensateXDPI (64); LvCol.fmt = LVCFMT_RIGHT; SendMessage (hList,LVM_INSERTCOLUMNW,2,(LPARAM)&LvCol); LvCol.pszText = GetString ("LABEL"); LvCol.cx = CompensateXDPI (128); LvCol.fmt = LVCFMT_LEFT; SendMessage (hList,LVM_INSERTCOLUMNW,3,(LPARAM)&LvCol); devices.clear(); itemToDeviceMap.clear(); if (pDlgParam->devices.empty()) { WaitCursor(); devices = GetAvailableHostDevices (false, true, false); NormalCursor(); } else devices = pDlgParam->devices; if (devices.empty()) { MessageBoxW (hwndDlg, GetString ("RAWDEVICES"), lpszTitle, ICON_HAND); EndDialog (hwndDlg, IDCANCEL); return 1; } int line = 1; LVITEM item; memset (&item, 0, sizeof (item)); item.mask = LVIF_TEXT; foreach (const HostDevice &device, devices) { item.iSubItem = 1; if (device.ContainsSystem) { if (device.IsPartition) StringCbCopyW (SysPartitionDevicePath, sizeof (SysPartitionDevicePath), device.Path.c_str()); else StringCbCopyW (SysDriveDevicePath, sizeof (SysDriveDevicePath), device.Path.c_str()); } // Path if (!device.IsPartition || device.DynamicVolume) { if (!device.Floppy && (device.Size == 0) && (device.IsPartition || device.Partitions.empty() || device.Partitions[0].Size == 0) ) continue; if (line > 1) { ListItemAdd (hList, item.iItem, L""); item.iItem = line++; } if (device.Floppy || device.DynamicVolume) { ListItemAdd (hList, item.iItem, (wchar_t *) device.Path.c_str()); } else { wchar_t s[1024]; if (device.Removable) StringCbPrintfW (s, sizeof(s), L"%s %d", GetString ("REMOVABLE_DISK"), device.SystemNumber); else StringCbPrintfW (s, sizeof(s), L"%s %d", GetString ("HARDDISK"), device.SystemNumber); if (!device.Partitions.empty()) StringCbCatW (s, sizeof(s), L":"); ListItemAdd (hList, item.iItem, s); } } else { ListItemAdd (hList, item.iItem, (wchar_t *) device.Path.c_str()); } itemToDeviceMap[item.iItem] = device; // Size if (device.Size != 0) { wchar_t size[100] = { 0 }; GetSizeString (device.Size, size, sizeof(size)); ListSubItemSet (hList, item.iItem, 2, size); } // Mount point if (!device.MountPoint.empty()) ListSubItemSet (hList, item.iItem, 1, (wchar_t *) device.MountPoint.c_str()); // Label if (!device.Name.empty()) ListSubItemSet (hList, item.iItem, 3, (wchar_t *) device.Name.c_str()); #ifdef TCMOUNT else { bool useInExplorer = false; wstring favoriteLabel = GetFavoriteVolumeLabel (device.Path, useInExplorer); if (!favoriteLabel.empty()) ListSubItemSet (hList, item.iItem, 3, (wchar_t *) favoriteLabel.c_str()); } #endif item.iItem = line++; } SendMessageW(hList, LVM_SETCOLUMNWIDTH, 0, MAKELPARAM(LVSCW_AUTOSIZE_USEHEADER, 0)); SendMessageW(hList, LVM_SETCOLUMNWIDTH, 1, MAKELPARAM(LVSCW_AUTOSIZE_USEHEADER, 0)); SendMessageW(hList, LVM_SETCOLUMNWIDTH, 2, MAKELPARAM(LVSCW_AUTOSIZE_USEHEADER, 0)); SendMessageW(hList, LVM_SETCOLUMNWIDTH, 3, MAKELPARAM(LVSCW_AUTOSIZE_USEHEADER, 0)); lpszFileName = pDlgParam->pszFileName; #ifdef VOLFORMAT EnableWindow (GetDlgItem (hwndDlg, IDOK), FALSE); #endif return 1; } case WM_COMMAND: case WM_NOTIFY: // catch non-device line selected if (msg == WM_NOTIFY && ((LPNMHDR) lParam)->code == LVN_ITEMCHANGED && (((LPNMLISTVIEW) lParam)->uNewState & LVIS_FOCUSED )) { BOOL bEnableOkButton = FALSE; LVITEM LvItem; memset(&LvItem,0,sizeof(LvItem)); LvItem.mask = LVIF_TEXT | LVIF_PARAM; LvItem.iItem = ((LPNMLISTVIEW) lParam)->iItem; LvItem.pszText = lpszFileName; LvItem.cchTextMax = TC_MAX_PATH; lpszFileName[0] = 0; SendMessage (GetDlgItem (hwndDlg, IDC_DEVICELIST), LVM_GETITEM, LvItem.iItem, (LPARAM) &LvItem); if (lpszFileName[0] != 0 && lpszFileName[0] != ' ') { bEnableOkButton = TRUE; #ifdef VOLFORMAT if ( bInPlaceEncNonSysResumed && (WizardMode == WIZARD_MODE_NONSYS_DEVICE) && LvItem.iItem != -1 && itemToDeviceMap.find (LvItem.iItem) != itemToDeviceMap.end() ) { const HostDevice selectedDevice = itemToDeviceMap[LvItem.iItem]; if (selectedDevice.ContainsSystem) { bEnableOkButton = FALSE; } } #endif } EnableWindow (GetDlgItem ((HWND) hwndDlg, IDOK), bEnableOkButton); return 1; } if (msg == WM_COMMAND && lw == IDOK || msg == WM_NOTIFY && ((NMHDR *)lParam)->code == LVN_ITEMACTIVATE) { int selectedItem = ListView_GetSelectionMark (GetDlgItem (hwndDlg, IDC_DEVICELIST)); if (selectedItem == -1 || itemToDeviceMap.find (selectedItem) == itemToDeviceMap.end()) return 1; // non-device line selected const HostDevice selectedDevice = itemToDeviceMap[selectedItem]; StringCchCopyW (lpszFileName, TC_MAX_PATH, selectedDevice.Path.c_str()); #ifdef VOLFORMAT if (selectedDevice.ContainsSystem && selectedDevice.IsPartition) { if (WizardMode != WIZARD_MODE_SYS_DEVICE) { if (bInPlaceEncNonSysResumed && (WizardMode == WIZARD_MODE_NONSYS_DEVICE)) { // disable selection return 1; } if (AskYesNo ("CONFIRM_SYSTEM_ENCRYPTION_MODE", hwndDlg) == IDNO) { EndDialog (hwndDlg, IDCANCEL); return 1; } bSysPartitionSelected = TRUE; bSysDriveSelected = FALSE; lpszFileName[0] = 0; SwitchWizardToSysEncMode (); NormalCursor (); EndDialog (hwndDlg, IDOK); return 1; } else { // This should never be the case because the Select Device dialog is not available in this wizard mode bSysPartitionSelected = TRUE; bSysDriveSelected = FALSE; lpszFileName[0] = 0; SwitchWizardToSysEncMode (); NormalCursor (); EndDialog (hwndDlg, IDCANCEL); return 1; } } if (!(selectedDevice.ContainsSystem && !selectedDevice.IsPartition)) { if (bWarnDeviceFormatAdvanced && !bHiddenVolDirect && AskWarnNoYes("FORMAT_DEVICE_FOR_ADVANCED_ONLY", hwndDlg) == IDNO) { if (AskNoYes("CONFIRM_CHANGE_WIZARD_MODE_TO_FILE_CONTAINER", hwndDlg) == IDYES) { SwitchWizardToFileContainerMode (); } EndDialog (hwndDlg, IDCANCEL); return 1; } if (!bHiddenVolDirect) bWarnDeviceFormatAdvanced = FALSE; } #else // #ifdef VOLFORMAT bSysPartitionSelected = (selectedDevice.ContainsSystem && selectedDevice.IsPartition); bSysDriveSelected = FALSE; #endif // #ifdef VOLFORMAT if (!selectedDevice.IsPartition && !selectedDevice.Floppy) { // Whole device selected #ifdef VOLFORMAT if (selectedDevice.ContainsSystem && !selectedDevice.IsPartition) { if (WizardMode != WIZARD_MODE_SYS_DEVICE) { if (bInPlaceEncNonSysResumed && (WizardMode == WIZARD_MODE_NONSYS_DEVICE)) { // disable selection return 1; } if (AskYesNo ("CONFIRM_SYSTEM_ENCRYPTION_MODE", hwndDlg) == IDNO) { NormalCursor (); EndDialog (hwndDlg, IDCANCEL); return 1; } bSysDriveSelected = TRUE; bSysPartitionSelected = FALSE; lpszFileName[0] = 0; SwitchWizardToSysEncMode (); NormalCursor (); EndDialog (hwndDlg, IDOK); return 1; } else { // This should never be the case because the Select Device dialog is not available in this wizard mode bSysDriveSelected = TRUE; bSysPartitionSelected = FALSE; lpszFileName[0] = 0; SwitchWizardToSysEncMode (); NormalCursor (); EndDialog (hwndDlg, IDCANCEL); return 1; } } // Disallow format if the device contains partitions, but not if the partition is virtual or system if (!selectedDevice.IsVirtualPartition && !bHiddenVolDirect) { if (!selectedDevice.Partitions.empty()) { EnableWindow (GetDlgItem (hwndDlg, IDOK), FALSE); Error ("DEVICE_PARTITIONS_ERR_W_INPLACE_ENC_NOTE", hwndDlg); return 1; } if (AskWarnNoYes ("WHOLE_NONSYS_DEVICE_ENC_CONFIRM", hwndDlg) == IDNO) return 1; } #else // #ifdef VOLFORMAT bSysDriveSelected = (selectedDevice.ContainsSystem && !selectedDevice.IsPartition); bSysPartitionSelected = FALSE; #endif // #ifdef VOLFORMAT } else bSysDriveSelected = FALSE; #ifdef VOLFORMAT bRemovableHostDevice = selectedDevice.Removable; #endif NormalCursor (); EndDialog (hwndDlg, IDOK); return 1; } if ((msg == WM_COMMAND) && (lw == IDCANCEL)) { NormalCursor (); EndDialog (hwndDlg, IDCANCEL); return 1; } return 0; } return 0; } #endif //!SETUP BOOL DoDriverInstall (HWND hwndDlg) { #ifdef SETUP if (SystemEncryptionUpdate) return TRUE; #endif SC_HANDLE hManager, hService = NULL; BOOL bOK = FALSE, bRet; hManager = OpenSCManager (NULL, NULL, SC_MANAGER_ALL_ACCESS); if (hManager == NULL) goto error; #ifdef SETUP StatusMessage (hwndDlg, "INSTALLING_DRIVER"); #endif hService = CreateService (hManager, L"veracrypt", L"veracrypt", SERVICE_ALL_ACCESS, SERVICE_KERNEL_DRIVER, SERVICE_SYSTEM_START, SERVICE_ERROR_NORMAL, L"System32\\drivers\\veracrypt.sys", NULL, NULL, NULL, NULL, NULL); if (hService == NULL) goto error; else CloseServiceHandle (hService); hService = OpenService (hManager, L"veracrypt", SERVICE_ALL_ACCESS); if (hService == NULL) goto error; #ifdef SETUP StatusMessage (hwndDlg, "STARTING_DRIVER"); #endif bRet = StartService (hService, 0, NULL); if (bRet == FALSE) goto error; bOK = TRUE; error: if (bOK == FALSE && GetLastError () != ERROR_SERVICE_ALREADY_RUNNING) { handleWin32Error (hwndDlg, SRC_POS); MessageBoxW (hwndDlg, GetString ("DRIVER_INSTALL_FAILED"), lpszTitle, MB_ICONHAND); } else bOK = TRUE; if (hService != NULL) CloseServiceHandle (hService); if (hManager != NULL) CloseServiceHandle (hManager); return bOK; } // Install and start driver service and mark it for removal (non-install mode) static int DriverLoad () { HANDLE file; WIN32_FIND_DATA find; SC_HANDLE hManager, hService = NULL; wchar_t driverPath[TC_MAX_PATH*2]; BOOL res; wchar_t *tmp; DWORD startType; if (ReadLocalMachineRegistryDword (L"SYSTEM\\CurrentControlSet\\Services\\veracrypt", L"Start", &startType) && startType == SERVICE_BOOT_START) return ERR_PARAMETER_INCORRECT; GetModuleFileName (NULL, driverPath, ARRAYSIZE (driverPath)); tmp = wcsrchr (driverPath, L'\\'); if (!tmp) { driverPath[0] = L'.'; driverPath[1] = 0; } else *tmp = 0; StringCbCatW (driverPath, sizeof(driverPath), !Is64BitOs () ? L"\\veracrypt.sys" : L"\\veracrypt-x64.sys"); file = FindFirstFile (driverPath, &find); if (file == INVALID_HANDLE_VALUE) { MessageBoxW (0, GetString ("DRIVER_NOT_FOUND"), lpszTitle, ICON_HAND); return ERR_DONT_REPORT; } FindClose (file); hManager = OpenSCManager (NULL, NULL, SC_MANAGER_ALL_ACCESS); if (hManager == NULL) { if (GetLastError () == ERROR_ACCESS_DENIED) { MessageBoxW (0, GetString ("ADMIN_PRIVILEGES_DRIVER"), lpszTitle, ICON_HAND); return ERR_DONT_REPORT; } return ERR_OS_ERROR; } hService = OpenService (hManager, L"veracrypt", SERVICE_ALL_ACCESS); if (hService != NULL) { // Remove stale service (driver is not loaded but service exists) DeleteService (hService); CloseServiceHandle (hService); Sleep (500); } hService = CreateService (hManager, L"veracrypt", L"veracrypt", SERVICE_ALL_ACCESS, SERVICE_KERNEL_DRIVER, SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL, driverPath, NULL, NULL, NULL, NULL, NULL); if (hService == NULL) { CloseServiceHandle (hManager); return ERR_OS_ERROR; } res = StartService (hService, 0, NULL); DeleteService (hService); CloseServiceHandle (hManager); CloseServiceHandle (hService); return !res ? ERR_OS_ERROR : ERROR_SUCCESS; } BOOL DriverUnload () { MOUNT_LIST_STRUCT driver; int refCount; int volumesMounted; DWORD dwResult; BOOL bResult; SC_HANDLE hManager, hService = NULL; BOOL bRet; SERVICE_STATUS status; int x; BOOL driverUnloaded = FALSE; if (hDriver == INVALID_HANDLE_VALUE) return TRUE; try { if (BootEncryption (NULL).GetStatus().DeviceFilterActive) return FALSE; } catch (...) { } // Test for mounted volumes bResult = DeviceIoControl (hDriver, TC_IOCTL_IS_ANY_VOLUME_MOUNTED, NULL, 0, &volumesMounted, sizeof (volumesMounted), &dwResult, NULL); if (!bResult) { bResult = DeviceIoControl (hDriver, TC_IOCTL_LEGACY_GET_MOUNTED_VOLUMES, NULL, 0, &driver, sizeof (driver), &dwResult, NULL); if (bResult) volumesMounted = driver.ulMountedDrives; } if (bResult) { if (volumesMounted != 0) return FALSE; } else return TRUE; // Test for any applications attached to driver refCount = GetDriverRefCount (); if (refCount > 1) return FALSE; CloseHandle (hDriver); hDriver = INVALID_HANDLE_VALUE; // Stop driver service hManager = OpenSCManager (NULL, NULL, SC_MANAGER_ALL_ACCESS); if (hManager == NULL) goto error; hService = OpenService (hManager, L"veracrypt", SERVICE_ALL_ACCESS); if (hService == NULL) goto error; bRet = QueryServiceStatus (hService, &status); if (bRet != TRUE) goto error; if (status.dwCurrentState != SERVICE_STOPPED) { ControlService (hService, SERVICE_CONTROL_STOP, &status); for (x = 0; x < 10; x++) { bRet = QueryServiceStatus (hService, &status); if (bRet != TRUE) goto error; if (status.dwCurrentState == SERVICE_STOPPED) { driverUnloaded = TRUE; break; } Sleep (200); } } else driverUnloaded = TRUE; error: if (hService != NULL) CloseServiceHandle (hService); if (hManager != NULL) CloseServiceHandle (hManager); if (driverUnloaded) { hDriver = INVALID_HANDLE_VALUE; return TRUE; } return FALSE; } int DriverAttach (void) { /* Try to open a handle to the device driver. It will be closed later. */ #ifndef SETUP int nLoadRetryCount = 0; start: #endif hDriver = CreateFile (WIN32_ROOT_PREFIX, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); if (hDriver == INVALID_HANDLE_VALUE) { #ifndef SETUP LoadSysEncSettings (); if (!CreateDriverSetupMutex ()) { // Another instance is already attempting to install, register or start the driver while (!CreateDriverSetupMutex ()) { Sleep (100); // Wait until the other instance finishes } // Try to open a handle to the driver again (keep the mutex in case the other instance failed) goto start; } else { // No other instance is currently attempting to install, register or start the driver if (SystemEncryptionStatus != SYSENC_STATUS_NONE) { // This is an inconsistent state. The config file indicates system encryption should be // active, but the driver is not running. This may happen e.g. when the pretest fails and // the user selects "Last Known Good Configuration" from the Windows boot menu. // To fix this, we're going to reinstall the driver, start it, and register it for boot. if (DoDriverInstall (NULL)) { Sleep (1000); hDriver = CreateFile (WIN32_ROOT_PREFIX, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); try { BootEncryption bootEnc (NULL); bootEnc.RegisterBootDriver (bootEnc.GetHiddenOSCreationPhase() != TC_HIDDEN_OS_CREATION_PHASE_NONE ? true : false); } catch (Exception &e) { e.Show (NULL); } } CloseDriverSetupMutex (); } else { // Attempt to load the driver (non-install/portable mode) load: BOOL res = DriverLoad (); CloseDriverSetupMutex (); if (res != ERROR_SUCCESS) return res; bPortableModeConfirmed = TRUE; if (hDriver != INVALID_HANDLE_VALUE) CloseHandle (hDriver); hDriver = CreateFile (WIN32_ROOT_PREFIX, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); } if (bPortableModeConfirmed) NotifyDriverOfPortableMode (); } #endif // #ifndef SETUP if (hDriver == INVALID_HANDLE_VALUE) return ERR_OS_ERROR; } CloseDriverSetupMutex (); if (hDriver != INVALID_HANDLE_VALUE) { DWORD dwResult; BOOL bResult = DeviceIoControl (hDriver, TC_IOCTL_GET_DRIVER_VERSION, NULL, 0, &DriverVersion, sizeof (DriverVersion), &dwResult, NULL); if (!bResult) bResult = DeviceIoControl (hDriver, TC_IOCTL_LEGACY_GET_DRIVER_VERSION, NULL, 0, &DriverVersion, sizeof (DriverVersion), &dwResult, NULL); #ifndef SETUP // Don't check version during setup to allow removal of another version if (bResult == FALSE) { return ERR_OS_ERROR; } else if (DriverVersion != VERSION_NUM) { // Unload an incompatbile version of the driver loaded in non-install mode and load the required version if (IsNonInstallMode () && CreateDriverSetupMutex () && DriverUnload () && nLoadRetryCount++ < 3) goto load; CloseDriverSetupMutex (); CloseHandle (hDriver); hDriver = INVALID_HANDLE_VALUE; return ERR_DRIVER_VERSION; } #else if (!bResult) DriverVersion = 0; #endif } return 0; } void ResetCurrentDirectory () { wchar_t p[MAX_PATH]; if (!IsNonInstallMode () && SHGetFolderPath (NULL, CSIDL_PROFILE, NULL, 0, p) == ERROR_SUCCESS) { SetCurrentDirectory (p); } else { GetModPath (p, ARRAYSIZE (p)); SetCurrentDirectory (p); } } BOOL BrowseFiles (HWND hwndDlg, char *stringId, wchar_t *lpszFileName, BOOL keepHistory, BOOL saveMode, wchar_t *browseFilter) { return BrowseFilesInDir (hwndDlg, stringId, NULL, lpszFileName, keepHistory, saveMode, browseFilter); } BOOL BrowseFilesInDir (HWND hwndDlg, char *stringId, wchar_t *initialDir, wchar_t *lpszFileName, BOOL keepHistory, BOOL saveMode, wchar_t *browseFilter, const wchar_t *initialFileName, const wchar_t *defaultExtension) { OPENFILENAMEW ofn; wchar_t file[TC_MAX_PATH] = { 0 }; wchar_t filter[1024]; BOOL status = FALSE; CoInitialize (NULL); ZeroMemory (&ofn, sizeof (ofn)); *lpszFileName = 0; if (initialDir) { ofn.lpstrInitialDir = initialDir; } if (initialFileName) StringCchCopyW (file, array_capacity (file), initialFileName); ofn.lStructSize = sizeof (ofn); ofn.hwndOwner = hwndDlg; StringCbPrintfW (filter, sizeof(filter), L"%ls (*.*)%c*.*%c%ls (*.hc)%c*.hc%c%c", GetString ("ALL_FILES"), 0, 0, GetString ("TC_VOLUMES"), 0, 0, 0); ofn.lpstrFilter = browseFilter ? browseFilter : filter; ofn.nFilterIndex = 1; ofn.lpstrFile = file; ofn.nMaxFile = sizeof (file) / sizeof (file[0]); ofn.lpstrTitle = GetString (stringId); ofn.lpstrDefExt = defaultExtension; ofn.Flags = OFN_HIDEREADONLY | OFN_PATHMUSTEXIST | (keepHistory ? 0 : OFN_DONTADDTORECENT) | (saveMode ? OFN_OVERWRITEPROMPT : 0); if (!keepHistory) CleanLastVisitedMRU (); SystemFileSelectorCallerThreadId = GetCurrentThreadId(); SystemFileSelectorCallPending = TRUE; if (!saveMode) { if (!GetOpenFileNameW (&ofn)) goto ret; } else { if (!GetSaveFileNameW (&ofn)) goto ret; } SystemFileSelectorCallPending = FALSE; StringCchCopyW (lpszFileName, MAX_PATH, file); if (!keepHistory) CleanLastVisitedMRU (); status = TRUE; ret: SystemFileSelectorCallPending = FALSE; ResetCurrentDirectory(); CoUninitialize(); return status; } static wchar_t SelectMultipleFilesPath[131072]; static int SelectMultipleFilesOffset; BOOL SelectMultipleFiles (HWND hwndDlg, const char *stringId, wchar_t *lpszFileName, size_t cbFileName,BOOL keepHistory) { OPENFILENAMEW ofn; wchar_t filter[1024]; BOOL status = FALSE; CoInitialize (NULL); ZeroMemory (&ofn, sizeof (ofn)); SelectMultipleFilesPath[0] = 0; *lpszFileName = 0; ofn.lStructSize = sizeof (ofn); ofn.hwndOwner = hwndDlg; StringCbPrintfW (filter, sizeof(filter), L"%ls (*.*)%c*.*%c%ls (*.hc)%c*.hc%c%c", GetString ("ALL_FILES"), 0, 0, GetString ("TC_VOLUMES"), 0, 0, 0); ofn.lpstrFilter = filter; ofn.nFilterIndex = 1; ofn.lpstrFile = SelectMultipleFilesPath; ofn.nMaxFile = 0xffff * 2; // The size must not exceed 0xffff*2 due to a bug in Windows 2000 and XP SP1 ofn.lpstrTitle = GetString (stringId); ofn.Flags = OFN_HIDEREADONLY | OFN_EXPLORER | OFN_PATHMUSTEXIST | OFN_ALLOWMULTISELECT | (keepHistory ? 0 : OFN_DONTADDTORECENT); if (!keepHistory) CleanLastVisitedMRU (); SystemFileSelectorCallerThreadId = GetCurrentThreadId(); SystemFileSelectorCallPending = TRUE; if (!GetOpenFileNameW (&ofn)) goto ret; SystemFileSelectorCallPending = FALSE; if (SelectMultipleFilesPath[ofn.nFileOffset - 1] != 0) { // Single file selected StringCbCopyW (lpszFileName, cbFileName, SelectMultipleFilesPath); SelectMultipleFilesOffset = 0; SecureZeroMemory (SelectMultipleFilesPath, sizeof (SelectMultipleFilesPath)); } else { // Multiple files selected SelectMultipleFilesOffset = ofn.nFileOffset; SelectMultipleFilesNext (lpszFileName, cbFileName); } if (!keepHistory) CleanLastVisitedMRU (); status = TRUE; ret: SystemFileSelectorCallPending = FALSE; ResetCurrentDirectory(); CoUninitialize(); return status; } BOOL SelectMultipleFilesNext (wchar_t *lpszFileName, size_t cbFileName) { if (SelectMultipleFilesOffset == 0) return FALSE; StringCbCopyW (lpszFileName, cbFileName,SelectMultipleFilesPath); lpszFileName[TC_MAX_PATH - 1] = 0; if (lpszFileName[wcslen (lpszFileName) - 1] != L'\\') StringCbCatW (lpszFileName, cbFileName,L"\\"); StringCbCatW (lpszFileName, cbFileName,SelectMultipleFilesPath + SelectMultipleFilesOffset); SelectMultipleFilesOffset += (int) wcslen (SelectMultipleFilesPath + SelectMultipleFilesOffset) + 1; if (SelectMultipleFilesPath[SelectMultipleFilesOffset] == 0) { SelectMultipleFilesOffset = 0; SecureZeroMemory (SelectMultipleFilesPath, sizeof (SelectMultipleFilesPath)); } return TRUE; } static int CALLBACK BrowseCallbackProc(HWND hwnd,UINT uMsg,LPARAM lp, LPARAM pData) { switch(uMsg) { case BFFM_INITIALIZED: { /* WParam is TRUE since we are passing a path. It would be FALSE if we were passing a pidl. */ SendMessageW (hwnd,BFFM_SETSELECTION,TRUE,(LPARAM)pData); break; } case BFFM_SELCHANGED: { wchar_t szDir[TC_MAX_PATH]; /* Set the status window to the currently selected path. */ if (SHGetPathFromIDList((LPITEMIDLIST) lp ,szDir)) { SendMessage (hwnd,BFFM_SETSTATUSTEXT,0,(LPARAM)szDir); } break; } default: break; } return 0; } BOOL BrowseDirectories (HWND hwndDlg, char *lpszTitle, wchar_t *dirName) { BROWSEINFOW bi; LPITEMIDLIST pidl; LPMALLOC pMalloc; BOOL bOK = FALSE; CoInitialize (NULL); if (SUCCEEDED (SHGetMalloc (&pMalloc))) { ZeroMemory (&bi, sizeof(bi)); bi.hwndOwner = hwndDlg; bi.pszDisplayName = 0; bi.lpszTitle = GetString (lpszTitle); bi.pidlRoot = 0; bi.ulFlags = BIF_RETURNONLYFSDIRS | BIF_STATUSTEXT; bi.lpfn = BrowseCallbackProc; bi.lParam = (LPARAM)dirName; pidl = SHBrowseForFolderW (&bi); if (pidl != NULL) { if (SHGetPathFromIDList(pidl, dirName)) { bOK = TRUE; } pMalloc->Free (pidl); pMalloc->Release(); } } CoUninitialize(); return bOK; } std::wstring GetWrongPasswordErrorMessage (HWND hwndDlg) { WCHAR szTmp[8192]; StringCbPrintfW (szTmp, sizeof(szTmp), GetString (KeyFilesEnable ? "PASSWORD_OR_KEYFILE_WRONG" : "PASSWORD_WRONG")); if (CheckCapsLock (hwndDlg, TRUE)) StringCbCatW (szTmp, sizeof(szTmp), GetString ("PASSWORD_WRONG_CAPSLOCK_ON")); #ifdef TCMOUNT wchar_t szDevicePath [TC_MAX_PATH+1] = {0}; GetWindowText (GetDlgItem (MainDlg, IDC_VOLUME), szDevicePath, ARRAYSIZE (szDevicePath)); if (TCBootLoaderOnInactiveSysEncDrive (szDevicePath)) { StringCbPrintfW (szTmp, sizeof(szTmp), GetString (KeyFilesEnable ? "PASSWORD_OR_KEYFILE_OR_MODE_WRONG" : "PASSWORD_OR_MODE_WRONG")); if (CheckCapsLock (hwndDlg, TRUE)) StringCbCatW (szTmp, sizeof(szTmp), GetString ("PASSWORD_WRONG_CAPSLOCK_ON")); StringCbCatW (szTmp, sizeof(szTmp), GetString ("SYSENC_MOUNT_WITHOUT_PBA_NOTE")); } #endif wstring msg = szTmp; #ifdef TCMOUNT if (KeyFilesEnable && HiddenFilesPresentInKeyfilePath) { msg += GetString ("HIDDEN_FILES_PRESENT_IN_KEYFILE_PATH"); HiddenFilesPresentInKeyfilePath = FALSE; } #endif return msg; } void handleError (HWND hwndDlg, int code, const char* srcPos) { WCHAR szTmp[4096]; if (Silent) return; switch (code & 0x0000FFFF) { case ERR_OS_ERROR: handleWin32Error (hwndDlg, srcPos); break; case ERR_OUTOFMEMORY: MessageBoxW (hwndDlg, AppendSrcPos (GetString ("OUTOFMEMORY"), srcPos).c_str(), lpszTitle, ICON_HAND); break; case ERR_PASSWORD_WRONG: MessageBoxW (hwndDlg, AppendSrcPos (GetWrongPasswordErrorMessage (hwndDlg).c_str(), srcPos).c_str(), lpszTitle, MB_ICONWARNING); break; case ERR_DRIVE_NOT_FOUND: MessageBoxW (hwndDlg, AppendSrcPos (GetString ("NOT_FOUND"), srcPos).c_str(), lpszTitle, ICON_HAND); break; case ERR_FILES_OPEN: MessageBoxW (hwndDlg, AppendSrcPos (GetString ("OPENFILES_DRIVER"), srcPos).c_str(), lpszTitle, ICON_HAND); break; case ERR_FILES_OPEN_LOCK: MessageBoxW (hwndDlg, AppendSrcPos (GetString ("OPENFILES_LOCK"), srcPos).c_str(), lpszTitle, ICON_HAND); break; case ERR_VOL_SIZE_WRONG: MessageBoxW (hwndDlg, AppendSrcPos (GetString ("VOL_SIZE_WRONG"), srcPos).c_str(), lpszTitle, ICON_HAND); break; case ERR_COMPRESSION_NOT_SUPPORTED: MessageBoxW (hwndDlg, AppendSrcPos (GetString ("COMPRESSION_NOT_SUPPORTED"), srcPos).c_str(), lpszTitle, ICON_HAND); break; case ERR_PASSWORD_CHANGE_VOL_TYPE: MessageBoxW (hwndDlg, AppendSrcPos (GetString ("WRONG_VOL_TYPE"), srcPos).c_str(), lpszTitle, ICON_HAND); break; case ERR_VOL_SEEKING: MessageBoxW (hwndDlg, AppendSrcPos (GetString ("VOL_SEEKING"), srcPos).c_str(), lpszTitle, ICON_HAND); break; case ERR_CIPHER_INIT_FAILURE: MessageBoxW (hwndDlg, AppendSrcPos (GetString ("ERR_CIPHER_INIT_FAILURE"), srcPos).c_str(), lpszTitle, ICON_HAND); break; case ERR_CIPHER_INIT_WEAK_KEY: MessageBoxW (hwndDlg, AppendSrcPos (GetString ("ERR_CIPHER_INIT_WEAK_KEY"), srcPos).c_str(), lpszTitle, ICON_HAND); break; case ERR_VOL_ALREADY_MOUNTED: MessageBoxW (hwndDlg, AppendSrcPos (GetString ("VOL_ALREADY_MOUNTED"), srcPos).c_str(), lpszTitle, ICON_HAND); break; case ERR_FILE_OPEN_FAILED: MessageBoxW (hwndDlg, AppendSrcPos (GetString ("FILE_OPEN_FAILED"), srcPos).c_str(), lpszTitle, ICON_HAND); break; case ERR_VOL_MOUNT_FAILED: MessageBoxW (hwndDlg, AppendSrcPos (GetString ("VOL_MOUNT_FAILED"), srcPos).c_str(), lpszTitle, ICON_HAND); break; case ERR_NO_FREE_DRIVES: MessageBoxW (hwndDlg, AppendSrcPos (GetString ("NO_FREE_DRIVES"), srcPos).c_str(), lpszTitle, ICON_HAND); break; case ERR_ACCESS_DENIED: MessageBoxW (hwndDlg, AppendSrcPos (GetString ("ACCESS_DENIED"), srcPos).c_str(), lpszTitle, ICON_HAND); break; case ERR_DRIVER_VERSION: Error ("DRIVER_VERSION", hwndDlg); break; case ERR_NEW_VERSION_REQUIRED: MessageBoxW (hwndDlg, AppendSrcPos (GetString ("NEW_VERSION_REQUIRED"), srcPos).c_str(), lpszTitle, ICON_HAND); break; case ERR_SELF_TESTS_FAILED: Error ("ERR_SELF_TESTS_FAILED", hwndDlg); break; case ERR_VOL_FORMAT_BAD: Error ("ERR_VOL_FORMAT_BAD", hwndDlg); break; case ERR_ENCRYPTION_NOT_COMPLETED: Error ("ERR_ENCRYPTION_NOT_COMPLETED", hwndDlg); break; case ERR_NONSYS_INPLACE_ENC_INCOMPLETE: Error ("ERR_NONSYS_INPLACE_ENC_INCOMPLETE", hwndDlg); break; case ERR_SYS_HIDVOL_HEAD_REENC_MODE_WRONG: Error ("ERR_SYS_HIDVOL_HEAD_REENC_MODE_WRONG", hwndDlg); break; case ERR_PARAMETER_INCORRECT: Error ("ERR_PARAMETER_INCORRECT", hwndDlg); break; case ERR_USER_ABORT: case ERR_DONT_REPORT: // A non-error break; case ERR_UNSUPPORTED_TRUECRYPT_FORMAT: StringCbPrintfW (szTmp, sizeof(szTmp), GetString ("UNSUPPORTED_TRUECRYPT_FORMAT"), (code >> 24), (code >> 16) & 0x000000FF); MessageBoxW (hwndDlg, AppendSrcPos (szTmp, srcPos).c_str(), lpszTitle, ICON_HAND); break; #ifndef SETUP case ERR_RAND_INIT_FAILED: StringCbPrintfW (szTmp, sizeof(szTmp), GetString ("INIT_RAND"), SRC_POS, GetLastError ()); MessageBoxW (hwndDlg, AppendSrcPos (szTmp, srcPos).c_str(), lpszTitle, MB_ICONERROR); break; case ERR_CAPI_INIT_FAILED: StringCbPrintfW (szTmp, sizeof(szTmp), GetString ("CAPI_RAND"), SRC_POS, CryptoAPILastError); MessageBoxW (hwndDlg, AppendSrcPos (szTmp, srcPos).c_str(), lpszTitle, MB_ICONERROR); break; #endif default: StringCbPrintfW (szTmp, sizeof(szTmp), GetString ("ERR_UNKNOWN"), code); MessageBoxW (hwndDlg, AppendSrcPos (szTmp, srcPos).c_str(), lpszTitle, ICON_HAND); } } BOOL CheckFileStreamWriteErrors (HWND hwndDlg, FILE *file, const wchar_t *fileName) { if (ferror (file)) { wchar_t s[TC_MAX_PATH]; StringCbPrintfW (s, sizeof (s), GetString ("CANNOT_WRITE_FILE_X"), fileName); ErrorDirect (s, hwndDlg); return FALSE; } return TRUE; } static BOOL CALLBACK LocalizeDialogEnum( HWND hwnd, LPARAM font) { // Localization of controls if (LocalizationActive) { int ctrlId = GetDlgCtrlID (hwnd); if (ctrlId != 0) { WCHAR name[10] = { 0 }; GetClassNameW (hwnd, name, array_capacity (name)); if (_wcsicmp (name, L"Button") == 0 || _wcsicmp (name, L"Static") == 0) { wchar_t *str = (wchar_t *) GetDictionaryValueByInt (ctrlId); if (str != NULL) SetWindowTextW (hwnd, str); } } } // Font SendMessageW (hwnd, WM_SETFONT, (WPARAM) font, 0); return TRUE; } void LocalizeDialog (HWND hwnd, char *stringId) { LastDialogId = stringId; SetWindowLongPtrW (hwnd, GWLP_USERDATA, (LONG_PTR) 'VERA'); SendMessageW (hwnd, WM_SETFONT, (WPARAM) hUserFont, 0); if (stringId == NULL) SetWindowTextW (hwnd, L"VeraCrypt"); else SetWindowTextW (hwnd, GetString (stringId)); if (hUserFont != 0) EnumChildWindows (hwnd, LocalizeDialogEnum, (LPARAM) hUserFont); } void OpenVolumeExplorerWindow (int driveNo) { wchar_t dosName[5]; SHFILEINFO fInfo; StringCbPrintfW (dosName, sizeof(dosName), L"%c:\\", (wchar_t) driveNo + L'A'); // Force explorer to discover the drive SHGetFileInfo (dosName, 0, &fInfo, sizeof (fInfo), 0); ShellExecute (NULL, L"open", dosName, NULL, NULL, SW_SHOWNORMAL); } static BOOL explorerCloseSent; static HWND explorerTopLevelWindow; static BOOL CALLBACK CloseVolumeExplorerWindowsChildEnum (HWND hwnd, LPARAM driveStr) { WCHAR s[MAX_PATH]; SendMessageW (hwnd, WM_GETTEXT, array_capacity (s), (LPARAM) s); if (wcsstr (s, (WCHAR *) driveStr) != NULL) { PostMessageW (explorerTopLevelWindow, WM_CLOSE, 0, 0); explorerCloseSent = TRUE; return FALSE; } return TRUE; } static BOOL CALLBACK CloseVolumeExplorerWindowsEnum (HWND hwnd, LPARAM driveNo) { WCHAR driveStr[10]; WCHAR s[MAX_PATH]; StringCbPrintfW (driveStr, sizeof(driveStr), L"%c:\\", driveNo + L'A'); GetClassNameW (hwnd, s, array_capacity (s)); if (wcscmp (s, L"CabinetWClass") == 0) { GetWindowTextW (hwnd, s, array_capacity (s)); if (wcsstr (s, driveStr) != NULL) { PostMessageW (hwnd, WM_CLOSE, 0, 0); explorerCloseSent = TRUE; return TRUE; } explorerTopLevelWindow = hwnd; EnumChildWindows (hwnd, CloseVolumeExplorerWindowsChildEnum, (LPARAM) driveStr); } return TRUE; } BOOL CloseVolumeExplorerWindows (HWND hwnd, int driveNo) { if (driveNo >= 0) { explorerCloseSent = FALSE; EnumWindows (CloseVolumeExplorerWindowsEnum, (LPARAM) driveNo); } return explorerCloseSent; } BOOL UpdateDriveCustomLabel (int driveNo, wchar_t* effectiveLabel, BOOL bSetValue) { wchar_t wszRegPath[MAX_PATH]; wchar_t driveStr[] = {L'A' + (wchar_t) driveNo, 0}; HKEY hKey; LSTATUS lStatus; DWORD cbLabelLen = (DWORD) ((wcslen (effectiveLabel) + 1) * sizeof (wchar_t)); BOOL bToBeDeleted = FALSE; StringCbPrintfW (wszRegPath, sizeof (wszRegPath), L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\DriveIcons\\%s\\DefaultLabel", driveStr); if (bSetValue) lStatus = RegCreateKeyExW (HKEY_CURRENT_USER, wszRegPath, NULL, NULL, 0, KEY_READ | KEY_WRITE | KEY_SET_VALUE, NULL, &hKey, NULL); else lStatus = RegOpenKeyExW (HKEY_CURRENT_USER, wszRegPath, 0, KEY_READ | KEY_WRITE | KEY_SET_VALUE, &hKey); if (ERROR_SUCCESS == lStatus) { if (bSetValue) lStatus = RegSetValueExW (hKey, NULL, NULL, REG_SZ, (LPCBYTE) effectiveLabel, cbLabelLen); else { wchar_t storedLabel[34] = {0}; DWORD cbStoredLen = sizeof (storedLabel) - 1, dwType; lStatus = RegQueryValueExW (hKey, NULL, NULL, &dwType, (LPBYTE) storedLabel, &cbStoredLen); if ((ERROR_SUCCESS == lStatus) && (REG_SZ == dwType) && (0 == wcscmp(storedLabel, effectiveLabel))) { // same label stored. mark key for deletion bToBeDeleted = TRUE; } } RegCloseKey (hKey); } if (bToBeDeleted) { StringCbPrintfW (wszRegPath, sizeof (wszRegPath), L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\DriveIcons\\%s", driveStr); lStatus = RegOpenKeyExW (HKEY_CURRENT_USER, wszRegPath, 0, KEY_READ | KEY_WRITE | KEY_SET_VALUE, &hKey); if (ERROR_SUCCESS == lStatus) { lStatus = RegDeleteKeyW (hKey, L"DefaultLabel"); RegCloseKey (hKey); } // delete drive letter of nothing else is present under it RegDeleteKeyW (HKEY_CURRENT_USER, wszRegPath); } return (ERROR_SUCCESS == lStatus)? TRUE : FALSE; } wstring GetUserFriendlyVersionString (int version) { wchar_t szTmp [64]; StringCbPrintfW (szTmp, sizeof(szTmp), L"%x", version); wstring versionString (szTmp); versionString.insert (version > 0xfff ? 2 : 1,L"."); return (versionString); } wstring IntToWideString (int val) { wchar_t szTmp [64]; StringCbPrintfW (szTmp, sizeof(szTmp), L"%d", val); return szTmp; } wstring ArrayToHexWideString (const unsigned char* pbData, int cbData) { static wchar_t* hexChar = L"0123456789ABCDEF"; wstring result; if (pbData) { for (int i = 0; i < cbData; i++) { result += hexChar[pbData[i] >> 4]; result += hexChar[pbData[i] & 0x0F]; } } return result; } bool HexToByte (wchar_t c, byte& b) { bool bRet = true; if (c >= L'0' && c <= L'9') b = (byte) (c - L'0'); else if (c >= L'a' && c <= L'z') b = (byte) (c - L'a' + 10); else if (c >= L'A' && c <= L'Z') b = (byte) (c - L'A' + 10); else bRet = false; return bRet; } bool HexWideStringToArray (const wchar_t* hexStr, std::vector<byte>& arr) { byte b1, b2; size_t i, len = wcslen (hexStr); arr.clear(); if (len %2) return false; for (i = 0; i < len/2; i++) { if (!HexToByte (*hexStr++, b1) || !HexToByte (*hexStr++, b2)) return false; arr.push_back (b1 << 4 | b2); } return true; } wstring GetTempPathString () { wchar_t tempPath[MAX_PATH]; DWORD tempLen = ::GetTempPath (ARRAYSIZE (tempPath), tempPath); if (tempLen == 0 || tempLen > ARRAYSIZE (tempPath)) throw ParameterIncorrect (SRC_POS); return wstring (tempPath); } void GetSizeString (unsigned __int64 size, wchar_t *str, size_t cbStr) { static wchar_t *b, *kb, *mb, *gb, *tb, *pb; static int serNo; if (b == NULL || serNo != LocalizationSerialNo) { serNo = LocalizationSerialNo; kb = GetString ("KB"); mb = GetString ("MB"); gb = GetString ("GB"); tb = GetString ("TB"); pb = GetString ("PB"); b = GetString ("BYTE"); } if (size > 1024I64*1024*1024*1024*1024*99) StringCbPrintfW (str, cbStr, L"%I64d %s", size/1024/1024/1024/1024/1024, pb); else if (size > 1024I64*1024*1024*1024*1024) StringCbPrintfW (str, cbStr, L"%.1f %s",(double)(size/1024.0/1024/1024/1024/1024), pb); else if (size > 1024I64*1024*1024*1024*99) StringCbPrintfW (str, cbStr, L"%I64d %s",size/1024/1024/1024/1024, tb); else if (size > 1024I64*1024*1024*1024) StringCbPrintfW (str, cbStr, L"%.1f %s",(double)(size/1024.0/1024/1024/1024), tb); else if (size > 1024I64*1024*1024*99) StringCbPrintfW (str, cbStr, L"%I64d %s",size/1024/1024/1024, gb); else if (size > 1024I64*1024*1024) StringCbPrintfW (str, cbStr, L"%.1f %s",(double)(size/1024.0/1024/1024), gb); else if (size > 1024I64*1024*99) StringCbPrintfW (str, cbStr, L"%I64d %s", size/1024/1024, mb); else if (size > 1024I64*1024) StringCbPrintfW (str, cbStr, L"%.1f %s",(double)(size/1024.0/1024), mb); else if (size >= 1024I64) StringCbPrintfW (str, cbStr, L"%I64d %s", size/1024, kb); else StringCbPrintfW (str, cbStr, L"%I64d %s", size, b); } #ifndef SETUP void GetSpeedString (unsigned __int64 speed, wchar_t *str, size_t cbStr) { static wchar_t *b, *kb, *mb, *gb, *tb, *pb; static int serNo; if (b == NULL || serNo != LocalizationSerialNo) { serNo = LocalizationSerialNo; kb = GetString ("KB_PER_SEC"); mb = GetString ("MB_PER_SEC"); gb = GetString ("GB_PER_SEC"); tb = GetString ("TB_PER_SEC"); pb = GetString ("PB_PER_SEC"); b = GetString ("B_PER_SEC"); } if (speed > 1024I64*1024*1024*1024*1024*99) StringCbPrintfW (str, cbStr, L"%I64d %s", speed/1024/1024/1024/1024/1024, pb); else if (speed > 1024I64*1024*1024*1024*1024) StringCbPrintfW (str, cbStr, L"%.1f %s",(double)(speed/1024.0/1024/1024/1024/1024), pb); else if (speed > 1024I64*1024*1024*1024*99) StringCbPrintfW (str, cbStr, L"%I64d %s",speed/1024/1024/1024/1024, tb); else if (speed > 1024I64*1024*1024*1024) StringCbPrintfW (str, cbStr, L"%.1f %s",(double)(speed/1024.0/1024/1024/1024), tb); else if (speed > 1024I64*1024*1024*99) StringCbPrintfW (str, cbStr, L"%I64d %s",speed/1024/1024/1024, gb); else if (speed > 1024I64*1024*1024) StringCbPrintfW (str, cbStr, L"%.1f %s",(double)(speed/1024.0/1024/1024), gb); else if (speed > 1024I64*1024*99) StringCbPrintfW (str, cbStr, L"%I64d %s", speed/1024/1024, mb); else if (speed > 1024I64*1024) StringCbPrintfW (str, cbStr, L"%.1f %s",(double)(speed/1024.0/1024), mb); else if (speed > 1024I64) StringCbPrintfW (str, cbStr, L"%I64d %s", speed/1024, kb); else StringCbPrintfW (str, cbStr, L"%I64d %s", speed, b); } static void ResetBenchmarkList (HWND hwndDlg) { LVCOLUMNW LvCol; HWND hList = GetDlgItem (hwndDlg, IDC_RESULTS); /* Render the results */ // delete data SendMessage (hList, LVM_DELETEALLITEMS, 0, 0); // Delete headers SendMessageW (hList, LVM_DELETECOLUMN, 1, 0); SendMessageW (hList, LVM_DELETECOLUMN, 1, 0); SendMessageW (hList, LVM_DELETECOLUMN, 1, 0); memset (&LvCol,0,sizeof(LvCol)); LvCol.mask = LVCF_TEXT|LVCF_WIDTH|LVCF_SUBITEM|LVCF_FMT; switch(benchmarkType) { case BENCHMARK_TYPE_ENCRYPTION: // Create headers LvCol.pszText = GetString ("ENCRYPTION"); LvCol.cx = CompensateXDPI (80); LvCol.fmt = LVCFMT_RIGHT; SendMessageW (hList,LVM_INSERTCOLUMNW,1,(LPARAM)&LvCol); LvCol.pszText = GetString ("DECRYPTION"); LvCol.cx = CompensateXDPI (80); LvCol.fmt = LVCFMT_RIGHT; SendMessageW (hList,LVM_INSERTCOLUMNW,2,(LPARAM)&LvCol); LvCol.pszText = GetString ("MEAN"); LvCol.cx = CompensateXDPI (80); LvCol.fmt = LVCFMT_RIGHT; SendMessageW (hList,LVM_INSERTCOLUMNW,3,(LPARAM)&LvCol); break; case BENCHMARK_TYPE_HASH: LvCol.pszText = GetString ("MEAN"); LvCol.cx = CompensateXDPI (80); LvCol.fmt = LVCFMT_RIGHT; SendMessageW (hList,LVM_INSERTCOLUMNW,1,(LPARAM)&LvCol); break; case BENCHMARK_TYPE_PRF: LvCol.pszText = GetString ("TIME"); LvCol.cx = CompensateXDPI (80); LvCol.fmt = LVCFMT_RIGHT; SendMessageW (hList,LVM_INSERTCOLUMNW,1,(LPARAM)&LvCol); LvCol.pszText = GetString ("ITERATIONS"); LvCol.cx = CompensateXDPI (80); LvCol.fmt = LVCFMT_RIGHT; SendMessageW (hList,LVM_INSERTCOLUMNW,2,(LPARAM)&LvCol); break; } } static void DisplayBenchmarkResults (HWND hwndDlg) { wchar_t item1[100]={0}; LVITEMW LvItem; HWND hList = GetDlgItem (hwndDlg, IDC_RESULTS); int ea, i; BOOL unsorted = TRUE; BENCHMARK_REC tmp_line; ResetBenchmarkList (hwndDlg); /* Sort the list */ switch (benchmarkSortMethod) { case BENCHMARK_SORT_BY_SPEED: while (unsorted) { unsorted = FALSE; for (i = 0; i < benchmarkTotalItems - 1; i++) { if (((benchmarkType == BENCHMARK_TYPE_PRF) && (benchmarkTable[i].meanBytesPerSec > benchmarkTable[i+1].meanBytesPerSec)) || ((benchmarkType != BENCHMARK_TYPE_PRF) && (benchmarkTable[i].meanBytesPerSec < benchmarkTable[i+1].meanBytesPerSec)) ) { unsorted = TRUE; memcpy (&tmp_line, &benchmarkTable[i], sizeof(BENCHMARK_REC)); memcpy (&benchmarkTable[i], &benchmarkTable[i+1], sizeof(BENCHMARK_REC)); memcpy (&benchmarkTable[i+1], &tmp_line, sizeof(BENCHMARK_REC)); } } } break; case BENCHMARK_SORT_BY_NAME: while (unsorted) { unsorted = FALSE; for (i = 0; i < benchmarkTotalItems - 1; i++) { if (benchmarkTable[i].id > benchmarkTable[i+1].id) { unsorted = TRUE; memcpy (&tmp_line, &benchmarkTable[i], sizeof(BENCHMARK_REC)); memcpy (&benchmarkTable[i], &benchmarkTable[i+1], sizeof(BENCHMARK_REC)); memcpy (&benchmarkTable[i+1], &tmp_line, sizeof(BENCHMARK_REC)); } } } break; } for (i = 0; i < benchmarkTotalItems; i++) { ea = benchmarkTable[i].id; memset (&LvItem,0,sizeof(LvItem)); LvItem.mask = LVIF_TEXT; LvItem.iItem = i; LvItem.iSubItem = 0; LvItem.pszText = (LPWSTR) benchmarkTable[i].name; SendMessageW (hList, LVM_INSERTITEM, 0, (LPARAM)&LvItem); switch(benchmarkType) { case BENCHMARK_TYPE_ENCRYPTION: GetSpeedString ((unsigned __int64) (benchmarkLastBufferSize / ((float) benchmarkTable[i].encSpeed / benchmarkPerformanceFrequency.QuadPart)), item1, sizeof(item1)); LvItem.iSubItem = 1; LvItem.pszText = item1; SendMessageW (hList, LVM_SETITEMW, 0, (LPARAM)&LvItem); GetSpeedString ((unsigned __int64) (benchmarkLastBufferSize / ((float) benchmarkTable[i].decSpeed / benchmarkPerformanceFrequency.QuadPart)), item1, sizeof(item1)); LvItem.iSubItem = 2; LvItem.pszText = item1; SendMessageW (hList, LVM_SETITEMW, 0, (LPARAM)&LvItem); GetSpeedString (benchmarkTable[i].meanBytesPerSec, item1, sizeof(item1)); LvItem.iSubItem = 3; LvItem.pszText = item1; SendMessageW (hList, LVM_SETITEMW, 0, (LPARAM)&LvItem); break; case BENCHMARK_TYPE_HASH: GetSpeedString (benchmarkTable[i].meanBytesPerSec, item1, sizeof(item1)); LvItem.iSubItem = 1; LvItem.pszText = item1; SendMessageW (hList, LVM_SETITEMW, 0, (LPARAM)&LvItem); break; case BENCHMARK_TYPE_PRF: swprintf_s (item1, sizeof(item1) / sizeof(item1[0]), L"%d ms", benchmarkTable[i].meanBytesPerSec); LvItem.iSubItem = 1; LvItem.pszText = item1; SendMessageW (hList, LVM_SETITEMW, 0, (LPARAM)&LvItem); swprintf_s (item1, sizeof(item1) / sizeof(item1[0]), L"%d", benchmarkTable[i].decSpeed); LvItem.iSubItem = 2; LvItem.pszText = item1; SendMessageW (hList, LVM_SETITEMW, 0, (LPARAM)&LvItem); break; } } SendMessageW(hList, LVM_SETCOLUMNWIDTH, 0, MAKELPARAM(LVSCW_AUTOSIZE_USEHEADER, 0)); SendMessageW(hList, LVM_SETCOLUMNWIDTH, 1, MAKELPARAM(LVSCW_AUTOSIZE_USEHEADER, 0)); SendMessageW(hList, LVM_SETCOLUMNWIDTH, 2, MAKELPARAM(LVSCW_AUTOSIZE_USEHEADER, 0)); SendMessageW(hList, LVM_SETCOLUMNWIDTH, 3, MAKELPARAM(LVSCW_AUTOSIZE_USEHEADER, 0)); } // specific implementation for support of benchmark operation in wait dialog mechanism typedef struct { HWND hBenchDlg; BOOL bStatus; } BenchmarkThreadParam; static BOOL PerformBenchmark(HWND hBenchDlg, HWND hwndDlg); void CALLBACK BenchmarkThreadProc(void* pArg, HWND hwndDlg) { BenchmarkThreadParam* pThreadParam = (BenchmarkThreadParam*) pArg; pThreadParam->bStatus = PerformBenchmark (pThreadParam->hBenchDlg, hwndDlg); } static BOOL PerformBenchmark(HWND hBenchDlg, HWND hwndDlg) { LARGE_INTEGER performanceCountStart, performanceCountEnd; BYTE *lpTestBuffer = NULL; PCRYPTO_INFO ci = NULL; UINT64_STRUCT startDataUnitNo; SYSTEM_INFO sysInfo = {0}; GetSystemInfo (&sysInfo); startDataUnitNo.Value = 0; /* set priority to critical only when there are 2 or more CPUs on the system */ if (sysInfo.dwNumberOfProcessors > 1 && (benchmarkType != BENCHMARK_TYPE_ENCRYPTION)) SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL); ci = crypto_open (); if (!ci) return FALSE; if (QueryPerformanceFrequency (&benchmarkPerformanceFrequency) == 0) { if (ci) crypto_close (ci); MessageBoxW (hwndDlg, GetString ("ERR_PERF_COUNTER"), lpszTitle, ICON_HAND); return FALSE; } if (benchmarkType != BENCHMARK_TYPE_PRF) { lpTestBuffer = (BYTE *) _aligned_malloc(benchmarkBufferSize - (benchmarkBufferSize % 16), 16); if (lpTestBuffer == NULL) { if (ci) crypto_close (ci); MessageBoxW (hwndDlg, GetString ("ERR_MEM_ALLOC"), lpszTitle, ICON_HAND); return FALSE; } VirtualLock (lpTestBuffer, benchmarkBufferSize - (benchmarkBufferSize % 16)); } WaitCursor (); benchmarkTotalItems = 0; switch(benchmarkType) { case BENCHMARK_TYPE_HASH: /* Measures the speed at which each of the hash algorithms processes the message to produce a single digest. */ { BYTE digest [MAX_DIGESTSIZE]; WHIRLPOOL_CTX wctx; RMD160_CTX rctx; sha512_ctx s2ctx; sha256_ctx s256ctx; STREEBOG_CTX stctx; int hid, i; for (hid = FIRST_PRF_ID; hid <= LAST_PRF_ID; hid++) { if (QueryPerformanceCounter (&performanceCountStart) == 0) goto counter_error; for (i = 1; i <= 2; i++) { switch (hid) { case SHA512: sha512_begin (&s2ctx); sha512_hash (lpTestBuffer, benchmarkBufferSize, &s2ctx); sha512_end ((unsigned char *) digest, &s2ctx); break; case SHA256: sha256_begin (&s256ctx); sha256_hash (lpTestBuffer, benchmarkBufferSize, &s256ctx); sha256_end ((unsigned char *) digest, &s256ctx); break; case RIPEMD160: RMD160Init(&rctx); RMD160Update(&rctx, lpTestBuffer, benchmarkBufferSize); RMD160Final((unsigned char *) digest, &rctx); break; case WHIRLPOOL: WHIRLPOOL_init (&wctx); WHIRLPOOL_add (lpTestBuffer, benchmarkBufferSize, &wctx); WHIRLPOOL_finalize (&wctx, (unsigned char *) digest); break; case STREEBOG: STREEBOG_init(&stctx); STREEBOG_add(&stctx, lpTestBuffer, benchmarkBufferSize); STREEBOG_finalize(&stctx, (unsigned char *)digest); break; } } if (QueryPerformanceCounter (&performanceCountEnd) == 0) goto counter_error; benchmarkTable[benchmarkTotalItems].encSpeed = performanceCountEnd.QuadPart - performanceCountStart.QuadPart; benchmarkTable[benchmarkTotalItems].decSpeed = benchmarkTable[benchmarkTotalItems].encSpeed; benchmarkTable[benchmarkTotalItems].id = hid; benchmarkTable[benchmarkTotalItems].meanBytesPerSec = (unsigned __int64) (benchmarkBufferSize / ((float) benchmarkTable[benchmarkTotalItems].encSpeed / benchmarkPerformanceFrequency.QuadPart / 2)); StringCbPrintfW (benchmarkTable[benchmarkTotalItems].name, sizeof(benchmarkTable[benchmarkTotalItems].name),L"%s", HashGetName(hid)); benchmarkTotalItems++; } } break; case BENCHMARK_TYPE_PRF: /* Measures the time that it takes for the PKCS-5 routine to derive a header key using each of the implemented PRF algorithms. */ { int thid, i; char dk[MASTER_KEYDATA_SIZE]; char *tmp_salt = {"\x00\x11\x22\x33\x44\x55\x66\x77\x88\x99\xAA\xBB\xCC\xDD\xEE\xFF\x01\x23\x45\x67\x89\xAB\xCD\xEF\x00\x11\x22\x33\x44\x55\x66\x77\x88\x99\xAA\xBB\xCC\xDD\xEE\xFF\x01\x23\x45\x67\x89\xAB\xCD\xEF\x00\x11\x22\x33\x44\x55\x66\x77\x88\x99\xAA\xBB\xCC\xDD\xEE\xFF"}; for (thid = FIRST_PRF_ID; thid <= LAST_PRF_ID; thid++) { if (benchmarkPreBoot && !benchmarkGPT && !HashForSystemEncryption (thid)) continue; if (QueryPerformanceCounter (&performanceCountStart) == 0) goto counter_error; for (i = 1; i <= 2; i++) { switch (thid) { case SHA512: /* PKCS-5 test with HMAC-SHA-512 used as the PRF */ derive_key_sha512 ("passphrase-1234567890", 21, tmp_salt, 64, get_pkcs5_iteration_count(thid, benchmarkPim, FALSE, benchmarkPreBoot), dk, MASTER_KEYDATA_SIZE); break; case SHA256: /* PKCS-5 test with HMAC-SHA-256 used as the PRF */ derive_key_sha256 ("passphrase-1234567890", 21, tmp_salt, 64, get_pkcs5_iteration_count(thid, benchmarkPim, FALSE, benchmarkPreBoot), dk, MASTER_KEYDATA_SIZE); break; case RIPEMD160: /* PKCS-5 test with HMAC-RIPEMD-160 used as the PRF */ derive_key_ripemd160 ("passphrase-1234567890", 21, tmp_salt, 64, get_pkcs5_iteration_count(thid, benchmarkPim, FALSE, benchmarkPreBoot), dk, MASTER_KEYDATA_SIZE); break; case WHIRLPOOL: /* PKCS-5 test with HMAC-Whirlpool used as the PRF */ derive_key_whirlpool ("passphrase-1234567890", 21, tmp_salt, 64, get_pkcs5_iteration_count(thid, benchmarkPim, FALSE, benchmarkPreBoot), dk, MASTER_KEYDATA_SIZE); break; case STREEBOG: /* PKCS-5 test with HMAC-STREEBOG used as the PRF */ derive_key_streebog("passphrase-1234567890", 21, tmp_salt, 64, get_pkcs5_iteration_count(thid, benchmarkPim, FALSE, benchmarkPreBoot), dk, MASTER_KEYDATA_SIZE); break; } } if (QueryPerformanceCounter (&performanceCountEnd) == 0) goto counter_error; benchmarkTable[benchmarkTotalItems].encSpeed = performanceCountEnd.QuadPart - performanceCountStart.QuadPart; benchmarkTable[benchmarkTotalItems].id = thid; benchmarkTable[benchmarkTotalItems].decSpeed = get_pkcs5_iteration_count(thid, benchmarkPim, FALSE, benchmarkPreBoot); benchmarkTable[benchmarkTotalItems].meanBytesPerSec = (unsigned __int64) (1000 * ((float) benchmarkTable[benchmarkTotalItems].encSpeed / benchmarkPerformanceFrequency.QuadPart / 2)); if (benchmarkPreBoot) { /* heuristics for boot times */ if (benchmarkGPT) { benchmarkTable[benchmarkTotalItems].meanBytesPerSec = (benchmarkTable[benchmarkTotalItems].meanBytesPerSec * 8) / 5; } else { if (thid == SHA256) { #ifdef _WIN64 benchmarkTable[benchmarkTotalItems].meanBytesPerSec = (benchmarkTable[benchmarkTotalItems].meanBytesPerSec * 26); #else benchmarkTable[benchmarkTotalItems].meanBytesPerSec = (benchmarkTable[benchmarkTotalItems].meanBytesPerSec * 24); #endif } else { #ifdef _WIN64 benchmarkTable[benchmarkTotalItems].meanBytesPerSec = (benchmarkTable[benchmarkTotalItems].meanBytesPerSec * 21) / 5; #else benchmarkTable[benchmarkTotalItems].meanBytesPerSec = (benchmarkTable[benchmarkTotalItems].meanBytesPerSec * 18) / 5; #endif } } } StringCbPrintfW (benchmarkTable[benchmarkTotalItems].name, sizeof(benchmarkTable[benchmarkTotalItems].name),L"%s", get_pkcs5_prf_name (thid)); benchmarkTotalItems++; } } break; case BENCHMARK_TYPE_ENCRYPTION: { /* Encryption algorithm benchmarks */ // CPU "warm up" (an attempt to prevent skewed results on systems where CPU frequency // gradually changes depending on CPU load). ci->ea = EAGetFirst(); if (!EAInit (ci->ea, ci->master_keydata, ci->ks)) { ci->mode = FIRST_MODE_OF_OPERATION_ID; if (EAInitMode (ci, ci->k2)) { int i; for (i = 0; i < 10; i++) { EncryptDataUnits (lpTestBuffer, &startDataUnitNo, (TC_LARGEST_COMPILER_UINT) benchmarkBufferSize / ENCRYPTION_DATA_UNIT_SIZE, ci); DecryptDataUnits (lpTestBuffer, &startDataUnitNo, (TC_LARGEST_COMPILER_UINT) benchmarkBufferSize / ENCRYPTION_DATA_UNIT_SIZE, ci); } } } for (ci->ea = EAGetFirst(); ci->ea != 0; ci->ea = EAGetNext(ci->ea)) { if (!EAIsFormatEnabled (ci->ea)) continue; if (ERR_CIPHER_INIT_FAILURE == EAInit (ci->ea, ci->master_keydata, ci->ks)) goto counter_error; ci->mode = FIRST_MODE_OF_OPERATION_ID; if (!EAInitMode (ci, ci->k2)) goto counter_error; if (QueryPerformanceCounter (&performanceCountStart) == 0) goto counter_error; EncryptDataUnits (lpTestBuffer, &startDataUnitNo, (TC_LARGEST_COMPILER_UINT) benchmarkBufferSize / ENCRYPTION_DATA_UNIT_SIZE, ci); if (QueryPerformanceCounter (&performanceCountEnd) == 0) goto counter_error; benchmarkTable[benchmarkTotalItems].encSpeed = performanceCountEnd.QuadPart - performanceCountStart.QuadPart; if (QueryPerformanceCounter (&performanceCountStart) == 0) goto counter_error; DecryptDataUnits (lpTestBuffer, &startDataUnitNo, (TC_LARGEST_COMPILER_UINT) benchmarkBufferSize / ENCRYPTION_DATA_UNIT_SIZE, ci); if (QueryPerformanceCounter (&performanceCountEnd) == 0) goto counter_error; benchmarkTable[benchmarkTotalItems].decSpeed = performanceCountEnd.QuadPart - performanceCountStart.QuadPart; benchmarkTable[benchmarkTotalItems].id = ci->ea; benchmarkTable[benchmarkTotalItems].meanBytesPerSec = ((unsigned __int64) (benchmarkBufferSize / ((float) benchmarkTable[benchmarkTotalItems].encSpeed / benchmarkPerformanceFrequency.QuadPart)) + (unsigned __int64) (benchmarkBufferSize / ((float) benchmarkTable[benchmarkTotalItems].decSpeed / benchmarkPerformanceFrequency.QuadPart))) / 2; EAGetName (benchmarkTable[benchmarkTotalItems].name, ci->ea, 1); benchmarkTotalItems++; } } break; } if (ci) crypto_close (ci); if (lpTestBuffer) { VirtualUnlock (lpTestBuffer, benchmarkBufferSize - (benchmarkBufferSize % 16)); _aligned_free(lpTestBuffer); } benchmarkLastBufferSize = benchmarkBufferSize; DisplayBenchmarkResults(hBenchDlg); EnableWindow (GetDlgItem (hBenchDlg, IDC_PERFORM_BENCHMARK), TRUE); EnableWindow (GetDlgItem (hBenchDlg, IDCLOSE), TRUE); NormalCursor (); return TRUE; counter_error: if (ci) crypto_close (ci); if (lpTestBuffer) { VirtualUnlock (lpTestBuffer, benchmarkBufferSize - (benchmarkBufferSize % 16)); _aligned_free(lpTestBuffer); } NormalCursor (); EnableWindow (GetDlgItem (hBenchDlg, IDC_PERFORM_BENCHMARK), TRUE); EnableWindow (GetDlgItem (hBenchDlg, IDCLOSE), TRUE); MessageBoxW (hwndDlg, GetString ("ERR_PERF_COUNTER"), lpszTitle, ICON_HAND); return FALSE; } BOOL CALLBACK BenchmarkDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) { WORD lw = LOWORD (wParam); LPARAM nIndex; static HWND hCboxSortMethod = NULL, hCboxBufferSize = NULL, hCboxList = NULL; switch (msg) { case WM_INITDIALOG: { LVCOLUMNW LvCol; wchar_t s[128]; HWND hList = GetDlgItem (hwndDlg, IDC_RESULTS); hCboxSortMethod = GetDlgItem (hwndDlg, IDC_BENCHMARK_SORT_METHOD); hCboxBufferSize = GetDlgItem (hwndDlg, IDC_BENCHMARK_BUFFER_SIZE); hCboxList = GetDlgItem (hwndDlg, IDC_BENCHMARK_LIST); LocalizeDialog (hwndDlg, "IDD_BENCHMARK_DLG"); benchmarkBufferSize = BENCHMARK_DEFAULT_BUF_SIZE; benchmarkSortMethod = BENCHMARK_SORT_BY_SPEED; benchmarkType = BENCHMARK_TYPE_ENCRYPTION; if (lParam) { benchmarkGPT = TRUE; } else benchmarkGPT = FALSE; SendMessage (hList,LVM_SETEXTENDEDLISTVIEWSTYLE,0, LVS_EX_FULLROWSELECT|LVS_EX_HEADERDRAGDROP|LVS_EX_LABELTIP ); memset (&LvCol,0,sizeof(LvCol)); LvCol.mask = LVCF_TEXT|LVCF_WIDTH|LVCF_SUBITEM|LVCF_FMT; LvCol.pszText = GetString ("ALGORITHM"); LvCol.cx = CompensateXDPI (114); LvCol.fmt = LVCFMT_LEFT; SendMessage (hList,LVM_INSERTCOLUMNW,0,(LPARAM)&LvCol); ResetBenchmarkList (hwndDlg); /* Combo boxes */ // Sort method SendMessage (hCboxSortMethod, CB_RESETCONTENT, 0, 0); nIndex = SendMessageW (hCboxSortMethod, CB_ADDSTRING, 0, (LPARAM) GetString ("ALPHABETICAL_CATEGORIZED")); SendMessage (hCboxSortMethod, CB_SETITEMDATA, nIndex, (LPARAM) 0); nIndex = SendMessageW (hCboxSortMethod, CB_ADDSTRING, 0, (LPARAM) GetString ("MEAN_SPEED")); SendMessage (hCboxSortMethod, CB_SETITEMDATA, nIndex, (LPARAM) 0); SendMessage (hCboxSortMethod, CB_SETCURSEL, 1, 0); // Default sort method // benchmark list SendMessage (hCboxList, CB_RESETCONTENT, 0, 0); nIndex = SendMessageW (hCboxList, CB_ADDSTRING, 0, (LPARAM) GetString ("ENCRYPTION_ALGORITHM")); SendMessage (hCboxList, CB_SETITEMDATA, nIndex, (LPARAM) 0); nIndex = SendMessageW (hCboxList, CB_ADDSTRING, 0, (LPARAM) GetString ("PKCS5_PRF")); SendMessage (hCboxList, CB_SETITEMDATA, nIndex, (LPARAM) 0); nIndex = SendMessageW (hCboxList, CB_ADDSTRING, 0, (LPARAM) GetString ("IDT_HASH_ALGO")); SendMessage (hCboxList, CB_SETITEMDATA, nIndex, (LPARAM) 0); SendMessage (hCboxList, CB_SETCURSEL, 0, 0); // Default: benchmark of encryption // Buffer size SendMessage (hCboxBufferSize, CB_RESETCONTENT, 0, 0); StringCbPrintfW (s, sizeof(s), L"100 %s", GetString ("KB")); nIndex = SendMessageW (hCboxBufferSize, CB_ADDSTRING, 0, (LPARAM) s); SendMessage (hCboxBufferSize, CB_SETITEMDATA, nIndex, (LPARAM) 100 * BYTES_PER_KB); StringCbPrintfW (s, sizeof(s), L"500 %s", GetString ("KB")); nIndex = SendMessageW (hCboxBufferSize, CB_ADDSTRING, 0, (LPARAM) s); SendMessage (hCboxBufferSize, CB_SETITEMDATA, nIndex, (LPARAM) 500 * BYTES_PER_KB); StringCbPrintfW (s, sizeof(s), L"1 %s", GetString ("MB")); nIndex = SendMessageW (hCboxBufferSize, CB_ADDSTRING, 0, (LPARAM) s); SendMessage (hCboxBufferSize, CB_SETITEMDATA, nIndex, (LPARAM) 1 * BYTES_PER_MB); StringCbPrintfW (s, sizeof(s), L"5 %s", GetString ("MB")); nIndex = SendMessageW (hCboxBufferSize, CB_ADDSTRING, 0, (LPARAM) s); SendMessage (hCboxBufferSize, CB_SETITEMDATA, nIndex, (LPARAM) 5 * BYTES_PER_MB); StringCbPrintfW (s, sizeof(s), L"10 %s", GetString ("MB")); nIndex = SendMessageW (hCboxBufferSize, CB_ADDSTRING, 0, (LPARAM) s); SendMessage (hCboxBufferSize, CB_SETITEMDATA, nIndex, (LPARAM) 10 * BYTES_PER_MB); StringCbPrintfW (s, sizeof(s), L"50 %s", GetString ("MB")); nIndex = SendMessageW (hCboxBufferSize, CB_ADDSTRING, 0, (LPARAM) s); SendMessage (hCboxBufferSize, CB_SETITEMDATA, nIndex, (LPARAM) 50 * BYTES_PER_MB); StringCbPrintfW (s, sizeof(s), L"100 %s", GetString ("MB")); nIndex = SendMessageW (hCboxBufferSize, CB_ADDSTRING, 0, (LPARAM) s); SendMessage (hCboxBufferSize, CB_SETITEMDATA, nIndex, (LPARAM) 100 * BYTES_PER_MB); StringCbPrintfW (s, sizeof(s), L"200 %s", GetString ("MB")); nIndex = SendMessageW (hCboxBufferSize, CB_ADDSTRING, 0, (LPARAM) s); SendMessage (hCboxBufferSize, CB_SETITEMDATA, nIndex, (LPARAM) 200 * BYTES_PER_MB); StringCbPrintfW (s, sizeof(s), L"500 %s", GetString ("MB")); nIndex = SendMessageW (hCboxBufferSize, CB_ADDSTRING, 0, (LPARAM) s); SendMessage (hCboxBufferSize, CB_SETITEMDATA, nIndex, (LPARAM) 500 * BYTES_PER_MB); StringCbPrintfW (s, sizeof(s), L"1 %s", GetString ("GB")); nIndex = SendMessageW (hCboxBufferSize, CB_ADDSTRING, 0, (LPARAM) s); SendMessage (hCboxBufferSize, CB_SETITEMDATA, nIndex, (LPARAM) 1 * BYTES_PER_GB); SendMessage (hCboxBufferSize, CB_SETCURSEL, 5, 0); // Default buffer size uint32 driverConfig = ReadDriverConfigurationFlags(); int isAesHwSupported = is_aes_hw_cpu_supported(); SetDlgItemTextW (hwndDlg, IDC_HW_AES, (wstring (L" ") + (GetString (isAesHwSupported ? ((driverConfig & TC_DRIVER_CONFIG_DISABLE_HARDWARE_ENCRYPTION) ? "UISTR_DISABLED" : "UISTR_YES") : "NOT_APPLICABLE_OR_NOT_AVAILABLE"))).c_str()); ToHyperlink (hwndDlg, IDC_HW_AES_LABEL_LINK); if (isAesHwSupported && (driverConfig & TC_DRIVER_CONFIG_DISABLE_HARDWARE_ENCRYPTION)) { Warning ("DISABLED_HW_AES_AFFECTS_PERFORMANCE", hwndDlg); } SYSTEM_INFO sysInfo; GetSystemInfo (&sysInfo); size_t nbrThreads = GetEncryptionThreadCount(); wchar_t nbrThreadsStr [300]; if (sysInfo.dwNumberOfProcessors < 2) { StringCbCopyW (nbrThreadsStr, sizeof(nbrThreadsStr), GetString ("NOT_APPLICABLE_OR_NOT_AVAILABLE")); } else if (nbrThreads < 2) { StringCbCopyW (nbrThreadsStr, sizeof(nbrThreadsStr), GetString ("UISTR_DISABLED")); } else { StringCbPrintfW (nbrThreadsStr, sizeof(nbrThreadsStr), GetString ("NUMBER_OF_THREADS"), nbrThreads); } SetDlgItemTextW (hwndDlg, IDC_PARALLELIZATION, (wstring (L" ") + nbrThreadsStr).c_str()); ToHyperlink (hwndDlg, IDC_PARALLELIZATION_LABEL_LINK); if (nbrThreads < min (sysInfo.dwNumberOfProcessors, GetMaxEncryptionThreadCount()) && sysInfo.dwNumberOfProcessors > 1) { Warning ("LIMITED_THREAD_COUNT_AFFECTS_PERFORMANCE", hwndDlg); } return 1; } break; case WM_COMMAND: switch (lw) { case IDC_BENCHMARK_SORT_METHOD: nIndex = SendMessage (hCboxSortMethod, CB_GETCURSEL, 0, 0); if (nIndex != benchmarkSortMethod) { benchmarkSortMethod = (int) nIndex; DisplayBenchmarkResults (hwndDlg); } return 1; case IDC_BENCHMARK_LIST: nIndex = SendMessage (hCboxList, CB_GETCURSEL, 0, 0); if (nIndex != benchmarkType) { benchmarkType = (int) nIndex; benchmarkTotalItems = 0; ResetBenchmarkList (hwndDlg); } if (benchmarkType == BENCHMARK_TYPE_PRF) { ShowWindow (GetDlgItem (hwndDlg, IDC_BENCHMARK_BUFFER_SIZE), SW_HIDE); ShowWindow (GetDlgItem (hwndDlg, IDT_BUFFER_SIZE), SW_HIDE); ShowWindow (GetDlgItem (hwndDlg, IDC_PIM), SW_SHOW); ShowWindow (GetDlgItem (hwndDlg, IDT_PIM), SW_SHOW); ShowWindow (GetDlgItem (hwndDlg, IDC_BENCHMARK_PREBOOT), SW_SHOW); } else { ShowWindow (GetDlgItem (hwndDlg, IDC_BENCHMARK_BUFFER_SIZE), SW_SHOW); ShowWindow (GetDlgItem (hwndDlg, IDT_BUFFER_SIZE), SW_SHOW); ShowWindow (GetDlgItem (hwndDlg, IDC_PIM), SW_HIDE); ShowWindow (GetDlgItem (hwndDlg, IDT_PIM), SW_HIDE); ShowWindow (GetDlgItem (hwndDlg, IDC_BENCHMARK_PREBOOT), SW_HIDE); } return 1; case IDC_PERFORM_BENCHMARK: if (benchmarkType == BENCHMARK_TYPE_PRF) { benchmarkPim = GetPim (hwndDlg, IDC_PIM, 0); benchmarkPreBoot = GetCheckBox (hwndDlg, IDC_BENCHMARK_PREBOOT); } else { nIndex = SendMessage (hCboxBufferSize, CB_GETCURSEL, 0, 0); benchmarkBufferSize = (int) SendMessage (hCboxBufferSize, CB_GETITEMDATA, nIndex, 0); } BenchmarkThreadParam threadParam; threadParam.hBenchDlg = hwndDlg; threadParam.bStatus = FALSE; WaitCursor (); ShowWaitDialog (hwndDlg, TRUE, BenchmarkThreadProc, &threadParam); NormalCursor (); if (threadParam.bStatus == FALSE) { EndDialog (hwndDlg, IDCLOSE); } return 1; case IDC_HW_AES_LABEL_LINK: Applink ("hwacceleration"); return 1; case IDC_PARALLELIZATION_LABEL_LINK: Applink ("parallelization"); return 1; case IDCLOSE: case IDCANCEL: EndDialog (hwndDlg, IDCLOSE); return 1; } return 0; break; case WM_CLOSE: EndDialog (hwndDlg, IDCLOSE); return 1; break; } return 0; } static BOOL CALLBACK RandomPoolEnrichementDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) { WORD lw = LOWORD (wParam); WORD hw = HIWORD (wParam); static unsigned char randPool [RNG_POOL_SIZE]; static unsigned char lastRandPool [RNG_POOL_SIZE]; static unsigned char maskRandPool [RNG_POOL_SIZE]; static BOOL bUseMask = FALSE; static DWORD mouseEntropyGathered = 0xFFFFFFFF; static DWORD mouseEventsInitialCount = 0; /* max value of entropy needed to fill all random pool = 8 * RNG_POOL_SIZE = 2560 bits */ static const DWORD maxEntropyLevel = RNG_POOL_SIZE * 8; static HWND hEntropyBar = NULL; static wchar_t outputDispBuffer [RNG_POOL_SIZE * 3 + RANDPOOL_DISPLAY_ROWS + 2]; static BOOL bDisplayPoolContents = FALSE; static BOOL bRandPoolDispAscii = FALSE; int hash_algo = RandGetHashFunction(); int hid; switch (msg) { case WM_INITDIALOG: { HWND hComboBox = GetDlgItem (hwndDlg, IDC_PRF_ID); HCRYPTPROV hRngProv = NULL; VirtualLock (randPool, sizeof(randPool)); VirtualLock (lastRandPool, sizeof(lastRandPool)); VirtualLock (outputDispBuffer, sizeof(outputDispBuffer)); VirtualLock (&mouseEntropyGathered, sizeof(mouseEntropyGathered)); VirtualLock (&mouseEventsInitialCount, sizeof(mouseEventsInitialCount)); VirtualLock (maskRandPool, sizeof(maskRandPool)); mouseEntropyGathered = 0xFFFFFFFF; mouseEventsInitialCount = 0; bUseMask = FALSE; if (CryptAcquireContext (&hRngProv, NULL, MS_ENHANCED_PROV, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT | CRYPT_SILENT)) { if (CryptGenRandom (hRngProv, sizeof (maskRandPool), maskRandPool)) bUseMask = TRUE; CryptReleaseContext (hRngProv, 0); } LocalizeDialog (hwndDlg, "IDD_RANDOM_POOL_ENRICHMENT"); SendMessage (hComboBox, CB_RESETCONTENT, 0, 0); for (hid = FIRST_PRF_ID; hid <= LAST_PRF_ID; hid++) { if (!HashIsDeprecated (hid)) AddComboPair (hComboBox, HashGetName(hid), hid); } SelectAlgo (hComboBox, &hash_algo); SetCheckBox (hwndDlg, IDC_DISPLAY_POOL_CONTENTS, bDisplayPoolContents); SetTimer (hwndDlg, 0xfd, RANDPOOL_DISPLAY_REFRESH_INTERVAL, NULL); SendMessage (GetDlgItem (hwndDlg, IDC_POOL_CONTENTS), WM_SETFONT, (WPARAM) hFixedDigitFont, (LPARAM) TRUE); hEntropyBar = GetDlgItem (hwndDlg, IDC_ENTROPY_BAR); SendMessage (hEntropyBar, PBM_SETRANGE32, 0, maxEntropyLevel); SendMessage (hEntropyBar, PBM_SETSTEP, 1, 0); SendMessage (hEntropyBar, PBM_SETSTATE, PBST_ERROR, 0); return 1; } case WM_TIMER: { wchar_t tmp[4]; unsigned char tmpByte; int col, row; DWORD mouseEventsCounter; RandpeekBytes (hwndDlg, randPool, sizeof (randPool), &mouseEventsCounter); ProcessEntropyEstimate (hEntropyBar, &mouseEventsInitialCount, mouseEventsCounter, maxEntropyLevel, &mouseEntropyGathered); if (memcmp (lastRandPool, randPool, sizeof(lastRandPool)) != 0) { outputDispBuffer[0] = 0; for (row = 0; row < RANDPOOL_DISPLAY_ROWS; row++) { for (col = 0; col < RANDPOOL_DISPLAY_COLUMNS; col++) { if (bDisplayPoolContents) { tmpByte = randPool[row * RANDPOOL_DISPLAY_COLUMNS + col]; StringCbPrintfW (tmp, sizeof(tmp), bRandPoolDispAscii ? ((tmpByte >= 32 && tmpByte < 255 && tmpByte != L'&') ? L" %c " : L" . ") : L"%02X ", tmpByte); } else if (bUseMask) { /* use mask to compute a randomized ascii representation */ tmpByte = (randPool[row * RANDPOOL_DISPLAY_COLUMNS + col] - lastRandPool[row * RANDPOOL_DISPLAY_COLUMNS + col]) ^ maskRandPool [row * RANDPOOL_DISPLAY_COLUMNS + col]; tmp[0] = (wchar_t) (((tmpByte >> 4) % 6) + L'*'); tmp[1] = (wchar_t) (((tmpByte & 0x0F) % 6) + L'*'); tmp[2] = L' '; tmp[3] = 0; } else { StringCbCopyW (tmp, sizeof(tmp), L"** "); } StringCbCatW (outputDispBuffer, sizeof(outputDispBuffer), tmp); } StringCbCatW (outputDispBuffer, sizeof(outputDispBuffer), L"\n"); } SetWindowText (GetDlgItem (hwndDlg, IDC_POOL_CONTENTS), outputDispBuffer); memcpy (lastRandPool, randPool, sizeof(lastRandPool)); } return 1; } case WM_COMMAND: if (lw == IDC_CONTINUE) lw = IDOK; if (lw == IDOK || lw == IDCLOSE || lw == IDCANCEL) { goto exit; } if (lw == IDC_PRF_ID && hw == CBN_SELCHANGE) { hid = (int) SendMessage (GetDlgItem (hwndDlg, IDC_PRF_ID), CB_GETCURSEL, 0, 0); hash_algo = (int) SendMessage (GetDlgItem (hwndDlg, IDC_PRF_ID), CB_GETITEMDATA, hid, 0); RandSetHashFunction (hash_algo); return 1; } if (lw == IDC_DISPLAY_POOL_CONTENTS) { if (!(bDisplayPoolContents = GetCheckBox (hwndDlg, IDC_DISPLAY_POOL_CONTENTS))) { wchar_t tmp[RNG_POOL_SIZE+1]; wmemset (tmp, L' ', ARRAYSIZE(tmp)); tmp [RNG_POOL_SIZE] = 0; SetWindowText (GetDlgItem (hwndDlg, IDC_POOL_CONTENTS), tmp); } return 1; } return 0; case WM_CLOSE: { wchar_t tmp[RNG_POOL_SIZE+1]; exit: KillTimer (hwndDlg, 0xfd); burn (randPool, sizeof(randPool)); burn (lastRandPool, sizeof(lastRandPool)); burn (outputDispBuffer, sizeof(outputDispBuffer)); burn (&mouseEntropyGathered, sizeof(mouseEntropyGathered)); burn (&mouseEventsInitialCount, sizeof(mouseEventsInitialCount)); burn (maskRandPool, sizeof(maskRandPool)); // Attempt to wipe the pool contents in the GUI text area wmemset (tmp, L' ', RNG_POOL_SIZE); tmp [RNG_POOL_SIZE] = 0; SetWindowText (GetDlgItem (hwndDlg, IDC_POOL_CONTENTS), tmp); if (msg == WM_COMMAND && lw == IDOK) EndDialog (hwndDlg, IDOK); else EndDialog (hwndDlg, IDCLOSE); return 1; } } return 0; } /* Randinit is always called before UserEnrichRandomPool, so we don't need * the extra Randinit call here since it will always succeed but we keep it * for clarity purposes */ void UserEnrichRandomPool (HWND hwndDlg) { if ((0 == Randinit()) && !IsRandomPoolEnrichedByUser()) { INT_PTR result = DialogBoxParamW (hInst, MAKEINTRESOURCEW (IDD_RANDOM_POOL_ENRICHMENT), hwndDlg ? hwndDlg : MainDlg, (DLGPROC) RandomPoolEnrichementDlgProc, (LPARAM) 0); SetRandomPoolEnrichedByUserStatus (result == IDOK); } } /* Except in response to the WM_INITDIALOG message, the dialog box procedure should return nonzero if it processes the message, and zero if it does not. - see DialogProc */ BOOL CALLBACK KeyfileGeneratorDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) { WORD lw = LOWORD (wParam); WORD hw = HIWORD (wParam); static unsigned char randPool [RNG_POOL_SIZE]; static unsigned char lastRandPool [RNG_POOL_SIZE]; static unsigned char maskRandPool [RNG_POOL_SIZE]; static BOOL bUseMask = FALSE; static DWORD mouseEntropyGathered = 0xFFFFFFFF; static DWORD mouseEventsInitialCount = 0; /* max value of entropy needed to fill all random pool = 8 * RNG_POOL_SIZE = 2560 bits */ static const DWORD maxEntropyLevel = RNG_POOL_SIZE * 8; static HWND hEntropyBar = NULL; static wchar_t outputDispBuffer [RNG_POOL_SIZE * 3 + RANDPOOL_DISPLAY_ROWS + 2]; static BOOL bDisplayPoolContents = FALSE; static BOOL bRandPoolDispAscii = FALSE; int hash_algo = RandGetHashFunction(); int hid; switch (msg) { case WM_INITDIALOG: { HWND hComboBox = GetDlgItem (hwndDlg, IDC_PRF_ID); HCRYPTPROV hRngProv = NULL; VirtualLock (randPool, sizeof(randPool)); VirtualLock (lastRandPool, sizeof(lastRandPool)); VirtualLock (outputDispBuffer, sizeof(outputDispBuffer)); VirtualLock (&mouseEntropyGathered, sizeof(mouseEntropyGathered)); VirtualLock (&mouseEventsInitialCount, sizeof(mouseEventsInitialCount)); VirtualLock (maskRandPool, sizeof(maskRandPool)); mouseEntropyGathered = 0xFFFFFFFF; mouseEventsInitialCount = 0; bUseMask = FALSE; if (CryptAcquireContext (&hRngProv, NULL, MS_ENHANCED_PROV, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT | CRYPT_SILENT)) { if (CryptGenRandom (hRngProv, sizeof (maskRandPool), maskRandPool)) bUseMask = TRUE; CryptReleaseContext (hRngProv, 0); } LocalizeDialog (hwndDlg, "IDD_KEYFILE_GENERATOR"); SendMessage (hComboBox, CB_RESETCONTENT, 0, 0); for (hid = FIRST_PRF_ID; hid <= LAST_PRF_ID; hid++) { if (!HashIsDeprecated (hid)) AddComboPair (hComboBox, HashGetName(hid), hid); } SelectAlgo (hComboBox, &hash_algo); SetCheckBox (hwndDlg, IDC_DISPLAY_POOL_CONTENTS, bDisplayPoolContents); hEntropyBar = GetDlgItem (hwndDlg, IDC_ENTROPY_BAR); SendMessage (hEntropyBar, PBM_SETRANGE32, 0, maxEntropyLevel); SendMessage (hEntropyBar, PBM_SETSTEP, 1, 0); SendMessage (hEntropyBar, PBM_SETSTATE, PBST_ERROR, 0); #ifndef VOLFORMAT if (Randinit ()) { handleError (hwndDlg, (CryptoAPILastError == ERROR_SUCCESS)? ERR_RAND_INIT_FAILED : ERR_CAPI_INIT_FAILED, SRC_POS); EndDialog (hwndDlg, IDCLOSE); } #endif SetTimer (hwndDlg, 0xfd, RANDPOOL_DISPLAY_REFRESH_INTERVAL, NULL); SendMessage (GetDlgItem (hwndDlg, IDC_POOL_CONTENTS), WM_SETFONT, (WPARAM) hFixedDigitFont, (LPARAM) TRUE); // 9-digit limit for the number of keyfiles (more than enough!) SendMessage (GetDlgItem (hwndDlg, IDC_NUMBER_KEYFILES), EM_SETLIMITTEXT, (WPARAM) 9, 0); SetWindowText(GetDlgItem (hwndDlg, IDC_NUMBER_KEYFILES), L"1"); // maximum keyfile size is 1048576, so limit the edit control to 7 characters SendMessage (GetDlgItem (hwndDlg, IDC_KEYFILES_SIZE), EM_SETLIMITTEXT, (WPARAM) 7, 0); SetWindowText(GetDlgItem (hwndDlg, IDC_KEYFILES_SIZE), L"64"); // set the maximum length of the keyfile base name to (TC_MAX_PATH - 1) SendMessage (GetDlgItem (hwndDlg, IDC_KEYFILES_BASE_NAME), EM_SETLIMITTEXT, (WPARAM) (TC_MAX_PATH - 1), 0); return 1; } case WM_TIMER: { wchar_t tmp[4]; unsigned char tmpByte; int col, row; DWORD mouseEventsCounter; RandpeekBytes (hwndDlg, randPool, sizeof (randPool), &mouseEventsCounter); ProcessEntropyEstimate (hEntropyBar, &mouseEventsInitialCount, mouseEventsCounter, maxEntropyLevel, &mouseEntropyGathered); if (memcmp (lastRandPool, randPool, sizeof(lastRandPool)) != 0) { outputDispBuffer[0] = 0; for (row = 0; row < RANDPOOL_DISPLAY_ROWS; row++) { for (col = 0; col < RANDPOOL_DISPLAY_COLUMNS; col++) { if (bDisplayPoolContents) { tmpByte = randPool[row * RANDPOOL_DISPLAY_COLUMNS + col]; StringCbPrintfW (tmp, sizeof(tmp), bRandPoolDispAscii ? ((tmpByte >= 32 && tmpByte < 255 && tmpByte != L'&') ? L" %c " : L" . ") : L"%02X ", tmpByte); } else if (bUseMask) { /* use mask to compute a randomized ASCII representation */ tmpByte = (randPool[row * RANDPOOL_DISPLAY_COLUMNS + col] - lastRandPool[row * RANDPOOL_DISPLAY_COLUMNS + col]) ^ maskRandPool [row * RANDPOOL_DISPLAY_COLUMNS + col]; tmp[0] = (wchar_t) (((tmpByte >> 4) % 6) + L'*'); tmp[1] = (wchar_t) (((tmpByte & 0x0F) % 6) + L'*'); tmp[2] = L' '; tmp[3] = 0; } else { StringCbCopyW (tmp, sizeof(tmp), L"** "); } StringCbCatW (outputDispBuffer, sizeof(outputDispBuffer), tmp); } StringCbCatW (outputDispBuffer, sizeof(outputDispBuffer), L"\n"); } SetWindowText (GetDlgItem (hwndDlg, IDC_POOL_CONTENTS), outputDispBuffer); memcpy (lastRandPool, randPool, sizeof(lastRandPool)); } return 1; } case WM_COMMAND: if (lw == IDCLOSE || lw == IDCANCEL) { goto exit; } if (lw == IDC_PRF_ID && hw == CBN_SELCHANGE) { hid = (int) SendMessage (GetDlgItem (hwndDlg, IDC_PRF_ID), CB_GETCURSEL, 0, 0); hash_algo = (int) SendMessage (GetDlgItem (hwndDlg, IDC_PRF_ID), CB_GETITEMDATA, hid, 0); RandSetHashFunction (hash_algo); return 1; } if (lw == IDC_DISPLAY_POOL_CONTENTS) { if (!(bDisplayPoolContents = GetCheckBox (hwndDlg, IDC_DISPLAY_POOL_CONTENTS))) { wchar_t tmp[RNG_POOL_SIZE+1]; wmemset (tmp, L' ', ARRAYSIZE(tmp)); tmp [RNG_POOL_SIZE] = 0; SetWindowText (GetDlgItem (hwndDlg, IDC_POOL_CONTENTS), tmp); } return 1; } if (lw == IDC_KEYFILES_RANDOM_SIZE) { EnableWindow(GetDlgItem (hwndDlg, IDC_KEYFILES_SIZE), !GetCheckBox (hwndDlg, IDC_KEYFILES_RANDOM_SIZE)); } if (lw == IDC_GENERATE_AND_SAVE_KEYFILE) { wchar_t szNumber[16] = {0}; wchar_t szFileBaseName[TC_MAX_PATH]; wchar_t szDirName[TC_MAX_PATH]; wchar_t szFileName [2*TC_MAX_PATH + 16]; unsigned char *keyfile = NULL; int fhKeyfile = -1, status; long keyfilesCount = 0, keyfilesSize = 0, i; wchar_t* fileExtensionPtr = 0; wchar_t szSuffix[32]; BOOL bRandomSize = GetCheckBox (hwndDlg, IDC_KEYFILES_RANDOM_SIZE); if (!GetWindowText(GetDlgItem (hwndDlg, IDC_NUMBER_KEYFILES), szNumber, ARRAYSIZE(szNumber))) szNumber[0] = 0; keyfilesCount = wcstoul(szNumber, NULL, 0); if (keyfilesCount <= 0 || keyfilesCount == LONG_MAX) { Warning("KEYFILE_INCORRECT_NUMBER", hwndDlg); SendMessage(hwndDlg, WM_NEXTDLGCTL, (WPARAM) GetDlgItem (hwndDlg, IDC_NUMBER_KEYFILES), TRUE); return 1; } if (!bRandomSize) { if (!GetWindowText(GetDlgItem (hwndDlg, IDC_KEYFILES_SIZE), szNumber, ARRAYSIZE(szNumber))) szNumber[0] = 0; keyfilesSize = wcstoul(szNumber, NULL, 0); if (keyfilesSize < 64 || keyfilesSize > 1024*1024) { Warning("KEYFILE_INCORRECT_SIZE", hwndDlg); SendMessage(hwndDlg, WM_NEXTDLGCTL, (WPARAM) GetDlgItem (hwndDlg, IDC_KEYFILES_SIZE), TRUE); return 1; } } if (!GetWindowText(GetDlgItem (hwndDlg, IDC_KEYFILES_BASE_NAME), szFileBaseName, TC_MAX_PATH)) szFileBaseName[0] = 0; // Trim trailing space if (TrimWhiteSpace(szFileBaseName) == 0) { Warning("KEYFILE_EMPTY_BASE_NAME", hwndDlg); SendMessage(hwndDlg, WM_NEXTDLGCTL, (WPARAM) GetDlgItem (hwndDlg, IDC_KEYFILES_BASE_NAME), TRUE); return 1; } if (!IsValidFileName(szFileBaseName)) { Warning("KEYFILE_INVALID_BASE_NAME", hwndDlg); SendMessage(hwndDlg, WM_NEXTDLGCTL, (WPARAM) GetDlgItem (hwndDlg, IDC_KEYFILES_BASE_NAME), TRUE); return 1; } fileExtensionPtr = wcsrchr(szFileBaseName, L'.'); /* Select directory */ if (!BrowseDirectories (hwndDlg, "SELECT_KEYFILE_GENERATION_DIRECTORY", szDirName)) return 1; if (szDirName[wcslen(szDirName) - 1] != L'\\' && szDirName[wcslen(szDirName) - 1] != L'/') StringCbCat(szDirName, sizeof(szDirName), L"\\"); WaitCursor(); keyfile = (unsigned char*) TCalloc( bRandomSize? KEYFILE_MAX_READ_LEN : keyfilesSize ); for (i= 0; i < keyfilesCount; i++) { StringCbCopyW(szFileName, sizeof(szFileName), szDirName); if (i > 0) { StringCbPrintfW(szSuffix, sizeof(szSuffix), L"_%d", i); // Append the counter to the name if (fileExtensionPtr) { StringCchCatN(szFileName, ARRAYSIZE(szFileName), szFileBaseName, (size_t) (fileExtensionPtr - szFileBaseName)); StringCbCat(szFileName, sizeof(szFileName), szSuffix); StringCbCat(szFileName, sizeof(szFileName), fileExtensionPtr); } else { StringCbCat(szFileName, sizeof(szFileName), szFileBaseName); StringCbCat(szFileName, sizeof(szFileName), szSuffix); } } else StringCbCat(szFileName, sizeof(szFileName), szFileBaseName); // check if the file exists if ((fhKeyfile = _wopen(szFileName, _O_RDONLY|_O_BINARY, _S_IREAD|_S_IWRITE)) != -1) { WCHAR s[4*TC_MAX_PATH] = {0}; _close (fhKeyfile); StringCbPrintfW (s, sizeof(s), GetString ("KEYFILE_ALREADY_EXISTS"), szFileName); status = AskWarnNoYesString (s, hwndDlg); if (status == IDNO) { TCfree(keyfile); NormalCursor(); return 1; } } /* Conceive the file */ if ((fhKeyfile = _wopen(szFileName, _O_CREAT|_O_TRUNC|_O_WRONLY|_O_BINARY, _S_IREAD|_S_IWRITE)) == -1) { TCfree(keyfile); NormalCursor(); handleWin32Error (hwndDlg, SRC_POS); return 1; } if (bRandomSize) { /* Generate a random size */ if (!RandgetBytes (hwndDlg, (unsigned char*) &keyfilesSize, sizeof(keyfilesSize), FALSE)) { _close (fhKeyfile); DeleteFile (szFileName); TCfree(keyfile); NormalCursor(); return 1; } /* since keyfilesSize < 1024 * 1024, we mask with 0x000FFFFF */ keyfilesSize = (long) (((unsigned long) keyfilesSize) & 0x000FFFFF); keyfilesSize %= ((KEYFILE_MAX_READ_LEN - 64) + 1); keyfilesSize += 64; } /* Generate the keyfile */ if (!RandgetBytesFull (hwndDlg, keyfile, keyfilesSize, TRUE, TRUE)) { _close (fhKeyfile); DeleteFile (szFileName); TCfree(keyfile); NormalCursor(); return 1; } /* Write the keyfile */ status = _write (fhKeyfile, keyfile, keyfilesSize); burn (keyfile, keyfilesSize); _close (fhKeyfile); if (status == -1) { TCfree(keyfile); NormalCursor(); handleWin32Error (hwndDlg, SRC_POS); return 1; } } TCfree(keyfile); NormalCursor(); Info("KEYFILE_CREATED", hwndDlg); return 1; } return 0; case WM_CLOSE: { wchar_t tmp[RNG_POOL_SIZE+1]; exit: WaitCursor(); KillTimer (hwndDlg, 0xfd); #ifndef VOLFORMAT RandStop (FALSE); #endif /* Cleanup */ burn (randPool, sizeof(randPool)); burn (lastRandPool, sizeof(lastRandPool)); burn (outputDispBuffer, sizeof(outputDispBuffer)); burn (&mouseEntropyGathered, sizeof(mouseEntropyGathered)); burn (&mouseEventsInitialCount, sizeof(mouseEventsInitialCount)); burn (maskRandPool, sizeof(maskRandPool)); // Attempt to wipe the pool contents in the GUI text area wmemset (tmp, L' ', RNG_POOL_SIZE); tmp [RNG_POOL_SIZE] = 0; SetWindowText (GetDlgItem (hwndDlg, IDC_POOL_CONTENTS), tmp); EndDialog (hwndDlg, IDCLOSE); NormalCursor (); return 1; } } return 0; } /* Except in response to the WM_INITDIALOG message, the dialog box procedure should return nonzero if it processes the message, and zero if it does not. - see DialogProc */ BOOL CALLBACK CipherTestDialogProc (HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { static int idTestCipher = -1; /* Currently selected cipher for the test vector facility (none = -1). */ static BOOL bXTSTestEnabled = FALSE; PCRYPTO_INFO ci; WORD lw = LOWORD (wParam); WORD hw = HIWORD (wParam); switch (uMsg) { case WM_INITDIALOG: { int ea; wchar_t buf[100]; LocalizeDialog (hwndDlg, "IDD_CIPHER_TEST_DLG"); SendMessage(GetDlgItem(hwndDlg, IDC_TESTS_MESSAGE), WM_SETFONT, (WPARAM)hBoldFont, MAKELPARAM(TRUE,0)); SendMessage(GetDlgItem(hwndDlg, IDC_KEY), EM_LIMITTEXT, 128,0); SendMessage(GetDlgItem(hwndDlg, IDC_KEY), WM_SETFONT, (WPARAM)hFixedDigitFont, MAKELPARAM(1,0)); SendMessage(GetDlgItem(hwndDlg, IDC_PLAINTEXT), EM_LIMITTEXT,64,0); SendMessage(GetDlgItem(hwndDlg, IDC_PLAINTEXT), WM_SETFONT, (WPARAM)hFixedDigitFont, MAKELPARAM(1,0)); SendMessage(GetDlgItem(hwndDlg, IDC_CIPHERTEXT), EM_LIMITTEXT,64,0); SendMessage(GetDlgItem(hwndDlg, IDC_CIPHERTEXT), WM_SETFONT, (WPARAM)hFixedDigitFont, MAKELPARAM(1,0)); SendMessage(GetDlgItem(hwndDlg, IDC_SECONDARY_KEY), EM_LIMITTEXT, 128,0); SendMessage(GetDlgItem(hwndDlg, IDC_SECONDARY_KEY), WM_SETFONT, (WPARAM)hFixedDigitFont, MAKELPARAM(1,0)); SendMessage(GetDlgItem(hwndDlg, IDC_TEST_DATA_UNIT_NUMBER), EM_LIMITTEXT,32,0); SendMessage(GetDlgItem(hwndDlg, IDC_TEST_DATA_UNIT_NUMBER), WM_SETFONT, (WPARAM)hFixedDigitFont, MAKELPARAM(1,0)); SetCheckBox (hwndDlg, IDC_XTS_MODE_ENABLED, bXTSTestEnabled); EnableWindow (GetDlgItem (hwndDlg, IDC_SECONDARY_KEY), bXTSTestEnabled); EnableWindow (GetDlgItem (hwndDlg, IDT_SECONDARY_KEY), bXTSTestEnabled); EnableWindow (GetDlgItem (hwndDlg, IDC_TEST_BLOCK_NUMBER), bXTSTestEnabled); EnableWindow (GetDlgItem (hwndDlg, IDT_TEST_BLOCK_NUMBER), bXTSTestEnabled); EnableWindow (GetDlgItem (hwndDlg, IDC_TEST_DATA_UNIT_NUMBER), bXTSTestEnabled); EnableWindow (GetDlgItem (hwndDlg, IDT_TEST_DATA_UNIT_NUMBER), bXTSTestEnabled); if (idTestCipher == -1) idTestCipher = (int) lParam; SendMessage (GetDlgItem (hwndDlg, IDC_CIPHER), CB_RESETCONTENT, 0, 0); for (ea = EAGetFirst (); ea != 0; ea = EAGetNext (ea)) { if (EAGetCipherCount (ea) == 1 && EAIsFormatEnabled (ea)) AddComboPair (GetDlgItem (hwndDlg, IDC_CIPHER), EAGetName (buf, ea, 1), EAGetFirstCipher (ea)); } ResetCipherTest(hwndDlg, idTestCipher); SelectAlgo (GetDlgItem (hwndDlg, IDC_CIPHER), &idTestCipher); return 1; } case WM_COMMAND: if (hw == CBN_SELCHANGE && lw == IDC_CIPHER) { idTestCipher = (int) SendMessage (GetDlgItem (hwndDlg, IDC_CIPHER), CB_GETITEMDATA, SendMessage (GetDlgItem (hwndDlg, IDC_CIPHER), CB_GETCURSEL, 0, 0), 0); ResetCipherTest(hwndDlg, idTestCipher); SendMessage (hwndDlg, WM_INITDIALOG, 0, 0); return 1; } if (hw == CBN_SELCHANGE && lw == IDC_KEY_SIZE) { // NOP return 1; } if (lw == IDC_RESET) { ResetCipherTest(hwndDlg, idTestCipher); return 1; } if (lw == IDC_AUTO) { WaitCursor (); if (!AutoTestAlgorithms()) { ShowWindow(GetDlgItem(hwndDlg, IDC_TESTS_MESSAGE), SW_SHOWNORMAL); SetWindowTextW(GetDlgItem(hwndDlg, IDC_TESTS_MESSAGE), GetString ("TESTS_FAILED")); } else { ShowWindow(GetDlgItem(hwndDlg, IDC_TESTS_MESSAGE), SW_SHOWNORMAL); SetWindowTextW(GetDlgItem(hwndDlg, IDC_TESTS_MESSAGE), GetString ("TESTS_PASSED")); ShowWindow(GetDlgItem(hwndDlg, IDC_REDTICK), SW_SHOWNORMAL); } NormalCursor (); return 1; } if (lw == IDC_XTS_MODE_ENABLED) { bXTSTestEnabled = GetCheckBox (hwndDlg, IDC_XTS_MODE_ENABLED); EnableWindow (GetDlgItem (hwndDlg, IDC_SECONDARY_KEY), bXTSTestEnabled); EnableWindow (GetDlgItem (hwndDlg, IDT_SECONDARY_KEY), bXTSTestEnabled); EnableWindow (GetDlgItem (hwndDlg, IDC_TEST_BLOCK_NUMBER), bXTSTestEnabled); EnableWindow (GetDlgItem (hwndDlg, IDT_TEST_BLOCK_NUMBER), bXTSTestEnabled); EnableWindow (GetDlgItem (hwndDlg, IDT_TEST_DATA_UNIT_NUMBER), bXTSTestEnabled); EnableWindow (GetDlgItem (hwndDlg, IDC_TEST_DATA_UNIT_NUMBER), bXTSTestEnabled); if (bXTSTestEnabled) SendMessage(GetDlgItem(hwndDlg, IDC_KEY_SIZE), CB_SETCURSEL, 0,0); } if (lw == IDOK || lw == IDC_ENCRYPT || lw == IDC_DECRYPT) { CRYPTOPP_ALIGN_DATA(16) char key[128+1], inputtext[128+1], secondaryKey[64+1], dataUnitNo[16+1]; wchar_t szTmp[128+1]; int ks, pt, n, tlen, blockNo = 0; BOOL bEncrypt; ShowWindow(GetDlgItem(hwndDlg, IDC_TESTS_MESSAGE), SW_HIDE); ShowWindow(GetDlgItem(hwndDlg, IDC_REDTICK), SW_HIDE); ks = (int) SendMessage(GetDlgItem(hwndDlg, IDC_KEY_SIZE), CB_GETCURSEL, 0,0); ks = (int) SendMessage(GetDlgItem(hwndDlg, IDC_KEY_SIZE), CB_GETITEMDATA, ks,0); pt = (int) SendMessage(GetDlgItem(hwndDlg, IDC_PLAINTEXT_SIZE), CB_GETITEMDATA, 0,0); bEncrypt = lw == IDC_ENCRYPT; memset(key,0,sizeof(key)); memset(szTmp,0,sizeof(szTmp)); n = GetWindowText(GetDlgItem(hwndDlg, IDC_KEY), szTmp, ARRAYSIZE(szTmp)); if (n != ks * 2) { Warning ("TEST_KEY_SIZE", hwndDlg); return 1; } for (n = 0; n < ks; n ++) { wchar_t szTmp2[3], *ptr; long x; szTmp2[2] = 0; szTmp2[0] = szTmp[n * 2]; szTmp2[1] = szTmp[n * 2 + 1]; x = wcstol(szTmp2, &ptr, 16); key[n] = (char) x; } memset(inputtext, 0, sizeof(inputtext)); memset(secondaryKey, 0, sizeof(secondaryKey)); memset(dataUnitNo, 0, sizeof(dataUnitNo)); memset(szTmp, 0, sizeof(szTmp)); if (bEncrypt) { n = GetWindowText(GetDlgItem(hwndDlg, IDC_PLAINTEXT), szTmp, ARRAYSIZE(szTmp)); } else { n = GetWindowText(GetDlgItem(hwndDlg, IDC_CIPHERTEXT), szTmp, ARRAYSIZE(szTmp)); } if (n != pt * 2) { if (bEncrypt) { Warning ("TEST_PLAINTEXT_SIZE", hwndDlg); return 1; } else { Warning ("TEST_CIPHERTEXT_SIZE", hwndDlg); return 1; } } for (n = 0; n < pt; n ++) { wchar_t szTmp2[3], *ptr; long x; szTmp2[2] = 0; szTmp2[0] = szTmp[n * 2]; szTmp2[1] = szTmp[n * 2 + 1]; x = wcstol(szTmp2, &ptr, 16); inputtext[n] = (char) x; } // XTS if (bXTSTestEnabled) { // Secondary key if (GetWindowText(GetDlgItem(hwndDlg, IDC_SECONDARY_KEY), szTmp, ARRAYSIZE(szTmp)) != 64) { Warning ("TEST_INCORRECT_SECONDARY_KEY_SIZE", hwndDlg); return 1; } for (n = 0; n < 64; n ++) { wchar_t szTmp2[3], *ptr; long x; szTmp2[2] = 0; szTmp2[0] = szTmp[n * 2]; szTmp2[1] = szTmp[n * 2 + 1]; x = wcstol(szTmp2, &ptr, 16); secondaryKey[n] = (char) x; } // Data unit number tlen = GetWindowText(GetDlgItem(hwndDlg, IDC_TEST_DATA_UNIT_NUMBER), szTmp, ARRAYSIZE(szTmp)); if (tlen > 16 || tlen < 1) { Warning ("TEST_INCORRECT_TEST_DATA_UNIT_SIZE", hwndDlg); return 1; } LeftPadString (szTmp, tlen, 16, L'0'); for (n = 0; n < 16; n ++) { wchar_t szTmp2[3], *ptr; long x; szTmp2[2] = 0; szTmp2[0] = szTmp[n * 2]; szTmp2[1] = szTmp[n * 2 + 1]; x = wcstol(szTmp2, &ptr, 16); dataUnitNo[n] = (char) x; } // Block number blockNo = (int) SendMessage (GetDlgItem (hwndDlg, IDC_TEST_BLOCK_NUMBER), CB_GETITEMDATA, SendMessage (GetDlgItem (hwndDlg, IDC_TEST_BLOCK_NUMBER), CB_GETCURSEL, 0, 0), 0); } // if (bXTSTestEnabled) /* Perform the actual tests */ if (ks != CB_ERR && pt != CB_ERR) { char tmp[128]; int tmpRetVal; /* Copy the plain/ciphertext */ memcpy(tmp,inputtext, pt); if (bXTSTestEnabled) { UINT64_STRUCT structDataUnitNo; /* XTS mode */ ci = crypto_open (); if (!ci) return 1; ci->mode = XTS; for (ci->ea = EAGetFirst (); ci->ea != 0 ; ci->ea = EAGetNext (ci->ea)) if (EAGetCipherCount (ci->ea) == 1 && EAGetFirstCipher (ci->ea) == idTestCipher) break; if ((tmpRetVal = EAInit (ci->ea, (unsigned char *) key, ci->ks)) != ERR_SUCCESS) { handleError (hwndDlg, tmpRetVal, SRC_POS); crypto_close (ci); return 1; } memcpy (&ci->k2, secondaryKey, sizeof (secondaryKey)); if (!EAInitMode (ci, ci->k2)) { crypto_close (ci); return 1; } structDataUnitNo.Value = BE64(((unsigned __int64 *)dataUnitNo)[0]); if (bEncrypt) EncryptBufferXTS ((unsigned char *) tmp, pt, &structDataUnitNo, blockNo, (unsigned char *) (ci->ks), (unsigned char *) ci->ks2, idTestCipher); else DecryptBufferXTS ((unsigned char *) tmp, pt, &structDataUnitNo, blockNo, (unsigned char *) (ci->ks), (unsigned char *) ci->ks2, idTestCipher); crypto_close (ci); } else { CipherInit2(idTestCipher, key, ks_tmp, ks); if (bEncrypt) { EncipherBlock(idTestCipher, tmp, ks_tmp); } else { DecipherBlock(idTestCipher, tmp, ks_tmp); } } *szTmp = 0; for (n = 0; n < pt; n ++) { wchar_t szTmp2[3]; StringCbPrintfW(szTmp2, sizeof(szTmp2), L"%02x", (int)((unsigned char)tmp[n])); StringCbCatW(szTmp, sizeof(szTmp), szTmp2); } if (bEncrypt) SetWindowText(GetDlgItem(hwndDlg,IDC_CIPHERTEXT), szTmp); else SetWindowText(GetDlgItem(hwndDlg,IDC_PLAINTEXT), szTmp); } return 1; } if (lw == IDCLOSE || lw == IDCANCEL) { idTestCipher = -1; EndDialog (hwndDlg, 0); return 1; } break; case WM_CLOSE: idTestCipher = -1; EndDialog (hwndDlg, 0); return 1; } return 0; } void ResetCipherTest(HWND hwndDlg, int idTestCipher) { int ndx; ShowWindow(GetDlgItem(hwndDlg, IDC_TESTS_MESSAGE), SW_HIDE); ShowWindow(GetDlgItem(hwndDlg, IDC_REDTICK), SW_HIDE); EnableWindow(GetDlgItem(hwndDlg,IDC_KEY_SIZE), FALSE); /* Setup the keysize and plaintext sizes for the selected cipher */ SendMessage (GetDlgItem(hwndDlg, IDC_PLAINTEXT_SIZE), CB_RESETCONTENT, 0,0); SendMessage (GetDlgItem(hwndDlg, IDC_KEY_SIZE), CB_RESETCONTENT, 0,0); SendMessage (GetDlgItem(hwndDlg, IDC_TEST_BLOCK_NUMBER), CB_RESETCONTENT, 0,0); ndx = (int) SendMessage (GetDlgItem(hwndDlg, IDC_PLAINTEXT_SIZE), CB_ADDSTRING, 0,(LPARAM) L"64"); SendMessage(GetDlgItem(hwndDlg, IDC_PLAINTEXT_SIZE), CB_SETITEMDATA, ndx,(LPARAM) 8); SendMessage(GetDlgItem(hwndDlg, IDC_PLAINTEXT_SIZE), CB_SETCURSEL, ndx,0); for (ndx = 0; ndx < BLOCKS_PER_XTS_DATA_UNIT; ndx++) { wchar_t tmpStr [16]; StringCbPrintfW (tmpStr, sizeof(tmpStr), L"%d", ndx); ndx = (int) SendMessage (GetDlgItem(hwndDlg, IDC_TEST_BLOCK_NUMBER), CB_ADDSTRING, 0,(LPARAM) tmpStr); SendMessage(GetDlgItem(hwndDlg, IDC_TEST_BLOCK_NUMBER), CB_SETITEMDATA, ndx,(LPARAM) ndx); } SendMessage(GetDlgItem(hwndDlg, IDC_TEST_BLOCK_NUMBER), CB_SETCURSEL, 0, 0); SetWindowText(GetDlgItem(hwndDlg, IDC_SECONDARY_KEY), L"0000000000000000000000000000000000000000000000000000000000000000"); SetWindowText(GetDlgItem(hwndDlg, IDC_TEST_DATA_UNIT_NUMBER), L"0"); SetWindowText(GetDlgItem(hwndDlg, IDC_PLAINTEXT), L"0000000000000000"); SetWindowText(GetDlgItem(hwndDlg, IDC_CIPHERTEXT), L"0000000000000000"); if (idTestCipher == AES || idTestCipher == SERPENT || idTestCipher == TWOFISH || idTestCipher == CAMELLIA #if defined(CIPHER_GOST89) || idTestCipher == GOST89 #endif || idTestCipher == KUZNYECHIK ) { ndx = (int) SendMessage (GetDlgItem(hwndDlg, IDC_KEY_SIZE), CB_ADDSTRING, 0,(LPARAM) L"256"); SendMessage(GetDlgItem(hwndDlg, IDC_KEY_SIZE), CB_SETITEMDATA, ndx,(LPARAM) 32); SendMessage(GetDlgItem(hwndDlg, IDC_KEY_SIZE), CB_SETCURSEL, ndx,0); SendMessage (GetDlgItem(hwndDlg, IDC_PLAINTEXT_SIZE), CB_RESETCONTENT, 0,0); ndx = (int) SendMessage (GetDlgItem(hwndDlg, IDC_PLAINTEXT_SIZE), CB_ADDSTRING, 0,(LPARAM) L"128"); SendMessage(GetDlgItem(hwndDlg, IDC_PLAINTEXT_SIZE), CB_SETITEMDATA, ndx,(LPARAM) 16); SendMessage(GetDlgItem(hwndDlg, IDC_PLAINTEXT_SIZE), CB_SETCURSEL, ndx,0); SetWindowText(GetDlgItem(hwndDlg, IDC_KEY), L"0000000000000000000000000000000000000000000000000000000000000000"); SetWindowText(GetDlgItem(hwndDlg, IDC_PLAINTEXT), L"00000000000000000000000000000000"); SetWindowText(GetDlgItem(hwndDlg, IDC_CIPHERTEXT), L"00000000000000000000000000000000"); } } #endif // #ifndef SETUP BOOL CALLBACK MultiChoiceDialogProc (HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { int nChoiceIDs [MAX_MULTI_CHOICES+1] = { IDC_MULTI_CHOICE_MSG, IDC_CHOICE1, IDC_CHOICE2, IDC_CHOICE3, IDC_CHOICE4, IDC_CHOICE5, IDC_CHOICE6, IDC_CHOICE7, IDC_CHOICE8, IDC_CHOICE9, IDC_CHOICE10 }; int nBaseButtonWidth = 0; int nBaseButtonHeight = 0; int nActiveChoices = -1; int nStr = 0; int vertSubOffset, horizSubOffset, vertMsgHeightOffset; int vertOffset = 0; int nLongestButtonCaptionWidth = 6; int nLongestButtonCaptionCharLen = 1; int nTextGfxLineHeight = 0; int nMainTextLenInChars = 0; int newLineSeqCount = 0; RECT rec, wrec, wtrec, trec; BOOL bResolve; WORD lw = LOWORD (wParam); switch (uMsg) { case WM_INITDIALOG: { char **pStr = (char **) ((MULTI_CHOICE_DLGPROC_PARAMS *) lParam)->strings; char **pStrOrig = pStr; wchar_t **pwStr = (wchar_t **) ((MULTI_CHOICE_DLGPROC_PARAMS *) lParam)->strings; wchar_t **pwStrOrig = pwStr; LocalizeDialog (hwndDlg, NULL); SetWindowPos (hwndDlg, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); SetWindowPos (hwndDlg, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); bResolve = (*pStr == NULL); // Style if (((MULTI_CHOICE_DLGPROC_PARAMS *) lParam)->bold) { SendMessage (GetDlgItem (hwndDlg, IDC_MULTI_CHOICE_MSG), WM_SETFONT, (WPARAM) hUserBoldFont, (LPARAM) TRUE); } // Process the strings pStr++; pwStr++; do { if (*pStr != 0) { SetWindowTextW (GetDlgItem(hwndDlg, nChoiceIDs[nStr]), bResolve ? GetString(*pStr) : *pwStr); if (nStr > 0) { nLongestButtonCaptionWidth = max ( GetTextGfxWidth (GetDlgItem(hwndDlg, IDC_CHOICE1), bResolve ? GetString(*pStr) : *pwStr, hUserFont), nLongestButtonCaptionWidth); nLongestButtonCaptionCharLen = max (nLongestButtonCaptionCharLen, (int) wcslen ((const wchar_t *) (bResolve ? GetString(*pStr) : *pwStr))); } nActiveChoices++; pStr++; pwStr++; } else { ShowWindow(GetDlgItem(hwndDlg, nChoiceIDs[nStr]), SW_HIDE); } nStr++; } while (nStr < MAX_MULTI_CHOICES+1); // Length of main message in characters (not bytes) nMainTextLenInChars = (int) wcslen ((const wchar_t *) (bResolve ? GetString(*(pStrOrig+1)) : *(pwStrOrig+1))); if (nMainTextLenInChars > 200 && nMainTextLenInChars / nLongestButtonCaptionCharLen >= 10) { // As the main text is longer than 200 characters, we will "pad" the widest button caption with // spaces (if it is not wide enough) so as to increase the width of the whole dialog window. // Otherwise, it would look too tall (dialog boxes look better when they are more wide than tall). nLongestButtonCaptionWidth = CompensateXDPI (max ( nLongestButtonCaptionWidth, min (350, nMainTextLenInChars))); } // Get the window coords GetWindowRect(hwndDlg, &wrec); // Get the base button size GetClientRect(GetDlgItem(hwndDlg, IDC_CHOICE1), &rec); nBaseButtonWidth = rec.right + 2; nBaseButtonHeight = rec.bottom + 2; // Increase in width based on the gfx length of the widest button caption horizSubOffset = min (CompensateXDPI (500), max (0, nLongestButtonCaptionWidth + CompensateXDPI (50) - nBaseButtonWidth)); // Vertical "title bar" offset GetClientRect(hwndDlg, &wtrec); vertOffset = wrec.bottom - wrec.top - wtrec.bottom - GetSystemMetrics(SM_CYFIXEDFRAME); // Height/width of the message text GetClientRect(GetDlgItem(hwndDlg, IDC_MULTI_CHOICE_MSG), &trec); // Determine the number of newlines contained in the message text { int64 offset = -1; do { offset = FindString ((char *) (bResolve ? GetString(*(pStrOrig+1)) : *(pwStrOrig+1)), (char *) L"\n", nMainTextLenInChars * 2, (int) wcslen (L"\n") * 2, offset + 1); newLineSeqCount++; } while (offset != -1); } nTextGfxLineHeight = GetTextGfxHeight (GetDlgItem(hwndDlg, IDC_MULTI_CHOICE_MSG), bResolve ? GetString(*(pStrOrig+1)) : *(pwStrOrig+1), hUserFont); vertMsgHeightOffset = ((GetTextGfxWidth (GetDlgItem(hwndDlg, IDC_MULTI_CHOICE_MSG), bResolve ? GetString(*(pStrOrig+1)) : *(pwStrOrig+1), hUserFont) / (trec.right + horizSubOffset) + 1) * nTextGfxLineHeight) - trec.bottom; vertMsgHeightOffset = min (CompensateYDPI (350), vertMsgHeightOffset + newLineSeqCount * nTextGfxLineHeight + (trec.bottom + vertMsgHeightOffset) / 10); // As reserve, we are adding 10% and the number of lines equal to the number of newlines in the message // Reduction in height according to the number of shown buttons vertSubOffset = ((MAX_MULTI_CHOICES - nActiveChoices) * nBaseButtonHeight); if (horizSubOffset > 0 || vertMsgHeightOffset > 0 || vertOffset > 0) { // Resize/move each button if necessary for (nStr = 1; nStr < MAX_MULTI_CHOICES+1; nStr++) { GetWindowRect(GetDlgItem(hwndDlg, nChoiceIDs[nStr]), &rec); MoveWindow (GetDlgItem(hwndDlg, nChoiceIDs[nStr]), rec.left - wrec.left - GetSystemMetrics(SM_CXFIXEDFRAME), rec.top - wrec.top - vertOffset + vertMsgHeightOffset, nBaseButtonWidth + horizSubOffset, nBaseButtonHeight, TRUE); } // Resize/move the remaining GUI elements GetWindowRect(GetDlgItem(hwndDlg, IDC_MULTI_CHOICE_MSG), &rec); GetClientRect(GetDlgItem(hwndDlg, IDC_MULTI_CHOICE_MSG), &trec); MoveWindow (GetDlgItem(hwndDlg, IDC_MULTI_CHOICE_MSG), rec.left - wrec.left - GetSystemMetrics(SM_CXFIXEDFRAME), rec.top - wrec.top - vertOffset, trec.right + 2 + horizSubOffset, trec.bottom + 2 + vertMsgHeightOffset, TRUE); GetWindowRect(GetDlgItem(hwndDlg, IDC_MC_DLG_HR1), &rec); GetClientRect(GetDlgItem(hwndDlg, IDC_MC_DLG_HR1), &trec); MoveWindow (GetDlgItem(hwndDlg, IDC_MC_DLG_HR1), rec.left - wrec.left - GetSystemMetrics(SM_CXFIXEDFRAME), rec.top - wrec.top - vertOffset, trec.right + 2 + horizSubOffset, trec.bottom + 2, TRUE); GetWindowRect(GetDlgItem(hwndDlg, IDC_MC_DLG_HR2), &rec); GetClientRect(GetDlgItem(hwndDlg, IDC_MC_DLG_HR2), &trec); MoveWindow (GetDlgItem(hwndDlg, IDC_MC_DLG_HR2), rec.left - wrec.left - GetSystemMetrics(SM_CXFIXEDFRAME), rec.top - wrec.top - vertOffset + vertMsgHeightOffset, trec.right + 2 + horizSubOffset, trec.bottom + 2, TRUE); } // Resize the window according to number of shown buttons and the longest button caption MoveWindow (hwndDlg, wrec.left - horizSubOffset / 2, wrec.top + vertSubOffset / 2 - vertMsgHeightOffset / 2, wrec.right - wrec.left + horizSubOffset, wrec.bottom - wrec.top - vertSubOffset + 1 + vertMsgHeightOffset, TRUE); DisableCloseButton (hwndDlg); return 1; } case WM_COMMAND: if (lw == IDCLOSE || lw == IDCANCEL) { EndDialog (hwndDlg, 0); return 1; } for (nStr = 1; nStr < MAX_MULTI_CHOICES+1; nStr++) { if (lw == nChoiceIDs[nStr]) { EndDialog (hwndDlg, nStr); return 1; } } break; case WM_CLOSE: // This prevents the window from being closed by pressing Alt-F4 (the Close button is hidden). // Note that the OS handles modal MessageBox() dialog windows the same way. return 1; } return 0; } BOOL CheckCapsLock (HWND hwnd, BOOL quiet) { if ((GetKeyState(VK_CAPITAL) & 1) != 0) { if (!quiet) { MessageBoxW (hwnd, GetString ("CAPSLOCK_ON"), lpszTitle, MB_ICONEXCLAMATION); } return TRUE; } return FALSE; } // Checks whether the file extension is not used for executable files or similarly problematic, which often // causes Windows and antivirus software to interfere with the container. BOOL CheckFileExtension (wchar_t *fileName) { int i = 0; wchar_t *ext = wcsrchr (fileName, L'.'); static wchar_t *problemFileExt[] = { // These are protected by the Windows Resource Protection L".asa", L".asp", L".aspx", L".ax", L".bas", L".bat", L".bin", L".cer", L".chm", L".clb", L".cmd", L".cnt", L".cnv", L".com", L".cpl", L".cpx", L".crt", L".csh", L".dll", L".drv", L".dtd", L".exe", L".fxp", L".grp", L".h1s", L".hlp", L".hta", L".ime", L".inf", L".ins", L".isp", L".its", L".js", L".jse", L".ksh", L".lnk", L".mad", L".maf", L".mag", L".mam", L".man", L".maq", L".mar", L".mas", L".mat", L".mau", L".mav", L".maw", L".mda", L".mdb", L".mde", L".mdt", L".mdw", L".mdz", L".msc", L".msi", L".msp", L".mst", L".mui", L".nls", L".ocx", L".ops", L".pal", L".pcd", L".pif", L".prf", L".prg", L".pst", L".reg", L".scf", L".scr", L".sct", L".shb", L".shs", L".sys", L".tlb", L".tsp", L".url", L".vb", L".vbe", L".vbs", L".vsmacros", L".vss", L".vst", L".vsw", L".ws", L".wsc", L".wsf", L".wsh", L".xsd", L".xsl", // These additional file extensions are usually watched by antivirus programs L".386", L".acm", L".ade", L".adp", L".ani", L".app", L".asd", L".asf", L".asx", L".awx", L".ax", L".boo", L".bz2", L".cdf", L".class", L".dhtm", L".dhtml",L".dlo", L".emf", L".eml", L".flt", L".fot", L".gz", L".hlp", L".htm", L".html", L".ini", L".j2k", L".jar", L".jff", L".jif", L".jmh", L".jng", L".jp2", L".jpe", L".jpeg", L".jpg", L".lsp", L".mod", L".nws", L".obj", L".olb", L".osd", L".ov1", L".ov2", L".ov3", L".ovl", L".ovl", L".ovr", L".pdr", L".pgm", L".php", L".pkg", L".pl", L".png", L".pot", L".pps", L".ppt", L".ps1", L".ps1xml", L".psc1", L".rar", L".rpl", L".rtf", L".sbf", L".script", L".sh", L".sha", L".shtm", L".shtml", L".spl", L".swf", L".tar", L".tgz", L".tmp", L".ttf", L".vcs", L".vlm", L".vxd", L".vxo", L".wiz", L".wll", L".wmd", L".wmf", L".wms", L".wmz", L".wpc", L".wsc", L".wsh", L".wwk", L".xhtm", L".xhtml", L".xl", L".xml", L".zip", L".7z", 0}; if (!ext) return FALSE; while (problemFileExt[i]) { if (!_wcsicmp (ext, problemFileExt[i++])) return TRUE; } return FALSE; } void CorrectFileName (wchar_t* fileName) { /* replace '/' by '\' */ size_t i, len = wcslen (fileName); for (i = 0; i < len; i++) { if (fileName [i] == L'/') fileName [i] = L'\\'; } } void CorrectFileName (std::wstring& fileName) { /* replace '/' by '\' */ size_t i, len = fileName.length(); for (i = 0; i < len; i++) { if (fileName [i] == L'/') fileName [i] = L'\\'; } } void CorrectURL (wchar_t* fileName) { /* replace '\' by '/' */ size_t i, len = wcslen (fileName); for (i = 0; i < len; i++) { if (fileName [i] == L'\\') fileName [i] = L'/'; } } void IncreaseWrongPwdRetryCount (int count) { WrongPwdRetryCounter += count; } void ResetWrongPwdRetryCount (void) { WrongPwdRetryCounter = 0; } BOOL WrongPwdRetryCountOverLimit (void) { return (WrongPwdRetryCounter > TC_TRY_HEADER_BAK_AFTER_NBR_WRONG_PWD_TRIES); } DWORD GetUsedLogicalDrives (void) { DWORD dwUsedDrives = GetLogicalDrives(); if (!bShowDisconnectedNetworkDrives) { static DWORD g_dwLastMappedDrives = 0; static time_t g_lastCallTime = 0; EnterCriticalSection (&csWNetCalls); finally_do ({ LeaveCriticalSection (&csWNetCalls); }); /* update values every 1 minute to reduce CPU consumption */ if ((time (NULL) - g_lastCallTime) > 60) { /* detect disconnected mapped network shares and removed * their associated drives from the list */ WCHAR remotePath[512]; WCHAR drive[3] = {L'A', L':', 0}; DWORD dwLen, status; g_dwLastMappedDrives = 0; for (WCHAR i = 0; i <= MAX_MOUNTED_VOLUME_DRIVE_NUMBER; i++) { if ((dwUsedDrives & (1 << i)) == 0) { drive[0] = L'A' + i; dwLen = ARRAYSIZE (remotePath); status = WNetGetConnection (drive, remotePath, &dwLen); if ((NO_ERROR == status) || (status == ERROR_CONNECTION_UNAVAIL)) { /* this is a mapped network share, mark it as used */ g_dwLastMappedDrives |= (1 << i); } } } g_lastCallTime = time (NULL); } dwUsedDrives |= g_dwLastMappedDrives; } return dwUsedDrives; } int GetFirstAvailableDrive () { DWORD dwUsedDrives = GetUsedLogicalDrives(); int i, drive; /* let A: and B: be used as last resort since they can introduce side effects */ for (i = 2; i < 28; i++) { drive = (i < 26) ? i : (i - 26); if (!(dwUsedDrives & 1 << drive)) return i; } return -1; } int GetLastAvailableDrive () { DWORD dwUsedDrives = GetUsedLogicalDrives(); int i; for (i = 25; i >= 0; i--) { if (!(dwUsedDrives & 1 << i)) return i; } return -1; } BOOL IsDriveAvailable (int driveNo) { return (GetUsedLogicalDrives() & (1 << driveNo)) == 0; } BOOL IsDeviceMounted (wchar_t *deviceName) { BOOL bResult = FALSE; DWORD dwResult; HANDLE dev = INVALID_HANDLE_VALUE; if ((dev = CreateFile (deviceName, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL)) != INVALID_HANDLE_VALUE) { bResult = DeviceIoControl (dev, FSCTL_IS_VOLUME_MOUNTED, NULL, 0, NULL, 0, &dwResult, NULL); CloseHandle (dev); } return bResult; } int DriverUnmountVolume (HWND hwndDlg, int nDosDriveNo, BOOL forced) { UNMOUNT_STRUCT unmount; DWORD dwResult; VOLUME_PROPERTIES_STRUCT prop; BOOL bResult; WCHAR wszLabel[33] = {0}; BOOL bDriverSetLabel = FALSE; memset (&prop, 0, sizeof(prop)); prop.driveNo = nDosDriveNo; if ( DeviceIoControl (hDriver, TC_IOCTL_GET_VOLUME_PROPERTIES, &prop, sizeof (prop), &prop, sizeof (prop), &dwResult, NULL) && prop.driveNo == nDosDriveNo ) { memcpy (wszLabel, prop.wszLabel, sizeof (wszLabel)); bDriverSetLabel = prop.bDriverSetLabel; } unmount.nDosDriveNo = nDosDriveNo; unmount.ignoreOpenFiles = forced; bResult = DeviceIoControl (hDriver, TC_IOCTL_DISMOUNT_VOLUME, &unmount, sizeof (unmount), &unmount, sizeof (unmount), &dwResult, NULL); if (bResult == FALSE) { handleWin32Error (hwndDlg, SRC_POS); return 1; } else if ((unmount.nReturnCode == ERR_SUCCESS) && bDriverSetLabel && wszLabel[0]) UpdateDriveCustomLabel (nDosDriveNo, wszLabel, FALSE); #ifdef TCMOUNT if (unmount.nReturnCode == ERR_SUCCESS && unmount.HiddenVolumeProtectionTriggered && !VolumeNotificationsList.bHidVolDamagePrevReported [nDosDriveNo] && !Silent) { wchar_t msg[4096]; VolumeNotificationsList.bHidVolDamagePrevReported [nDosDriveNo] = TRUE; StringCbPrintfW (msg, sizeof(msg), GetString ("DAMAGE_TO_HIDDEN_VOLUME_PREVENTED"), nDosDriveNo + L'A'); SetForegroundWindow (hwndDlg); MessageBoxW (hwndDlg, msg, lpszTitle, MB_ICONWARNING | MB_SETFOREGROUND | MB_TOPMOST); } #endif // #ifdef TCMOUNT return unmount.nReturnCode; } void BroadcastDeviceChange (WPARAM message, int nDosDriveNo, DWORD driveMap) { DEV_BROADCAST_VOLUME dbv; DWORD_PTR dwResult; LONG eventId = 0; int i; if (DeviceChangeBroadcastDisabled) return; if (message == DBT_DEVICEARRIVAL) eventId = SHCNE_DRIVEADD; else if (message == DBT_DEVICEREMOVECOMPLETE) eventId = SHCNE_DRIVEREMOVED; else if (IsOSAtLeast (WIN_7) && message == DBT_DEVICEREMOVEPENDING) // Explorer on Windows 7 holds open handles of all drives when 'Computer' is expanded in navigation pane. SHCNE_DRIVEREMOVED must be used as DBT_DEVICEREMOVEPENDING is ignored. eventId = SHCNE_DRIVEREMOVED; if (driveMap == 0) driveMap = (1 << nDosDriveNo); if (eventId != 0) { for (i = 0; i < 26; i++) { if (driveMap & (1 << i)) { wchar_t root[] = { (wchar_t) i + L'A', L':', L'\\', 0 }; SHChangeNotify (eventId, SHCNF_PATH, root, NULL); } } } dbv.dbcv_size = sizeof (dbv); dbv.dbcv_devicetype = DBT_DEVTYP_VOLUME; dbv.dbcv_reserved = 0; dbv.dbcv_unitmask = driveMap; dbv.dbcv_flags = 0; UINT timeOut = 1000; // SHChangeNotify() works on Vista, so the Explorer does not require WM_DEVICECHANGE if (CurrentOSMajor >= 6) timeOut = 100; IgnoreWmDeviceChange = TRUE; SendMessageTimeout (HWND_BROADCAST, WM_DEVICECHANGE, message, (LPARAM)(&dbv), SMTO_ABORTIFHUNG, timeOut, &dwResult); // Explorer prior Vista sometimes fails to register a new drive if (CurrentOSMajor < 6 && message == DBT_DEVICEARRIVAL) SendMessageTimeout (HWND_BROADCAST, WM_DEVICECHANGE, message, (LPARAM)(&dbv), SMTO_ABORTIFHUNG, 200, &dwResult); IgnoreWmDeviceChange = FALSE; } static BOOL GetDeviceStorageProperty (HANDLE hDevice, STORAGE_PROPERTY_ID propertyId, DWORD dwDescSize, void* pDesc) { DWORD dwRet = NO_ERROR; if (!pDesc) return FALSE; ZeroMemory (pDesc, dwDescSize); // Set the input data structure STORAGE_PROPERTY_QUERY storagePropertyQuery; ZeroMemory(&storagePropertyQuery, sizeof(STORAGE_PROPERTY_QUERY)); storagePropertyQuery.PropertyId = propertyId; storagePropertyQuery.QueryType = PropertyStandardQuery; // Get the necessary output buffer size STORAGE_DESCRIPTOR_HEADER descHeader = {0}; DWORD dwBytesReturned = 0; BOOL bRet = ::DeviceIoControl(hDevice, IOCTL_STORAGE_QUERY_PROPERTY, &storagePropertyQuery, sizeof(STORAGE_PROPERTY_QUERY), &descHeader, sizeof(STORAGE_DESCRIPTOR_HEADER), &dwBytesReturned, NULL); if (bRet) { if (dwBytesReturned == sizeof(STORAGE_DESCRIPTOR_HEADER)) { unsigned char* outputBuffer = (unsigned char*) TCalloc (descHeader.Size); bRet = ::DeviceIoControl(hDevice, IOCTL_STORAGE_QUERY_PROPERTY, &storagePropertyQuery, sizeof(STORAGE_PROPERTY_QUERY), outputBuffer, descHeader.Size, &dwBytesReturned, NULL); if (bRet) { if (dwBytesReturned >= dwDescSize) { memcpy (pDesc, outputBuffer, dwDescSize); ((STORAGE_DESCRIPTOR_HEADER*)pDesc)->Version = dwDescSize; ((STORAGE_DESCRIPTOR_HEADER*)pDesc)->Size = dwDescSize; } else { bRet = FALSE; dwRet = ERROR_UNHANDLED_ERROR; } } else dwRet = ::GetLastError(); TCfree (outputBuffer); } else { bRet = FALSE; dwRet = ERROR_UNHANDLED_ERROR; } } else dwRet = ::GetLastError(); if (!bRet) { SetLastError (dwRet); return FALSE; } else return TRUE; } BOOL GetPhysicalDriveStorageInformation(UINT nDriveNumber, STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR* pAlignmentDesc, STORAGE_ADAPTER_DESCRIPTOR* pAdapterDesc) { DWORD dwRet = NO_ERROR; if (!pAlignmentDesc || pAdapterDesc) { SetLastError (ERROR_INVALID_PARAMETER); return FALSE; } // Format physical drive path (may be '\\.\PhysicalDrive0', '\\.\PhysicalDrive1' and so on). TCHAR strDrivePath[512]; StringCbPrintf(strDrivePath, sizeof(strDrivePath), _T("\\\\.\\PhysicalDrive%u"), nDriveNumber); // Get a handle to physical drive HANDLE hDevice = ::CreateFile(strDrivePath, 0, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); if(INVALID_HANDLE_VALUE == hDevice) return FALSE; BOOL bRet = (GetDeviceStorageProperty (hDevice, StorageAccessAlignmentProperty, sizeof (STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR), pAlignmentDesc) || GetDeviceStorageProperty (hDevice, StorageAdapterProperty, sizeof (STORAGE_ADAPTER_DESCRIPTOR), pAdapterDesc))? TRUE : FALSE; dwRet = ::GetLastError(); ::CloseHandle(hDevice); if (!bRet) { SetLastError (dwRet); return FALSE; } else return TRUE; } #ifndef SETUP /************************************************************/ // implementation of the generic wait dialog mechanism static UINT g_wmWaitDlg = ::RegisterWindowMessage(L"VeraCryptWaitDlgMessage"); typedef struct { HWND hwnd; void* pArg; WaitThreadProc callback; } WaitThreadParam; static void _cdecl WaitThread (void* pParam) { WaitThreadParam* pThreadParam = (WaitThreadParam*) pParam; pThreadParam->callback(pThreadParam->pArg, pThreadParam->hwnd); /* close the wait dialog */ PostMessage (pThreadParam->hwnd, g_wmWaitDlg, 0, 0); } BOOL CALLBACK WaitDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) { WORD lw = LOWORD (wParam); switch (msg) { case WM_INITDIALOG: { WaitThreadParam* thParam = (WaitThreadParam*) lParam; // set the progress bar type to MARQUEE (indefinite progress) HWND hProgress = GetDlgItem (hwndDlg, IDC_WAIT_PROGRESS_BAR); if (hProgress) { SetWindowLongPtrW (hProgress, GWL_STYLE, PBS_MARQUEE | GetWindowLongPtrW (hProgress, GWL_STYLE)); ::SendMessageW(hProgress, PBM_SETMARQUEE, (WPARAM) TRUE, (LPARAM) 0); } thParam->hwnd = hwndDlg; // For now, we don't have system menu is the resources but we leave this code // if it is enabled in the future HMENU hSysMenu = GetSystemMenu(hwndDlg, FALSE); if (hSysMenu) { //disable the X EnableMenuItem(hSysMenu,SC_CLOSE, MF_BYCOMMAND|MF_GRAYED); // set icons HICON hIcon = (HICON)::LoadImage(hInst, MAKEINTRESOURCE(IDI_TRUECRYPT_ICON), IMAGE_ICON, ::GetSystemMetrics(SM_CXICON), ::GetSystemMetrics(SM_CYICON), LR_DEFAULTCOLOR); ::SendMessage(hwndDlg, WM_SETICON, TRUE, (LPARAM)hIcon); HICON hIconSmall = (HICON)::LoadImage(hInst, MAKEINTRESOURCE(IDI_TRUECRYPT_ICON), IMAGE_ICON, ::GetSystemMetrics(SM_CXSMICON), ::GetSystemMetrics(SM_CYSMICON), LR_DEFAULTCOLOR); ::SendMessage(hwndDlg, WM_SETICON, FALSE, (LPARAM)hIconSmall); } LocalizeDialog (hwndDlg, NULL); _beginthread(WaitThread, 0, thParam); return 0; } case WM_COMMAND: if (lw == IDOK || lw == IDCANCEL) return 1; else return 0; default: if (msg == g_wmWaitDlg) { EndDialog (hwndDlg, IDOK); return 1; } return 0; } } // Based on source: https://www.codeproject.com/Tips/76427/How-to-bring-window-to-top-with-SetForegroundWindo?msg=5285754#xx5285754xx void BringToForeground (HWND hWnd) { if(!::IsWindow(hWnd)) return; HWND hCurrWnd = ::GetForegroundWindow(); DWORD dwThisTID = ::GetCurrentThreadId(), dwCurrTID = ::GetWindowThreadProcessId(hCurrWnd,0); // This structure will be used to create the keyboard // input event. INPUT ip; if (hCurrWnd != hWnd) { if(dwThisTID != dwCurrTID) { // Set up a generic keyboard event. ip.type = INPUT_KEYBOARD; ip.ki.wScan = 0; // hardware scan code for key ip.ki.time = 0; ip.ki.dwExtraInfo = 0; // Press the "A" key ip.ki.wVk = VK_MENU; // virtual-key code for the "a" key ip.ki.dwFlags = 0; // 0 for key press SendInput(1, &ip, sizeof(INPUT)); ::Sleep(250); //Sometimes SetForegroundWindow will fail and the window will flash instead of it being show. Sleeping for a bit seems to help. } ::SetForegroundWindow(hWnd); if(dwThisTID != dwCurrTID) { // Release the "A" key ip.ki.dwFlags = KEYEVENTF_KEYUP; // KEYEVENTF_KEYUP for key release SendInput(1, &ip, sizeof(INPUT)); } } #ifdef TCMOUNT if (hWnd == MainDlg) { SetFocus (hWnd); ::SendMessage(hWnd, WM_NEXTDLGCTL, (WPARAM) GetDlgItem (hWnd, IDC_DRIVELIST), 1L); } #endif } static LRESULT CALLBACK ShowWaitDialogParentWndProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { return DefWindowProcW (hWnd, message, wParam, lParam); } void ShowWaitDialog(HWND hwnd, BOOL bUseHwndAsParent, WaitThreadProc callback, void* pArg) { BOOL bEffectiveHideWaitingDialog = bCmdHideWaitingDialogValid? bCmdHideWaitingDialog : bHideWaitingDialog; WaitThreadParam threadParam; threadParam.callback = callback; threadParam.pArg = pArg; if (WaitDialogDisplaying || bEffectiveHideWaitingDialog) { if (!WaitDialogDisplaying) WaitCursor (); callback (pArg, hwnd); if (!WaitDialogDisplaying) NormalCursor (); } else { const wchar_t *className = L"VeraCryptShowWaitDialogParent"; BOOL bIsForeground = FALSE; HWND creatorWnd = hwnd? hwnd : MainDlg; WaitDialogDisplaying = TRUE; HWND hParent = NULL; if (creatorWnd) { if (GetForegroundWindow () == creatorWnd) bIsForeground = TRUE; EnableWindow (creatorWnd, FALSE); } if (hwnd && bUseHwndAsParent) hParent = hwnd; else { /* create invisible window and use it as parent */ WNDCLASSEXW winClass; memset (&winClass, 0, sizeof (winClass)); winClass.cbSize = sizeof (WNDCLASSEX); winClass.lpfnWndProc = (WNDPROC) ShowWaitDialogParentWndProc; winClass.hInstance = hInst; winClass.lpszClassName = className; RegisterClassExW (&winClass); hParent = CreateWindowExW (WS_EX_TOOLWINDOW | WS_EX_LAYERED, className, L"VeraCrypt ShowWaitDialog Parent", 0, 0, 0, 1, 1, NULL, NULL, hInst, NULL); if (hParent) { SetLayeredWindowAttributes (hParent, 0, 1, LWA_ALPHA); ShowWindow (hParent, SW_SHOWNORMAL); } } finally_do_arg2 (HWND, creatorWnd, BOOL, bIsForeground, { if (finally_arg) { EnableWindow(finally_arg, TRUE); if (finally_arg2) BringToForeground (finally_arg);}}); DialogBoxParamW (hInst, MAKEINTRESOURCEW (IDD_STATIC_MODAL_WAIT_DLG), hParent, (DLGPROC) WaitDlgProc, (LPARAM) &threadParam); WaitDialogDisplaying = FALSE; if (!(hwnd && bUseHwndAsParent)) { if (hParent) DestroyWindow (hParent); UnregisterClassW (className, hInst); } } } #ifndef SETUP /************************************************************************/ static BOOL PerformMountIoctl (MOUNT_STRUCT* pmount, LPDWORD pdwResult, BOOL useVolumeID, BYTE volumeID[VOLUME_ID_SIZE]) { if (useVolumeID) { wstring devicePath = FindDeviceByVolumeID (volumeID, FALSE); if (devicePath == L"") { if (pdwResult) *pdwResult = 0; SetLastError (ERROR_PATH_NOT_FOUND); return FALSE; } else { BOOL bDevice = FALSE; CreateFullVolumePath (pmount->wszVolume, sizeof(pmount->wszVolume), devicePath.c_str(), &bDevice); } } return DeviceIoControl (hDriver, TC_IOCTL_MOUNT_VOLUME, pmount, sizeof (MOUNT_STRUCT), pmount, sizeof (MOUNT_STRUCT), pdwResult, NULL); } // specific definitions and implementation for support of mount operation // in wait dialog mechanism typedef struct { MOUNT_STRUCT* pmount; BOOL useVolumeID; BYTE volumeID[VOLUME_ID_SIZE]; BOOL* pbResult; DWORD* pdwResult; DWORD dwLastError; } MountThreadParam; void CALLBACK MountWaitThreadProc(void* pArg, HWND ) { MountThreadParam* pThreadParam = (MountThreadParam*) pArg; *(pThreadParam->pbResult) = PerformMountIoctl (pThreadParam->pmount, pThreadParam->pdwResult, pThreadParam->useVolumeID, pThreadParam->volumeID); pThreadParam->dwLastError = GetLastError (); } /************************************************************************/ // Use only cached passwords if password = NULL // // Returns: // -1 = user aborted mount / error // 0 = mount failed // 1 = mount OK // 2 = mount OK in shared mode // // Note that some code calling this relies on the content of the mountOptions struct // to remain unmodified (don't remove the 'const' without proper revision). int MountVolume (HWND hwndDlg, int driveNo, wchar_t *volumePath, Password *password, int pkcs5, int pim, BOOL truecryptMode, BOOL cachePassword, BOOL cachePim, BOOL sharedAccess, const MountOptions* const mountOptions, BOOL quiet, BOOL bReportWrongPassword) { MOUNT_STRUCT mount; DWORD dwResult, dwLastError = ERROR_SUCCESS; BOOL bResult, bDevice; wchar_t root[MAX_PATH]; int favoriteMountOnArrivalRetryCount = 0; BOOL useVolumeID = FALSE; BYTE volumeID[VOLUME_ID_SIZE] = {0}; #ifdef TCMOUNT if (mountOptions->PartitionInInactiveSysEncScope) { if (!CheckSysEncMountWithoutPBA (hwndDlg, volumePath, quiet)) return -1; } #endif if (IsMountedVolume (volumePath)) { if (!quiet) Error ("VOL_ALREADY_MOUNTED", hwndDlg); return -1; } if (!IsDriveAvailable (driveNo)) { if (!quiet) Error ("DRIVE_LETTER_UNAVAILABLE", hwndDlg); return -1; } // If using cached passwords, check cache status first if (password == NULL && IsPasswordCacheEmpty ()) return 0; ZeroMemory (&mount, sizeof (mount)); mount.bExclusiveAccess = sharedAccess ? FALSE : TRUE; mount.SystemFavorite = MountVolumesAsSystemFavorite; mount.UseBackupHeader = mountOptions->UseBackupHeader; mount.RecoveryMode = mountOptions->RecoveryMode; StringCbCopyW (mount.wszLabel, sizeof (mount.wszLabel), mountOptions->Label); retry: mount.nDosDriveNo = driveNo; mount.bCache = cachePassword; mount.bCachePim = cachePim; mount.bPartitionInInactiveSysEncScope = FALSE; if (password != NULL) mount.VolumePassword = *password; else mount.VolumePassword.Length = 0; if (!mountOptions->ReadOnly && mountOptions->ProtectHiddenVolume) { mount.ProtectedHidVolPassword = mountOptions->ProtectedHidVolPassword; mount.bProtectHiddenVolume = TRUE; mount.ProtectedHidVolPkcs5Prf = mountOptions->ProtectedHidVolPkcs5Prf; mount.ProtectedHidVolPim = mountOptions->ProtectedHidVolPim; } else mount.bProtectHiddenVolume = FALSE; mount.bMountReadOnly = mountOptions->ReadOnly; mount.bMountRemovable = mountOptions->Removable; mount.bPreserveTimestamp = mountOptions->PreserveTimestamp; if (mountOptions->DisableMountManager) mount.bMountManager = FALSE; else mount.bMountManager = TRUE; mount.pkcs5_prf = pkcs5; mount.bTrueCryptMode = truecryptMode; mount.VolumePim = pim; wstring path = volumePath; if (path.find (L"\\\\?\\") == 0) { // Remove \\?\ prefix path = path.substr (4); StringCchCopyW (volumePath, TC_MAX_PATH, path.c_str()); } if (path.find (L"Volume{") == 0 && path.rfind (L"}\\") == path.size() - 2) { wstring resolvedPath = VolumeGuidPathToDevicePath (path); if (!resolvedPath.empty()) StringCchCopyW (volumePath, TC_MAX_PATH, resolvedPath.c_str()); } if ((path.length () >= 3) && (_wcsnicmp (path.c_str(), L"ID:", 3) == 0)) { std::vector<byte> arr; if ( (path.length() == (3 + 2*VOLUME_ID_SIZE)) && HexWideStringToArray (path.c_str() + 3, arr) && (arr.size() == VOLUME_ID_SIZE) ) { useVolumeID = TRUE; bDevice = TRUE; memcpy (volumeID, &arr[0], VOLUME_ID_SIZE); } else { if (!quiet) Error ("VOLUME_ID_INVALID", hwndDlg); SetLastError (ERROR_INVALID_PARAMETER); return -1; } } else CreateFullVolumePath (mount.wszVolume, sizeof(mount.wszVolume), volumePath, &bDevice); if (!bDevice) { // put default values mount.BytesPerSector = 512; mount.BytesPerPhysicalSector = 512; mount.MaximumTransferLength = 65536; mount.MaximumPhysicalPages = 17; mount.AlignmentMask = 0; // UNC path if (path.find (L"\\\\") == 0) { StringCbCopyW (mount.wszVolume, sizeof (mount.wszVolume), (L"UNC" + path.substr (1)).c_str()); } if (GetVolumePathName (volumePath, root, ARRAYSIZE (root) - 1)) { DWORD bps, flags, d; if (GetDiskFreeSpace (root, &d, &bps, &d, &d)) { mount.BytesPerSector = bps; mount.BytesPerPhysicalSector = bps; } if (IsOSAtLeast (WIN_VISTA)) { if ( (wcslen(root) >= 2) && (root[1] == L':') && (towupper(root[0]) >= L'A' && towupper(root[0]) <= L'Z') ) { wstring drivePath = L"\\\\.\\X:"; HANDLE dev = INVALID_HANDLE_VALUE; VOLUME_DISK_EXTENTS extents = {0}; DWORD dwResult = 0; drivePath[4] = root[0]; if ((dev = CreateFile (drivePath.c_str(),0, 0, NULL, OPEN_EXISTING, 0, NULL)) != INVALID_HANDLE_VALUE) { if (DeviceIoControl (dev, IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS, NULL, 0, &extents, sizeof(extents), &dwResult, NULL)) { if (extents.NumberOfDiskExtents > 0) { STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR accessDesc; STORAGE_ADAPTER_DESCRIPTOR adapterDesc; if (GetPhysicalDriveStorageInformation (extents.Extents[0].DiskNumber, &accessDesc, &adapterDesc)) { if (accessDesc.Size >= sizeof (STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR)) { mount.BytesPerSector = accessDesc.BytesPerLogicalSector; mount.BytesPerPhysicalSector = accessDesc.BytesPerPhysicalSector; } if (adapterDesc.Size >= sizeof (STORAGE_ADAPTER_DESCRIPTOR)) { mount.MaximumTransferLength = adapterDesc.MaximumTransferLength; mount.MaximumPhysicalPages = adapterDesc.MaximumPhysicalPages; mount.AlignmentMask = adapterDesc.AlignmentMask; } } } } CloseHandle (dev); } } } // Read-only host filesystem if (!mount.bMountReadOnly && GetVolumeInformation (root, NULL, 0, NULL, &d, &flags, NULL, 0)) mount.bMountReadOnly = (flags & FILE_READ_ONLY_VOLUME) != 0; } } if (mountOptions->PartitionInInactiveSysEncScope) { if (mount.wszVolume == NULL || swscanf_s ((const wchar_t *) mount.wszVolume, WIDE("\\Device\\Harddisk%d\\Partition"), &mount.nPartitionInInactiveSysEncScopeDriveNo, sizeof(mount.nPartitionInInactiveSysEncScopeDriveNo)) != 1) { if (!quiet) Warning ("NO_SYSENC_PARTITION_SELECTED", hwndDlg); return -1; } mount.bPartitionInInactiveSysEncScope = TRUE; } if (!quiet) { MountThreadParam mountThreadParam; mountThreadParam.pmount = &mount; mountThreadParam.useVolumeID = useVolumeID; memcpy (mountThreadParam.volumeID, volumeID, VOLUME_ID_SIZE); mountThreadParam.pbResult = &bResult; mountThreadParam.pdwResult = &dwResult; mountThreadParam.dwLastError = ERROR_SUCCESS; ShowWaitDialog (hwndDlg, FALSE, MountWaitThreadProc, &mountThreadParam); dwLastError = mountThreadParam.dwLastError; } else { bResult = PerformMountIoctl (&mount, &dwResult, useVolumeID, volumeID); dwLastError = GetLastError (); } burn (&mount.VolumePassword, sizeof (mount.VolumePassword)); burn (&mount.ProtectedHidVolPassword, sizeof (mount.ProtectedHidVolPassword)); burn (&mount.pkcs5_prf, sizeof (mount.pkcs5_prf)); burn (&mount.bTrueCryptMode, sizeof (mount.bTrueCryptMode)); burn (&mount.ProtectedHidVolPkcs5Prf, sizeof (mount.ProtectedHidVolPkcs5Prf)); SetLastError (dwLastError); if (bResult == FALSE) { // Volume already open by another process if (GetLastError () == ERROR_SHARING_VIOLATION) { if (FavoriteMountOnArrivalInProgress && ++favoriteMountOnArrivalRetryCount < 10) { Sleep (500); goto retry; } if (mount.bExclusiveAccess == FALSE) { if (!quiet) Error ("FILE_IN_USE_FAILED", hwndDlg); return -1; } else { if (quiet) { mount.bExclusiveAccess = FALSE; goto retry; } // Ask user if (IDYES == AskWarnNoYes ("FILE_IN_USE", hwndDlg)) { mount.bExclusiveAccess = FALSE; goto retry; } } return -1; } if (!quiet && (!MultipleMountOperationInProgress || GetLastError() != ERROR_NOT_READY)) handleWin32Error (hwndDlg, SRC_POS); return -1; } if (mount.nReturnCode != 0) { if (mount.nReturnCode == ERR_PASSWORD_WRONG) { // Do not report wrong password, if not instructed to if (bReportWrongPassword) { IncreaseWrongPwdRetryCount (1); // We increase the count here only if bReportWrongPassword is TRUE, because "Auto-Mount All Devices" and other callers do it separately if (WrongPwdRetryCountOverLimit () && !mount.UseBackupHeader) { // Retry using embedded header backup (if any) mount.UseBackupHeader = TRUE; goto retry; } if (bDevice && mount.bProtectHiddenVolume) { int driveNo; if (swscanf (volumePath, L"\\Device\\Harddisk%d\\Partition", &driveNo) == 1) { OPEN_TEST_STRUCT openTestStruct; memset (&openTestStruct, 0, sizeof (openTestStruct)); openTestStruct.bDetectTCBootLoader = TRUE; StringCchPrintfW ((wchar_t *) openTestStruct.wszFileName, array_capacity (openTestStruct.wszFileName), L"\\Device\\Harddisk%d\\Partition0", driveNo); DWORD dwResult; if (DeviceIoControl (hDriver, TC_IOCTL_OPEN_TEST, &openTestStruct, sizeof (OPEN_TEST_STRUCT), &openTestStruct, sizeof (OPEN_TEST_STRUCT), &dwResult, NULL) && openTestStruct.TCBootLoaderDetected) WarningDirect ((GetWrongPasswordErrorMessage (hwndDlg) + L"\n\n" + GetString ("HIDDEN_VOL_PROT_PASSWORD_US_KEYB_LAYOUT")).c_str(), hwndDlg); else handleError (hwndDlg, mount.nReturnCode, SRC_POS); } } else handleError (hwndDlg, mount.nReturnCode, SRC_POS); } return 0; } if (!quiet) handleError (hwndDlg, mount.nReturnCode, SRC_POS); return 0; } // Mount successful if (mount.UseBackupHeader != mountOptions->UseBackupHeader && mount.UseBackupHeader) { if (bReportWrongPassword && !Silent) Warning ("HEADER_DAMAGED_AUTO_USED_HEADER_BAK", hwndDlg); } LastMountedVolumeDirty = mount.FilesystemDirty; if (mount.FilesystemDirty) { wchar_t msg[1024]; wchar_t mountPoint[] = { L'A' + (wchar_t) driveNo, L':', 0 }; StringCbPrintfW (msg, sizeof(msg), GetString ("MOUNTED_VOLUME_DIRTY"), mountPoint); if (AskWarnYesNoStringTopmost (msg, hwndDlg) == IDYES) CheckFilesystem (hwndDlg, driveNo, TRUE); } if (mount.VolumeMountedReadOnlyAfterAccessDenied && !Silent && !bDevice && !FileHasReadOnlyAttribute (volumePath) && !IsFileOnReadOnlyFilesystem (volumePath)) { wchar_t msg[1024]; wchar_t mountPoint[] = { L'A' + (wchar_t) driveNo, L':', 0 }; StringCbPrintfW (msg, sizeof(msg), GetString ("MOUNTED_CONTAINER_FORCED_READ_ONLY"), mountPoint); WarningDirect (msg, hwndDlg); } if (mount.VolumeMountedReadOnlyAfterAccessDenied && !Silent && bDevice) { wchar_t msg[1024]; wchar_t mountPoint[] = { L'A' + (wchar_t) driveNo, L':', 0 }; StringCbPrintfW (msg, sizeof(msg), GetString ("MOUNTED_DEVICE_FORCED_READ_ONLY"), mountPoint); WarningDirect (msg, hwndDlg); } if (mount.VolumeMountedReadOnlyAfterDeviceWriteProtected && !Silent && wcsstr (volumePath, L"\\Device\\Harddisk") == volumePath) { wchar_t msg[1024]; wchar_t mountPoint[] = { L'A' + (wchar_t) driveNo, L':', 0 }; StringCbPrintfW (msg, sizeof(msg), GetString ("MOUNTED_DEVICE_FORCED_READ_ONLY_WRITE_PROTECTION"), mountPoint); WarningDirect (msg, hwndDlg); if (CurrentOSMajor >= 6 && wcsstr (volumePath, L"\\Device\\HarddiskVolume") != volumePath && AskNoYes ("ASK_REMOVE_DEVICE_WRITE_PROTECTION", hwndDlg) == IDYES) { RemoveDeviceWriteProtection (hwndDlg, volumePath); } } if (mount.wszLabel[0] && !mount.bDriverSetLabel) { // try setting the drive label on user-mode using registry UpdateDriveCustomLabel (driveNo, mount.wszLabel, TRUE); } ResetWrongPwdRetryCount (); BroadcastDeviceChange (DBT_DEVICEARRIVAL, driveNo, 0); if (mount.bExclusiveAccess == FALSE) return 2; return 1; } #endif typedef struct { int nDosDriveNo; BOOL forced; int dismountMaxRetries; DWORD retryDelay; int* presult; DWORD dwLastError; } UnmountThreadParam; void CALLBACK UnmountWaitThreadProc(void* pArg, HWND hwnd) { UnmountThreadParam* pThreadParam = (UnmountThreadParam*) pArg; int dismountMaxRetries = pThreadParam->dismountMaxRetries; DWORD retryDelay = pThreadParam->retryDelay; do { *pThreadParam->presult = DriverUnmountVolume (hwnd, pThreadParam->nDosDriveNo, pThreadParam->forced); if (*pThreadParam->presult == ERR_FILES_OPEN) Sleep (retryDelay); else break; } while (--dismountMaxRetries > 0); pThreadParam->dwLastError = GetLastError (); } static BOOL UnmountVolumeBase (HWND hwndDlg, int nDosDriveNo, BOOL forceUnmount, BOOL ntfsFormatCase) { int result; BOOL forced = forceUnmount; int dismountMaxRetries = ntfsFormatCase? 5 : UNMOUNT_MAX_AUTO_RETRIES; DWORD retryDelay = ntfsFormatCase? 2000: UNMOUNT_AUTO_RETRY_DELAY; UnmountThreadParam param; retry: BroadcastDeviceChange (DBT_DEVICEREMOVEPENDING, nDosDriveNo, 0); param.nDosDriveNo = nDosDriveNo; param.forced = forced; param.dismountMaxRetries = dismountMaxRetries; param.retryDelay = retryDelay; param.presult = &result; if (Silent) { UnmountWaitThreadProc (&param, hwndDlg); } else { ShowWaitDialog (hwndDlg, FALSE, UnmountWaitThreadProc, &param); } SetLastError (param.dwLastError); if (result != 0) { if (result == ERR_FILES_OPEN && !Silent) { if (IDYES == AskWarnYesNoTopmost ("UNMOUNT_LOCK_FAILED", hwndDlg)) { forced = TRUE; goto retry; } if (IsOSAtLeast (WIN_7)) { // Undo SHCNE_DRIVEREMOVED wchar_t root[] = { (wchar_t) nDosDriveNo + L'A', L':', L'\\', 0 }; SHChangeNotify (SHCNE_DRIVEADD, SHCNF_PATH, root, NULL); } return FALSE; } Error ("UNMOUNT_FAILED", hwndDlg); return FALSE; } BroadcastDeviceChange (DBT_DEVICEREMOVECOMPLETE, nDosDriveNo, 0); return TRUE; } BOOL UnmountVolume (HWND hwndDlg, int nDosDriveNo, BOOL forceUnmount) { return UnmountVolumeBase (hwndDlg, nDosDriveNo, forceUnmount, FALSE); } BOOL UnmountVolumeAfterFormatExCall (HWND hwndDlg, int nDosDriveNo) { return UnmountVolumeBase (hwndDlg, nDosDriveNo, FALSE, TRUE); } BOOL IsPasswordCacheEmpty (void) { DWORD dw; return !DeviceIoControl (hDriver, TC_IOCTL_GET_PASSWORD_CACHE_STATUS, 0, 0, 0, 0, &dw, 0); } BOOL IsMountedVolumeID (BYTE volumeID[VOLUME_ID_SIZE]) { MOUNT_LIST_STRUCT mlist; DWORD dwResult; int i; memset (&mlist, 0, sizeof (mlist)); if ( !DeviceIoControl (hDriver, TC_IOCTL_GET_MOUNTED_VOLUMES, &mlist, sizeof (mlist), &mlist, sizeof (mlist), &dwResult, NULL) || (mlist.ulMountedDrives >= (1 << 26)) ) { return FALSE; } if (mlist.ulMountedDrives) { for (i=0 ; i<26; i++) { if ((mlist.ulMountedDrives & (1 << i)) && (0 == memcmp (mlist.volumeID[i], volumeID, VOLUME_ID_SIZE))) return TRUE; } } return FALSE; } BOOL IsMountedVolume (const wchar_t *volname) { if ((wcslen (volname) == (3 + 2*VOLUME_ID_SIZE)) && _wcsnicmp (volname, L"ID:", 3) == 0) { /* Volume ID specified. Use it for matching mounted volumes. */ std::vector<byte> arr; if (HexWideStringToArray (&volname[3], arr) && (arr.size() == VOLUME_ID_SIZE)) { return IsMountedVolumeID (&arr[0]); } } else { MOUNT_LIST_STRUCT mlist; DWORD dwResult; int i; wchar_t volume[TC_MAX_PATH*2+16]; StringCbCopyW (volume, sizeof(volume), volname); if (wcsstr (volname, L"\\Device\\") != volname) StringCbPrintfW(volume, sizeof(volume), L"\\??\\%s", volname); wstring resolvedPath = VolumeGuidPathToDevicePath (volname); if (!resolvedPath.empty()) StringCbCopyW (volume, sizeof (volume), resolvedPath.c_str()); memset (&mlist, 0, sizeof (mlist)); if ( !DeviceIoControl (hDriver, TC_IOCTL_GET_MOUNTED_VOLUMES, &mlist, sizeof (mlist), &mlist, sizeof (mlist), &dwResult, NULL) || (mlist.ulMountedDrives >= (1 << 26)) ) { return FALSE; } if (mlist.ulMountedDrives) { for (i=0 ; i<26; i++) { if ((mlist.ulMountedDrives & (1 << i)) && IsNullTerminateString (mlist.wszVolume[i], TC_MAX_PATH) && (0 == _wcsicmp ((wchar_t *) mlist.wszVolume[i], volume)) ) { return TRUE; } } } } return FALSE; } int GetMountedVolumeDriveNo (wchar_t *volname) { MOUNT_LIST_STRUCT mlist; DWORD dwResult; int i; wchar_t volume[TC_MAX_PATH*2+16]; if (volname == NULL) return -1; StringCbCopyW (volume, sizeof(volume), volname); if (wcsstr (volname, L"\\Device\\") != volname) StringCbPrintfW (volume, sizeof(volume), L"\\??\\%s", volname); wstring resolvedPath = VolumeGuidPathToDevicePath (volname); if (!resolvedPath.empty()) StringCbCopyW (volume, sizeof (volume), resolvedPath.c_str()); memset (&mlist, 0, sizeof (mlist)); if ( !DeviceIoControl (hDriver, TC_IOCTL_GET_MOUNTED_VOLUMES, &mlist, sizeof (mlist), &mlist, sizeof (mlist), &dwResult, NULL) || (mlist.ulMountedDrives >= (1 << 26)) ) { return -1; } if (mlist.ulMountedDrives) { for (i=0 ; i<26; i++) { if ((mlist.ulMountedDrives & (1 << i)) && IsNullTerminateString (mlist.wszVolume[i], TC_MAX_PATH) && (0 == _wcsicmp ((wchar_t *) mlist.wszVolume[i], (WCHAR *)volume)) ) { return i; } } } return -1; } #endif //!SETUP BOOL IsAdmin (void) { return IsUserAnAdmin (); } BOOL IsBuiltInAdmin () { HANDLE procToken; DWORD size; if (!IsAdmin() || !OpenProcessToken (GetCurrentProcess(), TOKEN_QUERY, &procToken)) return FALSE; finally_do_arg (HANDLE, procToken, { CloseHandle (finally_arg); }); if (GetTokenInformation (procToken, TokenUser, NULL, 0, &size) || GetLastError() != ERROR_INSUFFICIENT_BUFFER) return FALSE; TOKEN_USER *tokenUser = (TOKEN_USER *) malloc (size); if (!tokenUser) return FALSE; finally_do_arg (void *, tokenUser, { free (finally_arg); }); if (!GetTokenInformation (procToken, TokenUser, tokenUser, size, &size)) return FALSE; return IsWellKnownSid (tokenUser->User.Sid, WinAccountAdministratorSid); } BOOL IsUacSupported () { HKEY hkey; DWORD value = 1, size = sizeof (DWORD); if (!IsOSAtLeast (WIN_VISTA)) return FALSE; if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\System", 0, KEY_READ, &hkey) == ERROR_SUCCESS) { if (RegQueryValueEx (hkey, L"EnableLUA", 0, 0, (LPBYTE) &value, &size) != ERROR_SUCCESS) value = 1; RegCloseKey (hkey); } return value != 0; } BOOL ResolveSymbolicLink (const wchar_t *symLinkName, PWSTR targetName, size_t cbTargetName) { BOOL bResult; DWORD dwResult; RESOLVE_SYMLINK_STRUCT resolve; memset (&resolve, 0, sizeof(resolve)); StringCbCopyW (resolve.symLinkName, sizeof(resolve.symLinkName), symLinkName); bResult = DeviceIoControl (hDriver, TC_IOCTL_GET_RESOLVED_SYMLINK, &resolve, sizeof (resolve), &resolve, sizeof (resolve), &dwResult, NULL); StringCbCopyW (targetName, cbTargetName, resolve.targetName); return bResult; } BOOL GetPartitionInfo (const wchar_t *deviceName, PPARTITION_INFORMATION rpartInfo) { BOOL bResult; DWORD dwResult; DISK_PARTITION_INFO_STRUCT dpi; memset (&dpi, 0, sizeof(dpi)); StringCbCopyW ((PWSTR) &dpi.deviceName, sizeof(dpi.deviceName), deviceName); bResult = DeviceIoControl (hDriver, TC_IOCTL_GET_DRIVE_PARTITION_INFO, &dpi, sizeof (dpi), &dpi, sizeof (dpi), &dwResult, NULL); memcpy (rpartInfo, &dpi.partInfo, sizeof (PARTITION_INFORMATION)); return bResult; } BOOL GetDeviceInfo (const wchar_t *deviceName, DISK_PARTITION_INFO_STRUCT *info) { DWORD dwResult; memset (info, 0, sizeof(*info)); StringCbCopyW ((PWSTR) &info->deviceName, sizeof(info->deviceName), deviceName); return DeviceIoControl (hDriver, TC_IOCTL_GET_DRIVE_PARTITION_INFO, info, sizeof (*info), info, sizeof (*info), &dwResult, NULL); } #ifndef SETUP BOOL GetDriveGeometry (const wchar_t *deviceName, PDISK_GEOMETRY_EX diskGeometry) { BOOL bResult; DWORD dwResult; DISK_GEOMETRY_EX_STRUCT dg; memset (&dg, 0, sizeof(dg)); StringCbCopyW ((PWSTR) &dg.deviceName, sizeof(dg.deviceName), deviceName); bResult = DeviceIoControl (hDriver, VC_IOCTL_GET_DRIVE_GEOMETRY_EX, &dg, sizeof (dg), &dg, sizeof (dg), &dwResult, NULL); if (bResult && (dwResult == sizeof (dg)) && dg.diskGeometry.BytesPerSector) { ZeroMemory (diskGeometry, sizeof (DISK_GEOMETRY_EX)); memcpy (&diskGeometry->Geometry, &dg.diskGeometry, sizeof (DISK_GEOMETRY)); diskGeometry->DiskSize.QuadPart = dg.DiskSize.QuadPart; return TRUE; } else return FALSE; } BOOL GetPhysicalDriveGeometry (int driveNumber, PDISK_GEOMETRY_EX diskGeometry) { HANDLE hDev; BOOL bResult = FALSE; TCHAR devicePath[MAX_PATH]; StringCchPrintfW (devicePath, ARRAYSIZE (devicePath), L"\\\\.\\PhysicalDrive%d", driveNumber); if ((hDev = CreateFileW (devicePath, 0, 0, NULL, OPEN_EXISTING, 0, NULL)) != INVALID_HANDLE_VALUE) { DWORD bytesRead = 0; ZeroMemory (diskGeometry, sizeof (DISK_GEOMETRY_EX)); BYTE dgBuffer[256]; if ( DeviceIoControl (hDev, IOCTL_DISK_GET_DRIVE_GEOMETRY_EX, NULL, 0, dgBuffer, sizeof (dgBuffer), &bytesRead, NULL) && (bytesRead >= (sizeof (DISK_GEOMETRY) + sizeof (LARGE_INTEGER))) && ((PDISK_GEOMETRY_EX) dgBuffer)->Geometry.BytesPerSector) { memcpy (&diskGeometry->Geometry, &((PDISK_GEOMETRY_EX) dgBuffer)->Geometry, sizeof (DISK_GEOMETRY)); diskGeometry->DiskSize.QuadPart = ((PDISK_GEOMETRY_EX) dgBuffer)->DiskSize.QuadPart; bResult = TRUE; } else { DISK_GEOMETRY geo; if ( DeviceIoControl (hDev, IOCTL_DISK_GET_DRIVE_GEOMETRY, NULL, 0, (LPVOID) &geo, sizeof (geo), &bytesRead, NULL) && (bytesRead >= sizeof (DISK_GEOMETRY)) && geo.BytesPerSector) { memcpy (&diskGeometry->Geometry, &geo, sizeof (DISK_GEOMETRY)); diskGeometry->DiskSize.QuadPart = geo.Cylinders.QuadPart * geo.SectorsPerTrack * geo.TracksPerCylinder * geo.BytesPerSector; bResult = TRUE; if (CurrentOSMajor >= 6) { STORAGE_READ_CAPACITY storage = {0}; storage.Version = sizeof (STORAGE_READ_CAPACITY); storage.Size = sizeof (STORAGE_READ_CAPACITY); if (DeviceIoControl (hDev, IOCTL_STORAGE_READ_CAPACITY, NULL, 0, (LPVOID) &storage, sizeof (storage), &bytesRead, NULL) && (bytesRead >= sizeof (storage)) && (storage.Size == sizeof (STORAGE_READ_CAPACITY)) ) { diskGeometry->DiskSize.QuadPart = storage.DiskLength.QuadPart; } } } } CloseHandle (hDev); } return bResult; } #endif // Returns drive letter number assigned to device (-1 if none) int GetDiskDeviceDriveLetter (PWSTR deviceName) { int i; WCHAR link[MAX_PATH]; WCHAR target[MAX_PATH]; WCHAR device[MAX_PATH]; if (!ResolveSymbolicLink (deviceName, device, sizeof(device))) StringCchCopyW (device, MAX_PATH, deviceName); for (i = 0; i < 26; i++) { WCHAR drive[] = { (WCHAR) i + L'A', L':', 0 }; StringCchCopyW (link, MAX_PATH, L"\\DosDevices\\"); StringCchCatW (link, MAX_PATH, drive); if ( ResolveSymbolicLink (link, target, sizeof(target)) && (wcscmp (device, target) == 0) ) { return i; } } return -1; } // WARNING: This function does NOT provide 100% reliable results -- do NOT use it for critical/dangerous operations! // Return values: 0 - filesystem does not appear empty, 1 - filesystem appears empty, -1 - an error occurred int FileSystemAppearsEmpty (const wchar_t *devicePath) { float percentFreeSpace = 0.0; __int64 occupiedBytes = 0; if (GetStatsFreeSpaceOnPartition (devicePath, &percentFreeSpace, &occupiedBytes, TRUE) != -1) { if (occupiedBytes > BYTES_PER_GB && percentFreeSpace < 99.99 // "percentFreeSpace < 99.99" is needed because an NTFS filesystem larger than several terabytes can have more than 1GB of data in use, even if there are no files stored on it. || percentFreeSpace < 88) // A 24-MB NTFS filesystem has 11.5% of space in use even if there are no files stored on it. { return 0; } else return 1; } else return -1; } // Returns the free space on the specified partition (volume) in bytes. If the 'occupiedBytes' pointer // is not NULL, size of occupied space (in bytes) is written to the pointed location. In addition, if the // 'percent' pointer is not NULL, % of free space is stored in the pointed location. If there's an error, // returns -1. __int64 GetStatsFreeSpaceOnPartition (const wchar_t *devicePath, float *percentFree, __int64 *occupiedBytes, BOOL silent) { WCHAR devPath [MAX_PATH]; int driveLetterNo = -1; wchar_t szRootPath[4] = {0, L':', L'\\', 0}; ULARGE_INTEGER freeSpaceSize; ULARGE_INTEGER totalNumberOfBytes; ULARGE_INTEGER totalNumberOfFreeBytes; StringCbCopyW (devPath, sizeof(devPath), devicePath); driveLetterNo = GetDiskDeviceDriveLetter (devPath); szRootPath[0] = (wchar_t) driveLetterNo + L'A'; if (!GetDiskFreeSpaceEx (szRootPath, &freeSpaceSize, &totalNumberOfBytes, &totalNumberOfFreeBytes)) { if (!silent) { handleWin32Error (MainDlg, SRC_POS); Error ("CANNOT_CALC_SPACE", MainDlg); } return -1; } if (percentFree != NULL || occupiedBytes != NULL) { // Determine occupied space and % of free space PARTITION_INFORMATION partitionInfo; if (!GetPartitionInfo (devicePath, &partitionInfo)) { if (!silent) { handleWin32Error (MainDlg, SRC_POS); Error ("CANT_GET_VOLSIZE", MainDlg); } return -1; } if (occupiedBytes != NULL) *occupiedBytes = partitionInfo.PartitionLength.QuadPart - freeSpaceSize.QuadPart; if (percentFree != NULL) *percentFree = (float) ((double) freeSpaceSize.QuadPart / (double) partitionInfo.PartitionLength.QuadPart * 100.0); } return freeSpaceSize.QuadPart; } // Returns -1 if there's an error. __int64 GetDeviceSize (const wchar_t *devicePath) { PARTITION_INFORMATION partitionInfo; if (!GetPartitionInfo (devicePath, &partitionInfo)) return -1; return partitionInfo.PartitionLength.QuadPart; } HANDLE DismountDrive (wchar_t *devName, wchar_t *devicePath) { DWORD dwResult; HANDLE hVolume; BOOL bResult = FALSE; int attempt = UNMOUNT_MAX_AUTO_RETRIES; int driveLetterNo = -1; WCHAR devPath [MAX_PATH]; StringCbCopyW (devPath, sizeof(devPath), devicePath); driveLetterNo = GetDiskDeviceDriveLetter (devPath); hVolume = CreateFile (devName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); if (hVolume == INVALID_HANDLE_VALUE) return INVALID_HANDLE_VALUE; // Try to lock the volume first so that dismount is not forced. // If we fail, we will dismount anyway even if it needs to be forced. CloseVolumeExplorerWindows (MainDlg, driveLetterNo); while (!(bResult = DeviceIoControl (hVolume, FSCTL_LOCK_VOLUME, NULL, 0, NULL, 0, &dwResult, NULL)) && attempt > 0) { Sleep (UNMOUNT_AUTO_RETRY_DELAY); attempt--; } // Try to dismount the volume attempt = UNMOUNT_MAX_AUTO_RETRIES; while (!(bResult = DeviceIoControl (hVolume, FSCTL_DISMOUNT_VOLUME, NULL, 0, NULL, 0, &dwResult, NULL)) && attempt > 0) { Sleep (UNMOUNT_AUTO_RETRY_DELAY); attempt--; } if (!bResult) CloseHandle (hVolume); return (bResult ? hVolume : INVALID_HANDLE_VALUE); } // Returns -1 if the specified string is not found in the buffer. Otherwise, returns the // offset of the first occurrence of the string. The string and the buffer may contain zeroes, // which do NOT terminate them. int64 FindString (const char *buf, const char *str, int64 bufLen, int64 strLen, int64 startOffset) { if (buf == NULL || str == NULL || strLen > bufLen || bufLen < 1 || strLen < 1 || startOffset > bufLen - strLen) { return -1; } for (int64 i = startOffset; i <= bufLen - strLen; i++) { if (memcmp (buf + i, str, (size_t) strLen) == 0) return i; } return -1; } // Returns TRUE if the file or directory exists (both may be enclosed in quotation marks). BOOL FileExists (const wchar_t *filePathPtr) { wchar_t filePath [TC_MAX_PATH * 2 + 1]; // Strip quotation marks (if any) if (filePathPtr [0] == L'"') { StringCbCopyW (filePath, sizeof(filePath), filePathPtr + 1); } else { StringCbCopyW (filePath, sizeof(filePath), filePathPtr); } // Strip quotation marks (if any) if (filePath [wcslen (filePath) - 1] == L'"') filePath [wcslen (filePath) - 1] = 0; return (_waccess (filePath, 0) != -1); } // Searches the file from its end for the LAST occurrence of the string str. // The string may contain zeroes, which do NOT terminate the string. // If the string is found, its offset from the start of the file is returned. // If the string isn't found or if any error occurs, -1 is returned. __int64 FindStringInFile (const wchar_t *filePath, const char* str, int strLen) { int bufSize = 64 * BYTES_PER_KB; char *buffer = (char *) err_malloc (bufSize); HANDLE src = NULL; DWORD bytesRead; BOOL readRetVal; __int64 filePos = GetFileSize64 (filePath); int bufPos = 0; LARGE_INTEGER seekOffset, seekOffsetNew; BOOL bExit = FALSE; int filePosStep; __int64 retVal = -1; if (filePos <= 0 || buffer == NULL || strLen > bufSize || strLen < 1) { if (buffer) free (buffer); return -1; } src = CreateFile (filePath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); if (src == INVALID_HANDLE_VALUE) { free (buffer); return -1; } filePosStep = bufSize - strLen + 1; do { filePos -= filePosStep; if (filePos < 0) { filePos = 0; bExit = TRUE; } seekOffset.QuadPart = filePos; if (SetFilePointerEx (src, seekOffset, &seekOffsetNew, FILE_BEGIN) == 0) goto fsif_end; if ((readRetVal = ReadFile (src, buffer, bufSize, &bytesRead, NULL)) == 0 || bytesRead == 0) goto fsif_end; bufPos = bytesRead - strLen; while (bufPos > 0) { if (memcmp (buffer + bufPos, str, strLen) == 0) { // String found retVal = filePos + bufPos; goto fsif_end; } bufPos--; } } while (!bExit); fsif_end: CloseHandle (src); free (buffer); return retVal; } // System CopyFile() copies source file attributes (like FILE_ATTRIBUTE_ENCRYPTED) // so we need to use our own copy function BOOL TCCopyFileBase (HANDLE src, HANDLE dst) { __int8 *buffer; FILETIME fileTime; DWORD bytesRead, bytesWritten; BOOL res; buffer = (char *) malloc (64 * 1024); if (!buffer) { CloseHandle (src); CloseHandle (dst); return FALSE; } while (res = ReadFile (src, buffer, 64 * 1024, &bytesRead, NULL)) { if (bytesRead == 0) { res = 1; break; } if (!WriteFile (dst, buffer, bytesRead, &bytesWritten, NULL) || bytesRead != bytesWritten) { res = 0; break; } } if (GetFileTime (src, NULL, NULL, &fileTime)) SetFileTime (dst, NULL, NULL, &fileTime); CloseHandle (src); CloseHandle (dst); free (buffer); return res != 0; } BOOL TCCopyFile (wchar_t *sourceFileName, wchar_t *destinationFile) { HANDLE src, dst; src = CreateFileW (sourceFileName, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); if (src == INVALID_HANDLE_VALUE) return FALSE; dst = CreateFileW (destinationFile, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL); if (dst == INVALID_HANDLE_VALUE) { CloseHandle (src); return FALSE; } return TCCopyFileBase (src, dst); } BOOL DecompressZipToDir (const unsigned char *inputBuffer, DWORD inputLength, const wchar_t *destinationDir, ProgressFn progressFnPtr, HWND hwndDlg) { BOOL res = TRUE; zip_error_t zerr; zip_int64_t numFiles, i; zip_stat_t sb; zip_source_t* zsrc = zip_source_buffer_create (inputBuffer, inputLength, 0, &zerr); if (!zsrc) return FALSE; zip_t* z = zip_open_from_source (zsrc, ZIP_CHECKCONS | ZIP_RDONLY, &zerr); if (!z) { zip_source_free (zsrc); return FALSE; } finally_do_arg (zip_t*, z, { zip_close (finally_arg); }); numFiles = zip_get_num_entries (z, 0); if (numFiles <= 0) return FALSE; for (i = 0; (i < numFiles) && res; i++) { ZeroMemory (&sb, sizeof (sb)); if ((0 == zip_stat_index (z, i, 0, &sb)) && (sb.valid & (ZIP_STAT_NAME | ZIP_STAT_SIZE)) && (sb.size > 0)) { std::wstring wname = Utf8StringToWide (sb.name); CorrectFileName (wname); std::wstring filePath = destinationDir + wname; size_t pos = filePath.find_last_of (L"/\\"); // create the parent directory if it doesn't exist if (pos != std::wstring::npos) { SHCreateDirectoryEx (NULL, filePath.substr (0, pos).c_str(), NULL); } zip_file_t *f = zip_fopen_index (z, i, 0); if (f) { ByteArray buffer((ByteArray::size_type) sb.size); zip_fread (f, buffer.data(), sb.size); zip_fclose (f); if (progressFnPtr) progressFnPtr (hwndDlg, filePath.c_str()); res = SaveBufferToFile ((char *) buffer.data(), filePath.c_str(), (DWORD) buffer.size(), FALSE, TRUE); } } } return res; } // If bAppend is TRUE, the buffer is appended to an existing file. If bAppend is FALSE, any existing file // is replaced. If an error occurs, the incomplete file is deleted (provided that bAppend is FALSE). BOOL SaveBufferToFile (const char *inputBuffer, const wchar_t *destinationFile, DWORD inputLength, BOOL bAppend, BOOL bRenameIfFailed) { HANDLE dst; DWORD bytesWritten; BOOL res = TRUE; DWORD dwLastError = 0; dst = CreateFile (destinationFile, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, bAppend ? OPEN_EXISTING : CREATE_ALWAYS, 0, NULL); dwLastError = GetLastError(); if (!bAppend && bRenameIfFailed && (dst == INVALID_HANDLE_VALUE) && (GetLastError () == ERROR_SHARING_VIOLATION)) { wchar_t renamedPath[TC_MAX_PATH + 1]; StringCbCopyW (renamedPath, sizeof(renamedPath), destinationFile); StringCbCatW (renamedPath, sizeof(renamedPath), VC_FILENAME_RENAMED_SUFFIX); /* rename the locked file in order to be able to create a new one */ if (MoveFileEx (destinationFile, renamedPath, MOVEFILE_REPLACE_EXISTING)) { dst = CreateFile (destinationFile, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, 0, NULL); dwLastError = GetLastError(); if (dst == INVALID_HANDLE_VALUE) { /* restore the original file name */ MoveFileEx (renamedPath, destinationFile, MOVEFILE_REPLACE_EXISTING); } else { /* delete the renamed file when the machine reboots */ MoveFileEx (renamedPath, NULL, MOVEFILE_DELAY_UNTIL_REBOOT); } } } if (dst == INVALID_HANDLE_VALUE) { SetLastError (dwLastError); handleWin32Error (MainDlg, SRC_POS); return FALSE; } if (bAppend) SetFilePointer (dst, 0, NULL, FILE_END); if (!WriteFile (dst, inputBuffer, inputLength, &bytesWritten, NULL) || inputLength != bytesWritten) { res = FALSE; } if (!res) { // If CREATE_ALWAYS is used, ERROR_ALREADY_EXISTS is returned after successful overwrite // of an existing file (it's not an error) if (! (GetLastError() == ERROR_ALREADY_EXISTS && !bAppend) ) handleWin32Error (MainDlg, SRC_POS); } CloseHandle (dst); if (!res && !bAppend) _wremove (destinationFile); return res; } // Proper flush for Windows systems. Returns TRUE if successful. BOOL TCFlushFile (FILE *f) { HANDLE hf = (HANDLE) _get_osfhandle (_fileno (f)); fflush (f); if (hf == INVALID_HANDLE_VALUE) return FALSE; return FlushFileBuffers (hf) != 0; } // Prints a UTF-16 text (note that this involves a real printer, not a screen). // textByteLen - length of the text in bytes // title - printed as part of the page header and used as the filename for a temporary file BOOL PrintHardCopyTextUTF16 (wchar_t *text, wchar_t *title, size_t textByteLen) { wchar_t cl [MAX_PATH*3] = {L"/p \""}; wchar_t path [MAX_PATH * 2] = { 0 }; wchar_t filename [MAX_PATH + 1] = { 0 }; StringCbCopyW (filename, sizeof(filename), title); //strcat (filename, ".txt"); GetTempPath (ARRAYSIZE (path), path); if (!FileExists (path)) { StringCbCopyW (path, sizeof(path), GetConfigPath (filename)); if (wcslen(path) < 2) return FALSE; } else { StringCbCatW (path, sizeof(path), filename); } // Write the Unicode signature if (!SaveBufferToFile ("\xFF\xFE", path, 2, FALSE, FALSE)) { _wremove (path); return FALSE; } // Write the actual text if (!SaveBufferToFile ((char *) text, path, (DWORD) textByteLen, TRUE, FALSE)) { _wremove (path); return FALSE; } StringCbCatW (cl, sizeof(cl), path); StringCbCatW (cl, sizeof(cl), L"\""); // Get the absolute path for notepad if (GetWindowsDirectory(filename, MAX_PATH)) { if (filename[wcslen (filename) - 1] != L'\\') StringCbCatW (filename, sizeof(filename), L"\\"); StringCbCatW(filename, sizeof(filename), PRINT_TOOL); } else StringCbCopyW(filename, sizeof(filename), L"C:\\Windows\\" PRINT_TOOL); WaitCursor (); ShellExecute (NULL, L"open", filename, cl, NULL, SW_HIDE); Sleep (6000); NormalCursor(); _wremove (path); return TRUE; } BOOL IsNonInstallMode () { HKEY hkey; DWORD dw; if (bPortableModeConfirmed) return TRUE; if (hDriver != INVALID_HANDLE_VALUE) { // The driver is running if (DeviceIoControl (hDriver, TC_IOCTL_GET_PORTABLE_MODE_STATUS, NULL, 0, NULL, 0, &dw, 0)) { bPortableModeConfirmed = TRUE; return TRUE; } else { // This is also returned if we fail to determine the status (it does not mean that portable mode is disproved). return FALSE; } } else { // The tests in this block are necessary because this function is in some cases called before DriverAttach(). HANDLE hDriverTmp = CreateFile (WIN32_ROOT_PREFIX, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); if (hDriverTmp == INVALID_HANDLE_VALUE) { // The driver was not found in the system path wchar_t path[MAX_PATH * 2] = { 0 }; // We can't use GetConfigPath() here because it would call us back (indirect recursion) if (SUCCEEDED(SHGetFolderPath (NULL, CSIDL_APPDATA, NULL, 0, path))) { StringCbCatW (path, MAX_PATH * 2, L"\\VeraCrypt\\"); StringCbCatW (path, MAX_PATH * 2, TC_APPD_FILENAME_SYSTEM_ENCRYPTION); if (FileExists (path)) { // To maintain consistency and safety, if the system encryption config file exits, we cannot // allow portable mode. (This happens e.g. when the pretest fails and the user selects // "Last Known Good Configuration" from the Windows boot menu.) // However, if UAC elevation is needed, we have to confirm portable mode first (after we are elevated, we won't). if (!IsAdmin () && IsUacSupported ()) return TRUE; return FALSE; } } // As the driver was not found in the system path, we can predict that we will run in portable mode return TRUE; } else CloseHandle (hDriverTmp); } // The following test may be unreliable in some cases (e.g. after the user selects restore "Last Known Good // Configuration" from the Windows boot menu). if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\VeraCrypt", 0, KEY_READ | KEY_WOW64_32KEY, &hkey) == ERROR_SUCCESS) { RegCloseKey (hkey); return FALSE; } else return TRUE; } LRESULT SetCheckBox (HWND hwndDlg, int dlgItem, BOOL state) { return SendDlgItemMessage (hwndDlg, dlgItem, BM_SETCHECK, state ? BST_CHECKED : BST_UNCHECKED, 0); } BOOL GetCheckBox (HWND hwndDlg, int dlgItem) { return IsButtonChecked (GetDlgItem (hwndDlg, dlgItem)); } // Scroll the listview vertically so that the item with index of topMostVisibleItem is the topmost visible item. void SetListScrollHPos (HWND hList, int topMostVisibleItem) { int testedPos = 0; do { SendMessage (hList, LVM_SCROLL, 0, testedPos); } while (ListView_GetTopIndex (hList) < topMostVisibleItem && ++testedPos < 10000); } // Adds or removes TrueCrypt.exe to/from the system startup sequence (with appropriate command line arguments) void ManageStartupSeq (void) { if (!IsNonInstallMode ()) { wchar_t regk [64]; GetStartupRegKeyName (regk, sizeof(regk)); if (bStartOnLogon || bMountDevicesOnLogon || bMountFavoritesOnLogon) { wchar_t exe[MAX_PATH * 2] = { L'"' }; GetModuleFileName (NULL, exe + 1, ARRAYSIZE (exe) - 1); #ifdef VOLFORMAT { wchar_t *tmp = NULL; if (tmp = wcsrchr (exe, L'\\')) { *tmp = 0; StringCbCatW (exe, MAX_PATH * 2, L"\\VeraCrypt.exe"); } } #endif StringCbCatW (exe, MAX_PATH * 2, L"\" /q preferences /a logon"); if (bMountDevicesOnLogon) StringCbCatW (exe, MAX_PATH * 2, L" /a devices"); if (bMountFavoritesOnLogon) StringCbCatW (exe, MAX_PATH * 2, L" /a favorites"); WriteRegistryString (regk, L"VeraCrypt", exe); } else DeleteRegistryValue (regk, L"VeraCrypt"); } } // Adds or removes the VeraCrypt Volume Creation Wizard to/from the system startup sequence void ManageStartupSeqWiz (BOOL bRemove, const wchar_t *arg) { wchar_t regk [64]; GetStartupRegKeyName (regk, sizeof(regk)); if (!bRemove) { size_t exeSize = (MAX_PATH * 2) + 3 + 20 + wcslen (arg); // enough room for all concatenation operations wchar_t* exe = (wchar_t*) calloc(1, exeSize * sizeof (wchar_t)); exe[0] = L'"'; GetModuleFileName (NULL, exe + 1, (DWORD) (exeSize - 1)); #ifndef VOLFORMAT { wchar_t *tmp = NULL; if (tmp = wcsrchr (exe, L'\\')) { *tmp = 0; StringCchCatW (exe, exeSize, L"\\VeraCrypt Format.exe"); } } #endif if (wcslen (arg) > 0) { StringCchCatW (exe, exeSize, L"\" "); StringCchCatW (exe, exeSize, arg); } WriteRegistryString (regk, L"VeraCrypt Format", exe); free(exe); } else DeleteRegistryValue (regk, L"VeraCrypt Format"); } // Delete the last used Windows file selector path for TrueCrypt from the registry void CleanLastVisitedMRU (void) { WCHAR exeFilename[MAX_PATH]; WCHAR *strToMatch; WCHAR strTmp[4096]; WCHAR regPath[128]; WCHAR key[64]; int id, len; GetModuleFileNameW (NULL, exeFilename, sizeof (exeFilename) / sizeof(exeFilename[0])); strToMatch = wcsrchr (exeFilename, L'\\') + 1; StringCbPrintfW (regPath, sizeof(regPath), L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\ComDlg32\\LastVisited%sMRU", IsOSAtLeast (WIN_VISTA) ? L"Pidl" : L""); for (id = (IsOSAtLeast (WIN_VISTA) ? 0 : L'a'); id <= (IsOSAtLeast (WIN_VISTA) ? 1000 : L'z'); id++) { *strTmp = 0; StringCbPrintfW (key, sizeof(key), (IsOSAtLeast (WIN_VISTA) ? L"%d" : L"%c"), id); if ((len = ReadRegistryBytes (regPath, key, (char *) strTmp, sizeof (strTmp))) > 0) { if (_wcsicmp (strTmp, strToMatch) == 0) { char buf[65536], bufout[sizeof (buf)]; // Overwrite the entry with zeroes while keeping its original size memset (strTmp, 0, len); if (!WriteRegistryBytes (regPath, key, (char *) strTmp, len)) MessageBoxW (NULL, GetString ("CLEAN_WINMRU_FAILED"), lpszTitle, ICON_HAND); DeleteRegistryValue (regPath, key); // Remove ID from MRUList if (IsOSAtLeast (WIN_VISTA)) { int *p = (int *)buf; int *pout = (int *)bufout; int l; l = len = ReadRegistryBytes (L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\ComDlg32\\LastVisitedPidlMRU", L"MRUListEx", buf, sizeof (buf)); while (l > 0) { l -= sizeof (int); if (*p == id) { p++; len -= sizeof (int); continue; } *pout++ = *p++; } WriteRegistryBytes (L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\ComDlg32\\LastVisitedPidlMRU", L"MRUListEx", bufout, len); } else { wchar_t *p = (wchar_t*) buf; wchar_t *pout = (wchar_t*) bufout; ReadRegistryString (L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\ComDlg32\\LastVisitedMRU", L"MRUList", L"", (wchar_t*) buf, sizeof (buf)); while (*p) { if (*p == id) { p++; continue; } *pout++ = *p++; } *pout++ = 0; WriteRegistryString (L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\ComDlg32\\LastVisitedMRU", L"MRUList", (wchar_t*) bufout); } break; } } } } #ifndef SETUP void ClearHistory (HWND hwndDlgItem) { ArrowWaitCursor (); ClearCombo (hwndDlgItem); DumpCombo (hwndDlgItem, TRUE); CleanLastVisitedMRU (); NormalCursor (); } #endif // #ifndef SETUP LRESULT ListItemAdd (HWND list, int index, const wchar_t *string) { LVITEM li; memset (&li, 0, sizeof(li)); li.mask = LVIF_TEXT; li.pszText = (wchar_t*) string; li.iItem = index; li.iSubItem = 0; return ListView_InsertItem (list, &li); } LRESULT ListSubItemSet (HWND list, int index, int subIndex, const wchar_t *string) { LVITEM li; memset (&li, 0, sizeof(li)); li.mask = LVIF_TEXT; li.pszText = (wchar_t*) string; li.iItem = index; li.iSubItem = subIndex; return ListView_SetItem (list, &li); } BOOL GetMountList (MOUNT_LIST_STRUCT *list) { DWORD dwResult; MOUNT_LIST_STRUCT localList = {0}; if ( list && DeviceIoControl (hDriver, TC_IOCTL_GET_MOUNTED_VOLUMES, &localList, sizeof (localList), &localList, sizeof (localList), &dwResult, NULL) && (localList.ulMountedDrives < (1 << 26)) ) { memcpy (list, &localList, sizeof (MOUNT_LIST_STRUCT)); return TRUE; } else return FALSE; } int GetDriverRefCount () { DWORD dwResult; BOOL bResult; int refCount; bResult = DeviceIoControl (hDriver, TC_IOCTL_GET_DEVICE_REFCOUNT, &refCount, sizeof (refCount), &refCount, sizeof (refCount), &dwResult, NULL); if (bResult) return refCount; else return -1; } // Loads a 32-bit integer from the file at the specified file offset. The saved value is assumed to have been // processed by mputLong(). The result is stored in *result. Returns TRUE if successful (otherwise FALSE). BOOL LoadInt32 (const wchar_t *filePath, unsigned __int32 *result, __int64 fileOffset) { DWORD bufSize = sizeof(__int32); unsigned char *buffer = (unsigned char *) malloc (bufSize); unsigned char *bufferPtr = buffer; HANDLE src = NULL; DWORD bytesRead; LARGE_INTEGER seekOffset, seekOffsetNew; BOOL retVal = FALSE; if (buffer == NULL) return -1; src = CreateFile (filePath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); if (src == INVALID_HANDLE_VALUE) { free (buffer); return FALSE; } seekOffset.QuadPart = fileOffset; if (SetFilePointerEx (src, seekOffset, &seekOffsetNew, FILE_BEGIN) == 0) goto fsif_end; if (ReadFile (src, buffer, bufSize, &bytesRead, NULL) == 0 || bytesRead != bufSize) goto fsif_end; retVal = TRUE; *result = mgetLong(bufferPtr); fsif_end: CloseHandle (src); free (buffer); return retVal; } // Loads a 16-bit integer from the file at the specified file offset. The saved value is assumed to have been // processed by mputWord(). The result is stored in *result. Returns TRUE if successful (otherwise FALSE). BOOL LoadInt16 (const wchar_t *filePath, int *result, __int64 fileOffset) { DWORD bufSize = sizeof(__int16); unsigned char *buffer = (unsigned char *) malloc (bufSize); unsigned char *bufferPtr = buffer; HANDLE src = NULL; DWORD bytesRead; LARGE_INTEGER seekOffset, seekOffsetNew; BOOL retVal = FALSE; if (buffer == NULL) return -1; src = CreateFile (filePath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); if (src == INVALID_HANDLE_VALUE) { free (buffer); return FALSE; } seekOffset.QuadPart = fileOffset; if (SetFilePointerEx (src, seekOffset, &seekOffsetNew, FILE_BEGIN) == 0) goto fsif_end; if (ReadFile (src, buffer, bufSize, &bytesRead, NULL) == 0 || bytesRead != bufSize) goto fsif_end; retVal = TRUE; *result = mgetWord(bufferPtr); fsif_end: CloseHandle (src); free (buffer); return retVal; } // Returns NULL if there's any error. Although the buffer can contain binary data, it is always null-terminated. char *LoadFile (const wchar_t *fileName, DWORD *size) { char *buf; DWORD fileSize = INVALID_FILE_SIZE; HANDLE h = CreateFile (fileName, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); if (h == INVALID_HANDLE_VALUE) return NULL; if ((fileSize = GetFileSize (h, NULL)) == INVALID_FILE_SIZE) { CloseHandle (h); return NULL; } *size = fileSize; buf = (char *) calloc (*size + 1, 1); if (buf == NULL) { CloseHandle (h); return NULL; } if (!ReadFile (h, buf, *size, size, NULL)) { free (buf); buf = NULL; } CloseHandle (h); return buf; } // Returns NULL if there's any error. char *LoadFileBlock (const wchar_t *fileName, __int64 fileOffset, DWORD count) { char *buf; DWORD bytesRead = 0; LARGE_INTEGER seekOffset, seekOffsetNew; BOOL bStatus; HANDLE h = CreateFile (fileName, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); if (h == INVALID_HANDLE_VALUE) return NULL; seekOffset.QuadPart = fileOffset; if (SetFilePointerEx (h, seekOffset, &seekOffsetNew, FILE_BEGIN) == 0) { CloseHandle (h); return NULL; } buf = (char *) calloc (count, 1); if (buf == NULL) { CloseHandle (h); return NULL; } bStatus = ReadFile (h, buf, count, &bytesRead, NULL); CloseHandle (h); if (!bStatus || (bytesRead != count)) { free (buf); return NULL; } return buf; } // Returns -1 if there is an error, or the size of the file. __int64 GetFileSize64 (const wchar_t *path) { HANDLE h = CreateFile (path, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); LARGE_INTEGER size; __int64 retSize = -1; if (h) { if (GetFileSizeEx (h, &size)) { retSize = size.QuadPart; } CloseHandle (h); } return retSize; } wchar_t *GetModPath (wchar_t *path, int maxSize) { GetModuleFileName (NULL, path, maxSize); wchar_t* ptr = wcsrchr (path, L'\\'); if (ptr) ptr[1] = 0; return path; } wchar_t *GetConfigPath (wchar_t *fileName) { static wchar_t path[MAX_PATH * 2] = { 0 }; if (IsNonInstallMode ()) { GetModPath (path, ARRAYSIZE (path)); StringCchCatW (path, (MAX_PATH * 2), fileName); return path; } if (SUCCEEDED(SHGetFolderPath (NULL, CSIDL_APPDATA | CSIDL_FLAG_CREATE, NULL, 0, path))) { StringCchCatW (path, (MAX_PATH * 2), L"\\VeraCrypt\\"); CreateDirectory (path, NULL); StringCchCatW (path, (MAX_PATH * 2), fileName); } else path[0] = 0; return path; } wchar_t *GetProgramConfigPath (wchar_t *fileName) { static wchar_t path[MAX_PATH * 2] = { 0 }; if (SUCCEEDED (SHGetFolderPath (NULL, CSIDL_COMMON_APPDATA | CSIDL_FLAG_CREATE, NULL, 0, path))) { StringCchCatW (path, (MAX_PATH * 2), L"\\VeraCrypt\\"); CreateDirectory (path, NULL); StringCchCatW (path, (MAX_PATH * 2), fileName); } else path[0] = 0; return path; } std::wstring GetServiceConfigPath (const wchar_t *fileName, bool useLegacy) { wchar_t sysPath[TC_MAX_PATH]; if (Is64BitOs() && useLegacy) { typedef UINT (WINAPI *GetSystemWow64Directory_t) (LPWSTR lpBuffer, UINT uSize); GetSystemWow64Directory_t getSystemWow64Directory = (GetSystemWow64Directory_t) GetProcAddress (GetModuleHandle (L"kernel32"), "GetSystemWow64DirectoryW"); getSystemWow64Directory (sysPath, ARRAYSIZE (sysPath)); } else GetSystemDirectory (sysPath, ARRAYSIZE (sysPath)); return wstring (sysPath) + L"\\" + fileName; } // Returns 0 if an error occurs or the drive letter (as an upper-case char) of the system partition (e.g. 'C'); wchar_t GetSystemDriveLetter (void) { wchar_t systemDir [MAX_PATH]; if (GetSystemDirectory (systemDir, ARRAYSIZE (systemDir))) return (wchar_t) (towupper (systemDir [0])); else return 0; } void TaskBarIconDisplayBalloonTooltip (HWND hwnd, wchar_t *headline, wchar_t *text, BOOL warning) { if (nCurrentOS == WIN_2000) { MessageBoxW (MainDlg, text, headline, warning ? MB_ICONWARNING : MB_ICONINFORMATION); return; } NOTIFYICONDATAW tnid; ZeroMemory (&tnid, sizeof (tnid)); tnid.cbSize = sizeof (tnid); tnid.hWnd = hwnd; tnid.uID = IDI_TRUECRYPT_ICON; //tnid.uVersion = (IsOSAtLeast (WIN_VISTA) ? NOTIFYICON_VERSION_4 : NOTIFYICON_VERSION); //Shell_NotifyIconW (NIM_SETVERSION, &tnid); tnid.uFlags = NIF_INFO; tnid.dwInfoFlags = (warning ? NIIF_WARNING : NIIF_INFO); tnid.uTimeout = (IsOSAtLeast (WIN_VISTA) ? 1000 : 5000); // in ms StringCbCopyW (tnid.szInfoTitle, sizeof(tnid.szInfoTitle), headline); StringCbCopyW (tnid.szInfo, sizeof(tnid.szInfo),text); // Display the balloon tooltip quickly twice in a row to avoid the slow and unwanted "fade-in" phase Shell_NotifyIconW (NIM_MODIFY, &tnid); Shell_NotifyIconW (NIM_MODIFY, &tnid); } // Either of the pointers may be NULL void InfoBalloon (char *headingStringId, char *textStringId, HWND hwnd) { if (Silent) return; TaskBarIconDisplayBalloonTooltip (hwnd, headingStringId == NULL ? L"VeraCrypt" : GetString (headingStringId), textStringId == NULL ? L" " : GetString (textStringId), FALSE); } // Either of the pointers may be NULL void InfoBalloonDirect (wchar_t *headingString, wchar_t *textString, HWND hwnd) { if (Silent) return; TaskBarIconDisplayBalloonTooltip (hwnd, headingString == NULL ? L"VeraCrypt" : headingString, textString == NULL ? L" " : textString, FALSE); } // Either of the pointers may be NULL void WarningBalloon (char *headingStringId, char *textStringId, HWND hwnd) { if (Silent) return; TaskBarIconDisplayBalloonTooltip (hwnd, headingStringId == NULL ? L"VeraCrypt" : GetString (headingStringId), textStringId == NULL ? L" " : GetString (textStringId), TRUE); } // Either of the pointers may be NULL void WarningBalloonDirect (wchar_t *headingString, wchar_t *textString, HWND hwnd) { if (Silent) return; TaskBarIconDisplayBalloonTooltip (hwnd, headingString == NULL ? L"VeraCrypt" : headingString, textString == NULL ? L" " : textString, TRUE); } int Info (char *stringId, HWND hwnd) { if (Silent) return 0; return MessageBoxW (hwnd, GetString (stringId), lpszTitle, MB_ICONINFORMATION); } int InfoTopMost (char *stringId, HWND hwnd) { if (Silent) return 0; return MessageBoxW (hwnd, GetString (stringId), lpszTitle, MB_ICONINFORMATION | MB_SETFOREGROUND | MB_TOPMOST); } int InfoDirect (const wchar_t *msg, HWND hwnd) { if (Silent) return 0; return MessageBoxW (hwnd, msg, lpszTitle, MB_ICONINFORMATION); } int Warning (char *stringId, HWND hwnd) { if (Silent) return 0; return MessageBoxW (hwnd, GetString (stringId), lpszTitle, MB_ICONWARNING); } int WarningTopMost (char *stringId, HWND hwnd) { if (Silent) return 0; return MessageBoxW (hwnd, GetString (stringId), lpszTitle, MB_ICONWARNING | MB_SETFOREGROUND | MB_TOPMOST); } int WarningDirect (const wchar_t *warnMsg, HWND hwnd) { if (Silent) return 0; return MessageBoxW (hwnd, warnMsg, lpszTitle, MB_ICONWARNING); } int Error (char *stringId, HWND hwnd) { if (Silent) return 0; return MessageBoxW (hwnd, GetString (stringId), lpszTitle, MB_ICONERROR); } int ErrorRetryCancel (char *stringId, HWND hwnd) { if (Silent) return 0; return MessageBoxW (hwnd, GetString (stringId), lpszTitle, MB_ICONERROR | MB_RETRYCANCEL); } int ErrorTopMost (char *stringId, HWND hwnd) { if (Silent) return 0; return MessageBoxW (hwnd, GetString (stringId), lpszTitle, MB_ICONERROR | MB_SETFOREGROUND | MB_TOPMOST); } int ErrorDirect (const wchar_t *errMsg, HWND hwnd) { if (Silent) return 0; return MessageBoxW (hwnd, errMsg, lpszTitle, MB_ICONERROR); } int AskYesNo (char *stringId, HWND hwnd) { if (Silent) return IDNO; return MessageBoxW (hwnd, GetString (stringId), lpszTitle, MB_ICONQUESTION | MB_YESNO | MB_DEFBUTTON1); } int AskYesNoString (const wchar_t *str, HWND hwnd) { if (Silent) return IDNO; return MessageBoxW (hwnd, str, lpszTitle, MB_ICONQUESTION | MB_YESNO | MB_DEFBUTTON1); } int AskYesNoTopmost (char *stringId, HWND hwnd) { if (Silent) return IDNO; return MessageBoxW (hwnd, GetString (stringId), lpszTitle, MB_ICONQUESTION | MB_YESNO | MB_DEFBUTTON1 | MB_SETFOREGROUND | MB_TOPMOST); } int AskNoYes (char *stringId, HWND hwnd) { if (Silent) return IDNO; return MessageBoxW (hwnd, GetString (stringId), lpszTitle, MB_ICONQUESTION | MB_YESNO | MB_DEFBUTTON2); } int AskNoYesString (const wchar_t *string, HWND hwnd) { if (Silent) return IDNO; return MessageBoxW (hwnd, string, lpszTitle, MB_ICONQUESTION | MB_YESNO | MB_DEFBUTTON2); } int AskOkCancel (char *stringId, HWND hwnd) { if (Silent) return IDCANCEL; return MessageBoxW (hwnd, GetString (stringId), lpszTitle, MB_ICONQUESTION | MB_OKCANCEL | MB_DEFBUTTON1); } int AskWarnYesNo (char *stringId, HWND hwnd) { if (Silent) return IDNO; return MessageBoxW (hwnd, GetString (stringId), lpszTitle, MB_ICONWARNING | MB_YESNO | MB_DEFBUTTON1); } int AskWarnYesNoString (const wchar_t *string, HWND hwnd) { if (Silent) return IDNO; return MessageBoxW (hwnd, string, lpszTitle, MB_ICONWARNING | MB_YESNO | MB_DEFBUTTON1); } int AskWarnYesNoTopmost (char *stringId, HWND hwnd) { if (Silent) return IDNO; return MessageBoxW (hwnd, GetString (stringId), lpszTitle, MB_ICONWARNING | MB_YESNO | MB_DEFBUTTON1 | MB_SETFOREGROUND | MB_TOPMOST); } int AskWarnYesNoStringTopmost (const wchar_t *string, HWND hwnd) { if (Silent) return IDNO; return MessageBoxW (hwnd, string, lpszTitle, MB_ICONWARNING | MB_YESNO | MB_DEFBUTTON1 | MB_SETFOREGROUND | MB_TOPMOST); } int AskWarnNoYes (char *stringId, HWND hwnd) { if (Silent) return IDNO; return MessageBoxW (hwnd, GetString (stringId), lpszTitle, MB_ICONWARNING | MB_YESNO | MB_DEFBUTTON2); } int AskWarnNoYesString (const wchar_t *string, HWND hwnd) { if (Silent) return IDNO; return MessageBoxW (hwnd, string, lpszTitle, MB_ICONWARNING | MB_YESNO | MB_DEFBUTTON2); } int AskWarnNoYesTopmost (char *stringId, HWND hwnd) { if (Silent) return IDNO; return MessageBoxW (hwnd, GetString (stringId), lpszTitle, MB_ICONWARNING | MB_YESNO | MB_DEFBUTTON2 | MB_SETFOREGROUND | MB_TOPMOST); } int AskWarnOkCancel (char *stringId, HWND hwnd) { if (Silent) return IDCANCEL; return MessageBoxW (hwnd, GetString (stringId), lpszTitle, MB_ICONWARNING | MB_OKCANCEL | MB_DEFBUTTON1); } int AskWarnCancelOk (char *stringId, HWND hwnd) { if (Silent) return IDCANCEL; return MessageBoxW (hwnd, GetString (stringId), lpszTitle, MB_ICONWARNING | MB_OKCANCEL | MB_DEFBUTTON2); } int AskErrYesNo (char *stringId, HWND hwnd) { if (Silent) return IDNO; return MessageBoxW (hwnd, GetString (stringId), lpszTitle, MB_ICONERROR | MB_YESNO | MB_DEFBUTTON1); } int AskErrNoYes (char *stringId, HWND hwnd) { if (Silent) return IDNO; return MessageBoxW (hwnd, GetString (stringId), lpszTitle, MB_ICONERROR | MB_YESNO | MB_DEFBUTTON2); } // The function accepts two input formats: // Input format 1: {0, "MESSAGE_STRING_ID", "BUTTON_1_STRING_ID", ... "LAST_BUTTON_STRING_ID", 0}; // Input format 2: {L"", L"Message text", L"Button caption 1", ... L"Last button caption", 0}; // The second format is to be used if any of the strings contains format specification (e.g. %s, %d) or // in any other cases where a string needs to be resolved before calling this function. // The returned value is the ordinal number of the choice the user selected (1..MAX_MULTI_CHOICES) int AskMultiChoice (void *strings[], BOOL bBold, HWND hwnd) { MULTI_CHOICE_DLGPROC_PARAMS params; params.strings = &strings[0]; params.bold = bBold; return (int) DialogBoxParamW (hInst, MAKEINTRESOURCEW (IDD_MULTI_CHOICE_DLG), hwnd, (DLGPROC) MultiChoiceDialogProc, (LPARAM) &params); } BOOL ConfigWriteBegin () { DWORD size; if (ConfigFileHandle != NULL) return FALSE; if (ConfigBuffer == NULL) ConfigBuffer = LoadFile (GetConfigPath (TC_APPD_FILENAME_CONFIGURATION), &size); ConfigFileHandle = _wfopen (GetConfigPath (TC_APPD_FILENAME_CONFIGURATION), L"w,ccs=UTF-8"); if (ConfigFileHandle == NULL) { free (ConfigBuffer); ConfigBuffer = NULL; return FALSE; } XmlWriteHeader (ConfigFileHandle); fputws (L"\n\t<configuration>", ConfigFileHandle); return TRUE; } BOOL ConfigWriteEnd (HWND hwnd) { char *xml = ConfigBuffer; char key[128], value[2048]; if (ConfigFileHandle == NULL) return FALSE; // Write unmodified values while (xml && (xml = XmlFindElement (xml, "config"))) { XmlGetAttributeText (xml, "key", key, sizeof (key)); XmlGetNodeText (xml, value, sizeof (value)); fwprintf (ConfigFileHandle, L"\n\t\t<config key=\"%hs\">%hs</config>", key, value); xml++; } fputws (L"\n\t</configuration>", ConfigFileHandle); XmlWriteFooter (ConfigFileHandle); TCFlushFile (ConfigFileHandle); CheckFileStreamWriteErrors (hwnd, ConfigFileHandle, TC_APPD_FILENAME_CONFIGURATION); fclose (ConfigFileHandle); ConfigFileHandle = NULL; if (ConfigBuffer != NULL) { DWORD size; free (ConfigBuffer); ConfigBuffer = LoadFile (GetConfigPath (TC_APPD_FILENAME_CONFIGURATION), &size); } return TRUE; } BOOL ConfigWriteString (char *configKey, char *configValue) { char *c; if (ConfigFileHandle == NULL) return FALSE; // Mark previous config value as updated if (ConfigBuffer != NULL) { c = XmlFindElementByAttributeValue (ConfigBuffer, "config", "key", configKey); if (c != NULL) c[1] = '!'; } return 0 != fwprintf ( ConfigFileHandle, L"\n\t\t<config key=\"%hs\">%hs</config>", configKey, configValue); } BOOL ConfigWriteStringW (char *configKey, wchar_t *configValue) { char *c; if (ConfigFileHandle == NULL) return FALSE; // Mark previous config value as updated if (ConfigBuffer != NULL) { c = XmlFindElementByAttributeValue (ConfigBuffer, "config", "key", configKey); if (c != NULL) c[1] = '!'; } return 0 != fwprintf ( ConfigFileHandle, L"\n\t\t<config key=\"%hs\">%ls</config>", configKey, configValue); } BOOL ConfigWriteInt (char *configKey, int configValue) { char val[32]; StringCbPrintfA (val, sizeof(val), "%d", configValue); return ConfigWriteString (configKey, val); } static BOOL ConfigRead (char *configKey, char *configValue, int maxValueSize) { DWORD size; char *xml; if (ConfigBuffer == NULL) ConfigBuffer = LoadFile (GetConfigPath (TC_APPD_FILENAME_CONFIGURATION), &size); xml = ConfigBuffer; if (xml != NULL) { xml = XmlFindElementByAttributeValue (xml, "config", "key", configKey); if (xml != NULL) { XmlGetNodeText (xml, configValue, maxValueSize); return TRUE; } } return FALSE; } int ConfigReadInt (char *configKey, int defaultValue) { char s[32]; if (ConfigRead (configKey, s, sizeof (s))) return atoi (s); else return defaultValue; } char *ConfigReadString (char *configKey, char *defaultValue, char *str, int maxLen) { if (ConfigRead (configKey, str, maxLen)) return str; else { StringCbCopyA (str, maxLen, defaultValue); return defaultValue; } } void ConfigReadCompareInt(char *configKey, int defaultValue, int* pOutputValue, BOOL bOnlyCheckModified, BOOL* pbModified) { int intValue = ConfigReadInt (configKey, defaultValue); if (pOutputValue) { if (pbModified && (*pOutputValue != intValue)) *pbModified = TRUE; if (!bOnlyCheckModified) *pOutputValue = intValue; } } void ConfigReadCompareString (char *configKey, char *defaultValue, char *str, int maxLen, BOOL bOnlyCheckModified, BOOL *pbModified) { char *strValue = (char*) malloc (maxLen); if (strValue) { memcpy (strValue, str, maxLen); ConfigReadString (configKey, defaultValue, strValue, maxLen); if (pbModified && strcmp (str, strValue)) *pbModified = TRUE; if (!bOnlyCheckModified) memcpy(str, strValue, maxLen); free (strValue); } else { /* allocation failed. Suppose that value changed */ if (pbModified) *pbModified = TRUE; if (!bOnlyCheckModified) ConfigReadString (configKey, defaultValue, str, maxLen); } } void OpenPageHelp (HWND hwndDlg, int nPage) { int r = (int)ShellExecuteW (NULL, L"open", szHelpFile, NULL, NULL, SW_SHOWNORMAL); if (r == ERROR_FILE_NOT_FOUND) { // Try the secondary help file r = (int)ShellExecuteW (NULL, L"open", szHelpFile2, NULL, NULL, SW_SHOWNORMAL); if (r == ERROR_FILE_NOT_FOUND) { // Open local HTML help. It will fallback to online help if not found. Applink ("help"); return; } } if (r == SE_ERR_NOASSOC) { if (AskYesNo ("HELP_READER_ERROR", MainDlg) == IDYES) OpenOnlineHelp (); } } void OpenOnlineHelp () { Applink ("onlinehelp"); } #ifndef SETUP void RestoreDefaultKeyFilesParam (void) { KeyFileRemoveAll (&FirstKeyFile); if (defaultKeyFilesParam.FirstKeyFile != NULL) { KeyFileCloneAll (defaultKeyFilesParam.FirstKeyFile, &FirstKeyFile); KeyFilesEnable = defaultKeyFilesParam.EnableKeyFiles; } else KeyFilesEnable = FALSE; } BOOL LoadDefaultKeyFilesParam (void) { BOOL status = TRUE; DWORD size; char *defaultKeyfilesFile = LoadFile (GetConfigPath (TC_APPD_FILENAME_DEFAULT_KEYFILES), &size); char *xml = defaultKeyfilesFile; KeyFile *kf; if (xml == NULL) return FALSE; KeyFileRemoveAll (&defaultKeyFilesParam.FirstKeyFile); while (xml = XmlFindElement (xml, "keyfile")) { kf = (KeyFile *) malloc (sizeof (KeyFile)); if (kf) { char fileName [MAX_PATH + 1]; if (XmlGetNodeText (xml, fileName, sizeof (fileName)) != NULL) { std::wstring wszFileName = Utf8StringToWide(fileName); StringCbCopyW (kf->FileName, sizeof (kf->FileName), wszFileName.c_str ()); defaultKeyFilesParam.FirstKeyFile = KeyFileAdd (defaultKeyFilesParam.FirstKeyFile, kf); } else free (kf); } else { KeyFileRemoveAll (&defaultKeyFilesParam.FirstKeyFile); status = FALSE; break; } xml++; } free (defaultKeyfilesFile); if (status) KeyFilesEnable = defaultKeyFilesParam.EnableKeyFiles; return status; } #endif /* #ifndef SETUP */ void Debug (char *format, ...) { char buf[1024]; va_list val; va_start(val, format); StringCbVPrintfA (buf, sizeof (buf), format, val); va_end(val); OutputDebugStringA (buf); } void DebugMsgBox (char *format, ...) { char buf[1024]; va_list val; va_start(val, format); StringCbVPrintfA (buf, sizeof (buf), format, val); va_end(val); MessageBoxA (MainDlg, buf, "VeraCrypt debug", 0); } BOOL IsOSAtLeast (OSVersionEnum reqMinOS) { return IsOSVersionAtLeast (reqMinOS, 0); } // Returns TRUE if the operating system is at least reqMinOS and service pack at least reqMinServicePack. // Example 1: IsOSVersionAtLeast (WIN_VISTA, 1) called under Windows 2008, returns TRUE. // Example 2: IsOSVersionAtLeast (WIN_XP, 3) called under Windows XP SP1, returns FALSE. // Example 3: IsOSVersionAtLeast (WIN_XP, 3) called under Windows Vista SP1, returns TRUE. BOOL IsOSVersionAtLeast (OSVersionEnum reqMinOS, int reqMinServicePack) { /* When updating this function, update IsOSAtLeast() in Ntdriver.c too. */ if (CurrentOSMajor <= 0) TC_THROW_FATAL_EXCEPTION; int major = 0, minor = 0; switch (reqMinOS) { case WIN_2000: major = 5; minor = 0; break; case WIN_XP: major = 5; minor = 1; break; case WIN_SERVER_2003: major = 5; minor = 2; break; case WIN_VISTA: major = 6; minor = 0; break; case WIN_7: major = 6; minor = 1; break; case WIN_8: major = 6; minor = 2; break; case WIN_8_1: major = 6; minor = 3; break; case WIN_10: major = 10; minor = 0; break; default: TC_THROW_FATAL_EXCEPTION; break; } return ((CurrentOSMajor << 16 | CurrentOSMinor << 8 | CurrentOSServicePack) >= (major << 16 | minor << 8 | reqMinServicePack)); } BOOL Is64BitOs () { #ifdef _WIN64 return TRUE; #else static BOOL isWow64 = FALSE; static BOOL valid = FALSE; typedef BOOL (__stdcall *LPFN_ISWOW64PROCESS ) (HANDLE hProcess,PBOOL Wow64Process); LPFN_ISWOW64PROCESS fnIsWow64Process; if (valid) return isWow64; fnIsWow64Process = (LPFN_ISWOW64PROCESS) GetProcAddress (GetModuleHandle(L"kernel32"), "IsWow64Process"); if (fnIsWow64Process != NULL) if (!fnIsWow64Process (GetCurrentProcess(), &isWow64)) isWow64 = FALSE; valid = TRUE; return isWow64; #endif } BOOL IsServerOS () { OSVERSIONINFOEXW osVer; osVer.dwOSVersionInfoSize = sizeof (OSVERSIONINFOEXW); GetVersionExW ((LPOSVERSIONINFOW) &osVer); return (osVer.wProductType == VER_NT_SERVER || osVer.wProductType == VER_NT_DOMAIN_CONTROLLER); } // Returns TRUE, if the currently running operating system is installed in a hidden volume. If it's not, or if // there's an error, returns FALSE. BOOL IsHiddenOSRunning (void) { static BOOL statusCached = FALSE; static BOOL hiddenOSRunning; if (!statusCached) { try { hiddenOSRunning = BootEncryption (MainDlg).IsHiddenSystemRunning(); } catch (...) { hiddenOSRunning = FALSE; } statusCached = TRUE; } return hiddenOSRunning; } BOOL EnableWow64FsRedirection (BOOL enable) { typedef BOOLEAN (__stdcall *Wow64EnableWow64FsRedirection_t) (BOOL enable); Wow64EnableWow64FsRedirection_t wow64EnableWow64FsRedirection = (Wow64EnableWow64FsRedirection_t) GetProcAddress (GetModuleHandle (L"kernel32"), "Wow64EnableWow64FsRedirection"); if (!wow64EnableWow64FsRedirection) return FALSE; return wow64EnableWow64FsRedirection (enable); } BOOL RestartComputer (BOOL bShutdown) { TOKEN_PRIVILEGES tokenPrivil; HANDLE hTkn; if (!OpenProcessToken (GetCurrentProcess (), TOKEN_QUERY|TOKEN_ADJUST_PRIVILEGES, &hTkn)) { return false; } LookupPrivilegeValue (NULL, SE_SHUTDOWN_NAME, &tokenPrivil.Privileges[0].Luid); tokenPrivil.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; tokenPrivil.PrivilegeCount = 1; AdjustTokenPrivileges (hTkn, false, &tokenPrivil, 0, (PTOKEN_PRIVILEGES) NULL, 0); if (GetLastError() != ERROR_SUCCESS) { CloseHandle(hTkn); return false; } if (!ExitWindowsEx (bShutdown? EWX_POWEROFF: EWX_REBOOT, SHTDN_REASON_MAJOR_OTHER | SHTDN_REASON_MINOR_OTHER | SHTDN_REASON_FLAG_PLANNED)) { CloseHandle(hTkn); return false; } CloseHandle(hTkn); return true; } std::wstring GetWindowsEdition () { wstring osname = L"win"; OSVERSIONINFOEXW osVer; osVer.dwOSVersionInfoSize = sizeof (OSVERSIONINFOEXW); GetVersionExW ((LPOSVERSIONINFOW) &osVer); BOOL home = (osVer.wSuiteMask & VER_SUITE_PERSONAL); BOOL server = (osVer.wProductType == VER_NT_SERVER || osVer.wProductType == VER_NT_DOMAIN_CONTROLLER); HKEY hkey; wchar_t productName[300] = {0}; DWORD productNameSize = sizeof (productName); if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", 0, KEY_QUERY_VALUE, &hkey) == ERROR_SUCCESS) { if (RegQueryValueEx (hkey, L"ProductName", 0, 0, (LPBYTE) &productName, &productNameSize) != ERROR_SUCCESS || productNameSize < 1) productName[0] = 0; RegCloseKey (hkey); } switch (nCurrentOS) { case WIN_2000: osname += L"2000"; break; case WIN_XP: case WIN_XP64: osname += L"xp"; osname += home ? L"-home" : L"-pro"; break; case WIN_SERVER_2003: osname += L"2003"; break; case WIN_VISTA: osname += L"vista"; break; case WIN_SERVER_2008: osname += L"2008"; break; case WIN_7: osname += L"7"; break; case WIN_SERVER_2008_R2: osname += L"2008r2"; break; default: wstringstream s; s << CurrentOSMajor << L"." << CurrentOSMinor; osname += s.str(); break; } if (server) osname += L"-server"; if (IsOSAtLeast (WIN_VISTA)) { if (home) osname += L"-home"; else if (wcsstr (productName, L"Standard") != 0) osname += L"-standard"; else if (wcsstr (productName, L"Professional") != 0) osname += L"-pro"; else if (wcsstr (productName, L"Business") != 0) osname += L"-business"; else if (wcsstr (productName, L"Enterprise") != 0) osname += L"-enterprise"; else if (wcsstr (productName, L"Datacenter") != 0) osname += L"-datacenter"; else if (wcsstr (productName, L"Ultimate") != 0) osname += L"-ultimate"; } if (GetSystemMetrics (SM_STARTER)) osname += L"-starter"; else if (wcsstr (productName, L"Basic") != 0) osname += L"-basic"; if (Is64BitOs()) osname += L"-x64"; if (CurrentOSServicePack > 0) { wstringstream s; s << L"-sp" << CurrentOSServicePack; osname += s.str(); } return osname; } #ifdef SETUP extern wchar_t InstallationPath[TC_MAX_PATH]; #endif void Applink (const char *dest) { wchar_t url [MAX_URL_LENGTH] = {0}; wchar_t page[TC_MAX_PATH] = {0}; wchar_t installDir[TC_MAX_PATH] = {0}; BOOL buildUrl = TRUE; int r; ArrowWaitCursor (); #ifdef SETUP StringCbCopyW (installDir, sizeof (installDir), InstallationPath); #else GetModPath (installDir, TC_MAX_PATH); #endif if (strcmp(dest, "donate") == 0) { StringCbCopyW (page, sizeof (page),L"Donation.html"); } else if (strcmp(dest, "main") == 0) { StringCbCopyW (url, sizeof (url), TC_HOMEPAGE); buildUrl = FALSE; } else if (strcmp(dest,"localizations") == 0) { StringCbCopyW (page, sizeof (page),L"Language%20Packs.html"); } else if (strcmp(dest, "beginnerstutorial") == 0 || strcmp(dest,"tutorial") == 0) { StringCbCopyW (page, sizeof (page),L"Beginner%27s%20Tutorial.html"); } else if (strcmp(dest, "releasenotes") == 0 || strcmp(dest, "history") == 0) { StringCbCopyW (page, sizeof (page),L"Release%20Notes.html"); } else if (strcmp(dest, "hwacceleration") == 0) { StringCbCopyW (page, sizeof (page),L"Hardware%20Acceleration.html"); } else if (strcmp(dest, "parallelization") == 0) { StringCbCopyW (page, sizeof (page),L"Parallelization.html"); } else if (strcmp(dest, "help") == 0) { StringCbCopyW (page, sizeof (page),L"Documentation.html"); } else if (strcmp(dest, "onlinehelp") == 0) { StringCbCopyW (url, sizeof (url),L"https://www.veracrypt.fr/en/Documentation.html"); buildUrl = FALSE; } else if (strcmp(dest, "keyfiles") == 0) { StringCbCopyW (page, sizeof (page),L"Keyfiles.html"); } else if (strcmp(dest, "introcontainer") == 0) { StringCbCopyW (page, sizeof (page),L"Creating%20New%20Volumes.html"); } else if (strcmp(dest, "introsysenc") == 0) { StringCbCopyW (page, sizeof (page),L"System%20Encryption.html"); } else if (strcmp(dest, "hiddensysenc") == 0) { StringCbCopyW (page, sizeof (page),L"VeraCrypt%20Hidden%20Operating%20System.html"); } else if (strcmp(dest, "sysencprogressinfo") == 0) { StringCbCopyW (page, sizeof (page),L"System%20Encryption.html"); } else if (strcmp(dest, "hiddenvolume") == 0) { StringCbCopyW (page, sizeof (page),L"Hidden%20Volume.html"); } else if (strcmp(dest, "aes") == 0) { StringCbCopyW (page, sizeof (page),L"AES.html"); } else if (strcmp(dest, "serpent") == 0) { StringCbCopyW (page, sizeof (page),L"Serpent.html"); } else if (strcmp(dest, "twofish") == 0) { StringCbCopyW (page, sizeof (page),L"Twofish.html"); } else if (strcmp(dest, "kuznyechik") == 0) { StringCbCopyW (page, sizeof (page),L"Kuznyechik.html"); } else if (strcmp(dest, "camellia") == 0) { StringCbCopyW (page, sizeof (page),L"Camellia.html"); } else if (strcmp(dest, "cascades") == 0) { StringCbCopyW (page, sizeof (page),L"Cascades.html"); } else if (strcmp(dest, "hashalgorithms") == 0) { StringCbCopyW (page, sizeof (page),L"Hash%20Algorithms.html"); } else if (strcmp(dest, "isoburning") == 0) { StringCbCopyW (url, sizeof (url),L"https://cdburnerxp.se/en/home"); buildUrl = FALSE; } else if (strcmp(dest, "sysfavorites") == 0) { StringCbCopyW (page, sizeof (page),L"System%20Favorite%20Volumes.html"); } else if (strcmp(dest, "favorites") == 0) { StringCbCopyW (page, sizeof (page),L"Favorite%20Volumes.html"); } else if (strcmp(dest, "hiddenvolprotection") == 0) { StringCbCopyW (page, sizeof (page),L"Protection%20of%20Hidden%20Volumes.html"); } else if (strcmp(dest, "faq") == 0) { StringCbCopyW (page, sizeof (page),L"FAQ.html"); } else if (strcmp(dest, "downloads") == 0) { StringCbCopyW (page, sizeof (page),L"Downloads.html"); } else if (strcmp(dest, "news") == 0) { StringCbCopyW (page, sizeof (page),L"News.html"); } else if (strcmp(dest, "contact") == 0) { StringCbCopyW (page, sizeof (page),L"Contact.html"); } else if (strcmp(dest, "pim") == 0) { StringCbCopyW (page, sizeof (page),L"Personal%20Iterations%20Multiplier%20%28PIM%29.html"); } else { StringCbCopyW (url, sizeof (url),TC_APPLINK); buildUrl = FALSE; } if (buildUrl) { StringCbPrintfW (url, sizeof (url), L"file:///%sdocs/html/en/%s", installDir, page); CorrectURL (url); } r = (int) ShellExecuteW (NULL, L"open", url, NULL, NULL, SW_SHOWNORMAL); if (((r == ERROR_FILE_NOT_FOUND) || (r == ERROR_PATH_NOT_FOUND)) && buildUrl) { // fallbacl to online resources StringCbPrintfW (url, sizeof (url), L"https://www.veracrypt.fr/en/%s", page); ShellExecuteW (NULL, L"open", url, NULL, NULL, SW_SHOWNORMAL); } Sleep (200); NormalCursor (); } wchar_t *RelativePath2Absolute (wchar_t *szFileName) { if (szFileName[0] != L'\\' && wcschr (szFileName, L':') == 0 && wcsstr (szFileName, L"Volume{") != szFileName) { wchar_t path[MAX_PATH*2]; GetCurrentDirectory (MAX_PATH, path); if (path[wcslen (path) - 1] != L'\\') StringCbCatW (path, (MAX_PATH * 2), L"\\"); StringCbCatW (path, (MAX_PATH * 2), szFileName); StringCbCopyW (szFileName, MAX_PATH + 1, path); // szFileName size is always at least (MAX_PATH + 1) } return szFileName; } void HandleDriveNotReadyError (HWND hwnd) { HKEY hkey = 0; DWORD value = 0, size = sizeof (DWORD); if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Services\\MountMgr", 0, KEY_READ, &hkey) != ERROR_SUCCESS) return; if (RegQueryValueEx (hkey, L"NoAutoMount", 0, 0, (LPBYTE) &value, &size) == ERROR_SUCCESS && value != 0) { Warning ("SYS_AUTOMOUNT_DISABLED", hwnd); } else if (nCurrentOS == WIN_VISTA && CurrentOSServicePack < 1) Warning ("SYS_ASSIGN_DRIVE_LETTER", hwnd); else Warning ("DEVICE_NOT_READY_ERROR", hwnd); RegCloseKey (hkey); } BOOL CALLBACK CloseTCWindowsEnum (HWND hwnd, LPARAM lParam) { LONG_PTR userDataVal = GetWindowLongPtrW (hwnd, GWLP_USERDATA); if ((userDataVal == (LONG_PTR) 'VERA') || (userDataVal == (LONG_PTR) 'TRUE')) // Prior to 1.0e, 'TRUE' was used for VeraCrypt dialogs { wchar_t name[1024] = { 0 }; GetWindowText (hwnd, name, ARRAYSIZE (name) - 1); if (hwnd != MainDlg && wcsstr (name, L"VeraCrypt")) { PostMessage (hwnd, TC_APPMSG_CLOSE_BKG_TASK, 0, 0); PostMessage (hwnd, WM_CLOSE, 0, 0); if (lParam != 0) *((BOOL *)lParam) = TRUE; } } return TRUE; } BOOL CALLBACK FindTCWindowEnum (HWND hwnd, LPARAM lParam) { if (*(HWND *)lParam == hwnd) return TRUE; LONG_PTR userDataVal = GetWindowLongPtrW (hwnd, GWLP_USERDATA); if ((userDataVal == (LONG_PTR) 'VERA') || (userDataVal == (LONG_PTR) 'TRUE')) // Prior to 1.0e, 'TRUE' was used for VeraCrypt dialogs { wchar_t name[32] = { 0 }; GetWindowText (hwnd, name, ARRAYSIZE (name) - 1); if (hwnd != MainDlg && wcscmp (name, L"VeraCrypt") == 0) { if (lParam != 0) *((HWND *)lParam) = hwnd; } } return TRUE; } BYTE *MapResource (wchar_t *resourceType, int resourceId, PDWORD size) { HGLOBAL hResL; HRSRC hRes; hRes = FindResource (NULL, MAKEINTRESOURCE(resourceId), resourceType); hResL = LoadResource (NULL, hRes); if (size != NULL) *size = SizeofResource (NULL, hRes); return (BYTE *) LockResource (hResL); } void InconsistencyResolved (char *techInfo) { wchar_t finalMsg[8024]; StringCbPrintfW (finalMsg, sizeof(finalMsg), GetString ("INCONSISTENCY_RESOLVED"), techInfo); MessageBoxW (MainDlg, finalMsg, lpszTitle, MB_ICONWARNING | MB_SETFOREGROUND | MB_TOPMOST); } void ReportUnexpectedState (const char *techInfo) { wchar_t finalMsg[8024]; StringCbPrintfW (finalMsg, sizeof(finalMsg), GetString ("UNEXPECTED_STATE"), techInfo); MessageBoxW (MainDlg, finalMsg, lpszTitle, MB_ICONERROR | MB_SETFOREGROUND | MB_TOPMOST); } #ifndef SETUP int OpenVolume (OpenVolumeContext *context, const wchar_t *volumePath, Password *password, int pkcs5_prf, int pim, BOOL truecryptMode, BOOL write, BOOL preserveTimestamps, BOOL useBackupHeader) { int status = ERR_PARAMETER_INCORRECT; int volumeType; wchar_t szDiskFile[TC_MAX_PATH], szCFDevice[TC_MAX_PATH]; wchar_t szDosDevice[TC_MAX_PATH]; char buffer[TC_VOLUME_HEADER_EFFECTIVE_SIZE]; LARGE_INTEGER headerOffset; DWORD dwResult; DISK_GEOMETRY_EX deviceGeometry; context->VolumeIsOpen = FALSE; context->CryptoInfo = NULL; context->HostFileHandle = INVALID_HANDLE_VALUE; context->TimestampsValid = FALSE; CreateFullVolumePath (szDiskFile, sizeof(szDiskFile), volumePath, &context->IsDevice); if (context->IsDevice) { status = FakeDosNameForDevice (szDiskFile, szDosDevice, sizeof(szDosDevice), szCFDevice, sizeof(szCFDevice), FALSE); if (status != 0) return status; preserveTimestamps = FALSE; if (!GetDriveGeometry (volumePath, &deviceGeometry)) { status = ERR_OS_ERROR; goto error; } } else StringCbCopyW (szCFDevice, sizeof(szCFDevice), szDiskFile); if (preserveTimestamps) write = TRUE; context->HostFileHandle = CreateFile (szCFDevice, GENERIC_READ | (write ? GENERIC_WRITE : 0), FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); if (context->HostFileHandle == INVALID_HANDLE_VALUE) { status = ERR_OS_ERROR; goto error; } if (context->IsDevice) { // Try to gain "raw" access to the partition in case there is a live filesystem on it (otherwise, // the NTFS driver guards hidden sectors and prevents e.g. header backup restore after the user // accidentally quick-formats a dismounted partition-hosted TrueCrypt volume as NTFS, etc.) DeviceIoControl (context->HostFileHandle, FSCTL_ALLOW_EXTENDED_DASD_IO, NULL, 0, NULL, 0, &dwResult, NULL); } context->VolumeIsOpen = TRUE; // Remember the container modification/creation date and time if (!context->IsDevice && preserveTimestamps) { if (GetFileTime (context->HostFileHandle, &context->CreationTime, &context->LastAccessTime, &context->LastWriteTime) == 0) context->TimestampsValid = FALSE; else context->TimestampsValid = TRUE; } // Determine host size if (context->IsDevice) { PARTITION_INFORMATION diskInfo; if (GetPartitionInfo (volumePath, &diskInfo)) { context->HostSize = diskInfo.PartitionLength.QuadPart; } else { BYTE dgBuffer[256]; if (!DeviceIoControl (context->HostFileHandle, IOCTL_DISK_GET_DRIVE_GEOMETRY_EX, NULL, 0, dgBuffer, sizeof (dgBuffer), &dwResult, NULL)) { DISK_GEOMETRY geo; if (DeviceIoControl (context->HostFileHandle, IOCTL_DISK_GET_DRIVE_GEOMETRY, NULL, 0, (LPVOID) &geo, sizeof (geo), &dwResult, NULL)) { ((PDISK_GEOMETRY_EX) dgBuffer)->DiskSize.QuadPart = geo.Cylinders.QuadPart * geo.SectorsPerTrack * geo.TracksPerCylinder * geo.BytesPerSector; if (CurrentOSMajor >= 6) { STORAGE_READ_CAPACITY storage = {0}; storage.Version = sizeof (STORAGE_READ_CAPACITY); storage.Size = sizeof (STORAGE_READ_CAPACITY); if (DeviceIoControl (context->HostFileHandle, IOCTL_STORAGE_READ_CAPACITY, NULL, 0, (LPVOID) &storage, sizeof (storage), &dwResult, NULL)) { ((PDISK_GEOMETRY_EX) dgBuffer)->DiskSize.QuadPart = storage.DiskLength.QuadPart; } } } else { status = ERR_OS_ERROR; goto error; } } context->HostSize = ((PDISK_GEOMETRY_EX) dgBuffer)->DiskSize.QuadPart; } if (context->HostSize == 0) { status = ERR_VOL_SIZE_WRONG; goto error; } } else { LARGE_INTEGER fileSize; if (!GetFileSizeEx (context->HostFileHandle, &fileSize)) { status = ERR_OS_ERROR; goto error; } context->HostSize = fileSize.QuadPart; } for (volumeType = TC_VOLUME_TYPE_NORMAL; volumeType < TC_VOLUME_TYPE_COUNT; volumeType++) { // Seek the volume header switch (volumeType) { case TC_VOLUME_TYPE_NORMAL: headerOffset.QuadPart = useBackupHeader ? context->HostSize - TC_VOLUME_HEADER_GROUP_SIZE : TC_VOLUME_HEADER_OFFSET; break; case TC_VOLUME_TYPE_HIDDEN: if (TC_HIDDEN_VOLUME_HEADER_OFFSET + TC_VOLUME_HEADER_SIZE > context->HostSize) continue; headerOffset.QuadPart = useBackupHeader ? context->HostSize - TC_VOLUME_HEADER_SIZE : TC_HIDDEN_VOLUME_HEADER_OFFSET; break; } if (!SetFilePointerEx ((HANDLE) context->HostFileHandle, headerOffset, NULL, FILE_BEGIN)) { status = ERR_OS_ERROR; goto error; } // Read volume header DWORD bytesRead; if (!ReadEffectiveVolumeHeader (context->IsDevice, context->HostFileHandle, (byte *) buffer, &bytesRead)) { status = ERR_OS_ERROR; goto error; } if (bytesRead != sizeof (buffer) && context->IsDevice) { // If FSCTL_ALLOW_EXTENDED_DASD_IO failed and there is a live filesystem on the partition, then the // filesystem driver may report EOF when we are reading hidden sectors (when the filesystem is // shorter than the partition). This can happen for example after the user quick-formats a dismounted // partition-hosted TrueCrypt volume and then tries to read the embedded backup header. memset (buffer, 0, sizeof (buffer)); } // Decrypt volume header status = ReadVolumeHeader (FALSE, buffer, password, pkcs5_prf, pim, truecryptMode, &context->CryptoInfo, NULL); if (status == ERR_PASSWORD_WRONG) continue; // Try next volume type break; } if (status == ERR_SUCCESS) return status; error: DWORD sysError = GetLastError (); CloseVolume (context); SetLastError (sysError); return status; } void CloseVolume (OpenVolumeContext *context) { if (!context->VolumeIsOpen) return; if (context->HostFileHandle != INVALID_HANDLE_VALUE) { if (context->TimestampsValid) SetFileTime (context->HostFileHandle, &context->CreationTime, &context->LastAccessTime, &context->LastWriteTime); CloseHandle (context->HostFileHandle); context->HostFileHandle = INVALID_HANDLE_VALUE; } if (context->CryptoInfo) { crypto_close (context->CryptoInfo); context->CryptoInfo = NULL; } context->VolumeIsOpen = FALSE; } int ReEncryptVolumeHeader (HWND hwndDlg, char *buffer, BOOL bBoot, CRYPTO_INFO *cryptoInfo, Password *password, int pim, BOOL wipeMode) { CRYPTO_INFO *newCryptoInfo = NULL; RandSetHashFunction (cryptoInfo->pkcs5); if (Randinit() != ERR_SUCCESS) { if (CryptoAPILastError == ERROR_SUCCESS) return ERR_RAND_INIT_FAILED; else return ERR_CAPI_INIT_FAILED; } UserEnrichRandomPool (NULL); int status = CreateVolumeHeaderInMemory (hwndDlg, bBoot, buffer, cryptoInfo->ea, cryptoInfo->mode, password, cryptoInfo->pkcs5, pim, (char *) cryptoInfo->master_keydata, &newCryptoInfo, cryptoInfo->VolumeSize.Value, cryptoInfo->hiddenVolume ? cryptoInfo->hiddenVolumeSize : 0, cryptoInfo->EncryptedAreaStart.Value, cryptoInfo->EncryptedAreaLength.Value, cryptoInfo->RequiredProgramVersion, cryptoInfo->HeaderFlags, cryptoInfo->SectorSize, wipeMode); if (newCryptoInfo != NULL) crypto_close (newCryptoInfo); return status; } #endif // !SETUP BOOL IsPagingFileActive (BOOL checkNonWindowsPartitionsOnly) { // GlobalMemoryStatusEx() cannot be used to determine if a paging file is active wchar_t data[65536]; DWORD size = sizeof (data); if (IsPagingFileWildcardActive()) return TRUE; if (ReadLocalMachineRegistryMultiString (L"System\\CurrentControlSet\\Control\\Session Manager\\Memory Management", L"PagingFiles", data, &size) && size > 24 && !checkNonWindowsPartitionsOnly) return TRUE; if (!IsAdmin()) AbortProcess ("UAC_INIT_ERROR"); for (wchar_t drive = L'C'; drive <= L'Z'; ++drive) { // Query geometry of the drive first to prevent "no medium" pop-ups wstring drivePath = L"\\\\.\\X:"; drivePath[4] = drive; if (checkNonWindowsPartitionsOnly) { wchar_t sysDir[MAX_PATH]; if (GetSystemDirectory (sysDir, ARRAYSIZE (sysDir)) != 0 && towupper (sysDir[0]) == drive) continue; } HANDLE handle = CreateFile (drivePath.c_str(), GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); if (handle == INVALID_HANDLE_VALUE) continue; BYTE dgBuffer[256]; DWORD dwResult; if (!DeviceIoControl (handle, IOCTL_DISK_GET_DRIVE_GEOMETRY_EX, NULL, 0, dgBuffer, sizeof (dgBuffer), &dwResult, NULL) && !DeviceIoControl (handle, IOCTL_DISK_GET_DRIVE_GEOMETRY, NULL, 0, dgBuffer, sizeof (dgBuffer), &dwResult, NULL)) { CloseHandle (handle); continue; } CloseHandle (handle); // Test if a paging file exists and is locked by another process wstring path = L"X:\\pagefile.sys"; path[0] = drive; handle = CreateFile (path.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); if (handle != INVALID_HANDLE_VALUE) CloseHandle (handle); else if (GetLastError() == ERROR_SHARING_VIOLATION) return TRUE; } return FALSE; } BOOL IsPagingFileWildcardActive () { wchar_t pagingFiles[65536]; DWORD size = sizeof (pagingFiles); wchar_t *mmKey = L"System\\CurrentControlSet\\Control\\Session Manager\\Memory Management"; if (!ReadLocalMachineRegistryString (mmKey, L"PagingFiles", pagingFiles, &size)) { size = sizeof (pagingFiles); if (!ReadLocalMachineRegistryMultiString (mmKey, L"PagingFiles", pagingFiles, &size)) size = 0; } return size > 0 && wcsstr (pagingFiles, L"?:\\") == pagingFiles; } BOOL DisablePagingFile () { wchar_t empty[] = { 0, 0 }; return WriteLocalMachineRegistryMultiString (L"System\\CurrentControlSet\\Control\\Session Manager\\Memory Management", L"PagingFiles", empty, sizeof (empty)); } std::wstring SingleStringToWide (const std::string &singleString) { if (singleString.empty()) return std::wstring(); WCHAR wbuf[65536]; int wideLen = MultiByteToWideChar (CP_ACP, 0, singleString.c_str(), -1, wbuf, array_capacity (wbuf) - 1); // We don't throw exception here and only return empty string. // All calls to this function use valid strings. // throw_sys_if (wideLen == 0); wbuf[wideLen] = 0; return wbuf; } std::wstring Utf8StringToWide (const std::string &utf8String) { if (utf8String.empty()) return std::wstring(); WCHAR wbuf[65536]; int wideLen = MultiByteToWideChar (CP_UTF8, 0, utf8String.c_str(), -1, wbuf, array_capacity (wbuf) - 1); throw_sys_if (wideLen == 0); wbuf[wideLen] = 0; return wbuf; } std::string WideToUtf8String (const std::wstring &wideString) { if (wideString.empty()) return std::string(); char buf[65536]; int len = WideCharToMultiByte (CP_UTF8, 0, wideString.c_str(), -1, buf, array_capacity (buf) - 1, NULL, NULL); throw_sys_if (len == 0); buf[len] = 0; return buf; } #ifndef SETUP BOOL CALLBACK SecurityTokenPasswordDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) { WORD lw = LOWORD (wParam); static string *password; switch (msg) { case WM_INITDIALOG: { password = (string *) lParam; LocalizeDialog (hwndDlg, "IDD_TOKEN_PASSWORD"); wchar_t s[1024]; StringCbPrintfW (s, sizeof(s), GetString ("ENTER_TOKEN_PASSWORD"), Utf8StringToWide (password->c_str()).c_str()); SetWindowTextW (GetDlgItem (hwndDlg, IDT_TOKEN_PASSWORD_INFO), s); SendMessage (GetDlgItem (hwndDlg, IDC_TOKEN_PASSWORD), EM_LIMITTEXT, SecurityToken::MaxPasswordLength, 0); SetForegroundWindow (hwndDlg); SetFocus (GetDlgItem (hwndDlg, IDC_TOKEN_PASSWORD)); } return 0; case WM_COMMAND: if (lw == IDCANCEL || lw == IDOK) { if (lw == IDOK) { wchar_t passwordWide[SecurityToken::MaxPasswordLength + 1]; if (GetWindowTextW (GetDlgItem (hwndDlg, IDC_TOKEN_PASSWORD), passwordWide, SecurityToken::MaxPasswordLength + 1) == 0) { handleWin32Error (hwndDlg, SRC_POS); break; } char passwordUtf8[SecurityToken::MaxPasswordLength + 1]; int len = WideCharToMultiByte (CP_UTF8, 0, passwordWide, -1, passwordUtf8, array_capacity (passwordUtf8) - 1, nullptr, nullptr); passwordUtf8[len] = 0; *password = passwordUtf8; burn (passwordWide, sizeof (passwordWide)); burn (passwordUtf8, sizeof (passwordUtf8)); } // Attempt to wipe password stored in the input field buffer wchar_t tmp[SecurityToken::MaxPasswordLength+1]; wmemset (tmp, 'X', SecurityToken::MaxPasswordLength); tmp[SecurityToken::MaxPasswordLength] = 0; SetWindowText (GetDlgItem (hwndDlg, IDC_TOKEN_PASSWORD), tmp); EndDialog (hwndDlg, lw); } return 1; } return 0; } struct NewSecurityTokenKeyfileDlgProcParams { CK_SLOT_ID SlotId; string Name; }; static BOOL CALLBACK NewSecurityTokenKeyfileDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) { static NewSecurityTokenKeyfileDlgProcParams *newParams; WORD lw = LOWORD (wParam); switch (msg) { case WM_INITDIALOG: { LocalizeDialog (hwndDlg, "IDD_NEW_TOKEN_KEYFILE"); newParams = (NewSecurityTokenKeyfileDlgProcParams *) lParam; WaitCursor(); finally_do ({ NormalCursor(); }); list <SecurityTokenInfo> tokens; try { tokens = SecurityToken::GetAvailableTokens(); } catch (Exception &e) { e.Show (hwndDlg); } if (tokens.empty()) { Error ("NO_TOKENS_FOUND", hwndDlg); EndDialog (hwndDlg, IDCANCEL); return 1; } foreach (const SecurityTokenInfo &token, tokens) { wstringstream tokenLabel; tokenLabel << L"[" << token.SlotId << L"] " << token.Label; AddComboPair (GetDlgItem (hwndDlg, IDC_SELECTED_TOKEN), tokenLabel.str().c_str(), token.SlotId); } ComboBox_SetCurSel (GetDlgItem (hwndDlg, IDC_SELECTED_TOKEN), 0); SetWindowTextW (GetDlgItem (hwndDlg, IDC_TOKEN_KEYFILE_NAME), Utf8StringToWide (newParams->Name).c_str()); return 1; } case WM_COMMAND: switch (lw) { case IDOK: { int selectedToken = ComboBox_GetCurSel (GetDlgItem (hwndDlg, IDC_SELECTED_TOKEN)); if (selectedToken == CB_ERR) { EndDialog (hwndDlg, IDCANCEL); return 1; } newParams->SlotId = (CK_SLOT_ID) ComboBox_GetItemData (GetDlgItem (hwndDlg, IDC_SELECTED_TOKEN), selectedToken); wchar_t name[1024]; if (GetWindowTextW (GetDlgItem (hwndDlg, IDC_TOKEN_KEYFILE_NAME), name, array_capacity (name)) != 0) { try { newParams->Name = WideToUtf8String (name); } catch (...) { } } EndDialog (hwndDlg, IDOK); return 1; } case IDCANCEL: EndDialog (hwndDlg, IDCANCEL); return 1; } if (HIWORD (wParam) == EN_CHANGE) { wchar_t name[2]; EnableWindow (GetDlgItem (hwndDlg, IDOK), (GetWindowTextW (GetDlgItem (hwndDlg, IDC_TOKEN_KEYFILE_NAME), name, array_capacity (name)) != 0)); return 1; } } return 0; } static void SecurityTokenKeyfileDlgFillList (HWND hwndDlg, const vector <SecurityTokenKeyfile> &keyfiles) { HWND tokenListControl = GetDlgItem (hwndDlg, IDC_TOKEN_FILE_LIST); LVITEMW lvItem; int line = 0; ListView_DeleteAllItems (tokenListControl); foreach (const SecurityTokenKeyfile &keyfile, keyfiles) { memset (&lvItem, 0, sizeof(lvItem)); lvItem.mask = LVIF_TEXT; lvItem.iItem = line++; wstringstream s; s << keyfile.SlotId; ListItemAdd (tokenListControl, lvItem.iItem, (wchar_t *) s.str().c_str()); ListSubItemSet (tokenListControl, lvItem.iItem, 1, (wchar_t *) keyfile.Token.Label.c_str()); ListSubItemSet (tokenListControl, lvItem.iItem, 2, (wchar_t *) keyfile.Id.c_str()); } BOOL selected = (ListView_GetNextItem (GetDlgItem (hwndDlg, IDC_TOKEN_FILE_LIST), -1, LVIS_SELECTED) != -1); EnableWindow (GetDlgItem (hwndDlg, IDC_EXPORT), selected); EnableWindow (GetDlgItem (hwndDlg, IDC_DELETE), selected); } static list <SecurityTokenKeyfile> SecurityTokenKeyfileDlgGetSelected (HWND hwndDlg, const vector <SecurityTokenKeyfile> &keyfiles) { HWND tokenListControl = GetDlgItem (hwndDlg, IDC_TOKEN_FILE_LIST); list <SecurityTokenKeyfile> selectedKeyfiles; int itemId = -1; while ((itemId = ListView_GetNextItem (tokenListControl, itemId, LVIS_SELECTED)) != -1) { selectedKeyfiles.push_back (keyfiles[itemId]); } return selectedKeyfiles; } BOOL CALLBACK SecurityTokenKeyfileDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) { static list <SecurityTokenKeyfilePath> *selectedTokenKeyfiles; static vector <SecurityTokenKeyfile> keyfiles; WORD lw = LOWORD (wParam); switch (msg) { case WM_INITDIALOG: { selectedTokenKeyfiles = (list <SecurityTokenKeyfilePath> *) lParam; LVCOLUMNW LvCol; HWND tokenListControl = GetDlgItem (hwndDlg, IDC_TOKEN_FILE_LIST); LocalizeDialog (hwndDlg, selectedTokenKeyfiles ? "SELECT_TOKEN_KEYFILES" : "IDD_TOKEN_KEYFILES"); SendMessage (tokenListControl,LVM_SETEXTENDEDLISTVIEWSTYLE, 0, LVS_EX_FULLROWSELECT|LVS_EX_HEADERDRAGDROP|LVS_EX_TWOCLICKACTIVATE|LVS_EX_LABELTIP ); memset (&LvCol, 0, sizeof(LvCol)); LvCol.mask = LVCF_TEXT|LVCF_WIDTH|LVCF_SUBITEM|LVCF_FMT; LvCol.pszText = GetString ("TOKEN_SLOT_ID"); LvCol.cx = CompensateXDPI (40); LvCol.fmt = LVCFMT_CENTER; SendMessage (tokenListControl, LVM_INSERTCOLUMNW, 1, (LPARAM)&LvCol); LvCol.pszText = GetString ("TOKEN_NAME"); LvCol.cx = CompensateXDPI (128); LvCol.fmt = LVCFMT_LEFT; SendMessage (tokenListControl, LVM_INSERTCOLUMNW, 2, (LPARAM)&LvCol); LvCol.pszText = GetString ("TOKEN_DATA_OBJECT_LABEL"); LvCol.cx = CompensateXDPI (195); LvCol.fmt = LVCFMT_LEFT; SendMessage (tokenListControl, LVM_INSERTCOLUMNW, 3, (LPARAM)&LvCol); keyfiles.clear(); try { WaitCursor(); finally_do ({ NormalCursor(); }); keyfiles = SecurityToken::GetAvailableKeyfiles(); } catch (UserAbort&) { EndDialog (hwndDlg, IDCANCEL); return 1; } catch (Exception &e) { e.Show (hwndDlg); if (keyfiles.empty()) { EndDialog (hwndDlg, IDCANCEL); return 1; } } SecurityTokenKeyfileDlgFillList (hwndDlg, keyfiles); return 1; } case WM_COMMAND: case WM_NOTIFY: if (msg == WM_COMMAND && lw == IDOK || msg == WM_NOTIFY && ((NMHDR *)lParam)->code == LVN_ITEMACTIVATE) { if (selectedTokenKeyfiles) { foreach (const SecurityTokenKeyfile &keyfile, SecurityTokenKeyfileDlgGetSelected (hwndDlg, keyfiles)) { selectedTokenKeyfiles->push_back (SecurityTokenKeyfilePath (keyfile)); } } EndDialog (hwndDlg, IDOK); return 1; } if (msg == WM_NOTIFY && ((LPNMHDR) lParam)->code == LVN_ITEMCHANGED) { BOOL selected = (ListView_GetNextItem (GetDlgItem (hwndDlg, IDC_TOKEN_FILE_LIST), -1, LVIS_SELECTED) != -1); EnableWindow (GetDlgItem (hwndDlg, IDC_EXPORT), selected); EnableWindow (GetDlgItem (hwndDlg, IDC_DELETE), selected); return 1; } if (msg == WM_COMMAND) { switch (lw) { case IDCANCEL: EndDialog (hwndDlg, IDCANCEL); return 1; case IDC_IMPORT_KEYFILE: { wchar_t keyfilePath[TC_MAX_PATH]; if (BrowseFiles (hwndDlg, "SELECT_KEYFILE", keyfilePath, bHistory, FALSE, NULL)) { DWORD keyfileSize; byte *keyfileData = (byte *) LoadFile (keyfilePath, &keyfileSize); if (!keyfileData) { handleWin32Error (hwndDlg, SRC_POS); return 1; } if (keyfileSize != 0) { NewSecurityTokenKeyfileDlgProcParams newParams; newParams.Name = WideToUtf8String (keyfilePath); size_t lastBackSlash = newParams.Name.find_last_of ('\\'); if (lastBackSlash != string::npos) newParams.Name = newParams.Name.substr (lastBackSlash + 1); if (DialogBoxParamW (hInst, MAKEINTRESOURCEW (IDD_NEW_TOKEN_KEYFILE), hwndDlg, (DLGPROC) NewSecurityTokenKeyfileDlgProc, (LPARAM) &newParams) == IDOK) { vector <byte> keyfileDataVector (keyfileSize); memcpy (&keyfileDataVector.front(), keyfileData, keyfileSize); try { WaitCursor(); finally_do ({ NormalCursor(); }); SecurityToken::CreateKeyfile (newParams.SlotId, keyfileDataVector, newParams.Name); keyfiles = SecurityToken::GetAvailableKeyfiles(); SecurityTokenKeyfileDlgFillList (hwndDlg, keyfiles); } catch (Exception &e) { e.Show (hwndDlg); } burn (&keyfileDataVector.front(), keyfileSize); } } else { SetLastError (ERROR_HANDLE_EOF); handleWin32Error (hwndDlg, SRC_POS); } burn (keyfileData, keyfileSize); TCfree (keyfileData); } return 1; } case IDC_EXPORT: { try { foreach (const SecurityTokenKeyfile &keyfile, SecurityTokenKeyfileDlgGetSelected (hwndDlg, keyfiles)) { wchar_t keyfilePath[TC_MAX_PATH]; if (!BrowseFiles (hwndDlg, "OPEN_TITLE", keyfilePath, bHistory, TRUE, NULL)) break; { WaitCursor(); finally_do ({ NormalCursor(); }); vector <byte> keyfileData; SecurityToken::GetKeyfileData (keyfile, keyfileData); if (keyfileData.empty()) { SetLastError (ERROR_HANDLE_EOF); handleWin32Error (hwndDlg, SRC_POS); return 1; } finally_do_arg (vector <byte> *, &keyfileData, { burn (&finally_arg->front(), finally_arg->size()); }); if (!SaveBufferToFile ((char *) &keyfileData.front(), keyfilePath, (DWORD) keyfileData.size(), FALSE, FALSE)) throw SystemException (SRC_POS); } Info ("KEYFILE_EXPORTED", hwndDlg); } } catch (Exception &e) { e.Show (hwndDlg); } return 1; } case IDC_DELETE: { if (AskNoYes ("CONFIRM_SEL_FILES_DELETE", hwndDlg) == IDNO) return 1; try { WaitCursor(); finally_do ({ NormalCursor(); }); foreach (const SecurityTokenKeyfile &keyfile, SecurityTokenKeyfileDlgGetSelected (hwndDlg, keyfiles)) { SecurityToken::DeleteKeyfile (keyfile); } keyfiles = SecurityToken::GetAvailableKeyfiles(); SecurityTokenKeyfileDlgFillList (hwndDlg, keyfiles); } catch (Exception &e) { e.Show (hwndDlg); } return 1; } } } return 0; } return 0; } BOOL InitSecurityTokenLibrary (HWND hwndDlg) { if (SecurityTokenLibraryPath[0] == 0) { Error ("NO_PKCS11_MODULE_SPECIFIED", hwndDlg); return FALSE; } struct PinRequestHandler : public GetPinFunctor { HWND m_hwnd; PinRequestHandler(HWND hwnd) : m_hwnd(hwnd) {} virtual void operator() (string &str) { if (CmdTokenPin[0]) { str = CmdTokenPin; } else { HWND hParent = IsWindow (m_hwnd)? m_hwnd : GetActiveWindow(); if (!hParent) hParent = GetForegroundWindow (); if (SecureDesktopDialogBoxParam (hInst, MAKEINTRESOURCEW (IDD_TOKEN_PASSWORD), hParent, (DLGPROC) SecurityTokenPasswordDlgProc, (LPARAM) &str) == IDCANCEL) throw UserAbort (SRC_POS); } if (hCursor != NULL) SetCursor (hCursor); } virtual void notifyIncorrectPin () { // clear wrong PIN burn (&CmdTokenPin, sizeof (CmdTokenPin)); } }; struct WarningHandler : public SendExceptionFunctor { HWND m_hwnd; WarningHandler(HWND hwnd) : m_hwnd(hwnd) {} virtual void operator() (const Exception &e) { HWND hParent = IsWindow (m_hwnd)? m_hwnd : GetActiveWindow(); if (!hParent) hParent = GetForegroundWindow (); e.Show (hParent); } }; try { SecurityToken::InitLibrary (SecurityTokenLibraryPath, auto_ptr <GetPinFunctor> (new PinRequestHandler(MainDlg)), auto_ptr <SendExceptionFunctor> (new WarningHandler(MainDlg))); } catch (Exception &e) { e.Show (hwndDlg); Error ("PKCS11_MODULE_INIT_FAILED", hwndDlg); return FALSE; } return TRUE; } std::vector <HostDevice> GetAvailableHostDevices (bool noDeviceProperties, bool singleList, bool noFloppy, bool detectUnencryptedFilesystems) { vector <HostDevice> devices; size_t dev0; for (int devNumber = 0; devNumber < MAX_HOST_DRIVE_NUMBER; devNumber++) { for (int partNumber = 0; partNumber < MAX_HOST_PARTITION_NUMBER; partNumber++) { WCHAR devPath[32]; StringCbPrintfW (devPath, sizeof (devPath), L"\\Device\\Harddisk%d\\Partition%d", devNumber, partNumber); OPEN_TEST_STRUCT openTest = {0}; if (!OpenDevice (devPath, &openTest, detectUnencryptedFilesystems && partNumber != 0, FALSE)) { if (partNumber == 0) break; continue; } HostDevice device; device.SystemNumber = devNumber; device.Path = devPath; PARTITION_INFORMATION partInfo; if (GetPartitionInfo (devPath, &partInfo)) { device.Bootable = partInfo.BootIndicator ? true : false; device.Size = partInfo.PartitionLength.QuadPart; } else { // retrieve size using DISK_GEOMETRY_EX DISK_GEOMETRY_EX deviceGeometry = {0}; if ( GetDriveGeometry (devPath, &deviceGeometry) || ((partNumber == 0) && GetPhysicalDriveGeometry (devNumber, &deviceGeometry)) ) { device.Size = (uint64) deviceGeometry.DiskSize.QuadPart; } } device.HasUnencryptedFilesystem = (detectUnencryptedFilesystems && openTest.FilesystemDetected) ? true : false; if (!noDeviceProperties) { DISK_GEOMETRY_EX geometry; int driveNumber = GetDiskDeviceDriveLetter (devPath); if (driveNumber >= 0) { device.MountPoint += (wchar_t) (driveNumber + L'A'); device.MountPoint += L":"; wchar_t name[64]; if (GetDriveLabel (driveNumber, name, sizeof (name))) device.Name = name; if (GetSystemDriveLetter() == L'A' + driveNumber) device.ContainsSystem = true; } if (partNumber == 0 && GetDriveGeometry (devPath, &geometry)) device.Removable = (geometry.Geometry.MediaType == RemovableMedia); } if (partNumber == 0) { devices.push_back (device); dev0 = devices.size() - 1; } else { // System creates a virtual partition1 for some storage devices without // partition table. We try to detect this case by comparing sizes of // partition0 and partition1. If they match, no partition of the device // is displayed to the user to avoid confusion. Drive letter assigned by // system to partition1 is assigned partition0 if (partNumber == 1 && devices[dev0].Size == device.Size) { devices[dev0].IsVirtualPartition = true; devices[dev0].MountPoint = device.MountPoint; devices[dev0].Name = device.Name; devices[dev0].Path = device.Path; devices[dev0].HasUnencryptedFilesystem = device.HasUnencryptedFilesystem; break; } device.IsPartition = true; device.SystemNumber = partNumber; device.Removable = devices[dev0].Removable; if (device.ContainsSystem) devices[dev0].ContainsSystem = true; if (singleList) devices.push_back (device); devices[dev0].Partitions.push_back (device); } } } // Vista does not create partition links for dynamic volumes so it is necessary to scan \\Device\\HarddiskVolumeX devices if (CurrentOSMajor >= 6) { for (int devNumber = 0; devNumber < 256; devNumber++) { WCHAR devPath[32]; StringCbPrintfW (devPath, sizeof (devPath), L"\\Device\\HarddiskVolume%d", devNumber); OPEN_TEST_STRUCT openTest = {0}; if (!OpenDevice (devPath, &openTest, detectUnencryptedFilesystems, FALSE)) continue; DISK_PARTITION_INFO_STRUCT info; if (GetDeviceInfo (devPath, &info) && info.IsDynamic) { HostDevice device; device.DynamicVolume = true; device.IsPartition = true; device.SystemNumber = devNumber; device.Path = devPath; device.Size = info.partInfo.PartitionLength.QuadPart; device.HasUnencryptedFilesystem = (detectUnencryptedFilesystems && openTest.FilesystemDetected) ? true : false; if (!noDeviceProperties) { int driveNumber = GetDiskDeviceDriveLetter (devPath); if (driveNumber >= 0) { device.MountPoint += (wchar_t) (driveNumber + L'A'); device.MountPoint += L":"; wchar_t name[64]; if (GetDriveLabel (driveNumber, name, sizeof (name))) device.Name = name; if (GetSystemDriveLetter() == L'A' + driveNumber) device.ContainsSystem = true; } } devices.push_back (device); } } } return devices; } void AddDeviceToList (std::vector<HostDevice>& devices, int devNumber, int partNumber) { WCHAR devPath[64]; StringCbPrintfW (devPath, sizeof (devPath), L"\\Device\\Harddisk%d\\Partition%d", devNumber, partNumber); HostDevice device; device.SystemNumber = devNumber; device.Path = devPath; devices.push_back (device); } std::vector <HostDevice> GetHostRawDeviceList () { std::vector <HostDevice> list; HDEVINFO diskClassDevices; GUID diskClassDeviceInterfaceGuid = GUID_DEVINTERFACE_DISK; SP_DEVICE_INTERFACE_DATA deviceInterfaceData; PSP_DEVICE_INTERFACE_DETAIL_DATA deviceInterfaceDetailData; DWORD requiredSize; DWORD deviceIndex; STORAGE_DEVICE_NUMBER diskNumber; DWORD bytesReturned; diskClassDevices = SetupDiGetClassDevs( &diskClassDeviceInterfaceGuid, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE ); if ( INVALID_HANDLE_VALUE != diskClassDevices) { ZeroMemory( &deviceInterfaceData, sizeof( SP_DEVICE_INTERFACE_DATA ) ); deviceInterfaceData.cbSize = sizeof( SP_DEVICE_INTERFACE_DATA ); deviceIndex = 0; while ( SetupDiEnumDeviceInterfaces( diskClassDevices, NULL, &diskClassDeviceInterfaceGuid, deviceIndex, &deviceInterfaceData ) ) { ++deviceIndex; if (!SetupDiGetDeviceInterfaceDetail( diskClassDevices, &deviceInterfaceData, NULL, 0, &requiredSize, NULL ) && ( ERROR_INSUFFICIENT_BUFFER == GetLastError())) { deviceInterfaceDetailData = ( PSP_DEVICE_INTERFACE_DETAIL_DATA ) malloc( requiredSize ); if (deviceInterfaceDetailData) { ZeroMemory( deviceInterfaceDetailData, requiredSize ); deviceInterfaceDetailData->cbSize = sizeof( SP_DEVICE_INTERFACE_DETAIL_DATA ); if (SetupDiGetDeviceInterfaceDetail( diskClassDevices, &deviceInterfaceData, deviceInterfaceDetailData, requiredSize, NULL, NULL )) { HANDLE disk = CreateFile( deviceInterfaceDetailData->DevicePath, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL ); if ( INVALID_HANDLE_VALUE != disk) { if (DeviceIoControl( disk, IOCTL_STORAGE_GET_DEVICE_NUMBER, NULL, 0, &diskNumber, sizeof( STORAGE_DEVICE_NUMBER ), &bytesReturned, NULL )) { HostDevice device; device.Path = deviceInterfaceDetailData->DevicePath; device.SystemNumber = diskNumber.DeviceNumber; list.push_back (device); } CloseHandle( disk ); } } free (deviceInterfaceDetailData); } } } SetupDiDestroyDeviceInfoList( diskClassDevices ); } return list; } bool CompareDeviceList (const std::vector<HostDevice>& list1, const std::vector<HostDevice>& list2) { if (list1.size() != list2.size()) return false; for (std::vector<HostDevice>::const_iterator It1 = list1.begin(); It1 != list1.end(); It1++) { bool bFound = false; for (std::vector<HostDevice>::const_iterator It2 = list2.begin(); It2 != list2.end(); It2++) { if (It1->Path == It2->Path && It1->SystemNumber == It2->SystemNumber) { bFound = true; break; } } if (!bFound) return false; } return true; } void UpdateMountableHostDeviceList () { ByteArray buffer(4096); DWORD bytesReturned; bool dynamicVolumesPresent = false; EnterCriticalSection (&csMountableDevices); finally_do ({ LeaveCriticalSection (&csMountableDevices); }); std::vector<HostDevice> newList = GetHostRawDeviceList (); std::map<DWORD, bool> existingDevicesMap; if (CompareDeviceList (newList, rawHostDeviceList)) return; //no change, return // remove raw devices that don't exist anymore for (std::vector<HostDevice>::iterator It = rawHostDeviceList.begin(); It != rawHostDeviceList.end();) { for (std::vector<HostDevice>::iterator newIt = newList.begin(); newIt != newList.end(); newIt++) { if (newIt->SystemNumber == It->SystemNumber) { existingDevicesMap[It->SystemNumber] = true; break; } } if (existingDevicesMap[It->SystemNumber]) It++; else { It = rawHostDeviceList.erase (It); } } // remove mountable devices that don't exist anymore for (std::vector<HostDevice>::iterator It = mountableDevices.begin(); It != mountableDevices.end();) { if (existingDevicesMap[It->SystemNumber]) It++; else It = mountableDevices.erase (It); } // add new devices for (std::vector<HostDevice>::iterator It = newList.begin(); It != newList.end(); It++) { if (existingDevicesMap[It->SystemNumber]) continue; HANDLE disk = CreateFile( It->Path.c_str(), 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL ); if ( INVALID_HANDLE_VALUE != disk) { bool bIsDynamic = false; bool bHasPartition = false; if (DeviceIoControl( disk, IOCTL_DISK_GET_DRIVE_LAYOUT_EX, NULL, 0, (LPVOID) buffer.data(), (DWORD) buffer.size(), (LPDWORD) &bytesReturned, NULL) && (bytesReturned >= sizeof (DRIVE_LAYOUT_INFORMATION_EX))) { PDRIVE_LAYOUT_INFORMATION_EX layout = (PDRIVE_LAYOUT_INFORMATION_EX) buffer.data(); // sanity checks if (layout->PartitionCount <= 256) { for (DWORD i = 0; i < layout->PartitionCount; i++) { if (layout->PartitionEntry[i].PartitionStyle == PARTITION_STYLE_MBR) { if (layout->PartitionEntry[i].Mbr.PartitionType == 0) continue; bHasPartition = true; /* skip dynamic volume */ if (layout->PartitionEntry[i].Mbr.PartitionType == PARTITION_LDM) { bIsDynamic = true; /* remove any partition that may have been added */ while (!mountableDevices.empty() && (mountableDevices.back().SystemNumber == It->SystemNumber)) mountableDevices.pop_back (); break; } } if (layout->PartitionEntry[i].PartitionStyle == PARTITION_STYLE_GPT) { if (IsEqualGUID(layout->PartitionEntry[i].Gpt.PartitionType, PARTITION_ENTRY_UNUSED_GUID)) continue; bHasPartition = true; /* skip dynamic volume */ if ( IsEqualGUID(layout->PartitionEntry[i].Gpt.PartitionType, PARTITION_LDM_METADATA_GUID) || IsEqualGUID(layout->PartitionEntry[i].Gpt.PartitionType, PARTITION_LDM_DATA_GUID) ) { bIsDynamic = true; /* remove any partition that may have been added */ while (!mountableDevices.empty() && (mountableDevices.back().SystemNumber == It->SystemNumber)) mountableDevices.pop_back (); break; } } WCHAR path[MAX_PATH]; StringCbPrintfW (path, sizeof(path), L"\\\\?\\GLOBALROOT\\Device\\Harddisk%d\\Partition%d", It->SystemNumber, layout->PartitionEntry[i].PartitionNumber); HANDLE handle = CreateFile( path, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL ); if ((handle != INVALID_HANDLE_VALUE) || (GetLastError () == ERROR_ACCESS_DENIED)) { AddDeviceToList (mountableDevices, It->SystemNumber, layout->PartitionEntry[i].PartitionNumber); if (handle != INVALID_HANDLE_VALUE) CloseHandle (handle); } } } } if (bIsDynamic) dynamicVolumesPresent = true; if (!bHasPartition) AddDeviceToList (mountableDevices, It->SystemNumber, 0); CloseHandle (disk); } } rawHostDeviceList = newList; // Starting from Vista, Windows does not create partition links for dynamic volumes so it is necessary to scan \\Device\\HarddiskVolumeX devices if (dynamicVolumesPresent && (CurrentOSMajor >= 6)) { for (int devNumber = 0; devNumber < 256; devNumber++) { WCHAR devPath[32]; StringCbPrintfW (devPath, sizeof (devPath), L"\\Device\\HarddiskVolume%d", devNumber); OPEN_TEST_STRUCT openTest = {0}; if (!OpenDevice (devPath, &openTest, FALSE, FALSE)) continue; DISK_PARTITION_INFO_STRUCT info; if (GetDeviceInfo (devPath, &info) && info.IsDynamic) { HostDevice device; device.SystemNumber = devNumber; device.Path = devPath; mountableDevices.push_back (device); } } } } wstring FindDeviceByVolumeID (const BYTE volumeID [VOLUME_ID_SIZE], BOOL bFromService) { /* if it is already mounted, get the real path name used for mounting */ MOUNT_LIST_STRUCT mlist; DWORD dwResult; memset (&mlist, 0, sizeof (mlist)); if ( !DeviceIoControl (hDriver, TC_IOCTL_GET_MOUNTED_VOLUMES, &mlist, sizeof (mlist), &mlist, sizeof (mlist), &dwResult, NULL) || (mlist.ulMountedDrives >= (1 << 26)) ) { return L""; } if (mlist.ulMountedDrives) { for (int i=0 ; i < 26; i++) { if ((mlist.ulMountedDrives & (1 << i)) && (0 == memcmp (mlist.volumeID[i], volumeID, VOLUME_ID_SIZE))) { if (IsNullTerminateString (mlist.wszVolume[i], TC_MAX_PATH)) return mlist.wszVolume[i]; else return L""; } } } /* not mounted. Look for it in the local drives*/ if (bFromService) { for (int devNumber = 0; devNumber < MAX_HOST_DRIVE_NUMBER; devNumber++) { for (int partNumber = 0; partNumber < MAX_HOST_PARTITION_NUMBER; partNumber++) { WCHAR devPath[32]; StringCbPrintfW (devPath, sizeof (devPath), L"\\Device\\Harddisk%d\\Partition%d", devNumber, partNumber); OPEN_TEST_STRUCT openTest = {0}; if (OpenDevice (devPath, &openTest, TRUE, TRUE) && (openTest.VolumeIDComputed[TC_VOLUME_TYPE_NORMAL] && openTest.VolumeIDComputed[TC_VOLUME_TYPE_HIDDEN]) ) { if ( (0 == memcmp (volumeID, openTest.volumeIDs[TC_VOLUME_TYPE_NORMAL], VOLUME_ID_SIZE)) || (0 == memcmp (volumeID, openTest.volumeIDs[TC_VOLUME_TYPE_HIDDEN], VOLUME_ID_SIZE)) ) { return devPath; } } } } } else { static std::vector<HostDevice> volumeIdCandidates; EnterCriticalSection (&csMountableDevices); if (!NeedPeriodicDeviceListUpdate) UpdateMountableHostDeviceList (); std::vector<HostDevice> newDevices = mountableDevices; LeaveCriticalSection (&csMountableDevices); EnterCriticalSection (&csVolumeIdCandidates); finally_do ({ LeaveCriticalSection (&csVolumeIdCandidates); }); /* remove any devices that don't exist anymore */ for (std::vector<HostDevice>::iterator It = volumeIdCandidates.begin(); It != volumeIdCandidates.end();) { bool bFound = false; for (std::vector<HostDevice>::iterator newIt = newDevices.begin(); newIt != newDevices.end(); newIt++) { if (It->Path == newIt->Path) { bFound = true; break; } } if (bFound) It++; else It = volumeIdCandidates.erase (It); } /* Add newly inserted devices and compute their VolumeID */ for (std::vector<HostDevice>::iterator newIt = newDevices.begin(); newIt != newDevices.end(); newIt++) { bool bFound = false; for (std::vector<HostDevice>::iterator It = volumeIdCandidates.begin(); It != volumeIdCandidates.end(); It++) { if (It->Path == newIt->Path) { bFound = true; break; } } if (!bFound) { /* new device/partition. Compute its Volume IDs */ OPEN_TEST_STRUCT openTest = {0}; if (OpenDevice (newIt->Path.c_str(), &openTest, TRUE, TRUE) && (openTest.VolumeIDComputed[TC_VOLUME_TYPE_NORMAL] && openTest.VolumeIDComputed[TC_VOLUME_TYPE_HIDDEN]) ) { memcpy (newIt->VolumeIDs, openTest.volumeIDs, sizeof (newIt->VolumeIDs)); newIt->HasVolumeIDs = true; } else newIt->HasVolumeIDs = false; volumeIdCandidates.push_back (*newIt); } } for (std::vector<HostDevice>::iterator It = volumeIdCandidates.begin(); It != volumeIdCandidates.end(); It++) { if ( It->HasVolumeIDs && ( (0 == memcmp (volumeID, It->VolumeIDs[TC_VOLUME_TYPE_NORMAL], VOLUME_ID_SIZE)) || (0 == memcmp (volumeID, It->VolumeIDs[TC_VOLUME_TYPE_HIDDEN], VOLUME_ID_SIZE)) ) ) { return It->Path; } } } return L""; } #endif // !SETUP BOOL FileHasReadOnlyAttribute (const wchar_t *path) { DWORD attributes = GetFileAttributes (path); return attributes != INVALID_FILE_ATTRIBUTES && (attributes & FILE_ATTRIBUTE_READONLY) != 0; } BOOL IsFileOnReadOnlyFilesystem (const wchar_t *path) { wchar_t root[MAX_PATH]; if (!GetVolumePathName (path, root, ARRAYSIZE (root))) return FALSE; DWORD flags, d; if (!GetVolumeInformation (root, NULL, 0, NULL, &d, &flags, NULL, 0)) return FALSE; return (flags & FILE_READ_ONLY_VOLUME) ? TRUE : FALSE; } void CheckFilesystem (HWND hwndDlg, int driveNo, BOOL fixErrors) { wchar_t msg[1024], param[1024], cmdPath[MAX_PATH]; wchar_t driveRoot[] = { L'A' + (wchar_t) driveNo, L':', 0 }; if (fixErrors && AskWarnYesNo ("FILESYS_REPAIR_CONFIRM_BACKUP", hwndDlg) == IDNO) return; StringCbPrintfW (msg, sizeof(msg), GetString (fixErrors ? "REPAIRING_FS" : "CHECKING_FS"), driveRoot); StringCbPrintfW (param, sizeof(param), fixErrors ? L"/C echo %s & chkdsk %s /F /X & pause" : L"/C echo %s & chkdsk %s & pause", msg, driveRoot); if (GetSystemDirectoryW(cmdPath, MAX_PATH)) { StringCbCatW(cmdPath, sizeof(cmdPath), L"\\cmd.exe"); } else StringCbCopyW(cmdPath, sizeof(cmdPath), L"C:\\Windows\\System32\\cmd.exe"); ShellExecuteW (NULL, (!IsAdmin() && IsUacSupported()) ? L"runas" : L"open", cmdPath, param, NULL, SW_SHOW); } BOOL BufferContainsString (const byte *buffer, size_t bufferSize, const char *str) { size_t strLen = strlen (str); if (bufferSize < strLen) return FALSE; bufferSize -= strLen; for (size_t i = 0; i < bufferSize; ++i) { if (memcmp (buffer + i, str, strLen) == 0) return TRUE; } return FALSE; } #ifndef SETUP int AskNonSysInPlaceEncryptionResume (HWND hwndDlg, BOOL *pbDecrypt) { if (AskWarnYesNo ("NONSYS_INPLACE_ENC_RESUME_PROMPT", hwndDlg) == IDYES) { char *tmpStr[] = {0, "CHOOSE_ENCRYPT_OR_DECRYPT", "ENCRYPT", "DECRYPT", "IDCANCEL", 0}; switch (AskMultiChoice ((void **) tmpStr, FALSE, hwndDlg)) { case 1: *pbDecrypt = FALSE; return IDYES; case 2: *pbDecrypt = TRUE; return IDYES; default: break; } } char *multiChoiceStr[] = { 0, "ASK_NONSYS_INPLACE_ENC_NOTIFICATION_REMOVAL", "DO_NOT_PROMPT_ME", "KEEP_PROMPTING_ME", 0 }; switch (AskMultiChoice ((void **) multiChoiceStr, FALSE, hwndDlg)) { case 1: RemoveNonSysInPlaceEncNotifications(); Warning ("NONSYS_INPLACE_ENC_NOTIFICATION_REMOVAL_NOTE", hwndDlg); break; default: // NOP break; } return IDNO; } #endif // !SETUP BOOL RemoveDeviceWriteProtection (HWND hwndDlg, wchar_t *devicePath) { int driveNumber; int partitionNumber; wchar_t temp[MAX_PATH*2]; wchar_t cmdBatch[MAX_PATH*2]; wchar_t diskpartScript[MAX_PATH*2]; if (swscanf (devicePath, L"\\Device\\Harddisk%d\\Partition%d", &driveNumber, &partitionNumber) != 2) return FALSE; if (GetTempPath (ARRAYSIZE (temp), temp) == 0) return FALSE; StringCbPrintfW (cmdBatch, sizeof (cmdBatch), L"%s\\VeraCrypt_Write_Protection_Removal.cmd", temp); StringCbPrintfW (diskpartScript, sizeof (diskpartScript), L"%s\\VeraCrypt_Write_Protection_Removal.diskpart", temp); FILE *f = _wfopen (cmdBatch, L"w"); if (!f) { handleWin32Error (hwndDlg, SRC_POS); return FALSE; } fwprintf (f, L"@diskpart /s \"%s\"\n@pause\n@del \"%s\" \"%s\"", diskpartScript, diskpartScript, cmdBatch); CheckFileStreamWriteErrors (hwndDlg, f, cmdBatch); fclose (f); f = _wfopen (diskpartScript, L"w"); if (!f) { handleWin32Error (hwndDlg, SRC_POS); DeleteFile (cmdBatch); return FALSE; } fwprintf (f, L"select disk %d\nattributes disk clear readonly\n", driveNumber); if (partitionNumber != 0) fwprintf (f, L"select partition %d\nattributes volume clear readonly\n", partitionNumber); fwprintf (f, L"exit\n"); CheckFileStreamWriteErrors (hwndDlg, f, diskpartScript); fclose (f); ShellExecute (NULL, (!IsAdmin() && IsUacSupported()) ? L"runas" : L"open", cmdBatch, NULL, NULL, SW_SHOW); return TRUE; } static LRESULT CALLBACK EnableElevatedCursorChangeWndProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { return DefWindowProcW (hWnd, message, wParam, lParam); } void EnableElevatedCursorChange (HWND parent) { // Create a transparent window to work around a UAC issue preventing change of the cursor if (UacElevated) { const wchar_t *className = L"VeraCryptEnableElevatedCursorChange"; WNDCLASSEXW winClass; HWND hWnd; memset (&winClass, 0, sizeof (winClass)); winClass.cbSize = sizeof (WNDCLASSEX); winClass.lpfnWndProc = (WNDPROC) EnableElevatedCursorChangeWndProc; winClass.hInstance = hInst; winClass.lpszClassName = className; RegisterClassExW (&winClass); hWnd = CreateWindowExW (WS_EX_TOOLWINDOW | WS_EX_LAYERED, className, L"VeraCrypt UAC", 0, 0, 0, GetSystemMetrics (SM_CXSCREEN), GetSystemMetrics (SM_CYSCREEN), parent, NULL, hInst, NULL); if (hWnd) { SetLayeredWindowAttributes (hWnd, 0, 1, LWA_ALPHA); ShowWindow (hWnd, SW_SHOWNORMAL); DestroyWindow (hWnd); } UnregisterClassW (className, hInst); } } BOOL DisableFileCompression (HANDLE file) { USHORT format; DWORD bytesOut; if (!DeviceIoControl (file, FSCTL_GET_COMPRESSION, NULL, 0, &format, sizeof (format), &bytesOut, NULL)) return FALSE; if (format == COMPRESSION_FORMAT_NONE) return TRUE; format = COMPRESSION_FORMAT_NONE; return DeviceIoControl (file, FSCTL_SET_COMPRESSION, &format, sizeof (format), NULL, 0, &bytesOut, NULL); } #ifndef SETUP BOOL VolumePathExists (const wchar_t *volumePath) { OPEN_TEST_STRUCT openTest = {0}; wchar_t upperCasePath[TC_MAX_PATH + 1]; UpperCaseCopy (upperCasePath, sizeof(upperCasePath), volumePath); if (wcsstr (upperCasePath, L"\\DEVICE\\") == upperCasePath) return OpenDevice (volumePath, &openTest, FALSE, FALSE); wstring path = volumePath; if (path.find (L"\\\\?\\Volume{") == 0 && path.rfind (L"}\\") == path.size() - 2) { wchar_t devicePath[TC_MAX_PATH]; if (QueryDosDevice (path.substr (4, path.size() - 5).c_str(), devicePath, TC_MAX_PATH) != 0) return TRUE; } if (_waccess (volumePath, 0) == 0) return TRUE; else { DWORD dwResult = GetLastError (); if (dwResult == ERROR_SHARING_VIOLATION) return TRUE; else return FALSE; } } BOOL IsWindowsIsoBurnerAvailable () { wchar_t path[MAX_PATH*2] = { 0 }; if (!IsOSAtLeast (WIN_7)) { return FALSE; } if (SUCCEEDED(SHGetFolderPath (NULL, CSIDL_SYSTEM, NULL, 0, path))) { StringCbCatW (path, MAX_PATH*2, L"\\" ISO_BURNER_TOOL); return (FileExists (path)); } return FALSE; } BOOL LaunchWindowsIsoBurner (HWND hwnd, const wchar_t *isoPath) { wchar_t path[MAX_PATH*2] = { 0 }; int r; if (SUCCEEDED(SHGetFolderPath (NULL, CSIDL_SYSTEM, NULL, 0, path))) StringCbCatW (path, MAX_PATH*2, L"\\" ISO_BURNER_TOOL); else StringCbCopyW (path, MAX_PATH*2, L"C:\\Windows\\System32\\" ISO_BURNER_TOOL); r = (int) ShellExecute (hwnd, L"open", path, (wstring (L"\"") + isoPath + L"\"").c_str(), NULL, SW_SHOWNORMAL); if (r <= 32) { SetLastError (r); handleWin32Error (hwnd, SRC_POS); return FALSE; } return TRUE; } std::wstring VolumeGuidPathToDevicePath (std::wstring volumeGuidPath) { if (volumeGuidPath.find (L"\\\\?\\") == 0) volumeGuidPath = volumeGuidPath.substr (4); if (volumeGuidPath.find (L"Volume{") != 0 || volumeGuidPath.rfind (L"}\\") != volumeGuidPath.size() - 2) return wstring(); wchar_t volDevPath[TC_MAX_PATH]; if (QueryDosDevice (volumeGuidPath.substr (0, volumeGuidPath.size() - 1).c_str(), volDevPath, TC_MAX_PATH) == 0) return wstring(); wstring partitionPath = HarddiskVolumePathToPartitionPath (volDevPath); return partitionPath.empty() ? volDevPath : partitionPath; } std::wstring HarddiskVolumePathToPartitionPath (const std::wstring &harddiskVolumePath) { for (int driveNumber = 0; driveNumber < MAX_HOST_DRIVE_NUMBER; driveNumber++) { for (int partNumber = 0; partNumber < MAX_HOST_PARTITION_NUMBER; partNumber++) { wchar_t partitionPath[TC_MAX_PATH]; StringCchPrintfW (partitionPath, ARRAYSIZE (partitionPath), L"\\Device\\Harddisk%d\\Partition%d", driveNumber, partNumber); wchar_t resolvedPath[TC_MAX_PATH]; if (ResolveSymbolicLink (partitionPath, resolvedPath, sizeof(resolvedPath))) { if (harddiskVolumePath == resolvedPath) return partitionPath; } else if (partNumber == 0) break; } } return wstring(); } #endif BOOL IsApplicationInstalled (const wchar_t *appName, BOOL b32bitApp) { const wchar_t *uninstallRegName = L"Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall"; BOOL installed = FALSE; HKEY unistallKey; LONG res = RegOpenKeyEx (HKEY_LOCAL_MACHINE, uninstallRegName, 0, KEY_READ | (b32bitApp? KEY_WOW64_32KEY: KEY_WOW64_64KEY), &unistallKey); if (res != ERROR_SUCCESS) { SetLastError (res); return FALSE; } wchar_t regName[1024]; DWORD regNameSize = sizeof (regName); DWORD index = 0; while (RegEnumKeyEx (unistallKey, index++, regName, &regNameSize, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) { if (wcsstr (regName, L"{") == regName) { regNameSize = sizeof (regName); if (!ReadLocalMachineRegistryStringNonReflected ((wstring (uninstallRegName) + L"\\" + regName).c_str(), L"DisplayName", regName, &regNameSize, b32bitApp)) regName[0] = 0; } if (_wcsicmp (regName, appName) == 0) { installed = TRUE; break; } regNameSize = sizeof (regName); } RegCloseKey (unistallKey); return installed; } std::wstring FindLatestFileOrDirectory (const std::wstring &directory, const wchar_t *namePattern, bool findDirectory, bool findFile) { wstring name; ULARGE_INTEGER latestTime; latestTime.QuadPart = 0; WIN32_FIND_DATA findData; HANDLE find = FindFirstFile ((directory + L"\\" + namePattern).c_str(), &findData); if (find != INVALID_HANDLE_VALUE) { do { if (wcscmp (findData.cFileName, L".") == 0 || wcscmp (findData.cFileName, L"..") == 0) continue; ULARGE_INTEGER writeTime; writeTime.LowPart = findData.ftLastWriteTime.dwLowDateTime; writeTime.HighPart = findData.ftLastWriteTime.dwHighDateTime; if ((!findFile && !(findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) || (!findDirectory && (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))) continue; if (latestTime.QuadPart < writeTime.QuadPart) { latestTime = writeTime; name = findData.cFileName; } } while (FindNextFile (find, &findData)); FindClose (find); } if (name.empty()) return name; return wstring (directory) + L"\\" + name; } int GetPim (HWND hwndDlg, UINT ctrlId, int defaultPim) { int pim = defaultPim; HWND hCtrl = GetDlgItem (hwndDlg, ctrlId); if (IsWindowEnabled (hCtrl) && IsWindowVisible (hCtrl)) { wchar_t szTmp[MAX_PIM + 1] = {0}; if (GetDlgItemText (hwndDlg, ctrlId, szTmp, MAX_PIM + 1) > 0) { wchar_t* endPtr = NULL; pim = wcstol(szTmp, &endPtr, 10); if (pim < 0 || endPtr == szTmp || !endPtr || *endPtr != L'\0') pim = defaultPim; } } return pim; } void SetPim (HWND hwndDlg, UINT ctrlId, int pim) { if (pim > 0) { wchar_t szTmp[MAX_PIM + 1]; StringCbPrintfW (szTmp, sizeof(szTmp), L"%d", pim); SetDlgItemText (hwndDlg, ctrlId, szTmp); } else SetDlgItemText (hwndDlg, ctrlId, L""); } BOOL GetPassword (HWND hwndDlg, UINT ctrlID, char* passValue, int bufSize, BOOL bLegacyPassword, BOOL bShowError) { wchar_t tmp [MAX_PASSWORD + 1]; int utf8Len; BOOL bRet = FALSE; GetWindowText (GetDlgItem (hwndDlg, ctrlID), tmp, ARRAYSIZE (tmp)); if ((bLegacyPassword || bUseLegacyMaxPasswordLength) && (lstrlen (tmp) > MAX_LEGACY_PASSWORD)) wmemset (&tmp[MAX_LEGACY_PASSWORD], 0, MAX_PASSWORD + 1 - MAX_LEGACY_PASSWORD); utf8Len = WideCharToMultiByte (CP_UTF8, 0, tmp, -1, passValue, bufSize, NULL, NULL); burn (tmp, sizeof (tmp)); if (utf8Len > 0) { bRet = TRUE; } else { passValue [0] = 0; if (bShowError) { SetFocus (GetDlgItem(hwndDlg, ctrlID)); if (GetLastError () == ERROR_INSUFFICIENT_BUFFER) Error ("PASSWORD_UTF8_TOO_LONG", hwndDlg); else Error ("PASSWORD_UTF8_INVALID", hwndDlg); } } return bRet; } void SetPassword (HWND hwndDlg, UINT ctrlID, char* passValue) { wchar_t tmp [MAX_PASSWORD + 1] = {0}; MultiByteToWideChar (CP_UTF8, 0, passValue, -1, tmp, MAX_PASSWORD + 1); SetWindowText ( GetDlgItem (hwndDlg, ctrlID), tmp); burn (tmp, sizeof (tmp)); } void HandleShowPasswordFieldAction (HWND hwndDlg, UINT checkBoxId, UINT edit1Id, UINT edit2Id) { if ((EditPasswordChar == 0) && GetCheckBox (hwndDlg, checkBoxId)) { EditPasswordChar = (WCHAR) SendMessageW (GetDlgItem (hwndDlg, edit1Id), EM_GETPASSWORDCHAR, 0, 0); } SendMessageW (GetDlgItem (hwndDlg, edit1Id), EM_SETPASSWORDCHAR, GetCheckBox (hwndDlg, checkBoxId) ? 0 : EditPasswordChar, 0); InvalidateRect (GetDlgItem (hwndDlg, edit1Id), NULL, TRUE); if (edit2Id) { SendMessageW (GetDlgItem (hwndDlg, edit2Id), EM_SETPASSWORDCHAR, GetCheckBox (hwndDlg, checkBoxId) ? 0 : EditPasswordChar, 0); InvalidateRect (GetDlgItem (hwndDlg, edit2Id), NULL, TRUE); } } void RegisterDriverInf (bool registerFilter, const string& filter, const string& filterReg, HWND ParentWindow, HKEY regKey) { wstring infFileName = GetTempPathString() + L"\\veracrypt_driver_setup.inf"; File infFile (infFileName, false, true); finally_do_arg (wstring, infFileName, { DeleteFile (finally_arg.c_str()); }); string infTxt = "[veracrypt]\r\n" + string (registerFilter ? "Add" : "Del") + "Reg=veracrypt_reg\r\n\r\n" "[veracrypt_reg]\r\n" "HKR,,\"" + filterReg + "\",0x0001" + string (registerFilter ? "0008" : "8002") + ",\"" + filter + "\"\r\n"; infFile.Write ((byte *) infTxt.c_str(), (DWORD) infTxt.size()); infFile.Close(); HINF hInf = SetupOpenInfFileWFn (infFileName.c_str(), NULL, INF_STYLE_OLDNT | INF_STYLE_WIN4, NULL); throw_sys_if (hInf == INVALID_HANDLE_VALUE); finally_do_arg (HINF, hInf, { SetupCloseInfFileFn (finally_arg); }); throw_sys_if (!SetupInstallFromInfSectionWFn (ParentWindow, hInf, L"veracrypt", SPINST_REGISTRY, regKey, NULL, 0, NULL, NULL, NULL, NULL)); } HKEY OpenDeviceClassRegKey (const GUID *deviceClassGuid) { return SetupDiOpenClassRegKeyFn (deviceClassGuid, KEY_READ | KEY_WRITE); } LSTATUS DeleteRegistryKey (HKEY hKey, LPCTSTR keyName) { return SHDeleteKeyWFn(hKey, keyName); } HIMAGELIST CreateImageList(int cx, int cy, UINT flags, int cInitial, int cGrow) { return ImageList_CreateFn(cx, cy, flags, cInitial, cGrow); } int AddBitmapToImageList(HIMAGELIST himl, HBITMAP hbmImage, HBITMAP hbmMask) { return ImageList_AddFn(himl, hbmImage, hbmMask); } HRESULT VCStrDupW(LPCWSTR psz, LPWSTR *ppwsz) { return SHStrDupWFn (psz, ppwsz); } void ProcessEntropyEstimate (HWND hProgress, DWORD* pdwInitialValue, DWORD dwCounter, DWORD dwMaxLevel, DWORD* pdwEntropy) { /* conservative estimate: 1 mouse move event brings 1 bit of entropy * https://security.stackexchange.com/questions/32844/for-how-much-time-should-i-randomly-move-the-mouse-for-generating-encryption-key/32848#32848 */ if (*pdwEntropy == 0xFFFFFFFF) { *pdwInitialValue = dwCounter; *pdwEntropy = 0; } else { if ( *pdwEntropy < dwMaxLevel && (dwCounter >= *pdwInitialValue) && (dwCounter - *pdwInitialValue) <= dwMaxLevel) *pdwEntropy = dwCounter - *pdwInitialValue; else *pdwEntropy = dwMaxLevel; if (IsOSAtLeast (WIN_VISTA)) { int state = PBST_ERROR; if (*pdwEntropy >= (dwMaxLevel/2)) state = PBST_NORMAL; else if (*pdwEntropy >= (dwMaxLevel/4)) state = PBST_PAUSED; SendMessage (hProgress, PBM_SETSTATE, state, 0); } SendMessage (hProgress, PBM_SETPOS, (WPARAM) (*pdwEntropy), 0); } } void AllowMessageInUIPI (UINT msg) { if (ChangeWindowMessageFilterFn) { ChangeWindowMessageFilterFn (msg, MSGFLT_ADD); } } BOOL IsRepeatedByteArray (byte value, const byte* buffer, size_t bufferSize) { if (buffer && bufferSize) { size_t i; for (i = 0; i < bufferSize; i++) { if (*buffer++ != value) return FALSE; } return TRUE; } else return FALSE; } #ifndef SETUP BOOL TranslateVolumeID (HWND hwndDlg, wchar_t* pathValue, size_t cchPathValue) { BOOL bRet = TRUE; size_t pathLen = pathValue? wcslen (pathValue) : 0; if ((pathLen >= 3) && (_wcsnicmp (pathValue, L"ID:", 3) == 0)) { std::vector<byte> arr; if ( (pathLen == (3 + 2*VOLUME_ID_SIZE)) && HexWideStringToArray (pathValue + 3, arr) && (arr.size() == VOLUME_ID_SIZE) ) { std::wstring devicePath = FindDeviceByVolumeID (&arr[0], FALSE); if (devicePath.length() > 0) StringCchCopyW (pathValue, cchPathValue, devicePath.c_str()); else { if (!Silent && !MultipleMountOperationInProgress) Error ("VOLUME_ID_NOT_FOUND", hwndDlg); SetLastError (ERROR_PATH_NOT_FOUND); bRet = FALSE; } } else { if (!Silent) Error ("VOLUME_ID_INVALID", hwndDlg); SetLastError (ERROR_INVALID_PARAMETER); bRet = FALSE; } } return bRet; } #endif BOOL CopyTextToClipboard (LPCWSTR txtValue) { size_t txtLen = wcslen(txtValue); HGLOBAL hdst; LPWSTR dst; BOOL bRet = FALSE; // Allocate string for cwd hdst = GlobalAlloc(GMEM_MOVEABLE, (txtLen + 1) * sizeof(WCHAR)); if (hdst) { dst = (LPWSTR)GlobalLock(hdst); wmemcpy(dst, txtValue, txtLen + 1); GlobalUnlock(hdst); if (OpenClipboard(NULL)) { EmptyClipboard(); SetClipboardData(CF_UNICODETEXT, hdst); CloseClipboard(); } } return bRet; } BOOL GetFreeDriveLetter(WCHAR* pCh) { DWORD dwUsedDrives = GetLogicalDrives(); WCHAR l; for (l = L'A'; l <= L'Z'; l++) { if ((dwUsedDrives & 1) == 0) { *pCh = l; return TRUE; } dwUsedDrives = dwUsedDrives >> 1; } return FALSE; } BOOL SetPrivilege(LPTSTR szPrivilegeName, BOOL bEnable) { HANDLE hToken; TOKEN_PRIVILEGES tkp; BOOL bRet = FALSE; DWORD dwLastError = 0; if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) { if (LookupPrivilegeValue(NULL, szPrivilegeName, &tkp.Privileges[0].Luid)) { tkp.PrivilegeCount = 1; tkp.Privileges[0].Attributes = bEnable? SE_PRIVILEGE_ENABLED : SE_PRIVILEGE_REMOVED; bRet = AdjustTokenPrivileges(hToken, FALSE, &tkp, 0, NULL, NULL); if (!bRet) dwLastError = GetLastError (); } else dwLastError = GetLastError (); CloseHandle(hToken); } else dwLastError = GetLastError (); SetLastError (dwLastError); return bRet; } BOOL DeleteDirectory (const wchar_t* szDirName) { BOOL bStatus = RemoveDirectory (szDirName); if (!bStatus) { /* force removal of the non empty directory */ wchar_t szOpPath[TC_MAX_PATH + 1] = {0}; SHFILEOPSTRUCTW op; StringCchCopyW(szOpPath, ARRAYSIZE(szOpPath)-1, szDirName); ZeroMemory(&op, sizeof(op)); op.wFunc = FO_DELETE; op.pFrom = szOpPath; op.fFlags = FOF_SILENT | FOF_NOCONFIRMATION | FOF_NOERRORUI | FOF_NOCONFIRMMKDIR; if ((0 == SHFileOperation(&op)) && (!op.fAnyOperationsAborted)) bStatus = TRUE; } return bStatus; } #if defined (TCMOUNT) || defined (VOLFORMAT) /*********************************************************************/ static BOOL GenerateRandomString (HWND hwndDlg, LPTSTR szName, DWORD maxCharsCount) { BOOL bRet = FALSE; int alreadyInitialized = 0; if (RandinitWithCheck (&alreadyInitialized) != ERR_SUCCESS) { handleError (hwndDlg, (CryptoAPILastError == ERROR_SUCCESS)? ERR_RAND_INIT_FAILED : ERR_CAPI_INIT_FAILED, SRC_POS); } else { BYTE* indexes = (BYTE*) malloc (maxCharsCount + 1); bRet = RandgetBytesFull (hwndDlg, indexes, maxCharsCount + 1, TRUE, TRUE); if (bRet) { static LPCTSTR chars = _T("0123456789@#$%^&_-*abcdefghijklmnopqrstuvwxyz"); DWORD i, charsLen = (DWORD) _tcslen (chars); DWORD effectiveLen = (indexes[0] % (64 - 16)) + 16; // random length between 16 to 64 effectiveLen = (effectiveLen > maxCharsCount)? maxCharsCount : effectiveLen; for (i = 0; i < effectiveLen; i++) { szName[i] = chars[indexes[i + 1] % charsLen]; } szName[effectiveLen] = 0; } burn (indexes, maxCharsCount + 1); free (indexes); /* If RNG was not initialized before us, then stop it in order to * stop the fast poll thread which consumes CPU. Next time a critical operation * that requires RNG is performed, it will be initialized again. * * We do this because since the addition of secure desktop support, every time * secure desktop is displayed, the RNG fast poll thread was started even if the * user will never perform any critical operation that requires random bytes. */ if (!alreadyInitialized) { RandStop (FALSE); } } return bRet; } typedef struct { HDESK hDesk; LPCWSTR szDesktopName; HINSTANCE hInstance; LPCWSTR lpTemplateName; DLGPROC lpDialogFunc; LPARAM dwInitParam; INT_PTR retValue; } SecureDesktopThreadParam; typedef struct { LPCWSTR szVCDesktopName; HDESK hVcDesktop; volatile BOOL* pbStopMonitoring; } SecureDesktopMonitoringThreadParam; #define SECUREDESKTOP_MONOTIR_PERIOD 500 // This thread checks if VeraCrypt secure desktop is the one that has user input // and if it is not then it will call SwitchDesktop to make it the input desktop static unsigned int __stdcall SecureDesktopMonitoringThread( LPVOID lpThreadParameter ) { SecureDesktopMonitoringThreadParam* pMonitorParam = (SecureDesktopMonitoringThreadParam*) lpThreadParameter; if (pMonitorParam) { volatile BOOL* pbStopMonitoring = pMonitorParam->pbStopMonitoring; LPCWSTR szVCDesktopName = pMonitorParam->szVCDesktopName; HDESK hVcDesktop = pMonitorParam->hVcDesktop; while (!*pbStopMonitoring) { // check that our secure desktop is still the input desktop // otherwise, switch to it BOOL bPerformSwitch = FALSE; HDESK currentDesk = OpenInputDesktop (0, FALSE, GENERIC_READ); if (currentDesk) { LPWSTR szName = NULL; DWORD dwLen = 0; if (!GetUserObjectInformation (currentDesk, UOI_NAME, NULL, 0, &dwLen)) { szName = (LPWSTR) malloc (dwLen); if (szName) { if (GetUserObjectInformation (currentDesk, UOI_NAME, szName, dwLen, &dwLen)) { if (0 != _wcsicmp (szName, szVCDesktopName)) bPerformSwitch = TRUE; } free (szName); } } CloseDesktop (currentDesk); } if (bPerformSwitch) SwitchDesktop (hVcDesktop); Sleep (SECUREDESKTOP_MONOTIR_PERIOD); } } return 0; } static DWORD WINAPI SecureDesktopThread(LPVOID lpThreadParameter) { volatile BOOL bStopMonitoring = FALSE; HANDLE hMonitoringThread = NULL; unsigned int monitoringThreadID = 0; SecureDesktopThreadParam* pParam = (SecureDesktopThreadParam*) lpThreadParameter; SecureDesktopMonitoringThreadParam monitorParam; HDESK hOriginalDesk = GetThreadDesktop (GetCurrentThreadId ()); BOOL bNewDesktopSet = FALSE; // wait for SwitchDesktop to succeed before using it for current thread while (true) { if (SwitchDesktop (pParam->hDesk)) { bNewDesktopSet = TRUE; break; } Sleep (SECUREDESKTOP_MONOTIR_PERIOD); } if (bNewDesktopSet) { SetThreadDesktop (pParam->hDesk); // create the thread that will ensure that VeraCrypt secure desktop has always user input monitorParam.szVCDesktopName = pParam->szDesktopName; monitorParam.hVcDesktop = pParam->hDesk; monitorParam.pbStopMonitoring = &bStopMonitoring; hMonitoringThread = (HANDLE) _beginthreadex (NULL, 0, SecureDesktopMonitoringThread, (LPVOID) &monitorParam, 0, &monitoringThreadID); } pParam->retValue = DialogBoxParamW (pParam->hInstance, pParam->lpTemplateName, NULL, pParam->lpDialogFunc, pParam->dwInitParam); if (hMonitoringThread) { bStopMonitoring = TRUE; WaitForSingleObject (hMonitoringThread, INFINITE); CloseHandle (hMonitoringThread); } if (bNewDesktopSet) { SetThreadDesktop (hOriginalDesk); SwitchDesktop (hOriginalDesk); } return 0; } static void GetCtfMonProcessIdList (map<DWORD, BOOL>& processIdList) { HANDLE hSnapShot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL); PROCESSENTRY32 pEntry; BOOL hRes; pEntry.dwSize = sizeof (pEntry); processIdList.clear(); hRes = Process32First(hSnapShot, &pEntry); while (hRes) { LPTSTR szFileName = PathFindFileName (pEntry.szExeFile); if (_wcsicmp(szFileName, L"ctfmon.exe") == 0) { processIdList[pEntry.th32ProcessID] = TRUE; } hRes = Process32Next(hSnapShot, &pEntry); } CloseHandle(hSnapShot); } static void KillProcess (DWORD dwProcessId) { HANDLE hProcess = OpenProcess(PROCESS_TERMINATE, 0, dwProcessId); if (hProcess != NULL) { TerminateProcess(hProcess, (UINT) -1); CloseHandle(hProcess); } } INT_PTR SecureDesktopDialogBoxParam( HINSTANCE hInstance, LPCWSTR lpTemplateName, HWND hWndParent, DLGPROC lpDialogFunc, LPARAM dwInitParam) { TCHAR szDesktopName[65] = {0}; BOOL bSuccess = FALSE; INT_PTR retValue = 0; BOOL bEffectiveUseSecureDesktop = bCmdUseSecureDesktopValid? bCmdUseSecureDesktop : bUseSecureDesktop; if (bEffectiveUseSecureDesktop) { EnterCriticalSection (&csSecureDesktop); bSecureDesktopOngoing = TRUE; finally_do ({ bSecureDesktopOngoing = FALSE; LeaveCriticalSection (&csSecureDesktop); }); if (GenerateRandomString (hWndParent, szDesktopName, 64)) { map<DWORD, BOOL> ctfmonBeforeList, ctfmonAfterList; DWORD desktopAccess = DESKTOP_CREATEMENU | DESKTOP_CREATEWINDOW | DESKTOP_READOBJECTS | DESKTOP_SWITCHDESKTOP | DESKTOP_WRITEOBJECTS; HDESK hSecureDesk; HDESK hInputDesk = NULL; // wait for the input desktop to be available before switching to // secure desktop. Under Windows 10, the user session can be started // in the background even before the user has authenticated and in this // case, we wait for the user to be really authenticated before starting // secure desktop mechanism while (!(hInputDesk = OpenInputDesktop (0, TRUE, GENERIC_READ))) { Sleep (SECUREDESKTOP_MONOTIR_PERIOD); } CloseDesktop (hInputDesk); // get the initial list of ctfmon.exe processes before creating new desktop GetCtfMonProcessIdList (ctfmonBeforeList); hSecureDesk = CreateDesktop (szDesktopName, NULL, NULL, 0, desktopAccess, NULL); if (hSecureDesk) { SecureDesktopThreadParam param; param.hDesk = hSecureDesk; param.szDesktopName = szDesktopName; param.hInstance = hInstance; param.lpTemplateName = lpTemplateName; param.lpDialogFunc = lpDialogFunc; param.dwInitParam = dwInitParam; param.retValue = 0; HANDLE hThread = ::CreateThread (NULL, 0, SecureDesktopThread, (LPVOID) &param, 0, NULL); if (hThread) { WaitForSingleObject (hThread, INFINITE); CloseHandle (hThread); retValue = param.retValue; bSuccess = TRUE; } CloseDesktop (hSecureDesk); // get the new list of ctfmon.exe processes in order to find the ID of the // ctfmon.exe instance that corresponds to the desktop we create so that // we can kill it, otherwise it would remain running GetCtfMonProcessIdList (ctfmonAfterList); for (map<DWORD, BOOL>::iterator It = ctfmonAfterList.begin(); It != ctfmonAfterList.end(); It++) { if (ctfmonBeforeList[It->first] != TRUE) { // Kill process KillProcess (It->first); } } } burn (szDesktopName, sizeof (szDesktopName)); } } if (!bSuccess) { // fallback to displaying in normal desktop retValue = DialogBoxParamW (hInstance, lpTemplateName, hWndParent, lpDialogFunc, dwInitParam); } return retValue; } #endif #ifdef NDEBUG static BOOL InitializeWintrust() { if (!hWinTrustLib) { wchar_t szPath[MAX_PATH] = {0}; if (GetSystemDirectory(szPath, MAX_PATH)) StringCchCatW (szPath, MAX_PATH, L"\\Wintrust.dll"); else StringCchCopyW (szPath, MAX_PATH, L"C:\\Windows\\System32\\Wintrust.dll"); hWinTrustLib = LoadLibrary (szPath); if (hWinTrustLib) { WinVerifyTrustFn = (WINVERIFYTRUST) GetProcAddress (hWinTrustLib, "WinVerifyTrust"); WTHelperProvDataFromStateDataFn = (WTHELPERPROVDATAFROMSTATEDATA) GetProcAddress (hWinTrustLib, "WTHelperProvDataFromStateData"); WTHelperGetProvSignerFromChainFn = (WTHELPERGETPROVSIGNERFROMCHAIN) GetProcAddress (hWinTrustLib, "WTHelperGetProvSignerFromChain"); WTHelperGetProvCertFromChainFn = (WTHELPERGETPROVCERTFROMCHAIN) GetProcAddress (hWinTrustLib, "WTHelperGetProvCertFromChain"); if ( !WinVerifyTrustFn || !WTHelperProvDataFromStateDataFn || !WTHelperGetProvSignerFromChainFn || !WTHelperGetProvCertFromChainFn) { FreeLibrary (hWinTrustLib); hWinTrustLib = NULL; } } } if (hWinTrustLib) return TRUE; else return FALSE; } static void FinalizeWintrust() { if (hWinTrustLib) { FreeLibrary (hWinTrustLib); hWinTrustLib = NULL; } } #endif BOOL VerifyModuleSignature (const wchar_t* path) { #ifdef NDEBUG BOOL bResult = FALSE; HRESULT hResult; GUID gActionID = WINTRUST_ACTION_GENERIC_VERIFY_V2; WINTRUST_FILE_INFO fileInfo = {0}; WINTRUST_DATA WVTData = {0}; wchar_t filePath [TC_MAX_PATH + 1024]; // Strip quotation marks (if any) if (path [0] == L'"') { StringCbCopyW (filePath, sizeof(filePath), path + 1); } else { StringCbCopyW (filePath, sizeof(filePath), path); } // Strip quotation marks (if any) if (filePath [wcslen (filePath) - 1] == L'"') filePath [wcslen (filePath) - 1] = 0; if (!InitializeWintrust ()) return FALSE; fileInfo.cbStruct = sizeof(WINTRUST_FILE_INFO); fileInfo.pcwszFilePath = filePath; fileInfo.hFile = NULL; WVTData.cbStruct = sizeof(WINTRUST_DATA); WVTData.dwUIChoice = WTD_UI_NONE; WVTData.fdwRevocationChecks = WTD_REVOKE_NONE; WVTData.dwUnionChoice = WTD_CHOICE_FILE; WVTData.pFile = &fileInfo; WVTData.dwStateAction = WTD_STATEACTION_VERIFY; WVTData.dwProvFlags = WTD_REVOCATION_CHECK_NONE | WTD_CACHE_ONLY_URL_RETRIEVAL; hResult = WinVerifyTrustFn(0, &gActionID, &WVTData); if (SUCCEEDED (hResult)) { PCRYPT_PROVIDER_DATA pProviderData = WTHelperProvDataFromStateDataFn (WVTData.hWVTStateData); if (pProviderData) { PCRYPT_PROVIDER_SGNR pProviderSigner = WTHelperGetProvSignerFromChainFn (pProviderData, 0, FALSE, 0); if (pProviderSigner) { PCRYPT_PROVIDER_CERT pProviderCert = WTHelperGetProvCertFromChainFn (pProviderSigner, 0); if (pProviderCert && (pProviderCert->pCert)) { BYTE hashVal[64]; sha512 (hashVal, pProviderCert->pCert->pbCertEncoded, pProviderCert->pCert->cbCertEncoded); if (0 == memcmp (hashVal, gpbSha1CodeSignCertFingerprint, 64)) { bResult = TRUE; } } } } } WVTData.dwUIChoice = WTD_UI_NONE; WVTData.dwStateAction = WTD_STATEACTION_CLOSE; WinVerifyTrustFn(0, &gActionID, &WVTData); FinalizeWintrust (); return bResult; #else return TRUE; #endif } void GetInstallationPath (HWND hwndDlg, wchar_t* szInstallPath, DWORD cchSize, BOOL* pbInstallPathDetermined) { HKEY hkey; BOOL bInstallPathDetermined = FALSE; wchar_t path[MAX_PATH+20]; ITEMIDLIST *itemList; memset (szInstallPath, 0, cchSize * sizeof (wchar_t)); // Determine if VeraCrypt is already installed and try to determine its "Program Files" location if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\VeraCrypt", 0, KEY_READ | KEY_WOW64_32KEY, &hkey) == ERROR_SUCCESS) { /* Default 'UninstallString' registry strings written by VeraCrypt: ------------------------------------------------------------------------------------ 5.0+ "C:\Program Files\VeraCrypt\VeraCrypt Setup.exe" /u */ wchar_t rv[MAX_PATH*4]; DWORD size = sizeof (rv); if (RegQueryValueEx (hkey, L"UninstallString", 0, 0, (LPBYTE) &rv, &size) == ERROR_SUCCESS && wcsrchr (rv, L'/')) { size_t len = 0; // Cut and paste the location (path) where VeraCrypt is installed to InstallationPath if (rv[0] == L'"') { len = wcsrchr (rv, L'/') - rv - 2; StringCchCopyNW (szInstallPath, cchSize, rv + 1, len); szInstallPath [len] = 0; bInstallPathDetermined = TRUE; if (szInstallPath [wcslen (szInstallPath) - 1] != L'\\') { len = wcsrchr (szInstallPath, L'\\') - szInstallPath; szInstallPath [len] = 0; } } } RegCloseKey (hkey); } if (!bInstallPathDetermined) { /* VeraCrypt is not installed or it wasn't possible to determine where it is installed. */ // Default "Program Files" path. SHGetSpecialFolderLocation (hwndDlg, CSIDL_PROGRAM_FILES, &itemList); SHGetPathFromIDList (itemList, path); if (Is64BitOs()) { // Use a unified default installation path (registry redirection of %ProgramFiles% does not work if the installation path is user-selectable) wstring s = path; size_t p = s.find (L" (x86)"); if (p != wstring::npos) { s = s.substr (0, p); if (_waccess (s.c_str(), 0) != -1) StringCbCopyW (path, sizeof (path), s.c_str()); } } StringCbCatW (path, sizeof(path), L"\\VeraCrypt\\"); StringCbCopyW (szInstallPath, cchSize, path); } // Make sure the path ends with a backslash if (szInstallPath [wcslen (szInstallPath) - 1] != L'\\') { StringCbCatW (szInstallPath, cchSize, L"\\"); } if (pbInstallPathDetermined) *pbInstallPathDetermined = bInstallPathDetermined; } BOOL GetSetupconfigLocation (wchar_t* path, DWORD cchSize) { wchar_t szShell32Path[MAX_PATH] = {0}; HMODULE hShell32 = NULL; BOOL bResult = FALSE; path[0] = 0; if (GetSystemDirectory(szShell32Path, MAX_PATH)) StringCchCatW (szShell32Path, MAX_PATH, L"\\Shell32.dll"); else StringCchCopyW (szShell32Path, MAX_PATH, L"C:\\Windows\\System32\\Shell32.dll"); hShell32 = LoadLibrary (szShell32Path); if (hShell32) { SHGETKNOWNFOLDERPATH SHGetKnownFolderPathFn = (SHGETKNOWNFOLDERPATH) GetProcAddress (hShell32, "SHGetKnownFolderPath"); if (SHGetKnownFolderPathFn) { wchar_t* pszUsersPath = NULL; if (S_OK == SHGetKnownFolderPathFn (FOLDERID_UserProfiles, 0, NULL, &pszUsersPath)) { StringCchPrintfW (path, cchSize, L"%s\\Default\\AppData\\Local\\Microsoft\\Windows\\WSUS\\", pszUsersPath); CoTaskMemFree (pszUsersPath); bResult = TRUE; } } FreeLibrary (hShell32); } if (!bResult && CurrentOSMajor >= 10) { StringCchPrintfW (path, cchSize, L"%c:\\Users\\Default\\AppData\\Local\\Microsoft\\Windows\\WSUS\\", szShell32Path[0]); bResult = TRUE; } return bResult; } BOOL BufferHasPattern (const unsigned char* buffer, size_t bufferLen, const void* pattern, size_t patternLen) { BOOL bRet = FALSE; if (patternLen <= bufferLen) { size_t i; for (i = 0; i <= (bufferLen - patternLen); ++i) { if (memcmp (&buffer[i], pattern, patternLen) == 0) { bRet = TRUE; break; } } } return bRet; } /* Implementation borrowed from KeePassXC source code (https://github.com/keepassxreboot/keepassxc/blob/release/2.4.0/src/core/Bootstrap.cpp#L150) * * Reduce current user acess rights for this process to the minimum in order to forbid non-admin users from reading the process memory. */ BOOL EnableProcessProtection() { BOOL bSuccess = FALSE; // Process token and user HANDLE hToken = NULL; PTOKEN_USER pTokenUser = NULL; DWORD cbBufferSize = 0; // Access control list PACL pACL = NULL; DWORD cbACL = 0; // Open the access token associated with the calling process if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken)) { goto Cleanup; } // Retrieve the token information in a TOKEN_USER structure GetTokenInformation(hToken, TokenUser, NULL, 0, &cbBufferSize); pTokenUser = (PTOKEN_USER) HeapAlloc(GetProcessHeap(), 0, cbBufferSize); if (pTokenUser == NULL) { goto Cleanup; } if (!GetTokenInformation(hToken, TokenUser, pTokenUser, cbBufferSize, &cbBufferSize)) { goto Cleanup; } if (!IsValidSid(pTokenUser->User.Sid)) { goto Cleanup; } // Calculate the amount of memory that must be allocated for the DACL cbACL = sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE) + GetLengthSid(pTokenUser->User.Sid); // Create and initialize an ACL pACL = (PACL) HeapAlloc(GetProcessHeap(), 0, cbACL); if (pACL == NULL) { goto Cleanup; } if (!InitializeAcl(pACL, cbACL, ACL_REVISION)) { goto Cleanup; } // Add allowed access control entries, everything else is denied if (!AddAccessAllowedAce( pACL, ACL_REVISION, SYNCHRONIZE | PROCESS_QUERY_LIMITED_INFORMATION | PROCESS_TERMINATE, // same as protected process pTokenUser->User.Sid // pointer to the trustee's SID )) { goto Cleanup; } // Set discretionary access control list bSuccess = (ERROR_SUCCESS == SetSecurityInfo(GetCurrentProcess(), // object handle SE_KERNEL_OBJECT, // type of object DACL_SECURITY_INFORMATION, // change only the objects DACL NULL, NULL, // do not change owner or group pACL, // DACL specified NULL // do not change SACL ))? TRUE: FALSE; Cleanup: if (pACL != NULL) { HeapFree(GetProcessHeap(), 0, pACL); } if (pTokenUser != NULL) { HeapFree(GetProcessHeap(), 0, pTokenUser); } if (hToken != NULL) { CloseHandle(hToken); } return bSuccess; } #if !defined(SETUP) && defined(_WIN64) #define RtlGenRandom SystemFunction036 extern "C" BOOLEAN NTAPI RtlGenRandom(PVOID RandomBuffer, ULONG RandomBufferLength); void GetAppRandomSeed (unsigned char* pbRandSeed, size_t cbRandSeed) { LARGE_INTEGER iSeed; SYSTEMTIME sysTime; byte digest[WHIRLPOOL_DIGESTSIZE]; WHIRLPOOL_CTX tctx; size_t count; while (cbRandSeed) { WHIRLPOOL_init (&tctx); // we hash current content of digest buffer which is uninitialized the first time WHIRLPOOL_add (digest, WHIRLPOOL_DIGESTSIZE, &tctx); // we use various time information as source of entropy GetSystemTime (&sysTime); WHIRLPOOL_add ((unsigned char *) &sysTime, sizeof(sysTime), &tctx); if (QueryPerformanceCounter (&iSeed)) WHIRLPOOL_add ((unsigned char *) &(iSeed.QuadPart), sizeof(iSeed.QuadPart), &tctx); if (QueryPerformanceFrequency (&iSeed)) WHIRLPOOL_add ((unsigned char *) &(iSeed.QuadPart), sizeof(iSeed.QuadPart), &tctx); /* use Windows random generator as entropy source */ if (RtlGenRandom (digest, sizeof (digest))) WHIRLPOOL_add (digest, sizeof(digest), &tctx); /* use JitterEntropy library to get good quality random bytes based on CPU timing jitter */ if (0 == jent_entropy_init ()) { struct rand_data *ec = jent_entropy_collector_alloc (1, 0); if (ec) { ssize_t rndLen = jent_read_entropy (ec, (char*) digest, sizeof (digest)); if (rndLen > 0) WHIRLPOOL_add (digest, (unsigned int) rndLen, &tctx); jent_entropy_collector_free (ec); } } // use RDSEED or RDRAND from CPU as source of entropy if enabled if ( IsCpuRngEnabled() && ( (HasRDSEED() && RDSEED_getBytes (digest, sizeof (digest))) || (HasRDRAND() && RDRAND_getBytes (digest, sizeof (digest))) )) { WHIRLPOOL_add (digest, sizeof(digest), &tctx); } WHIRLPOOL_finalize (&tctx, digest); count = VC_MIN (cbRandSeed, sizeof (digest)); // copy digest value to seed buffer memcpy (pbRandSeed, digest, count); cbRandSeed -= count; pbRandSeed += count; } FAST_ERASE64 (digest, sizeof (digest)); FAST_ERASE64 (&iSeed.QuadPart, 8); burn (&sysTime, sizeof(sysTime)); burn (&tctx, sizeof(tctx)); } #endif