mirror of
https://gitlab.com/cryptsetup/cryptsetup.git
synced 2025-12-05 16:00:05 +01:00
Compare commits
1966 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0f8e7f317f | ||
|
|
c5b0a4dd32 | ||
|
|
5c5551d1d3 | ||
|
|
aa324567a8 | ||
|
|
0ee752c42d | ||
|
|
4746717b75 | ||
|
|
3ad942e338 | ||
|
|
b5190da581 | ||
|
|
5fa8e84ef0 | ||
|
|
63adb3b0cf | ||
|
|
20774374a9 | ||
|
|
d169020001 | ||
|
|
76766f11c0 | ||
|
|
5d6d65ce86 | ||
|
|
24ab0871e7 | ||
|
|
11e325a112 | ||
|
|
6ea32db1fa | ||
|
|
49c8a8b9ef | ||
|
|
a480c388b8 | ||
|
|
5406064f55 | ||
|
|
9b66d0d039 | ||
|
|
adff844c46 | ||
|
|
f702246d78 | ||
|
|
8606342b53 | ||
|
|
ccb0f7c0b2 | ||
|
|
72384b43bd | ||
|
|
5ef3de8945 | ||
|
|
ad913cf437 | ||
|
|
7820f07e85 | ||
|
|
01bda280ee | ||
|
|
b40f31fb8c | ||
|
|
066d651210 | ||
|
|
b00946d449 | ||
|
|
6a14f52e5d | ||
|
|
3c68e3f5b1 | ||
|
|
ec1ef8f19d | ||
|
|
6a64c2e932 | ||
|
|
835c603b13 | ||
|
|
a718b90ac6 | ||
|
|
089edb74b4 | ||
|
|
8c60cf8645 | ||
|
|
f364990b9b | ||
|
|
3b826d0fa3 | ||
|
|
cab332c367 | ||
|
|
9ee74f59d7 | ||
|
|
46afee6299 | ||
|
|
90bba399ab | ||
|
|
c403f73ad0 | ||
|
|
470b99a647 | ||
|
|
a68968af8f | ||
|
|
ee9c7855ca | ||
|
|
1a156458f2 | ||
|
|
796b901912 | ||
|
|
508284cd28 | ||
|
|
5d1972bb97 | ||
|
|
7c76d17a9c | ||
|
|
8ff663a761 | ||
|
|
d3ad9fe25f | ||
|
|
cc374ee10d | ||
|
|
06f132066b | ||
|
|
82816cb52f | ||
|
|
426cab3aeb | ||
|
|
152ed1fb44 | ||
|
|
c6ff9f8bd7 | ||
|
|
c104bccc3f | ||
|
|
4654e6f578 | ||
|
|
2cf38465c4 | ||
|
|
3428296186 | ||
|
|
877afd2281 | ||
|
|
2f320f3148 | ||
|
|
a0277d3ff6 | ||
|
|
531ebba50b | ||
|
|
d8bac63e5c | ||
|
|
b408b8238c | ||
|
|
2e80962501 | ||
|
|
43827ba380 | ||
|
|
cd374664d4 | ||
|
|
3694f9c099 | ||
|
|
06249b8e99 | ||
|
|
bf915e82f4 | ||
|
|
bfe0c7fc5f | ||
|
|
0eb8493156 | ||
|
|
9736f533bb | ||
|
|
cc6df5fa39 | ||
|
|
62896c20ff | ||
|
|
ea5fb82a48 | ||
|
|
25c29b80b5 | ||
|
|
f8caa82186 | ||
|
|
c35b896209 | ||
|
|
5a36a1f3a2 | ||
|
|
afb7cd6d01 | ||
|
|
c9af248c38 | ||
|
|
95eb986206 | ||
|
|
b4670ce7f0 | ||
|
|
6633fa626a | ||
|
|
df7a995fa2 | ||
|
|
ca2e93b69d | ||
|
|
3589f9578a | ||
|
|
07d23c2ee8 | ||
|
|
eadbcac115 | ||
|
|
3dc7dff2b2 | ||
|
|
35793c24f0 | ||
|
|
ff958d376e | ||
|
|
6545523df3 | ||
|
|
3e52aa820c | ||
|
|
73cd60b1cc | ||
|
|
c7b0f8fcda | ||
|
|
057af1e20a | ||
|
|
aea841eeb0 | ||
|
|
5b9e98f941 | ||
|
|
c645045adb | ||
|
|
224555aaf9 | ||
|
|
d9fc45de04 | ||
|
|
db77541790 | ||
|
|
e884fe93bd | ||
|
|
c2507f02cf | ||
|
|
fc6982f577 | ||
|
|
06fff68255 | ||
|
|
8f752a2bd7 | ||
|
|
07e687106a | ||
|
|
9125df1398 | ||
|
|
52cc01c977 | ||
|
|
b8d2218720 | ||
|
|
05a4d3fe0a | ||
|
|
df5e54545e | ||
|
|
f79ef935a7 | ||
|
|
cd3cb945ab | ||
|
|
f1d624b6c8 | ||
|
|
3f268c3052 | ||
|
|
0ec7027d83 | ||
|
|
0ae5240f55 | ||
|
|
51f5f71ee0 | ||
|
|
5784692218 | ||
|
|
f82d3ee51a | ||
|
|
d02c809bc7 | ||
|
|
b7a07efdcf | ||
|
|
a8bb07ae9f | ||
|
|
897e798fc0 | ||
|
|
2d0b19b359 | ||
|
|
702f9b1cf4 | ||
|
|
1d20a60e4a | ||
|
|
71422b411e | ||
|
|
f446dbb896 | ||
|
|
975425d0eb | ||
|
|
c020fafd66 | ||
|
|
2954b46d43 | ||
|
|
4cdd826282 | ||
|
|
413b484774 | ||
|
|
351d7fefca | ||
|
|
a7872ab856 | ||
|
|
c1613285e7 | ||
|
|
8805eb2b45 | ||
|
|
a3f919bd25 | ||
|
|
4f6f7404df | ||
|
|
5776c52bcf | ||
|
|
db44e9de22 | ||
|
|
c40be6cc7a | ||
|
|
b047b8ae20 | ||
|
|
e9434dc9e3 | ||
|
|
c6149c9cd8 | ||
|
|
8f2b23cd94 | ||
|
|
8d449aa9a6 | ||
|
|
e6089dd9c9 | ||
|
|
bc488fd4f1 | ||
|
|
ec3a9746a9 | ||
|
|
530bcfd4fa | ||
|
|
bd4f374b47 | ||
|
|
0a7c13207d | ||
|
|
c5fc3fe84a | ||
|
|
8d0e90b90a | ||
|
|
1aeb0a1f6e | ||
|
|
ce80f7c5b1 | ||
|
|
25cd2b2fb7 | ||
|
|
78797ae078 | ||
|
|
96d83455ca | ||
|
|
36805b3cfe | ||
|
|
5d0a11a21b | ||
|
|
d4cd675f33 | ||
|
|
c3328a123c | ||
|
|
2cc320f180 | ||
|
|
6f26d7a77f | ||
|
|
9d559bba8f | ||
|
|
cb9cb7154d | ||
|
|
da15a67c96 | ||
|
|
69efb9177d | ||
|
|
f9ce835e58 | ||
|
|
3dd6e222c8 | ||
|
|
04b8c4ff32 | ||
|
|
9b2adfede9 | ||
|
|
520aea9de0 | ||
|
|
9f233a68f3 | ||
|
|
476cd2f764 | ||
|
|
ca87b74333 | ||
|
|
25a943ad01 | ||
|
|
f22a6613eb | ||
|
|
8914ae468b | ||
|
|
3e712b2dcd | ||
|
|
17e0e9fd27 | ||
|
|
e7f67f8928 | ||
|
|
4b049fe848 | ||
|
|
fea4074e8f | ||
|
|
9209d7e3b5 | ||
|
|
ca2e1fc956 | ||
|
|
1592f1e274 | ||
|
|
74027ca922 | ||
|
|
1910960364 | ||
|
|
2708021e6f | ||
|
|
8e8ecd50de | ||
|
|
3ebf7fa3bd | ||
|
|
68130ef2f5 | ||
|
|
a77acb21c9 | ||
|
|
6e6e9f169e | ||
|
|
6a8bade7e6 | ||
|
|
3367b78958 | ||
|
|
28603e4de7 | ||
|
|
d8cf203d46 | ||
|
|
9faa602f6c | ||
|
|
c9b727e9ea | ||
|
|
1534dc6c61 | ||
|
|
dd6d6cfa1c | ||
|
|
8e564bbb5c | ||
|
|
284a49443e | ||
|
|
61abbc6e5d | ||
|
|
1fe2d3d92b | ||
|
|
b0da623c8a | ||
|
|
ff1502edd0 | ||
|
|
2d9c0b507d | ||
|
|
20320dfd0e | ||
|
|
6483fb027a | ||
|
|
030d50f6ba | ||
|
|
dc8bbbf352 | ||
|
|
c72030d25a | ||
|
|
4309294c2a | ||
|
|
f5dd3c8e32 | ||
|
|
6dd347ddb4 | ||
|
|
e15e09025d | ||
|
|
caf71248df | ||
|
|
7b327509b4 | ||
|
|
83138b7803 | ||
|
|
cea7a1489a | ||
|
|
f6e2fbb366 | ||
|
|
2e4a3a9888 | ||
|
|
639ffa36a5 | ||
|
|
05f9297141 | ||
|
|
28baeca882 | ||
|
|
b1558ec973 | ||
|
|
4862c38ca9 | ||
|
|
bec7394722 | ||
|
|
42479bd1df | ||
|
|
01f896711e | ||
|
|
ed2117c724 | ||
|
|
bc7511762f | ||
|
|
03cc8a9ce4 | ||
|
|
a4d7c46d80 | ||
|
|
7d912c7d3e | ||
|
|
65b43d5d12 | ||
|
|
36fd8d6b3c | ||
|
|
f28e159ff2 | ||
|
|
633ffbf8b7 | ||
|
|
4359973586 | ||
|
|
0dfeb304cc | ||
|
|
12cc7ea745 | ||
|
|
1ff2b85252 | ||
|
|
76301cef4c | ||
|
|
4471452105 | ||
|
|
d703301fe8 | ||
|
|
85f7ee59f8 | ||
|
|
fe71fd469a | ||
|
|
f05c9833ee | ||
|
|
11e7e267f7 | ||
|
|
0738ba2451 | ||
|
|
12ff94c02f | ||
|
|
da2f6e9d93 | ||
|
|
49b246193b | ||
|
|
1862a991d8 | ||
|
|
89839cb1cf | ||
|
|
07bb8b3023 | ||
|
|
56d55a4585 | ||
|
|
3cd158b983 | ||
|
|
d1ffca3189 | ||
|
|
e21e3b298a | ||
|
|
f47f6b7fb4 | ||
|
|
1e7521c056 | ||
|
|
bb6d522198 | ||
|
|
c0b2f99b04 | ||
|
|
89b3105493 | ||
|
|
37cc06444d | ||
|
|
2d10545e70 | ||
|
|
04b781d613 | ||
|
|
5a252c9166 | ||
|
|
373d4c9848 | ||
|
|
fa84d60586 | ||
|
|
7dc4a336bd | ||
|
|
362d523fa6 | ||
|
|
586b0a39d8 | ||
|
|
6df3488654 | ||
|
|
10e4d8fbac | ||
|
|
81c44b5eee | ||
|
|
aa9eef28c4 | ||
|
|
0a2c6fccc3 | ||
|
|
88a95c7f03 | ||
|
|
90c1873134 | ||
|
|
d1d9dd8e20 | ||
|
|
39dc77d825 | ||
|
|
24d349f491 | ||
|
|
0eff642d2f | ||
|
|
b7c1f1e13d | ||
|
|
c27123cf61 | ||
|
|
0edfeb19f1 | ||
|
|
f069c256a6 | ||
|
|
670d08b406 | ||
|
|
0c29321407 | ||
|
|
b4643cb5be | ||
|
|
3c886ccff8 | ||
|
|
eddc3b0381 | ||
|
|
83cc90be5d | ||
|
|
ba92a5e865 | ||
|
|
8a12f6dc2c | ||
|
|
9fad8a8c92 | ||
|
|
57eab17262 | ||
|
|
fc5f9cc46d | ||
|
|
38e631d174 | ||
|
|
3283135f16 | ||
|
|
bd491b4479 | ||
|
|
6dbfe52c35 | ||
|
|
9da23371d5 | ||
|
|
29c5deb4f1 | ||
|
|
9bc45ae15f | ||
|
|
08abc0eb77 | ||
|
|
fea3a76c38 | ||
|
|
3a7f03bae6 | ||
|
|
652081426b | ||
|
|
406d2d8b0a | ||
|
|
7a1df1c323 | ||
|
|
5a44d14d97 | ||
|
|
b444d1ecd7 | ||
|
|
0456670328 | ||
|
|
eff4da95a1 | ||
|
|
ad7d16a1b4 | ||
|
|
f5abfde1fa | ||
|
|
02d13d7257 | ||
|
|
941b82a8be | ||
|
|
482fcd0602 | ||
|
|
14c7148edd | ||
|
|
a00722e80c | ||
|
|
42f4dcef88 | ||
|
|
37188482fe | ||
|
|
eb3228233a | ||
|
|
8dec7eac05 | ||
|
|
e9c2aaccb5 | ||
|
|
112c0ff08b | ||
|
|
e431cbdfa7 | ||
|
|
6514d1bc2e | ||
|
|
53d3ca0062 | ||
|
|
3062a9ba91 | ||
|
|
dcc2b252dd | ||
|
|
66b3aa9582 | ||
|
|
32a141d548 | ||
|
|
69e7d64c49 | ||
|
|
7d5025a865 | ||
|
|
c65cd4eb74 | ||
|
|
8ff3b0cd63 | ||
|
|
cc2d29dbf4 | ||
|
|
6ed739d9ca | ||
|
|
5d07b0730c | ||
|
|
fe05e47656 | ||
|
|
8399bd8309 | ||
|
|
a730d56e66 | ||
|
|
6599ae1f2f | ||
|
|
0b5426da12 | ||
|
|
be9c3cd979 | ||
|
|
02106c3292 | ||
|
|
e078650435 | ||
|
|
7d6b4d9936 | ||
|
|
ab087f7342 | ||
|
|
962735cf7a | ||
|
|
4ce7766e14 | ||
|
|
cdc70991f7 | ||
|
|
a1fe799afd | ||
|
|
157f72f611 | ||
|
|
c97080cee7 | ||
|
|
5b623d2314 | ||
|
|
26f87c284b | ||
|
|
8cddcb76b2 | ||
|
|
6199fed6bb | ||
|
|
96da06430b | ||
|
|
752c9a5279 | ||
|
|
46ee71edcd | ||
|
|
bcfb7731ab | ||
|
|
57d0f19bda | ||
|
|
4cf663a661 | ||
|
|
0b9893c640 | ||
|
|
ba4c028f5f | ||
|
|
52f5cb8ced | ||
|
|
f3ec1e2254 | ||
|
|
d5729bdf01 | ||
|
|
3c54d8a239 | ||
|
|
f647333f49 | ||
|
|
fcddbf5c03 | ||
|
|
1bce69cfde | ||
|
|
32d4f243e6 | ||
|
|
8e6b8cd6e6 | ||
|
|
6a6c4d0887 | ||
|
|
737ecd9d42 | ||
|
|
191d8a0716 | ||
|
|
cfcc908cae | ||
|
|
cf2e099087 | ||
|
|
d6cc88cabb | ||
|
|
42692418c2 | ||
|
|
a985c12659 | ||
|
|
5ebf128023 | ||
|
|
911b16bab8 | ||
|
|
693f61c47f | ||
|
|
3a8c866393 | ||
|
|
0851c2cfb0 | ||
|
|
958eaf4b24 | ||
|
|
07f9248448 | ||
|
|
c2371f95c6 | ||
|
|
379322f0b8 | ||
|
|
b30b17d1eb | ||
|
|
ef3beeb390 | ||
|
|
48e0b20e62 | ||
|
|
018680046c | ||
|
|
aebe14a6e9 | ||
|
|
c4b7bf8635 | ||
|
|
3973f6a57c | ||
|
|
5906ca25f7 | ||
|
|
2ce8573f04 | ||
|
|
f6706ce124 | ||
|
|
31ebf3dc2c | ||
|
|
cb183de1da | ||
|
|
c867f2e8a0 | ||
|
|
c9ff83bfa3 | ||
|
|
05c997da1f | ||
|
|
f677bdc12f | ||
|
|
2178461c89 | ||
|
|
d438151f25 | ||
|
|
7d475266b6 | ||
|
|
367cb7a761 | ||
|
|
4604f00218 | ||
|
|
8eff9151ac | ||
|
|
50797c7948 | ||
|
|
c34a3e2c5b | ||
|
|
35211cdc8f | ||
|
|
4a8a1f2dde | ||
|
|
f2ab443cca | ||
|
|
abc15094c6 | ||
|
|
f390695767 | ||
|
|
f092bcdfdb | ||
|
|
1633f030e8 | ||
|
|
4451df15b4 | ||
|
|
f50062517e | ||
|
|
967e3de552 | ||
|
|
d95472e757 | ||
|
|
3e0e5bac2a | ||
|
|
08cb76bbfd | ||
|
|
281dd51f5a | ||
|
|
1c7c815108 | ||
|
|
d177af8842 | ||
|
|
544129d240 | ||
|
|
9f79678723 | ||
|
|
a491b938ba | ||
|
|
588c8cf5b3 | ||
|
|
876ca59234 | ||
|
|
f5910d83c4 | ||
|
|
e43a22abcf | ||
|
|
2a7aa8992b | ||
|
|
e36597e2c6 | ||
|
|
6403de2109 | ||
|
|
9b49e47b13 | ||
|
|
8540be5b82 | ||
|
|
ae6d6261a1 | ||
|
|
ce4fcd2009 | ||
|
|
76620881f4 | ||
|
|
f99efd6166 | ||
|
|
74e94e7bdd | ||
|
|
72cd628357 | ||
|
|
45367e4a34 | ||
|
|
7d76831250 | ||
|
|
d2ff3fc2ee | ||
|
|
537b8454a4 | ||
|
|
a7c71b90b1 | ||
|
|
e0be3deb3a | ||
|
|
5490476d84 | ||
|
|
90865eb887 | ||
|
|
157f71d78e | ||
|
|
176fee54e4 | ||
|
|
61f4363ed7 | ||
|
|
86cc67e081 | ||
|
|
dcc9888350 | ||
|
|
6af6a424b4 | ||
|
|
e1ceb63023 | ||
|
|
4eb7193a27 | ||
|
|
e6ff3b37a4 | ||
|
|
c3e095969f | ||
|
|
2e345a1059 | ||
|
|
e759ebe0bd | ||
|
|
533b874590 | ||
|
|
780ebb4680 | ||
|
|
02a579af59 | ||
|
|
9bcf1c4b8d | ||
|
|
dec9b4f7c7 | ||
|
|
4701842829 | ||
|
|
488b4bdbe8 | ||
|
|
c8d886b422 | ||
|
|
a83bbd2e92 | ||
|
|
c3a47cb72f | ||
|
|
0971e55d4d | ||
|
|
6f45c7a8ac | ||
|
|
c567d852a5 | ||
|
|
0b38128e21 | ||
|
|
b9daa8b2ee | ||
|
|
878c7173c3 | ||
|
|
f69b980dcf | ||
|
|
33378792ca | ||
|
|
c7a2b4d5e3 | ||
|
|
4a077fc2c9 | ||
|
|
f309ec21d7 | ||
|
|
e261cf7481 | ||
|
|
fa8390b23e | ||
|
|
af89858d47 | ||
|
|
e6a3569743 | ||
|
|
604abec333 | ||
|
|
790666ffb0 | ||
|
|
c9f6ccff9f | ||
|
|
02b3f42500 | ||
|
|
e10724accb | ||
|
|
5b68dec43a | ||
|
|
9d13da0050 | ||
|
|
1e94425279 | ||
|
|
fc48f9bc08 | ||
|
|
2eb25910a1 | ||
|
|
1dab341b33 | ||
|
|
1f7ed87e6c | ||
|
|
c59ea422cc | ||
|
|
0bcb71f742 | ||
|
|
7e38a3386e | ||
|
|
c25b5ef215 | ||
|
|
72fb507de2 | ||
|
|
45c4c95b98 | ||
|
|
e8861d1043 | ||
|
|
c48fcb743b | ||
|
|
d5d732ddf4 | ||
|
|
f83bd5cdf6 | ||
|
|
76c87c628f | ||
|
|
fa125a354d | ||
|
|
f184b54796 | ||
|
|
75925fb2f7 | ||
|
|
b780228ade | ||
|
|
91c012eff0 | ||
|
|
05d45c6948 | ||
|
|
a2c13fbc48 | ||
|
|
16c7aab99b | ||
|
|
0cf5e309a0 | ||
|
|
b5fbd682f2 | ||
|
|
90e04b0046 | ||
|
|
329f6562c2 | ||
|
|
852bad1ef4 | ||
|
|
aa44a61ab2 | ||
|
|
3e237cb490 | ||
|
|
7b206fb13d | ||
|
|
8f7e898341 | ||
|
|
7499d9f245 | ||
|
|
ba6e6f051a | ||
|
|
d4f4dfb54f | ||
|
|
3e7dedaf99 | ||
|
|
f18cd7ae81 | ||
|
|
0ae4fcf8eb | ||
|
|
d3d1e30c7c | ||
|
|
47d0cf495d | ||
|
|
2e883f9d91 | ||
|
|
af0c30e3ea | ||
|
|
da5a35356a | ||
|
|
d98cc3bb6c | ||
|
|
9697f17b9d | ||
|
|
ce3a9d172d | ||
|
|
4448ddc488 | ||
|
|
b77d3c66ae | ||
|
|
2debdfead5 | ||
|
|
b168c65fa1 | ||
|
|
2b46d171db | ||
|
|
64c131d132 | ||
|
|
678a251858 | ||
|
|
bf9d2f6cb0 | ||
|
|
61f5dcb11e | ||
|
|
e4387d2bd1 | ||
|
|
48906f354e | ||
|
|
1ddc098e43 | ||
|
|
165e6c234c | ||
|
|
1be631f43f | ||
|
|
f5f34c2f50 | ||
|
|
33f3619e98 | ||
|
|
3720b66d00 | ||
|
|
864bbc5472 | ||
|
|
080566a1fd | ||
|
|
d9766037a3 | ||
|
|
02821adc47 | ||
|
|
7b08fd4b7d | ||
|
|
0505c70be2 | ||
|
|
f247038e65 | ||
|
|
d7667e9e6e | ||
|
|
188cb114af | ||
|
|
35c49ababf | ||
|
|
faafe09bd0 | ||
|
|
a0e87c9420 | ||
|
|
d9d39f1812 | ||
|
|
82af225742 | ||
|
|
919f4df1a7 | ||
|
|
71a1698bf2 | ||
|
|
a987dd95b8 | ||
|
|
ab6ab8e65c | ||
|
|
3b28d66410 | ||
|
|
eee46ef2f4 | ||
|
|
3c189b4183 | ||
|
|
fd5ab0edf7 | ||
|
|
420387a7a5 | ||
|
|
fc740f8b6d | ||
|
|
834059ddfa | ||
|
|
5ec2fbcd38 | ||
|
|
2fbf5cd79f | ||
|
|
64ebe95751 | ||
|
|
77109b3a33 | ||
|
|
b43429e684 | ||
|
|
97e39f0744 | ||
|
|
fad592b512 | ||
|
|
565de3c536 | ||
|
|
c802269ea3 | ||
|
|
06268963fb | ||
|
|
2227797691 | ||
|
|
f0888c1fe0 | ||
|
|
eda2e62589 | ||
|
|
494d8ec04c | ||
|
|
bb8088ca0f | ||
|
|
26f4bc39fc | ||
|
|
025e4d9fc6 | ||
|
|
b2774d57ba | ||
|
|
51edfb4ec9 | ||
|
|
79019b1ced | ||
|
|
bc87140b5b | ||
|
|
1c5251069b | ||
|
|
0b6dfefcec | ||
|
|
a9e32c55c0 | ||
|
|
a494228407 | ||
|
|
9932b5fc5c | ||
|
|
966ba44a33 | ||
|
|
62c872eb49 | ||
|
|
434fee2e13 | ||
|
|
d3f829c065 | ||
|
|
83934bdcf3 | ||
|
|
3691add163 | ||
|
|
cc7a9e4607 | ||
|
|
943fa69da6 | ||
|
|
3bef291184 | ||
|
|
7316c53b04 | ||
|
|
5e1d1e1850 | ||
|
|
e52c8e148c | ||
|
|
7eb47f3db1 | ||
|
|
ec59d31d04 | ||
|
|
ddd15b63b2 | ||
|
|
e91b35a53d | ||
|
|
fb4079aa4d | ||
|
|
48b203a134 | ||
|
|
2746fd708f | ||
|
|
684f43d84d | ||
|
|
6b1be52e6b | ||
|
|
de6258d366 | ||
|
|
5e4dbf33be | ||
|
|
b03cb3f3d8 | ||
|
|
e08401a2ec | ||
|
|
0a9e7028ae | ||
|
|
ba0ecc54df | ||
|
|
6920f9dc27 | ||
|
|
ba2547212e | ||
|
|
bbe1a8a5b6 | ||
|
|
c82728f04d | ||
|
|
cc0d33bca7 | ||
|
|
3933ec7dce | ||
|
|
f8c9507612 | ||
|
|
7c5c9ae8fd | ||
|
|
cd00792fe9 | ||
|
|
df390509b2 | ||
|
|
dd6abe9375 | ||
|
|
a3f199d0a3 | ||
|
|
8e3b85ee12 | ||
|
|
e60fbfc865 | ||
|
|
a512488fd7 | ||
|
|
1981d909cf | ||
|
|
ea14f2c98c | ||
|
|
c81becf10d | ||
|
|
1433d040ae | ||
|
|
206b70c837 | ||
|
|
bb857dcef2 | ||
|
|
5568a780a9 | ||
|
|
7c2086967b | ||
|
|
f7fbf4d38c | ||
|
|
0c8cf5c1e0 | ||
|
|
33f2af1c09 | ||
|
|
c9a7e6e4ec | ||
|
|
86bb4ea8f2 | ||
|
|
99c4e83994 | ||
|
|
ca2f5a8160 | ||
|
|
7af304251e | ||
|
|
15f5126296 | ||
|
|
21edd66892 | ||
|
|
3e9d6b6960 | ||
|
|
62b580904b | ||
|
|
c4c4f9d159 | ||
|
|
67a5ec1567 | ||
|
|
c646832bfe | ||
|
|
539d4756f2 | ||
|
|
8714e115ad | ||
|
|
9c38e09ad3 | ||
|
|
5628d7d8b5 | ||
|
|
5f2e8d6062 | ||
|
|
630e336ea0 | ||
|
|
430852736d | ||
|
|
4eeb741358 | ||
|
|
bb1ce4a069 | ||
|
|
5e3e4a225e | ||
|
|
583d05e32a | ||
|
|
2c0914b2ba | ||
|
|
3ebedfe7b0 | ||
|
|
1af2f85d43 | ||
|
|
0395e8935a | ||
|
|
7ffd182197 | ||
|
|
fae1abdea9 | ||
|
|
f17b8ad550 | ||
|
|
883b600617 | ||
|
|
f26a9abddb | ||
|
|
4a7180a4f2 | ||
|
|
af0c5c3ccb | ||
|
|
a6e8db99b3 | ||
|
|
e4684752c2 | ||
|
|
4d6269a42d | ||
|
|
593f5ee569 | ||
|
|
4862e22cd0 | ||
|
|
d13a6f7487 | ||
|
|
09066b1ba6 | ||
|
|
8f8f0b3258 | ||
|
|
d9283970a5 | ||
|
|
994afad279 | ||
|
|
b72ea28540 | ||
|
|
fc69c6fac4 | ||
|
|
4100fd2817 | ||
|
|
686744e48e | ||
|
|
0f49221f57 | ||
|
|
725720dfc3 | ||
|
|
96cdb8edb7 | ||
|
|
7aa197be7d | ||
|
|
ea1dbfe961 | ||
|
|
4c73da31ba | ||
|
|
5febae8ad0 | ||
|
|
d06f01a7d7 | ||
|
|
54d757a4c7 | ||
|
|
a23e1cf729 | ||
|
|
91879960e6 | ||
|
|
270e6959b8 | ||
|
|
cbb3ca01f4 | ||
|
|
9845d6fd40 | ||
|
|
e5a59d6925 | ||
|
|
574170488c | ||
|
|
9ea99efe13 | ||
|
|
b3af88708d | ||
|
|
b96ce0b764 | ||
|
|
97ea39404a | ||
|
|
4054f26c4d | ||
|
|
7380731bf7 | ||
|
|
3bea349f9e | ||
|
|
98e0c8d609 | ||
|
|
71f7385fcb | ||
|
|
fbedf0ba6b | ||
|
|
cf710eab13 | ||
|
|
b216a6a30e | ||
|
|
b79086b3e9 | ||
|
|
b551bdb0ce | ||
|
|
0886bc7afd | ||
|
|
e7027e3d40 | ||
|
|
243690b5ab | ||
|
|
5b5f76002e | ||
|
|
fc03f1a1e6 | ||
|
|
1d59ae9aa9 | ||
|
|
8fde1b9f2c | ||
|
|
5e03f8c725 | ||
|
|
d6d4a50f7c | ||
|
|
fe4e1de566 | ||
|
|
e0d34b8f47 | ||
|
|
17c9d35449 | ||
|
|
0e994265c6 | ||
|
|
e16319a290 | ||
|
|
c033643f07 | ||
|
|
607e2248c8 | ||
|
|
a1111c7aa0 | ||
|
|
1b82e70fc1 | ||
|
|
35068c2e6e | ||
|
|
212703edf8 | ||
|
|
7460d1a446 | ||
|
|
c851205f83 | ||
|
|
dd0e073159 | ||
|
|
193b477086 | ||
|
|
3f85da0098 | ||
|
|
dad28f3dfe | ||
|
|
e8e1da3fb5 | ||
|
|
4a24311161 | ||
|
|
4f8c6b7773 | ||
|
|
26fc2c24bd | ||
|
|
330f9daade | ||
|
|
4a232bc868 | ||
|
|
61dff96474 | ||
|
|
bda28bbf38 | ||
|
|
66bedfd8e4 | ||
|
|
c18f968d84 | ||
|
|
5dfbc57117 | ||
|
|
e3fb6771d6 | ||
|
|
f4da3c7f1b | ||
|
|
81dbc9c070 | ||
|
|
431bc87f85 | ||
|
|
b0e224a9f8 | ||
|
|
e3e6e75d40 | ||
|
|
ed856f2ab8 | ||
|
|
6425e1c52f | ||
|
|
c842087cc1 | ||
|
|
2651b381bb | ||
|
|
4143d9871e | ||
|
|
fb9e467147 | ||
|
|
8b959158e3 | ||
|
|
ecb898c7ff | ||
|
|
c2b2b1ab5c | ||
|
|
d4682b3b38 | ||
|
|
2f4a50064f | ||
|
|
6851535fe7 | ||
|
|
292a5f50b2 | ||
|
|
c25ce7c585 | ||
|
|
b22c9a86a9 | ||
|
|
767bb952a5 | ||
|
|
32e7178bbb | ||
|
|
614f671b92 | ||
|
|
af62dbf3d3 | ||
|
|
249e6af3a6 | ||
|
|
59bed375d0 | ||
|
|
aba95b00aa | ||
|
|
011ee5b180 | ||
|
|
4e19719bdd | ||
|
|
fa469aaf41 | ||
|
|
3cabf608ca | ||
|
|
2e841622f8 | ||
|
|
9b5e3797b1 | ||
|
|
07df177332 | ||
|
|
ff364347cf | ||
|
|
4c74ff5e5a | ||
|
|
2ebd19c9bc | ||
|
|
875ffa49b3 | ||
|
|
ff0030d74f | ||
|
|
7a71feed8c | ||
|
|
70c4ce199d | ||
|
|
ed0f8ccbaf | ||
|
|
3e5ca2e168 | ||
|
|
d0dc59e792 | ||
|
|
0106c64369 | ||
|
|
69fdb41934 | ||
|
|
550b3ee1d3 | ||
|
|
961cc6a6d3 | ||
|
|
05091ab656 | ||
|
|
272505b99d | ||
|
|
60a769955b | ||
|
|
34bec53474 | ||
|
|
c77ae65a0d | ||
|
|
1ed0430b82 | ||
|
|
82f640e360 | ||
|
|
44aabc3ae4 | ||
|
|
bbdf9b2745 | ||
|
|
96a87170f7 | ||
|
|
281323db42 | ||
|
|
32258ee8ae | ||
|
|
df0faef9ca | ||
|
|
9c3a020ecf | ||
|
|
4c4cc55bb7 | ||
|
|
f4c2e7e629 | ||
|
|
eadef08fd5 | ||
|
|
0c725a257d | ||
|
|
6f35fb5f80 | ||
|
|
cd1fe75987 | ||
|
|
e92e320956 | ||
|
|
0e4757e0fb | ||
|
|
bd6af68bc5 | ||
|
|
13050f73c1 | ||
|
|
5472fb0c56 | ||
|
|
73c2424b24 | ||
|
|
5117eda688 | ||
|
|
cfbef51d3d | ||
|
|
09cb2d76ef | ||
|
|
3f549ad0df | ||
|
|
60d26be325 | ||
|
|
013d0d3753 | ||
|
|
97da67c6a8 | ||
|
|
f74072ba28 | ||
|
|
19eac239b7 | ||
|
|
31cd41bfe4 | ||
|
|
af6c321395 | ||
|
|
448fca1fdf | ||
|
|
1923928fdc | ||
|
|
bee5574656 | ||
|
|
8c8a68d850 | ||
|
|
9159b5b120 | ||
|
|
2d0079905e | ||
|
|
83c227d53c | ||
|
|
ee57b865b0 | ||
|
|
ecbb9cfa90 | ||
|
|
8545e8496b | ||
|
|
75b2610e85 | ||
|
|
237021ec15 | ||
|
|
4f5c25d0dd | ||
|
|
4c33ab1997 | ||
|
|
5bb65aca8f | ||
|
|
3fd7babacc | ||
|
|
caea8a9588 | ||
|
|
e1d6cba014 | ||
|
|
1f91fe7a2c | ||
|
|
dc53261c3b | ||
|
|
b3e90a93b0 | ||
|
|
1f3e2b770c | ||
|
|
d310e896cb | ||
|
|
a36245cef6 | ||
|
|
092ef90f29 | ||
|
|
64f59ff71e | ||
|
|
a7f80a2770 | ||
|
|
a5c5e3e876 | ||
|
|
8e4fb993c0 | ||
|
|
846567275a | ||
|
|
741c972935 | ||
|
|
6c2760c9cd | ||
|
|
b35a5ee4a3 | ||
|
|
345385376a | ||
|
|
dbe9db26fc | ||
|
|
91ba22b157 | ||
|
|
86b2736480 | ||
|
|
cfe2fb66ab | ||
|
|
428e61253c | ||
|
|
95bcd0c9d5 | ||
|
|
23bada3c5a | ||
|
|
de0cf8433b | ||
|
|
1b49ea4061 | ||
|
|
29b94d6ba3 | ||
|
|
80a435f00b | ||
|
|
fdcd5806b1 | ||
|
|
9ddcfce915 | ||
|
|
6ba358533b | ||
|
|
73aa329d57 | ||
|
|
379016fd78 | ||
|
|
ea4b586c77 | ||
|
|
6961f2caae | ||
|
|
4df2ce4409 | ||
|
|
052a4f432c | ||
|
|
de86ff051e | ||
|
|
f5feeab48d | ||
|
|
1317af028e | ||
|
|
cdcd4ddd35 | ||
|
|
2960164cf8 | ||
|
|
a98ef9787c | ||
|
|
b6d406fbc8 | ||
|
|
e3488292ba | ||
|
|
fea2e0be4f | ||
|
|
751f5dfda3 | ||
|
|
d5f71e66f9 | ||
|
|
03e810ec72 | ||
|
|
6c6f4bcd45 | ||
|
|
304942302b | ||
|
|
8dc1a74df8 | ||
|
|
e295d01505 | ||
|
|
aa1b29ea0e | ||
|
|
cef857fbbd | ||
|
|
6bba8ce0dc | ||
|
|
b0330d62e5 | ||
|
|
fc0c857cfe | ||
|
|
238b18b8ac | ||
|
|
6a2d023b7b | ||
|
|
4bb1fff15d | ||
|
|
37f5bda227 | ||
|
|
56b571fcaa | ||
|
|
46bf3c9e9c | ||
|
|
361fb22954 | ||
|
|
203fe0f4bf | ||
|
|
36ac5fe735 | ||
|
|
7569519530 | ||
|
|
a848179286 | ||
|
|
456ab38caa | ||
|
|
c71b5c0426 | ||
|
|
868cc52415 | ||
|
|
8c168cc337 | ||
|
|
f9fa4cc099 | ||
|
|
a0540cafb3 | ||
|
|
88b3924132 | ||
|
|
3023f26911 | ||
|
|
c9347d3d7d | ||
|
|
d85c7d06af | ||
|
|
e229f79741 | ||
|
|
a4d236eebe | ||
|
|
1192fd27c6 | ||
|
|
cd1cb40033 | ||
|
|
14e085f70e | ||
|
|
fc37d81144 | ||
|
|
a859455aad | ||
|
|
93d596ace2 | ||
|
|
c03e3fe88a | ||
|
|
a90a5c9244 | ||
|
|
26772f8184 | ||
|
|
8f8ad83861 | ||
|
|
d111b42cf1 | ||
|
|
821c965b45 | ||
|
|
4acac9a294 | ||
|
|
4adb06ae91 | ||
|
|
dce7a1e2aa | ||
|
|
a354b72546 | ||
|
|
ac8f41404b | ||
|
|
fc7b257bab | ||
|
|
787066c292 | ||
|
|
71ab6cb818 | ||
|
|
1158ba453e | ||
|
|
2e3f764272 | ||
|
|
2172f1d2cd | ||
|
|
6efc1eae9f | ||
|
|
6a740033de | ||
|
|
d754598143 | ||
|
|
47f632263e | ||
|
|
98af0b0c77 | ||
|
|
b9c6a62437 | ||
|
|
57670eeeb7 | ||
|
|
f26ee11913 | ||
|
|
2435d76a39 | ||
|
|
348d460ab7 | ||
|
|
2b8b43b3db | ||
|
|
91b74b6896 | ||
|
|
319fd19b5e | ||
|
|
4edd796509 | ||
|
|
b0ced1bd2c | ||
|
|
6ed3a7774f | ||
|
|
1ce3feb893 | ||
|
|
ebbc5eceb8 | ||
|
|
0cac4a4e0c | ||
|
|
1908403324 | ||
|
|
faa07b71f9 | ||
|
|
e9dcf6b8dd | ||
|
|
3ea60ea0ae | ||
|
|
54171dfdd3 | ||
|
|
dc8db34155 | ||
|
|
a68f3939cf | ||
|
|
ae90497762 | ||
|
|
2b55f6420a | ||
|
|
6d3545624d | ||
|
|
46dc5beee9 | ||
|
|
943cc16020 | ||
|
|
a6f5ce8c7b | ||
|
|
bc3d0feb5c | ||
|
|
580f0f1a28 | ||
|
|
715b0c9b6c | ||
|
|
388afa07f4 | ||
|
|
1def60cd2c | ||
|
|
cdb4816fbb | ||
|
|
be46588cf0 | ||
|
|
6dc2f7231b | ||
|
|
3165b77ec9 | ||
|
|
ad0e2b86dc | ||
|
|
5ee0b01118 | ||
|
|
fbfd0c7353 | ||
|
|
ee8970c11e | ||
|
|
82a1f33260 | ||
|
|
9607b322d2 | ||
|
|
238c74643b | ||
|
|
712c1783b6 | ||
|
|
081fb6ec78 | ||
|
|
c04d332b7f | ||
|
|
32786acf19 | ||
|
|
51dd2762a9 | ||
|
|
cf31bdb65c | ||
|
|
50cae84100 | ||
|
|
98feca280f | ||
|
|
304c4e3d3b | ||
|
|
c5b55049b9 | ||
|
|
c494eb94f4 | ||
|
|
5f173e9357 | ||
|
|
307a7ad077 | ||
|
|
0039834bb9 | ||
|
|
d064c625f4 | ||
|
|
77a62b8594 | ||
|
|
d4339661df | ||
|
|
39a014f601 | ||
|
|
1e22160e74 | ||
|
|
267bf01259 | ||
|
|
e23fa65ef2 | ||
|
|
ee7ff024c1 | ||
|
|
e8a92b67c3 | ||
|
|
3ce7489531 | ||
|
|
ffbb35fa01 | ||
|
|
de0b69691d | ||
|
|
82aae20e9c | ||
|
|
7362b14d41 | ||
|
|
77d7babf92 | ||
|
|
545b347ca5 | ||
|
|
df2111eb4f | ||
|
|
c7d3b7438c | ||
|
|
5c0ad86f19 | ||
|
|
675cf7ef59 | ||
|
|
d74e7fc084 | ||
|
|
2cd85ddf11 | ||
|
|
3c1dc9cfaa | ||
|
|
8b2553b3f4 | ||
|
|
b9373700a2 | ||
|
|
bdce4b84d8 | ||
|
|
2dd4609699 | ||
|
|
5c67ca015b | ||
|
|
957b329e94 | ||
|
|
120ebea917 | ||
|
|
6e1e11f6cd | ||
|
|
dbc056f9ac | ||
|
|
7de815e957 | ||
|
|
1894d6e6ff | ||
|
|
1cc722d0cc | ||
|
|
ec07927b55 | ||
|
|
41c7e4fe87 | ||
|
|
217cd0f5e9 | ||
|
|
fd02dca60e | ||
|
|
2a1d58ed22 | ||
|
|
7d8003da46 | ||
|
|
03edcd2bfd | ||
|
|
a9d3f48372 | ||
|
|
316ec5b398 | ||
|
|
d06defd885 | ||
|
|
0fed68dd16 | ||
|
|
ce60fe04cb | ||
|
|
4e1c62d7f1 | ||
|
|
3ea8e01a9d | ||
|
|
9cbd36163c | ||
|
|
0f5c3e107e | ||
|
|
1ae251ea5b | ||
|
|
90742541c6 | ||
|
|
84d8dfd46c | ||
|
|
3ed404e5bb | ||
|
|
4b64ffc365 | ||
|
|
e297cc4c2a | ||
|
|
9ab63c58f2 | ||
|
|
3c0aceb9f7 | ||
|
|
d7bd3d2d69 | ||
|
|
3136226134 | ||
|
|
5a7535c513 | ||
|
|
991ab5de64 | ||
|
|
b17e4fa3bf | ||
|
|
35fa5b7dfc | ||
|
|
7812214db6 | ||
|
|
a5a8467993 | ||
|
|
544ea7ccfc | ||
|
|
024b5310fa | ||
|
|
177cb8bbe1 | ||
|
|
35f137df35 | ||
|
|
c71ee7a3e6 | ||
|
|
9a2dbb26a5 | ||
|
|
3d2fd06035 | ||
|
|
2f6d0c006c | ||
|
|
43088ee8ba | ||
|
|
c17b6e7be3 | ||
|
|
71299633d5 | ||
|
|
dfe61cbe9c | ||
|
|
18c9210342 | ||
|
|
1167e6b86f | ||
|
|
1684fa8c63 | ||
|
|
b4dce61918 | ||
|
|
d7ddcc0768 | ||
|
|
36c26b6903 | ||
|
|
2300c692b8 | ||
|
|
da6dbbd433 | ||
|
|
0a4bd8cb7d | ||
|
|
32d357e1a8 | ||
|
|
21e259d1a4 | ||
|
|
c3a54aa59a | ||
|
|
7713df9e41 | ||
|
|
49900b79a9 | ||
|
|
4f075a1aef | ||
|
|
d4cd902e1c | ||
|
|
ef4484ab27 | ||
|
|
9e7f9f3471 | ||
|
|
493e8580d6 | ||
|
|
bce567db46 | ||
|
|
38e2c8cb8a | ||
|
|
16309544ac | ||
|
|
517b5da67a | ||
|
|
98460af44f | ||
|
|
7213d5a76b | ||
|
|
bb29c5b322 | ||
|
|
58ad7bae48 | ||
|
|
82a3480b12 | ||
|
|
c00811a846 | ||
|
|
27eaf46c8a | ||
|
|
202aeece3c | ||
|
|
825fc895dc | ||
|
|
a74aecedf1 | ||
|
|
fa1f63bcd0 | ||
|
|
c2bce3e93e | ||
|
|
a46733e701 | ||
|
|
8f350f9b9f | ||
|
|
484692aacd | ||
|
|
7f0df99511 | ||
|
|
bebd2fe7e7 | ||
|
|
36e8839675 | ||
|
|
61305a50c1 | ||
|
|
1d7749a40f | ||
|
|
f01d044618 | ||
|
|
31532adf86 | ||
|
|
879e06db39 | ||
|
|
4beb0f702a | ||
|
|
a771460dbd | ||
|
|
f849f83d84 | ||
|
|
1d084a41ad | ||
|
|
c4198986f1 | ||
|
|
7514786b20 | ||
|
|
9df042c0b8 | ||
|
|
37e0150f70 | ||
|
|
294e4cbcb7 | ||
|
|
952716afe1 | ||
|
|
24aba9a514 | ||
|
|
905993751c | ||
|
|
0b10d877b0 | ||
|
|
874fa5810d | ||
|
|
5be31bbce6 | ||
|
|
a6e3a31690 | ||
|
|
506f3f7b57 | ||
|
|
cd1c36ef94 | ||
|
|
ee689d88b4 | ||
|
|
b93b676336 | ||
|
|
1c6d66fccc | ||
|
|
114356ad2e | ||
|
|
7ab419701c | ||
|
|
d41b1a7560 | ||
|
|
622943529e | ||
|
|
9d7cc152f9 | ||
|
|
3f73d448f3 | ||
|
|
a1b606803f | ||
|
|
b2c7b40568 | ||
|
|
0cbe09d43a | ||
|
|
f1d5b94762 | ||
|
|
6fc2e7c774 | ||
|
|
3b39c1d1ef | ||
|
|
5a3e4abf71 | ||
|
|
48e9362186 | ||
|
|
03a74b74e5 | ||
|
|
248f99cad3 | ||
|
|
d2f0773eb8 | ||
|
|
dd36d56d47 | ||
|
|
0270fc66a1 | ||
|
|
69a844c654 | ||
|
|
5b5a64361f | ||
|
|
26f6d1cb10 | ||
|
|
f87eb1668a | ||
|
|
3114abfd55 | ||
|
|
5a94cff91e | ||
|
|
d704e87ee4 | ||
|
|
c8ce996872 | ||
|
|
0e7b068061 | ||
|
|
71dd149ca2 | ||
|
|
b30ba41d6a | ||
|
|
a0bf790892 | ||
|
|
caefc4eb8e | ||
|
|
31364c17d6 | ||
|
|
5e56966e72 | ||
|
|
1f951ed7ec | ||
|
|
ecd82f1fc9 | ||
|
|
7aaf1eeb1b | ||
|
|
e53fe70668 | ||
|
|
9e2e0a4a2d | ||
|
|
b52719fd73 | ||
|
|
7953976d25 | ||
|
|
39d6b94835 | ||
|
|
4fdce0695d | ||
|
|
ae8247fe6a | ||
|
|
d664565174 | ||
|
|
b24a46ad8f | ||
|
|
6bffe34faa | ||
|
|
abe3fb4acb | ||
|
|
39905bd8fd | ||
|
|
078dbfb0a9 | ||
|
|
dfeb5cfdd2 | ||
|
|
c1777cfb89 | ||
|
|
974072bdae | ||
|
|
b95e18956f | ||
|
|
3c1c5ef281 | ||
|
|
7194b14cd2 | ||
|
|
4e6f8d561c | ||
|
|
ac26921569 | ||
|
|
a60543728b | ||
|
|
f35ec9771e | ||
|
|
de4fe99e34 | ||
|
|
8ea6b3eebd | ||
|
|
a01836fe8d | ||
|
|
268dc97857 | ||
|
|
fc203c9654 | ||
|
|
8eedd5b277 | ||
|
|
561d9ac2bc | ||
|
|
1112da76f1 | ||
|
|
081aa18f39 | ||
|
|
c05c8bbba1 | ||
|
|
eabd23f31e | ||
|
|
cc27088df9 | ||
|
|
97ab7e9c65 | ||
|
|
bbf92828f6 | ||
|
|
2f83bf9f83 | ||
|
|
b2a1728201 | ||
|
|
18cbbbe9aa | ||
|
|
d90f8a3697 | ||
|
|
fe3ef6fc2e | ||
|
|
1b9148f12f | ||
|
|
deb8e49483 | ||
|
|
d75af2a156 | ||
|
|
9895edefff | ||
|
|
b60e856087 | ||
|
|
6244b4d00f | ||
|
|
ee167b1a43 | ||
|
|
e8b9bfe44c | ||
|
|
50f5593ffc | ||
|
|
3f0f7acbc0 | ||
|
|
7f6f8ec386 | ||
|
|
24d1798779 | ||
|
|
3e9d603f0b | ||
|
|
71a8fd3106 | ||
|
|
49279a3c19 | ||
|
|
43a1291f7c | ||
|
|
6dc5340f60 | ||
|
|
2a6e33bc73 | ||
|
|
0f6b2cfd3d | ||
|
|
30d109c0e9 | ||
|
|
e8e1f844d9 | ||
|
|
05a89e5566 | ||
|
|
c122889c95 | ||
|
|
9de5dc932b | ||
|
|
289c9ecf5d | ||
|
|
2c1a6e3f94 | ||
|
|
ad092a898d | ||
|
|
56f2548b6e | ||
|
|
25467243a6 | ||
|
|
e07d40fc26 | ||
|
|
09877e4e63 | ||
|
|
d3460b6cf5 | ||
|
|
ba384d15d2 | ||
|
|
2f38ade0e0 | ||
|
|
4d110d4c82 | ||
|
|
1bf5ff3e6e | ||
|
|
cd2a1a169f | ||
|
|
59b5f360af | ||
|
|
e8b6890318 | ||
|
|
d7b9ed05f0 | ||
|
|
dc852a100f | ||
|
|
838d51d296 | ||
|
|
e2845bc032 | ||
|
|
8c021fd784 | ||
|
|
406ec14585 | ||
|
|
c27b42e425 | ||
|
|
2d94d7ab0c | ||
|
|
5fcf430c81 | ||
|
|
cea4b3e363 | ||
|
|
e00d8fb544 | ||
|
|
e654fabe04 | ||
|
|
18592a08be | ||
|
|
1763260578 | ||
|
|
955f10e621 | ||
|
|
2565fedeb7 | ||
|
|
6b8e553ecc | ||
|
|
14f81cb275 | ||
|
|
ddb844226d | ||
|
|
f87ee5112a | ||
|
|
2a1a773777 | ||
|
|
7fede3ee45 | ||
|
|
abcd3511bf | ||
|
|
a387557970 | ||
|
|
daba04d54b | ||
|
|
b00a87d8fa | ||
|
|
aee55b0595 | ||
|
|
e58883c183 | ||
|
|
321e840c1c | ||
|
|
19ac1dd393 | ||
|
|
13796ee4c7 | ||
|
|
10bb78458d | ||
|
|
6997506bb9 | ||
|
|
480c7178a8 | ||
|
|
0279d8f466 | ||
|
|
1a6183d0c4 | ||
|
|
487acbb573 | ||
|
|
f97eba6539 | ||
|
|
cac84abdd9 | ||
|
|
ef045f9f65 | ||
|
|
6002099288 | ||
|
|
181f621a90 | ||
|
|
5a71c6f2eb | ||
|
|
487965dc8a | ||
|
|
874c573bd4 | ||
|
|
f63e1cfbfc | ||
|
|
f049f719f8 | ||
|
|
30754473fc | ||
|
|
7c70e6ce74 | ||
|
|
a702b7ccc5 | ||
|
|
f6be62ac5f | ||
|
|
dddd30bef8 | ||
|
|
a054206d25 | ||
|
|
5b6f06b2ac | ||
|
|
6f83822b6e | ||
|
|
9b635a3e90 | ||
|
|
172af5465d | ||
|
|
22f10dd8d2 | ||
|
|
790fdc0aa6 | ||
|
|
45356f5e12 | ||
|
|
08ee50403d | ||
|
|
aa1551c6e8 | ||
|
|
879403a172 | ||
|
|
6ddf765d8d | ||
|
|
38d83c27b4 | ||
|
|
103fa8fa2c | ||
|
|
53dcee6176 | ||
|
|
0c6129c54e | ||
|
|
1f01754ea6 | ||
|
|
f8a7ab1752 | ||
|
|
09842ce46f | ||
|
|
0b849985b2 | ||
|
|
34b8a48252 | ||
|
|
6f6e1efbc8 | ||
|
|
9a72ec366d | ||
|
|
d97302f351 | ||
|
|
4eb75f3c80 | ||
|
|
e5f72a0d4f | ||
|
|
b11b11f9b0 | ||
|
|
70077db07d | ||
|
|
eed682c529 | ||
|
|
fbf2d64f34 | ||
|
|
48bf08922c | ||
|
|
3616ee50c0 | ||
|
|
255c8e8ff4 | ||
|
|
0891e84bf8 | ||
|
|
a63db4ab24 | ||
|
|
169d45fbdb | ||
|
|
965e0237a3 | ||
|
|
4caef0dec7 | ||
|
|
622763b240 | ||
|
|
35d29b22c0 | ||
|
|
fee1d659cf | ||
|
|
869767a5cf | ||
|
|
23b01621ff | ||
|
|
f21ebaf839 | ||
|
|
f6f00b98a7 | ||
|
|
187170ec51 | ||
|
|
f7ad64a3d3 | ||
|
|
103d75f773 | ||
|
|
ed2968e3e8 | ||
|
|
fef5121cee | ||
|
|
c84983f91e | ||
|
|
86f4f4440a | ||
|
|
af0887fb48 | ||
|
|
610c7858d6 | ||
|
|
8d1fb88a20 | ||
|
|
1e2ad19d68 | ||
|
|
7bee66fe36 | ||
|
|
303fe886b7 | ||
|
|
761a472b45 | ||
|
|
3cf2da877f | ||
|
|
5b7b1596a2 | ||
|
|
dc58985ac6 | ||
|
|
5e0db46f17 | ||
|
|
4e19bc01d5 | ||
|
|
2d2acda404 | ||
|
|
fa8d5d1769 | ||
|
|
fe058e2c27 | ||
|
|
a22a24bc98 | ||
|
|
b7c2465887 | ||
|
|
f34158250a | ||
|
|
87dcc9fe07 | ||
|
|
c56e0eb556 | ||
|
|
ba959970c6 | ||
|
|
c75e31d3da | ||
|
|
bcc2330a18 | ||
|
|
f0f5913efe | ||
|
|
17aefd333a | ||
|
|
b86a652b90 | ||
|
|
5968323642 | ||
|
|
26727882d0 | ||
|
|
106e441a61 | ||
|
|
6d22ba9f87 | ||
|
|
8cd9db272f | ||
|
|
b8691649c5 | ||
|
|
e9a2938c6b | ||
|
|
44fa0bfbc6 | ||
|
|
36c213ed3a | ||
|
|
5f26f8a03d | ||
|
|
471f781022 | ||
|
|
f6cb8e4118 | ||
|
|
515eff269c | ||
|
|
bd370ab789 | ||
|
|
3e10116437 | ||
|
|
05f665ecda | ||
|
|
cd65f6a84d | ||
|
|
6d2979459e | ||
|
|
dee38e9c0b | ||
|
|
b4fc36ea62 | ||
|
|
fb6b4739e4 | ||
|
|
32700cc51b | ||
|
|
1ac353d24e | ||
|
|
d7686201dc | ||
|
|
248733de44 | ||
|
|
e410ba9623 | ||
|
|
8295bde95a | ||
|
|
f3a9e95dd8 | ||
|
|
7378e3be01 | ||
|
|
1968efe9f0 | ||
|
|
2b6808f165 | ||
|
|
92f14d28d1 | ||
|
|
954214e48c | ||
|
|
828e6f2077 | ||
|
|
982b7373ea | ||
|
|
39b5359efd | ||
|
|
627a538bf2 | ||
|
|
e07e3ecc22 | ||
|
|
b426db6086 | ||
|
|
d4b43d8578 | ||
|
|
b9b1680f08 | ||
|
|
3e37975a00 | ||
|
|
b0e252684d | ||
|
|
919e1c3f08 | ||
|
|
16dc58312c | ||
|
|
169bd9db5e | ||
|
|
4e5e8fd8fe | ||
|
|
8728ba08e2 | ||
|
|
3ba07ed27f | ||
|
|
9b4b659804 | ||
|
|
c00a31077c | ||
|
|
e8fc17f816 | ||
|
|
4a2da4b51e | ||
|
|
180d96234e | ||
|
|
1a04ffbae4 | ||
|
|
1fe014dbae | ||
|
|
579c31aa23 | ||
|
|
74c914475f | ||
|
|
1ca439f4e0 | ||
|
|
08e7c143b3 | ||
|
|
d399dfa792 | ||
|
|
f6e613a76f | ||
|
|
c6a8b6471a | ||
|
|
83589b7cec | ||
|
|
aeea93fa95 | ||
|
|
be417d6605 | ||
|
|
2f890dea18 | ||
|
|
de76628539 | ||
|
|
598dd672bc | ||
|
|
d12fb3d6e1 | ||
|
|
9504d866b6 | ||
|
|
865b1dc66e | ||
|
|
5143b210cf | ||
|
|
f34ce81f25 | ||
|
|
b072c6c4c9 | ||
|
|
7951ed3bce | ||
|
|
02431c57db | ||
|
|
3f186c009c | ||
|
|
6f4c15b2b2 | ||
|
|
b31e029000 | ||
|
|
5f5ffcd48a | ||
|
|
cc76f3746f | ||
|
|
982da4d20c | ||
|
|
113374fd04 | ||
|
|
e4520693dd | ||
|
|
ccffc88ceb | ||
|
|
7c9312607c | ||
|
|
286c2960c8 | ||
|
|
a12e374a04 | ||
|
|
d799c8bd1e | ||
|
|
251eec8401 | ||
|
|
bca8a32674 | ||
|
|
c740324636 | ||
|
|
f049afcb5b | ||
|
|
c188654ebd | ||
|
|
a6aba8cab2 | ||
|
|
583fbfdb2a | ||
|
|
7c34ac6f6d | ||
|
|
b72354ca22 | ||
|
|
82d81b9e86 | ||
|
|
ed19ddf620 | ||
|
|
ebbd33db7a | ||
|
|
7ba4ca1854 | ||
|
|
fa1f8c0d87 | ||
|
|
e0cacef52e | ||
|
|
767ed40b75 | ||
|
|
3c2f92a7af | ||
|
|
2568f828c8 | ||
|
|
5427f55358 | ||
|
|
92b41e4935 | ||
|
|
6edae6ddef | ||
|
|
f787eafd8a | ||
|
|
9588a961d6 | ||
|
|
88758703fa | ||
|
|
3c839f44d8 | ||
|
|
304bdd7d0d | ||
|
|
382d27b4dc | ||
|
|
b80278c04f | ||
|
|
7d4fcfa191 | ||
|
|
ad3fe00dea | ||
|
|
f507d16baa | ||
|
|
dcce2edc4f | ||
|
|
e7e1e7a0a3 | ||
|
|
68f4485cdd | ||
|
|
d93ac3c496 | ||
|
|
a97de38b6b | ||
|
|
444eac3597 | ||
|
|
1f01c76fa5 | ||
|
|
16da1a5c88 | ||
|
|
e514d1201d | ||
|
|
eb0293a637 | ||
|
|
03581fc8cc | ||
|
|
246cf0df26 | ||
|
|
cf1d6461cb | ||
|
|
9bcc97bc5e | ||
|
|
3bc124d9d3 | ||
|
|
764ae2a489 | ||
|
|
e678d5ae8e | ||
|
|
13b1720899 | ||
|
|
35512f4ee9 | ||
|
|
e55f10a8f1 | ||
|
|
b187e499a4 | ||
|
|
dd397a9957 | ||
|
|
cdfed8fabc | ||
|
|
759577ad9b | ||
|
|
356402942f | ||
|
|
76947fa835 | ||
|
|
f7dadfb646 | ||
|
|
4e31595c7a | ||
|
|
31779c0763 | ||
|
|
6e3622e0f1 | ||
|
|
b78bd4ccce | ||
|
|
a10059d531 | ||
|
|
1f2ce01c08 | ||
|
|
fb5a70a663 | ||
|
|
d62d0ed076 | ||
|
|
a4b9ce13ee | ||
|
|
43ee152eb4 | ||
|
|
fee909deee | ||
|
|
702bcb8684 | ||
|
|
961e65424e | ||
|
|
f901cb7b25 | ||
|
|
1d9d248456 | ||
|
|
86ef5475b9 | ||
|
|
087c314154 | ||
|
|
956ea10f56 | ||
|
|
4a4faa5d46 | ||
|
|
7e2a3fda4d | ||
|
|
786e51ecd1 | ||
|
|
d77bbe93c1 | ||
|
|
892b80ffa4 | ||
|
|
1c2cc9f35c | ||
|
|
12908709bb | ||
|
|
b42d183b08 | ||
|
|
e1ed664adc | ||
|
|
de2f07b82f | ||
|
|
cc5c91158d | ||
|
|
8dc35a7906 | ||
|
|
7e53c87f5c | ||
|
|
59e6b33c6f | ||
|
|
9843014dce | ||
|
|
728a454919 | ||
|
|
dff09b7e65 | ||
|
|
bb40433960 | ||
|
|
6cd770e501 | ||
|
|
0f347b9c5c | ||
|
|
c3b3d7b022 | ||
|
|
948006561a | ||
|
|
3ccbb8fe84 | ||
|
|
c1c541642e | ||
|
|
b4782809d4 | ||
|
|
b3feae5474 | ||
|
|
c015aeca4e | ||
|
|
9bbc13f256 | ||
|
|
38d53db6e9 | ||
|
|
0f4d83960f | ||
|
|
19a1852e4b | ||
|
|
c6d4ebd80c | ||
|
|
9f2727bb77 | ||
|
|
00b103c85c | ||
|
|
a0d2d4c0b1 | ||
|
|
64e91951b2 | ||
|
|
e7de19fe1d | ||
|
|
5536b3a58d | ||
|
|
a8347d2820 | ||
|
|
c56bdee177 | ||
|
|
894e7b9357 | ||
|
|
2aee1426de | ||
|
|
66db5b39bb | ||
|
|
a73bb733ff | ||
|
|
3d57f5fcbb | ||
|
|
c34bee2009 | ||
|
|
c3a0cbfc85 | ||
|
|
57825365fe | ||
|
|
b35785bb1b | ||
|
|
0d2f888413 | ||
|
|
a85fee7a0d | ||
|
|
f66dedc759 | ||
|
|
a62da3d530 | ||
|
|
1cc972c723 | ||
|
|
6b7a2f6641 | ||
|
|
34b79794ea | ||
|
|
fb114d8d20 | ||
|
|
a6106117a9 | ||
|
|
b27507790f | ||
|
|
a0880b64f2 | ||
|
|
6e057c010f | ||
|
|
540972ff59 | ||
|
|
677adc7adc | ||
|
|
096c50cafc | ||
|
|
8c57e3ffca | ||
|
|
4e2deadba7 | ||
|
|
497fb0b3c3 | ||
|
|
8debcf9f92 | ||
|
|
db0a21b93f | ||
|
|
e2fee206c2 | ||
|
|
596e374313 | ||
|
|
503956707c | ||
|
|
87dd427d79 | ||
|
|
5fc79f5627 | ||
|
|
f4bb2ad613 | ||
|
|
15b4f64b91 | ||
|
|
a1a7d41e7a | ||
|
|
74547a4313 | ||
|
|
9a532080d0 | ||
|
|
32c6afb120 | ||
|
|
896eb26877 | ||
|
|
0a8bc6f1c7 | ||
|
|
175aaedc79 | ||
|
|
4125beb0fb | ||
|
|
93ea4f4f6f | ||
|
|
d3f4eedb12 | ||
|
|
5a49efec58 | ||
|
|
3435f9cb2c | ||
|
|
d891e00f63 | ||
|
|
8a859391be | ||
|
|
0abf57be5d | ||
|
|
09d14a0b6c | ||
|
|
9bd06be43b | ||
|
|
01598028c4 | ||
|
|
cf9428fba1 | ||
|
|
4faa9e9f45 | ||
|
|
4bcba41d77 | ||
|
|
12040570ca | ||
|
|
5824e8d242 | ||
|
|
d7a0d860b9 | ||
|
|
dbdb611bcc | ||
|
|
3b3e14d056 | ||
|
|
962bf58f8f | ||
|
|
6f2ff93519 | ||
|
|
e853aa2e7c | ||
|
|
248e35036f | ||
|
|
96f1cdf687 | ||
|
|
d483b6d25c | ||
|
|
293fa48884 | ||
|
|
45bd005be9 | ||
|
|
efe88d4979 | ||
|
|
913c9aa3d3 | ||
|
|
a36c53af99 | ||
|
|
8ff808c882 | ||
|
|
9ade110a25 | ||
|
|
2b3be9055a | ||
|
|
10bb186c76 | ||
|
|
198f1d10c4 | ||
|
|
5be69e92ce | ||
|
|
c80acbe4c8 | ||
|
|
29681c0aa7 | ||
|
|
fdd6794ce3 | ||
|
|
6c7e9608b9 | ||
|
|
5171f65c05 | ||
|
|
86f327d0f5 | ||
|
|
b16fbde032 | ||
|
|
9437035147 | ||
|
|
f24fb2899e | ||
|
|
19c5248675 | ||
|
|
2c3e0aee08 | ||
|
|
552e9c8408 | ||
|
|
164bbdfcfc | ||
|
|
3efa00d59a | ||
|
|
ea694a4588 | ||
|
|
32d5e59ab6 | ||
|
|
a58ed1ada3 | ||
|
|
c80dbb2210 | ||
|
|
ce1e5374b9 | ||
|
|
c4fa881303 | ||
|
|
d02b291e2f | ||
|
|
4d21f4673d | ||
|
|
6682e6b663 | ||
|
|
bef56af730 | ||
|
|
c7de6939ae | ||
|
|
2059266a24 | ||
|
|
edba04c978 | ||
|
|
73030aa5fb | ||
|
|
34bf809e51 | ||
|
|
fd6fc16001 | ||
|
|
e438acfc5f | ||
|
|
3a27c84d98 | ||
|
|
c6408f4b31 | ||
|
|
fc026a722b | ||
|
|
573a05a10f | ||
|
|
6fc383ade1 | ||
|
|
40a9178c7f | ||
|
|
82f7cae22c | ||
|
|
f786ed8505 | ||
|
|
7e06265568 | ||
|
|
2a50be152e | ||
|
|
ba5e91e278 | ||
|
|
5a3e3339e0 | ||
|
|
0bb7098fd8 | ||
|
|
290b593d0b | ||
|
|
2745be83dd | ||
|
|
44d5269c0a | ||
|
|
3f9346836e | ||
|
|
5d1b6f9af3 | ||
|
|
882751b51e | ||
|
|
bbd59fa314 | ||
|
|
57c9d78629 | ||
|
|
78c9004a87 | ||
|
|
8df2a598a7 | ||
|
|
1691282314 | ||
|
|
3d6bb53b31 | ||
|
|
6a8a6aea54 | ||
|
|
8c5760fee7 | ||
|
|
3c2135b36b | ||
|
|
aad597b987 | ||
|
|
5fdfc0b54a | ||
|
|
ef966bd261 | ||
|
|
54cb40fce7 | ||
|
|
c6a0048b9b | ||
|
|
425e8b9495 | ||
|
|
82dd6c7fa2 | ||
|
|
e4f1faa478 | ||
|
|
c7907630f4 | ||
|
|
e18a7400b4 | ||
|
|
058831d88c | ||
|
|
1da785cb77 | ||
|
|
3a058a4f21 | ||
|
|
3d6a589a04 | ||
|
|
6c8b3686b4 | ||
|
|
fc0bef732b | ||
|
|
e8eab081c5 | ||
|
|
00419c6c41 | ||
|
|
7307293c87 | ||
|
|
912f5b8f5b | ||
|
|
c2cf33af24 | ||
|
|
eb59311136 | ||
|
|
fc42f878e9 | ||
|
|
98368c4770 | ||
|
|
c9da7f9f8c | ||
|
|
e7f8727d2d | ||
|
|
2657746451 | ||
|
|
2701993dd6 | ||
|
|
9a798a766e | ||
|
|
36419b25aa | ||
|
|
9da67b701d | ||
|
|
ef7ecb5567 | ||
|
|
a77c609c62 | ||
|
|
bca2bab560 | ||
|
|
e129b13402 | ||
|
|
520b6d7344 | ||
|
|
bed395d039 | ||
|
|
566f8c322b | ||
|
|
807cedf4f3 | ||
|
|
ef8a7d82d8 | ||
|
|
b906e8d299 | ||
|
|
0e14147132 | ||
|
|
c10e106787 | ||
|
|
61725ee7cc | ||
|
|
39f88f1712 | ||
|
|
e14aba8cf1 | ||
|
|
97e774226d | ||
|
|
6220e9c6cc | ||
|
|
cba2a6c87c | ||
|
|
71d7383491 | ||
|
|
2c833c2342 | ||
|
|
45fa8e724f | ||
|
|
b2a6e338b5 | ||
|
|
34734395c8 | ||
|
|
a3ee8f9cb8 | ||
|
|
7f9e33ca1e | ||
|
|
d4e8033fe0 | ||
|
|
ab61af7481 | ||
|
|
8f204b4e23 | ||
|
|
3b40e9dc93 | ||
|
|
b181b0ef6e | ||
|
|
4083bb2c0f | ||
|
|
9d004a6aa4 | ||
|
|
d30bfe8b8e | ||
|
|
38fbd85004 | ||
|
|
467728b535 | ||
|
|
0c990eb0a2 | ||
|
|
23ce9aa47e | ||
|
|
a0587d4307 | ||
|
|
ea5e9c9fe2 | ||
|
|
14ebbce280 | ||
|
|
67d55d08f8 | ||
|
|
4d3a501b83 | ||
|
|
16fab74ab1 | ||
|
|
f397d42d73 | ||
|
|
576a2e5b86 | ||
|
|
060a4fbef0 | ||
|
|
f473fb3d7d | ||
|
|
36f6073ec5 | ||
|
|
ebf7732943 | ||
|
|
c62427fd47 | ||
|
|
ff09d1c531 | ||
|
|
2852a48e6a | ||
|
|
1ab1803a43 | ||
|
|
8f84fb49fa | ||
|
|
e1dca468f5 | ||
|
|
b1b3d93c96 | ||
|
|
7d80112d4f | ||
|
|
4dd703ea6c | ||
|
|
99a254f2f6 | ||
|
|
1b7799cb1d | ||
|
|
7eba57b4c0 | ||
|
|
1f51cfcf57 | ||
|
|
683e4db48b | ||
|
|
c2ddd48f50 | ||
|
|
eb8ff73595 | ||
|
|
54c4b1656f | ||
|
|
1000b40a3a | ||
|
|
e7e5354332 | ||
|
|
b5365ba13d | ||
|
|
f2cdc6f5f4 | ||
|
|
a0c251c7cc | ||
|
|
d7a224e47a | ||
|
|
6894701392 | ||
|
|
8e4e898ce5 | ||
|
|
add8fb8fd2 | ||
|
|
3807dbf2f3 | ||
|
|
b5d1c9241c | ||
|
|
3e742452cd | ||
|
|
d7b127549c | ||
|
|
d841f97d44 | ||
|
|
0c7d947d2d | ||
|
|
05604b77ea | ||
|
|
2c072eb6b6 | ||
|
|
080a9863c1 | ||
|
|
22f5760d47 | ||
|
|
4dc88e8ffb | ||
|
|
229497871d | ||
|
|
9ce5dd1082 | ||
|
|
03d9db921b | ||
|
|
93ed401b7c | ||
|
|
e34938f21d | ||
|
|
87dbaa0bd7 | ||
|
|
119627c8cf | ||
|
|
973efb63ab | ||
|
|
a1511e6a86 | ||
|
|
1d5663ddec | ||
|
|
5e8d92146b | ||
|
|
8e160562ee | ||
|
|
7033105ce7 | ||
|
|
091dfa0c26 | ||
|
|
7fc006b63b | ||
|
|
3e653ace3e | ||
|
|
64f3df44ee | ||
|
|
42ccddeff3 | ||
|
|
0435fbf2e5 | ||
|
|
34ddae154e | ||
|
|
8da37ce4b0 | ||
|
|
9cbe74c2db | ||
|
|
002ba59ff1 | ||
|
|
d293de579a | ||
|
|
4aea3b81ee | ||
|
|
5293f5aae1 | ||
|
|
39698fa6b7 | ||
|
|
e80f9b5c65 | ||
|
|
f0986be2e3 | ||
|
|
252cdef110 |
28
.github/workflows/cibuild-setup-ubuntu.sh
vendored
Executable file
28
.github/workflows/cibuild-setup-ubuntu.sh
vendored
Executable file
@@ -0,0 +1,28 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -ex
|
||||
|
||||
PACKAGES=(
|
||||
git make autoconf automake autopoint pkg-config libtool libtool-bin
|
||||
gettext libssl-dev libdevmapper-dev libpopt-dev uuid-dev libsepol1-dev
|
||||
libjson-c-dev libssh-dev libblkid-dev tar libargon2-0-dev libpwquality-dev
|
||||
sharutils dmsetup jq xxd expect keyutils netcat passwd openssh-client sshpass
|
||||
)
|
||||
|
||||
COMPILER="${COMPILER:?}"
|
||||
COMPILER_VERSION="${COMPILER_VERSION:?}"
|
||||
RELEASE="$(lsb_release -cs)"
|
||||
|
||||
bash -c "echo 'deb-src http://archive.ubuntu.com/ubuntu/ $RELEASE main restricted universe multiverse' >>/etc/apt/sources.list"
|
||||
|
||||
# Latest gcc stack deb packages provided by
|
||||
# https://launchpad.net/~ubuntu-toolchain-r/+archive/ubuntu/test
|
||||
add-apt-repository -y ppa:ubuntu-toolchain-r/test
|
||||
PACKAGES+=(gcc-$COMPILER_VERSION)
|
||||
|
||||
# scsi_debug, gost crypto
|
||||
PACKAGES+=(dkms linux-headers-$(uname -r) linux-modules-extra-$(uname -r) gost-crypto-dkms)
|
||||
|
||||
apt-get -y update --fix-missing
|
||||
apt-get -y install "${PACKAGES[@]}"
|
||||
apt-get -y build-dep cryptsetup
|
||||
38
.github/workflows/cibuild.sh
vendored
Executable file
38
.github/workflows/cibuild.sh
vendored
Executable file
@@ -0,0 +1,38 @@
|
||||
#!/bin/bash
|
||||
|
||||
PHASES=(${@:-CONFIGURE MAKE CHECK})
|
||||
COMPILER="${COMPILER:?}"
|
||||
COMPILER_VERSION="${COMPILER_VERSION}"
|
||||
CFLAGS=(-O1 -g)
|
||||
CXXFLAGS=(-O1 -g)
|
||||
|
||||
CC="gcc${COMPILER_VERSION:+-$COMPILER_VERSION}"
|
||||
CXX="g++${COMPILER_VERSION:+-$COMPILER_VERSION}"
|
||||
|
||||
set -ex
|
||||
|
||||
for phase in "${PHASES[@]}"; do
|
||||
case $phase in
|
||||
CONFIGURE)
|
||||
opts=(
|
||||
--enable-libargon2
|
||||
)
|
||||
|
||||
sudo -E git clean -xdf
|
||||
|
||||
./autogen.sh
|
||||
CC="$CC" CXX="$CXX" CFLAGS="${CFLAGS[@]}" CXXFLAGS="${CXXFLAGS[@]}" ./configure "${opts[@]}"
|
||||
;;
|
||||
MAKE)
|
||||
make -j
|
||||
make -j -C tests check-programs
|
||||
;;
|
||||
CHECK)
|
||||
make check
|
||||
;;
|
||||
|
||||
*)
|
||||
echo >&2 "Unknown phase '$phase'"
|
||||
exit 1
|
||||
esac
|
||||
done
|
||||
29
.github/workflows/cibuild.yml
vendored
Normal file
29
.github/workflows/cibuild.yml
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
name: Build test
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- 'master'
|
||||
- 'wip-luks2'
|
||||
- 'v2.3.x'
|
||||
paths-ignore:
|
||||
- 'docs/**'
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.repository == 'mbroz/cryptsetup'
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
env:
|
||||
- { COMPILER: "gcc", COMPILER_VERSION: "11", RUN_SSH_PLUGIN_TEST: "1" }
|
||||
env: ${{ matrix.env }}
|
||||
steps:
|
||||
- name: Repository checkout
|
||||
uses: actions/checkout@v1
|
||||
- name: Ubuntu setup
|
||||
run: sudo -E .github/workflows/cibuild-setup-ubuntu.sh
|
||||
- name: Configure & Make
|
||||
run: .github/workflows/cibuild.sh CONFIGURE MAKE
|
||||
- name: Check
|
||||
run: sudo -E .github/workflows/cibuild.sh CHECK
|
||||
56
.gitignore
vendored
Normal file
56
.gitignore
vendored
Normal file
@@ -0,0 +1,56 @@
|
||||
po/*gmo
|
||||
*~
|
||||
Makefile
|
||||
Makefile.in
|
||||
Makefile.in.in
|
||||
*.lo
|
||||
*.la
|
||||
*.o
|
||||
**/*.dirstamp
|
||||
.deps/
|
||||
.libs/
|
||||
src/cryptsetup
|
||||
src/veritysetup
|
||||
ABOUT-NLS
|
||||
aclocal.m4
|
||||
autom4te.cache/
|
||||
compile
|
||||
config.guess
|
||||
config.h
|
||||
config.h.in
|
||||
config.log
|
||||
config.rpath
|
||||
config.status
|
||||
config.sub
|
||||
configure
|
||||
cryptsetup
|
||||
cryptsetup-reencrypt
|
||||
cryptsetup-ssh
|
||||
depcomp
|
||||
install-sh
|
||||
integritysetup
|
||||
lib/libcryptsetup.pc
|
||||
libtool
|
||||
ltmain.sh
|
||||
m4/
|
||||
missing
|
||||
po/Makevars.template
|
||||
po/POTFILES
|
||||
po/Rules-quot
|
||||
po/*.header
|
||||
po/*.sed
|
||||
po/*.sin
|
||||
po/stamp-po
|
||||
scripts/cryptsetup.conf
|
||||
stamp-h1
|
||||
veritysetup
|
||||
tests/valglog.*
|
||||
*/*.dirstamp
|
||||
*-debug-luks2-backup*
|
||||
tests/api-test
|
||||
tests/api-test-2
|
||||
tests/differ
|
||||
tests/luks1-images
|
||||
tests/tcrypt-images
|
||||
tests/unit-utils-io
|
||||
tests/vectors-test
|
||||
46
.gitlab-ci.yml
Normal file
46
.gitlab-ci.yml
Normal file
@@ -0,0 +1,46 @@
|
||||
default:
|
||||
before_script:
|
||||
- sudo apt-get -y update --fix-missing
|
||||
- >
|
||||
sudo apt-get -y install -y -qq git gcc make
|
||||
autoconf automake autopoint pkg-config libtool libtool-bin gettext
|
||||
libssl-dev libdevmapper-dev libpopt-dev uuid-dev libsepol1-dev
|
||||
libjson-c-dev libssh-dev libblkid-dev tar libargon2-0-dev
|
||||
libpwquality-dev sharutils dmsetup jq xxd expect keyutils
|
||||
netcat passwd openssh-client sshpass
|
||||
- sudo apt-get -y build-dep cryptsetup
|
||||
- sudo -E git clean -xdf
|
||||
- ./autogen.sh
|
||||
- ./configure --enable-libargon2
|
||||
|
||||
stages:
|
||||
- test
|
||||
|
||||
# Merge request: Build and run only non-root tests
|
||||
test-mergerq-job:
|
||||
stage: test
|
||||
interruptible: true
|
||||
rules:
|
||||
- if: $CI_PROJECT_PATH != "cryptsetup/cryptsetup"
|
||||
when: never
|
||||
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
|
||||
script:
|
||||
- make -j
|
||||
- make -j -C tests check-programs
|
||||
- make check
|
||||
|
||||
# For main branch commit, run all tests as root
|
||||
test-main-commit-job:
|
||||
stage: test
|
||||
interruptible: true
|
||||
variables:
|
||||
RUN_SSH_PLUGIN_TEST: "1"
|
||||
rules:
|
||||
- if: $CI_PROJECT_PATH != "cryptsetup/cryptsetup"
|
||||
when: never
|
||||
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
|
||||
script:
|
||||
- make -j
|
||||
- make -j -C tests check-programs
|
||||
- sudo -E make check
|
||||
- sudo -E make clean
|
||||
15
.gitlab/issue_templates/Bug.md
Normal file
15
.gitlab/issue_templates/Bug.md
Normal file
@@ -0,0 +1,15 @@
|
||||
### Issue description
|
||||
<!-- Please, shortly describe the issue here. -->
|
||||
|
||||
### Steps for reproducing the issue
|
||||
<!-- How it can be reproduced? Include all important steps. -->
|
||||
|
||||
### Additional info
|
||||
<!-- Please mention what distribution you are using. -->
|
||||
|
||||
### Debug log
|
||||
<!-- Paste a debug log of the failing command (add --debug option) between the markers below (to keep raw debug format).-->
|
||||
```
|
||||
Output with --debug option:
|
||||
|
||||
```
|
||||
5
.gitlab/issue_templates/Documentation.md
Normal file
5
.gitlab/issue_templates/Documentation.md
Normal file
@@ -0,0 +1,5 @@
|
||||
### Documentation issue
|
||||
<!-- Please, shortly describe the issue in documentation here. -->
|
||||
|
||||
### Additional info
|
||||
<!-- Please mention what cryptsetup version you are using. -->
|
||||
5
.gitlab/issue_templates/Feature.md
Normal file
5
.gitlab/issue_templates/Feature.md
Normal file
@@ -0,0 +1,5 @@
|
||||
### New feature description
|
||||
<!-- Please, shortly describe the requested feature here. -->
|
||||
|
||||
### Additional info
|
||||
<!-- Please mention what distribution and cryptsetup version you are using. -->
|
||||
1
AUTHORS
1
AUTHORS
@@ -1,3 +1,4 @@
|
||||
Jana Saout <jana@saout.de>
|
||||
Clemens Fruhwirth <clemens@endorphin.org>
|
||||
Milan Broz <gmazyland@gmail.com>
|
||||
Ondrej Kozina <okozina@redhat.com>
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
Since version 1.6 this file is no longer maintained.
|
||||
|
||||
See docs/*ReleaseNotes for release changes documentation.
|
||||
|
||||
See version control history for full commit messages.
|
||||
http://code.google.com/p/cryptsetup/source/list
|
||||
229
INSTALL
229
INSTALL
@@ -1,229 +0,0 @@
|
||||
Copyright 1994, 1995, 1996, 1999, 2000, 2001, 2002 Free Software
|
||||
Foundation, Inc.
|
||||
|
||||
This file is free documentation; the Free Software Foundation gives
|
||||
unlimited permission to copy, distribute and modify it.
|
||||
|
||||
Basic Installation
|
||||
==================
|
||||
|
||||
These are generic installation instructions.
|
||||
|
||||
The `configure' shell script attempts to guess correct values for
|
||||
various system-dependent variables used during compilation. It uses
|
||||
those values to create a `Makefile' in each directory of the package.
|
||||
It may also create one or more `.h' files containing system-dependent
|
||||
definitions. Finally, it creates a shell script `config.status' that
|
||||
you can run in the future to recreate the current configuration, and a
|
||||
file `config.log' containing compiler output (useful mainly for
|
||||
debugging `configure').
|
||||
|
||||
It can also use an optional file (typically called `config.cache'
|
||||
and enabled with `--cache-file=config.cache' or simply `-C') that saves
|
||||
the results of its tests to speed up reconfiguring. (Caching is
|
||||
disabled by default to prevent problems with accidental use of stale
|
||||
cache files.)
|
||||
|
||||
If you need to do unusual things to compile the package, please try
|
||||
to figure out how `configure' could check whether to do them, and mail
|
||||
diffs or instructions to the address given in the `README' so they can
|
||||
be considered for the next release. If you are using the cache, and at
|
||||
some point `config.cache' contains results you don't want to keep, you
|
||||
may remove or edit it.
|
||||
|
||||
The file `configure.ac' (or `configure.in') is used to create
|
||||
`configure' by a program called `autoconf'. You only need
|
||||
`configure.ac' if you want to change it or regenerate `configure' using
|
||||
a newer version of `autoconf'.
|
||||
|
||||
The simplest way to compile this package is:
|
||||
|
||||
1. `cd' to the directory containing the package's source code and type
|
||||
`./configure' to configure the package for your system. If you're
|
||||
using `csh' on an old version of System V, you might need to type
|
||||
`sh ./configure' instead to prevent `csh' from trying to execute
|
||||
`configure' itself.
|
||||
|
||||
Running `configure' takes awhile. While running, it prints some
|
||||
messages telling which features it is checking for.
|
||||
|
||||
2. Type `make' to compile the package.
|
||||
|
||||
3. Optionally, type `make check' to run any self-tests that come with
|
||||
the package.
|
||||
|
||||
4. Type `make install' to install the programs and any data files and
|
||||
documentation.
|
||||
|
||||
5. You can remove the program binaries and object files from the
|
||||
source code directory by typing `make clean'. To also remove the
|
||||
files that `configure' created (so you can compile the package for
|
||||
a different kind of computer), type `make distclean'. There is
|
||||
also a `make maintainer-clean' target, but that is intended mainly
|
||||
for the package's developers. If you use it, you may have to get
|
||||
all sorts of other programs in order to regenerate files that came
|
||||
with the distribution.
|
||||
|
||||
Compilers and Options
|
||||
=====================
|
||||
|
||||
Some systems require unusual options for compilation or linking that
|
||||
the `configure' script does not know about. Run `./configure --help'
|
||||
for details on some of the pertinent environment variables.
|
||||
|
||||
You can give `configure' initial values for configuration parameters
|
||||
by setting variables in the command line or in the environment. Here
|
||||
is an example:
|
||||
|
||||
./configure CC=c89 CFLAGS=-O2 LIBS=-lposix
|
||||
|
||||
*Note Defining Variables::, for more details.
|
||||
|
||||
Compiling For Multiple Architectures
|
||||
====================================
|
||||
|
||||
You can compile the package for more than one kind of computer at the
|
||||
same time, by placing the object files for each architecture in their
|
||||
own directory. To do this, you must use a version of `make' that
|
||||
supports the `VPATH' variable, such as GNU `make'. `cd' to the
|
||||
directory where you want the object files and executables to go and run
|
||||
the `configure' script. `configure' automatically checks for the
|
||||
source code in the directory that `configure' is in and in `..'.
|
||||
|
||||
If you have to use a `make' that does not support the `VPATH'
|
||||
variable, you have to compile the package for one architecture at a
|
||||
time in the source code directory. After you have installed the
|
||||
package for one architecture, use `make distclean' before reconfiguring
|
||||
for another architecture.
|
||||
|
||||
Installation Names
|
||||
==================
|
||||
|
||||
By default, `make install' will install the package's files in
|
||||
`/usr/local/bin', `/usr/local/man', etc. You can specify an
|
||||
installation prefix other than `/usr/local' by giving `configure' the
|
||||
option `--prefix=PATH'.
|
||||
|
||||
You can specify separate installation prefixes for
|
||||
architecture-specific files and architecture-independent files. If you
|
||||
give `configure' the option `--exec-prefix=PATH', the package will use
|
||||
PATH as the prefix for installing programs and libraries.
|
||||
Documentation and other data files will still use the regular prefix.
|
||||
|
||||
In addition, if you use an unusual directory layout you can give
|
||||
options like `--bindir=PATH' to specify different values for particular
|
||||
kinds of files. Run `configure --help' for a list of the directories
|
||||
you can set and what kinds of files go in them.
|
||||
|
||||
If the package supports it, you can cause programs to be installed
|
||||
with an extra prefix or suffix on their names by giving `configure' the
|
||||
option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
|
||||
|
||||
Optional Features
|
||||
=================
|
||||
|
||||
Some packages pay attention to `--enable-FEATURE' options to
|
||||
`configure', where FEATURE indicates an optional part of the package.
|
||||
They may also pay attention to `--with-PACKAGE' options, where PACKAGE
|
||||
is something like `gnu-as' or `x' (for the X Window System). The
|
||||
`README' should mention any `--enable-' and `--with-' options that the
|
||||
package recognizes.
|
||||
|
||||
For packages that use the X Window System, `configure' can usually
|
||||
find the X include and library files automatically, but if it doesn't,
|
||||
you can use the `configure' options `--x-includes=DIR' and
|
||||
`--x-libraries=DIR' to specify their locations.
|
||||
|
||||
Specifying the System Type
|
||||
==========================
|
||||
|
||||
There may be some features `configure' cannot figure out
|
||||
automatically, but needs to determine by the type of machine the package
|
||||
will run on. Usually, assuming the package is built to be run on the
|
||||
_same_ architectures, `configure' can figure that out, but if it prints
|
||||
a message saying it cannot guess the machine type, give it the
|
||||
`--build=TYPE' option. TYPE can either be a short name for the system
|
||||
type, such as `sun4', or a canonical name which has the form:
|
||||
|
||||
CPU-COMPANY-SYSTEM
|
||||
|
||||
where SYSTEM can have one of these forms:
|
||||
|
||||
OS KERNEL-OS
|
||||
|
||||
See the file `config.sub' for the possible values of each field. If
|
||||
`config.sub' isn't included in this package, then this package doesn't
|
||||
need to know the machine type.
|
||||
|
||||
If you are _building_ compiler tools for cross-compiling, you should
|
||||
use the `--target=TYPE' option to select the type of system they will
|
||||
produce code for.
|
||||
|
||||
If you want to _use_ a cross compiler, that generates code for a
|
||||
platform different from the build platform, you should specify the
|
||||
"host" platform (i.e., that on which the generated programs will
|
||||
eventually be run) with `--host=TYPE'.
|
||||
|
||||
Sharing Defaults
|
||||
================
|
||||
|
||||
If you want to set default values for `configure' scripts to share,
|
||||
you can create a site shell script called `config.site' that gives
|
||||
default values for variables like `CC', `cache_file', and `prefix'.
|
||||
`configure' looks for `PREFIX/share/config.site' if it exists, then
|
||||
`PREFIX/etc/config.site' if it exists. Or, you can set the
|
||||
`CONFIG_SITE' environment variable to the location of the site script.
|
||||
A warning: not all `configure' scripts look for a site script.
|
||||
|
||||
Defining Variables
|
||||
==================
|
||||
|
||||
Variables not defined in a site shell script can be set in the
|
||||
environment passed to `configure'. However, some packages may run
|
||||
configure again during the build, and the customized values of these
|
||||
variables may be lost. In order to avoid this problem, you should set
|
||||
them in the `configure' command line, using `VAR=value'. For example:
|
||||
|
||||
./configure CC=/usr/local2/bin/gcc
|
||||
|
||||
will cause the specified gcc to be used as the C compiler (unless it is
|
||||
overridden in the site shell script).
|
||||
|
||||
`configure' Invocation
|
||||
======================
|
||||
|
||||
`configure' recognizes the following options to control how it
|
||||
operates.
|
||||
|
||||
`--help'
|
||||
`-h'
|
||||
Print a summary of the options to `configure', and exit.
|
||||
|
||||
`--version'
|
||||
`-V'
|
||||
Print the version of Autoconf used to generate the `configure'
|
||||
script, and exit.
|
||||
|
||||
`--cache-file=FILE'
|
||||
Enable the cache: use and save the results of the tests in FILE,
|
||||
traditionally `config.cache'. FILE defaults to `/dev/null' to
|
||||
disable caching.
|
||||
|
||||
`--config-cache'
|
||||
`-C'
|
||||
Alias for `--cache-file=config.cache'.
|
||||
|
||||
`--quiet'
|
||||
`--silent'
|
||||
`-q'
|
||||
Do not print messages saying which checks are being made. To
|
||||
suppress all normal output, redirect it to `/dev/null' (any error
|
||||
messages will still be shown).
|
||||
|
||||
`--srcdir=DIR'
|
||||
Look for the package's source code in directory DIR. Usually
|
||||
`configure' can determine that directory automatically.
|
||||
|
||||
`configure' also accepts some other, not widely useful, options. Run
|
||||
`configure --help' for more details.
|
||||
|
||||
67
Makefile.am
67
Makefile.am
@@ -1,13 +1,62 @@
|
||||
EXTRA_DIST = COPYING.LGPL FAQ docs misc
|
||||
SUBDIRS = \
|
||||
lib \
|
||||
src \
|
||||
man \
|
||||
python \
|
||||
tests \
|
||||
po
|
||||
EXTRA_DIST = README.md COPYING.LGPL FAQ docs misc autogen.sh
|
||||
SUBDIRS = po tests
|
||||
CLEANFILES =
|
||||
DISTCLEAN_TARGETS =
|
||||
|
||||
AM_CPPFLAGS = \
|
||||
-include config.h \
|
||||
-I$(top_srcdir)/lib \
|
||||
-DDATADIR=\""$(datadir)"\" \
|
||||
-DLOCALEDIR=\""$(datadir)/locale"\" \
|
||||
-DLIBDIR=\""$(libdir)"\" \
|
||||
-DPREFIX=\""$(prefix)"\" \
|
||||
-DSYSCONFDIR=\""$(sysconfdir)"\" \
|
||||
-DVERSION=\""$(VERSION)"\" \
|
||||
-DEXTERNAL_LUKS2_TOKENS_PATH=\"${EXTERNAL_LUKS2_TOKENS_PATH}\"
|
||||
AM_CFLAGS = -Wall
|
||||
AM_LDFLAGS =
|
||||
|
||||
LDADD = $(LTLIBINTL) -lm
|
||||
|
||||
tmpfilesddir = @DEFAULT_TMPFILESDIR@
|
||||
|
||||
include_HEADERS =
|
||||
lib_LTLIBRARIES =
|
||||
noinst_LTLIBRARIES =
|
||||
sbin_PROGRAMS =
|
||||
man8_MANS =
|
||||
tmpfilesd_DATA =
|
||||
pkgconfig_DATA =
|
||||
|
||||
include man/Makemodule.am
|
||||
|
||||
include scripts/Makemodule.am
|
||||
|
||||
if CRYPTO_INTERNAL_ARGON2
|
||||
include lib/crypto_backend/argon2/Makemodule.am
|
||||
endif
|
||||
include lib/crypto_backend/Makemodule.am
|
||||
include lib/Makemodule.am
|
||||
|
||||
include src/Makemodule.am
|
||||
include tokens/Makemodule.am
|
||||
|
||||
ACLOCAL_AMFLAGS = -I m4
|
||||
|
||||
DISTCHECK_CONFIGURE_FLAGS = \
|
||||
--with-tmpfilesdir=$$dc_install_base/usr/lib/tmpfiles.d \
|
||||
--enable-internal-argon2 --enable-internal-sse-argon2 \
|
||||
--enable-external-tokens --enable-ssh-token
|
||||
|
||||
distclean-local:
|
||||
-find . -name \*~ -o -name \*.orig -o -name \*.rej | xargs rm -f
|
||||
rm -rf autom4te.cache
|
||||
|
||||
clean-local:
|
||||
-rm -rf docs/doxygen_api_docs
|
||||
-rm -rf docs/doxygen_api_docs libargon2.la
|
||||
|
||||
install-data-local:
|
||||
$(MKDIR_P) -m 0755 $(DESTDIR)/${EXTERNAL_LUKS2_TOKENS_PATH}
|
||||
|
||||
uninstall-local:
|
||||
rmdir $(DESTDIR)/${EXTERNAL_LUKS2_TOKENS_PATH} 2>/dev/null || :
|
||||
|
||||
31
README
31
README
@@ -1,31 +0,0 @@
|
||||
|
||||
cryptsetup
|
||||
|
||||
setup cryptographic volumes for dm-crypt (including LUKS extension)
|
||||
|
||||
WEB PAGE:
|
||||
|
||||
https://gitlab.com/cryptsetup/cryptsetup/
|
||||
|
||||
FAQ:
|
||||
|
||||
https://gitlab.com/cryptsetup/cryptsetup/wikis/FrequentlyAskedQuestions
|
||||
|
||||
MAILING LIST:
|
||||
|
||||
E-MAIL: dm-crypt@saout.de
|
||||
URL: http://www.saout.de/mailman/listinfo/dm-crypt
|
||||
|
||||
DOWNLOAD:
|
||||
|
||||
https://www.kernel.org/pub/linux/utils/cryptsetup/
|
||||
|
||||
SOURCE CODE:
|
||||
|
||||
URL: https://gitlab.com/cryptsetup/cryptsetup/tree/master
|
||||
Checkout: git clone https://gitlab.com/cryptsetup/cryptsetup.git
|
||||
|
||||
NLS (PO TRANSLATIONS):
|
||||
|
||||
PO files are maintained by:
|
||||
http://translationproject.org/domain/cryptsetup.html
|
||||
80
README.md
80
README.md
@@ -2,25 +2,33 @@
|
||||
|
||||
What the ...?
|
||||
=============
|
||||
**Cryptsetup** is utility used to conveniently setup disk encryption based
|
||||
on [DMCrypt](https://gitlab.com/cryptsetup/cryptsetup/wikis/DMCrypt) kernel module.
|
||||
**Cryptsetup** is a utility used to conveniently set up disk encryption based
|
||||
on the [DMCrypt](https://gitlab.com/cryptsetup/cryptsetup/wikis/DMCrypt) kernel module.
|
||||
|
||||
These include **plain** **dm-crypt** volumes, **LUKS** volumes, **loop-AES**
|
||||
and **TrueCrypt** (including **VeraCrypt** extension) format.
|
||||
These include **plain** **dm-crypt** volumes, **LUKS** volumes, **loop-AES**,
|
||||
**TrueCrypt** (including **VeraCrypt** extension) and **BitLocker** formats.
|
||||
|
||||
The project also includes a **veritysetup** utility used to conveniently setup
|
||||
[DMVerity](https://gitlab.com/cryptsetup/cryptsetup/wikis/DMVerity) block integrity checking kernel module
|
||||
and **integritysetup** to setup
|
||||
[DMIntegrity](https://gitlab.com/cryptsetup/cryptsetup/wikis/DMIntegrity) block integrity kernel module.
|
||||
|
||||
Project also includes **veritysetup** utility used to conveniently setup
|
||||
[DMVerity](https://gitlab.com/cryptsetup/cryptsetup/wikis/DMVerity) block integrity checking kernel module.
|
||||
|
||||
LUKS Design
|
||||
-----------
|
||||
**LUKS** is the standard for Linux hard disk encryption. By providing a standard on-disk-format, it does not
|
||||
only facilitate compatibility among distributions, but also provides secure management of multiple user passwords.
|
||||
In contrast to existing solution, LUKS stores all setup necessary setup information in the partition header,
|
||||
enabling the user to transport or migrate his data seamlessly.
|
||||
LUKS stores all necessary setup information in the partition header, enabling to transport or migrate data seamlessly.
|
||||
|
||||
Last version of the LUKS2 format specification is
|
||||
[available here](https://gitlab.com/cryptsetup/LUKS2-docs).
|
||||
|
||||
Last version of the LUKS1 format specification is
|
||||
[available here](https://www.kernel.org/pub/linux/utils/cryptsetup/LUKS_docs/on-disk-format.pdf).
|
||||
|
||||
Why LUKS?
|
||||
---------
|
||||
* compatiblity via standardization,
|
||||
* compatibility via standardization,
|
||||
* secure against low entropy attacks,
|
||||
* support for multiple keys,
|
||||
* effective passphrase revocation,
|
||||
@@ -36,44 +44,50 @@ Download
|
||||
--------
|
||||
All release tarballs and release notes are hosted on [kernel.org](https://www.kernel.org/pub/linux/utils/cryptsetup/).
|
||||
|
||||
**The latest cryptsetup version is 1.7.0**
|
||||
* [cryptsetup-1.7.0.tar.xz](https://www.kernel.org/pub/linux/utils/cryptsetup/v1.7/cryptsetup-1.7.0.tar.xz)
|
||||
* Signature [cryptsetup-1.7.0.tar.sign](https://www.kernel.org/pub/linux/utils/cryptsetup/v1.7/cryptsetup-1.7.0.tar.sign)
|
||||
**The latest stable cryptsetup version is 2.4.0**
|
||||
* [cryptsetup-2.4.0.tar.xz](https://www.kernel.org/pub/linux/utils/cryptsetup/v2.4/cryptsetup-2.4.0.tar.xz)
|
||||
* Signature [cryptsetup-2.4.0.tar.sign](https://www.kernel.org/pub/linux/utils/cryptsetup/v2.4/cryptsetup-2.4.0.tar.sign)
|
||||
_(You need to decompress file first to check signature.)_
|
||||
* [Cryptsetup 1.7.0 Release Notes](https://www.kernel.org/pub/linux/utils/cryptsetup/v1.7/v1.7.0-ReleaseNotes).
|
||||
* [Cryptsetup 2.4.0 Release Notes](https://www.kernel.org/pub/linux/utils/cryptsetup/v2.4/v2.4.0-ReleaseNotes).
|
||||
|
||||
Previous versions
|
||||
* [Version 1.6.8](https://www.kernel.org/pub/linux/utils/cryptsetup/v1.6/cryptsetup-1.6.8.tar.xz) -
|
||||
[Signature](https://www.kernel.org/pub/linux/utils/cryptsetup/v1.6/cryptsetup-1.6.8.tar.sign) -
|
||||
[Release Notes](https://www.kernel.org/pub/linux/utils/cryptsetup/v1.6/v1.6.8-ReleaseNotes).
|
||||
* [Version 1.6.7](https://www.kernel.org/pub/linux/utils/cryptsetup/v1.6/cryptsetup-1.6.7.tar.xz) -
|
||||
[Signature](https://www.kernel.org/pub/linux/utils/cryptsetup/v1.6/cryptsetup-1.6.7.tar.sign) -
|
||||
[Release Notes](https://www.kernel.org/pub/linux/utils/cryptsetup/v1.6/v1.6.7-ReleaseNotes).
|
||||
* [Version 1.6.6](https://www.kernel.org/pub/linux/utils/cryptsetup/v1.6/cryptsetup-1.6.6.tar.xz) -
|
||||
[Signature](https://www.kernel.org/pub/linux/utils/cryptsetup/v1.6/cryptsetup-1.6.6.tar.sign) -
|
||||
[Release Notes](https://www.kernel.org/pub/linux/utils/cryptsetup/v1.6/v1.6.6-ReleaseNotes).
|
||||
* [Version 1.6.5](https://www.kernel.org/pub/linux/utils/cryptsetup/v1.6/cryptsetup-1.6.5.tar.xz) -
|
||||
[Signature](https://www.kernel.org/pub/linux/utils/cryptsetup/v1.6/cryptsetup-1.6.5.tar.sign) -
|
||||
[Release Notes](https://www.kernel.org/pub/linux/utils/cryptsetup/v1.6/v1.6.5-ReleaseNotes).
|
||||
* [Version 1.6.4](https://www.kernel.org/pub/linux/utils/cryptsetup/v1.6/cryptsetup-1.6.4.tar.xz) -
|
||||
[Signature](https://www.kernel.org/pub/linux/utils/cryptsetup/v1.6/cryptsetup-1.6.4.tar.sign) -
|
||||
[Release Notes](https://www.kernel.org/pub/linux/utils/cryptsetup/v1.6/v1.6.4-ReleaseNotes).
|
||||
* [Version 2.3.6](https://www.kernel.org/pub/linux/utils/cryptsetup/v2.3/cryptsetup-2.3.6.tar.xz) -
|
||||
[Signature](https://www.kernel.org/pub/linux/utils/cryptsetup/v2.3/cryptsetup-2.3.6.tar.sign) -
|
||||
[Release Notes](https://www.kernel.org/pub/linux/utils/cryptsetup/v2.3/v2.3.6-ReleaseNotes).
|
||||
* [Version 1.7.5](https://www.kernel.org/pub/linux/utils/cryptsetup/v1.7/cryptsetup-1.7.5.tar.xz) -
|
||||
[Signature](https://www.kernel.org/pub/linux/utils/cryptsetup/v1.7/cryptsetup-1.7.5.tar.sign) -
|
||||
[Release Notes](https://www.kernel.org/pub/linux/utils/cryptsetup/v1.7/v1.7.5-ReleaseNotes).
|
||||
|
||||
Source and API docs
|
||||
-------------------
|
||||
For development version code, please refer to [source](https://gitlab.com/cryptsetup/cryptsetup/tree/master) page,
|
||||
mirror on [kernel.org](https://git.kernel.org/cgit/utils/cryptsetup/cryptsetup.git/) or [GitHub](https://github.com/mbroz/cryptsetup).
|
||||
|
||||
For libcryptsetup documentation see [libcryptsetup API](https://gitlab.com/cryptsetup/cryptsetup/wikis/API/index.html) page.
|
||||
For libcryptsetup documentation see [libcryptsetup API](https://mbroz.fedorapeople.org/libcryptsetup_API/) page.
|
||||
|
||||
NLS PO files are maintained by [TranslationProject](http://translationproject.org/domain/cryptsetup.html).
|
||||
The libcryptsetup API/ABI changes are tracked in [compatibility report](https://abi-laboratory.pro/tracker/timeline/cryptsetup/).
|
||||
|
||||
NLS PO files are maintained by [TranslationProject](https://translationproject.org/domain/cryptsetup.html).
|
||||
|
||||
Required packages
|
||||
-----------------
|
||||
All distributions provide cryptsetup as distro package. If you need to compile cryptsetup youfself, some packages are required for compilation. Please always prefer distro specific build tools to manually configuring cryptsetup.
|
||||
Fo available compile options, check ``configure --help`` for more info. If you are using a git snapshot, you need to generate configure script with ``autogen.sh`` script.
|
||||
|
||||
Here is the list of packages needed for the compilation of project for particular distributions:
|
||||
* For Fedora: `git gcc make autoconf automake gettext-devel pkgconfig openssl-devel popt-devel device-mapper-devel libuuid-devel json-c-devel libblkid-devel findutils libtool libssh-devel tar`. Optionally `libargon2-devel libpwquality-devel`. To run internal testsuite you also need `sharutils device-mapper jq vim-common expect keyutils netcat shadow-utils openssh-clients openssh sshpass`.
|
||||
|
||||
* For Debian and Ubuntu: `git gcc make autoconf automake autopoint pkg-config libtool gettext libssl-dev libdevmapper-dev libpopt-dev uuid-dev libsepol1-dev libjson-c-dev libssh-dev libblkid-dev tar`. Optionally `libargon2-0-dev libpwquality-dev`. To run internal testsuite you also need `sharutils dmsetup jq xxd expect keyutils netcat passwd openssh-client sshpass`
|
||||
|
||||
Note that the list could change as distributions evolve.
|
||||
|
||||
Help!
|
||||
-----
|
||||
Please always read [FAQ](https://gitlab.com/cryptsetup/cryptsetup/wikis/FrequentlyAskedQuestions) first.
|
||||
Please read the [FAQ](https://gitlab.com/cryptsetup/cryptsetup/wikis/FrequentlyAskedQuestions) and search the manuals (man page, man-page) before posting questions in the mailing list. You will be able to ask better questions and better understand the answers. The FAQ is online and in the source code. The man pages are in source and should be available after installation using standard man commands. e.g. man cryptsetup
|
||||
|
||||
For cryptsetup and LUKS related questions, please use the dm-crypt mailing list, [dm-crypt@saout.de](mailto:dm-crypt@saout.de).
|
||||
|
||||
If you want to subscribe just send an empty mail to [dm-crypt-subscribe@saout.de](mailto:dm-crypt-subscribe@saout.de).
|
||||
|
||||
You can also browse [list archive](http://www.saout.de/pipermail/dm-crypt/) or read it through
|
||||
[web interface](http://news.gmane.org/gmane.linux.kernel.device-mapper.dm-crypt).
|
||||
You can also browse [list archive](https://www.saout.de/pipermail/dm-crypt/) or read and search it through
|
||||
[web interface on lore.kernel.org](https://lore.kernel.org/dm-crypt/) or alternatively on [marc.info](https://marc.info/?l=dm-crypt).
|
||||
|
||||
8
TODO
8
TODO
@@ -1,8 +0,0 @@
|
||||
Version 1.7:
|
||||
- Export wipe device functions
|
||||
- Support K/M suffixes for align payload (new switch?).
|
||||
- TRIM for keyslots
|
||||
- Do we need crypt_data_path() - path to data device (if differs)?
|
||||
- Resync ETA time is not accurate, calculate it better (last minute window?).
|
||||
- Extend existing LUKS header to use another KDF? (https://password-hashing.net/)
|
||||
- Fix all crazy automake warnings (or switch to Cmake).
|
||||
48
autogen.sh
48
autogen.sh
@@ -9,25 +9,31 @@ DIE=0
|
||||
(autopoint --version) < /dev/null > /dev/null 2>&1 || {
|
||||
echo
|
||||
echo "**Error**: You must have autopoint installed."
|
||||
echo "Download the appropriate package for your distribution,"
|
||||
echo "or see http://www.gnu.org/software/gettext"
|
||||
echo "Download the appropriate package for your distribution."
|
||||
DIE=1
|
||||
}
|
||||
|
||||
|
||||
(msgfmt --version) < /dev/null > /dev/null 2>&1 || {
|
||||
echo
|
||||
echo "**Warning**: You should have gettext installed."
|
||||
echo "Download the appropriate package for your distribution."
|
||||
echo "To disable translation, you can also use --disable-nls"
|
||||
echo "configure option."
|
||||
}
|
||||
|
||||
(autoconf --version) < /dev/null > /dev/null 2>&1 || {
|
||||
echo
|
||||
echo "**Error**: You must have autoconf installed to."
|
||||
echo "Download the appropriate package for your distribution,"
|
||||
echo "or get the source tarball at ftp://ftp.gnu.org/pub/gnu/"
|
||||
echo "**Error**: You must have autoconf installed."
|
||||
echo "Download the appropriate package for your distribution."
|
||||
DIE=1
|
||||
}
|
||||
|
||||
(grep "^AM_PROG_LIBTOOL" $srcdir/configure.ac >/dev/null) && {
|
||||
(libtool --version) < /dev/null > /dev/null 2>&1 || {
|
||||
(grep "^LT_INIT" $srcdir/configure.ac >/dev/null) && {
|
||||
(libtoolize --version) < /dev/null > /dev/null 2>&1 || {
|
||||
echo
|
||||
echo "**Error**: You must have libtool installed."
|
||||
echo "Get ftp://ftp.gnu.org/pub/gnu/"
|
||||
echo "(or a newer version if it is available)"
|
||||
echo "**Error**: You must have libtoolize installed."
|
||||
echo "Download the appropriate package for your distribution."
|
||||
DIE=1
|
||||
}
|
||||
}
|
||||
@@ -35,8 +41,7 @@ DIE=0
|
||||
(automake --version) < /dev/null > /dev/null 2>&1 || {
|
||||
echo
|
||||
echo "**Error**: You must have automake installed."
|
||||
echo "Get ftp://ftp.gnu.org/pub/gnu/"
|
||||
echo "(or a newer version if it is available)"
|
||||
echo "Download the appropriate package for your distribution."
|
||||
DIE=1
|
||||
NO_AUTOMAKE=yes
|
||||
}
|
||||
@@ -47,8 +52,6 @@ test -n "$NO_AUTOMAKE" || (aclocal --version) < /dev/null > /dev/null 2>&1 || {
|
||||
echo
|
||||
echo "**Error**: Missing aclocal. The version of automake"
|
||||
echo "installed doesn't appear recent enough."
|
||||
echo "Get ftp://ftp.gnu.org/pub/gnu/"
|
||||
echo "(or a newer version if it is available)"
|
||||
DIE=1
|
||||
}
|
||||
|
||||
@@ -56,13 +59,6 @@ if test "$DIE" -eq 1; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if test -z "$*"; then
|
||||
echo
|
||||
echo "**Warning**: I am going to run 'configure' with no arguments."
|
||||
echo "If you wish to pass any to it, please specify them on the"
|
||||
echo \'$0\'" command line."
|
||||
fi
|
||||
|
||||
echo
|
||||
echo "Generate build-system by:"
|
||||
echo " autopoint: $(autopoint --version | head -1)"
|
||||
@@ -81,10 +77,6 @@ autoheader $AH_OPTS
|
||||
automake --add-missing --copy --gnu $AM_OPTS
|
||||
autoconf $AC_OPTS
|
||||
|
||||
if test x$NOCONFIGURE = x; then
|
||||
echo Running $srcdir/configure $conf_flags "$@" ...
|
||||
$srcdir/configure $conf_flags "$@" \
|
||||
&& echo Now type \`make\' to compile $PKG_NAME
|
||||
else
|
||||
echo Skipping configure process.
|
||||
fi
|
||||
echo
|
||||
echo "Now type '$srcdir/configure' and 'make' to compile."
|
||||
echo
|
||||
|
||||
432
configure.ac
432
configure.ac
@@ -1,9 +1,9 @@
|
||||
AC_PREREQ([2.67])
|
||||
AC_INIT([cryptsetup],[1.7.1-git])
|
||||
AC_INIT([cryptsetup],[2.4.0])
|
||||
|
||||
dnl library version from <major>.<minor>.<release>[-<suffix>]
|
||||
LIBCRYPTSETUP_VERSION=$(echo $PACKAGE_VERSION | cut -f1 -d-)
|
||||
LIBCRYPTSETUP_VERSION_INFO=11:0:7
|
||||
LIBCRYPTSETUP_VERSION_INFO=19:0:7
|
||||
|
||||
AM_SILENT_RULES([yes])
|
||||
AC_CONFIG_SRCDIR(src/cryptsetup.c)
|
||||
@@ -15,8 +15,8 @@ AC_CONFIG_HEADERS([config.h:config.h.in])
|
||||
# http://lists.gnu.org/archive/html/automake/2013-01/msg00060.html
|
||||
|
||||
# For old automake use this
|
||||
#AM_INIT_AUTOMAKE(dist-xz)
|
||||
AM_INIT_AUTOMAKE([dist-xz 1.12 serial-tests])
|
||||
#AM_INIT_AUTOMAKE(dist-xz subdir-objects)
|
||||
AM_INIT_AUTOMAKE([dist-xz 1.12 serial-tests subdir-objects foreign])
|
||||
|
||||
if test "x$prefix" = "xNONE"; then
|
||||
sysconfdir=/etc
|
||||
@@ -30,27 +30,81 @@ AM_PROG_CC_C_O
|
||||
AC_PROG_CPP
|
||||
AC_PROG_INSTALL
|
||||
AC_PROG_MAKE_SET
|
||||
AC_PROG_MKDIR_P
|
||||
AC_ENABLE_STATIC(no)
|
||||
LT_INIT
|
||||
PKG_PROG_PKG_CONFIG
|
||||
AM_ICONV
|
||||
|
||||
dnl ==========================================================================
|
||||
dnl define PKG_CHECK_VAR for old pkg-config <= 0.28
|
||||
m4_ifndef([AS_VAR_COPY],
|
||||
[m4_define([AS_VAR_COPY],
|
||||
[AS_LITERAL_IF([$1[]$2], [$1=$$2], [eval $1=\$$2])])
|
||||
])
|
||||
m4_ifndef([PKG_CHECK_VAR], [
|
||||
AC_DEFUN([PKG_CHECK_VAR],
|
||||
[AC_REQUIRE([PKG_PROG_PKG_CONFIG])
|
||||
AC_ARG_VAR([$1], [value of $3 for $2, overriding pkg-config])
|
||||
|
||||
_PKG_CONFIG([$1], [variable="][$3]["], [$2])
|
||||
AS_VAR_COPY([$1], [pkg_cv_][$1])
|
||||
|
||||
AS_VAR_IF([$1], [""], [$5], [$4])
|
||||
])
|
||||
])
|
||||
dnl ==========================================================================
|
||||
|
||||
AC_C_RESTRICT
|
||||
|
||||
AC_HEADER_DIRENT
|
||||
AC_HEADER_STDC
|
||||
AC_CHECK_HEADERS(fcntl.h malloc.h inttypes.h sys/ioctl.h sys/mman.h \
|
||||
ctype.h unistd.h locale.h byteswap.h endian.h)
|
||||
sys/sysmacros.h sys/statvfs.h ctype.h unistd.h locale.h byteswap.h endian.h stdint.h)
|
||||
AC_CHECK_DECLS([O_CLOEXEC],,[AC_DEFINE([O_CLOEXEC],[0], [Defined to 0 if not provided])],
|
||||
[[
|
||||
#ifdef HAVE_FCNTL_H
|
||||
# include <fcntl.h>
|
||||
#endif
|
||||
]])
|
||||
|
||||
AC_CHECK_HEADERS(uuid/uuid.h,,[AC_MSG_ERROR([You need the uuid library.])])
|
||||
AC_CHECK_HEADER(libdevmapper.h,,[AC_MSG_ERROR([You need the device-mapper library.])])
|
||||
|
||||
AC_ARG_ENABLE([keyring],
|
||||
AS_HELP_STRING([--disable-keyring], [disable kernel keyring support and builtin kernel keyring token]),
|
||||
[], [enable_keyring=yes])
|
||||
if test "x$enable_keyring" = "xyes"; then
|
||||
AC_CHECK_HEADERS(linux/keyctl.h,,[AC_MSG_ERROR([You need Linux kernel headers with kernel keyring service compiled.])])
|
||||
|
||||
dnl ==========================================================================
|
||||
dnl check whether kernel is compiled with kernel keyring service syscalls
|
||||
AC_CHECK_DECL(__NR_add_key,,[AC_MSG_ERROR([The kernel is missing add_key syscall.])], [#include <syscall.h>])
|
||||
AC_CHECK_DECL(__NR_keyctl,,[AC_MSG_ERROR([The kernel is missing keyctl syscall.])], [#include <syscall.h>])
|
||||
AC_CHECK_DECL(__NR_request_key,,[AC_MSG_ERROR([The kernel is missing request_key syscall.])], [#include <syscall.h>])
|
||||
|
||||
dnl ==========================================================================
|
||||
dnl check that key_serial_t hasn't been adopted yet in stdlib
|
||||
AC_CHECK_TYPES([key_serial_t], [], [], [
|
||||
AC_INCLUDES_DEFAULT
|
||||
#ifdef HAVE_LINUX_KEYCTL_H
|
||||
# include <linux/keyctl.h>
|
||||
#endif
|
||||
])
|
||||
|
||||
AC_DEFINE(KERNEL_KEYRING, 1, [Enable kernel keyring service support])
|
||||
fi
|
||||
AM_CONDITIONAL(KERNEL_KEYRING, test "x$enable_keyring" = "xyes")
|
||||
|
||||
saved_LIBS=$LIBS
|
||||
AC_CHECK_LIB(uuid, uuid_clear, ,[AC_MSG_ERROR([You need the uuid library.])])
|
||||
AC_SUBST(UUID_LIBS, $LIBS)
|
||||
LIBS=$saved_LIBS
|
||||
|
||||
AC_SEARCH_LIBS([clock_gettime],[rt posix4])
|
||||
AC_CHECK_FUNCS([posix_memalign clock_gettime])
|
||||
AC_CHECK_FUNCS([posix_memalign clock_gettime posix_fallocate explicit_bzero])
|
||||
|
||||
if test "x$enable_largefile" = "xno" ; then
|
||||
if test "x$enable_largefile" = "xno"; then
|
||||
AC_MSG_ERROR([Building with --disable-largefile is not supported, it can cause data corruption.])
|
||||
fi
|
||||
|
||||
@@ -62,10 +116,29 @@ AC_FUNC_FSEEKO
|
||||
AC_PROG_GCC_TRADITIONAL
|
||||
AC_FUNC_STRERROR_R
|
||||
|
||||
dnl ==========================================================================
|
||||
dnl LUKS2 external tokens
|
||||
|
||||
AC_ARG_ENABLE([external-tokens],
|
||||
AS_HELP_STRING([--disable-external-tokens], [disable external LUKS2 tokens]),
|
||||
[], [enable_external_tokens=yes])
|
||||
if test "x$enable_external_tokens" = "xyes"; then
|
||||
AC_DEFINE(USE_EXTERNAL_TOKENS, 1, [Use external tokens])
|
||||
fi
|
||||
|
||||
AC_ARG_ENABLE([ssh-token],
|
||||
AS_HELP_STRING([--disable-ssh-token], [disable LUKS2 ssh-token]),
|
||||
[], [enable_ssh_token=yes])
|
||||
AM_CONDITIONAL(SSHPLUGIN_TOKEN, test "x$enable_ssh_token" = "xyes")
|
||||
|
||||
if test "x$enable_ssh_token" = "xyes" -a "x$enable_external_tokens" = "xno"; then
|
||||
AC_MSG_ERROR([Requested LUKS2 ssh-token build, but external tokens are disabled.])
|
||||
fi
|
||||
|
||||
dnl ==========================================================================
|
||||
|
||||
AM_GNU_GETTEXT([external],[need-ngettext])
|
||||
AM_GNU_GETTEXT_VERSION([0.15])
|
||||
AM_GNU_GETTEXT_VERSION([0.18.3])
|
||||
|
||||
dnl ==========================================================================
|
||||
|
||||
@@ -76,12 +149,10 @@ AC_SUBST(POPT_LIBS, $LIBS)
|
||||
LIBS=$saved_LIBS
|
||||
|
||||
dnl ==========================================================================
|
||||
dnl FIPS extensions (only for RHEL)
|
||||
AC_ARG_ENABLE([fips], AS_HELP_STRING([--enable-fips],[enable FIPS mode restrictions]),
|
||||
[with_fips=$enableval],
|
||||
[with_fips=no])
|
||||
|
||||
if test "x$with_fips" = "xyes"; then
|
||||
dnl FIPS extensions
|
||||
AC_ARG_ENABLE([fips],
|
||||
AS_HELP_STRING([--enable-fips], [enable FIPS mode restrictions]))
|
||||
if test "x$enable_fips" = "xyes"; then
|
||||
AC_DEFINE(ENABLE_FIPS, 1, [Enable FIPS mode restrictions])
|
||||
|
||||
if test "x$enable_static" = "xyes" -o "x$enable_static_cryptsetup" = "xyes" ; then
|
||||
@@ -90,7 +161,7 @@ if test "x$with_fips" = "xyes"; then
|
||||
fi
|
||||
|
||||
AC_DEFUN([NO_FIPS], [
|
||||
if test "x$with_fips" = "xyes"; then
|
||||
if test "x$enable_fips" = "xyes"; then
|
||||
AC_MSG_ERROR([This option is not compatible with FIPS.])
|
||||
fi
|
||||
])
|
||||
@@ -98,12 +169,9 @@ AC_DEFUN([NO_FIPS], [
|
||||
dnl ==========================================================================
|
||||
dnl pwquality library (cryptsetup CLI only)
|
||||
AC_ARG_ENABLE([pwquality],
|
||||
AS_HELP_STRING([--enable-pwquality],
|
||||
[enable password quality checking using pwquality library]),
|
||||
[with_pwquality=$enableval],
|
||||
[with_pwquality=no])
|
||||
AS_HELP_STRING([--enable-pwquality], [enable password quality checking using pwquality library]))
|
||||
|
||||
if test "x$with_pwquality" = "xyes"; then
|
||||
if test "x$enable_pwquality" = "xyes"; then
|
||||
AC_DEFINE(ENABLE_PWQUALITY, 1, [Enable password quality checking using pwquality library])
|
||||
PKG_CHECK_MODULES([PWQUALITY], [pwquality >= 1.0.0],,
|
||||
AC_MSG_ERROR([You need pwquality library.]))
|
||||
@@ -115,13 +183,11 @@ fi
|
||||
dnl ==========================================================================
|
||||
dnl passwdqc library (cryptsetup CLI only)
|
||||
AC_ARG_ENABLE([passwdqc],
|
||||
AS_HELP_STRING([--enable-passwdqc@<:@=CONFIG_PATH@:>@],
|
||||
[enable password quality checking using passwdqc library (optionally with CONFIG_PATH)]),
|
||||
[enable_passwdqc=$enableval],
|
||||
[enable_passwdqc=no])
|
||||
AS_HELP_STRING([--enable-passwdqc@<:@=CONFIG_PATH@:>@],
|
||||
[enable password quality checking using passwdqc library (optionally with CONFIG_PATH)]))
|
||||
|
||||
case "$enable_passwdqc" in
|
||||
yes|no) use_passwdqc_config="" ;;
|
||||
""|yes|no) use_passwdqc_config="" ;;
|
||||
/*) use_passwdqc_config="$enable_passwdqc"; enable_passwdqc=yes ;;
|
||||
*) AC_MSG_ERROR([Unrecognized --enable-passwdqc parameter.]) ;;
|
||||
esac
|
||||
@@ -130,10 +196,18 @@ AC_DEFINE_UNQUOTED([PASSWDQC_CONFIG_FILE], ["$use_passwdqc_config"], [passwdqc l
|
||||
if test "x$enable_passwdqc" = "xyes"; then
|
||||
AC_DEFINE(ENABLE_PASSWDQC, 1, [Enable password quality checking using passwdqc library])
|
||||
|
||||
PASSWDQC_LIBS="-lpasswdqc"
|
||||
saved_LIBS="$LIBS"
|
||||
AC_SEARCH_LIBS([passwdqc_check], [passwdqc])
|
||||
case "$ac_cv_search_passwdqc_check" in
|
||||
no) AC_MSG_ERROR([failed to find passwdqc_check]) ;;
|
||||
-l*) PASSWDQC_LIBS="$ac_cv_search_passwdqc_check" ;;
|
||||
*) PASSWDQC_LIBS= ;;
|
||||
esac
|
||||
AC_CHECK_FUNCS([passwdqc_params_free])
|
||||
LIBS="$saved_LIBS"
|
||||
fi
|
||||
|
||||
if test "x$with_pwquality$enable_passwdqc" = "xyesyes"; then
|
||||
if test "x$enable_pwquality$enable_passwdqc" = "xyesyes"; then
|
||||
AC_MSG_ERROR([--enable-pwquality and --enable-passwdqc are mutually incompatible.])
|
||||
fi
|
||||
|
||||
@@ -141,20 +215,26 @@ dnl ==========================================================================
|
||||
dnl Crypto backend functions
|
||||
|
||||
AC_DEFUN([CONFIGURE_GCRYPT], [
|
||||
if test "x$with_fips" = "xyes"; then
|
||||
if test "x$enable_fips" = "xyes"; then
|
||||
GCRYPT_REQ_VERSION=1.4.5
|
||||
else
|
||||
GCRYPT_REQ_VERSION=1.1.42
|
||||
fi
|
||||
dnl Check if we can use gcrypt PBKDF2 (1.6.0 supports empty password)
|
||||
AC_ARG_ENABLE([gcrypt-pbkdf2], AS_HELP_STRING([--enable-gcrypt-pbkdf2],[force enable internal gcrypt PBKDF2]),
|
||||
|
||||
dnl libgcrypt rejects to use pkgconfig, use AM_PATH_LIBGCRYPT from gcrypt-devel here.
|
||||
dnl Do not require gcrypt-devel if other crypto backend is used.
|
||||
m4_ifdef([AM_PATH_LIBGCRYPT],[
|
||||
AC_ARG_ENABLE([gcrypt-pbkdf2],
|
||||
dnl Check if we can use gcrypt PBKDF2 (1.6.0 supports empty password)
|
||||
AS_HELP_STRING([--enable-gcrypt-pbkdf2], [force enable internal gcrypt PBKDF2]),
|
||||
if test "x$enableval" = "xyes"; then
|
||||
[use_internal_pbkdf2=0]
|
||||
else
|
||||
[use_internal_pbkdf2=1]
|
||||
fi,
|
||||
[AM_PATH_LIBGCRYPT([1.6.1], [use_internal_pbkdf2=0], [use_internal_pbkdf2=1])])
|
||||
AM_PATH_LIBGCRYPT($GCRYPT_REQ_VERSION,,[AC_MSG_ERROR([You need the gcrypt library.])])
|
||||
AM_PATH_LIBGCRYPT($GCRYPT_REQ_VERSION,,[AC_MSG_ERROR([You need the gcrypt library.])])],
|
||||
AC_MSG_ERROR([Missing support for gcrypt: install gcrypt and regenerate configure.]))
|
||||
|
||||
AC_MSG_CHECKING([if internal cryptsetup PBKDF2 is compiled-in])
|
||||
if test $use_internal_pbkdf2 = 0; then
|
||||
@@ -164,7 +244,9 @@ AC_DEFUN([CONFIGURE_GCRYPT], [
|
||||
NO_FIPS([])
|
||||
fi
|
||||
|
||||
if test x$enable_static_cryptsetup = xyes; then
|
||||
AC_CHECK_DECLS([GCRY_CIPHER_MODE_XTS], [], [], [#include <gcrypt.h>])
|
||||
|
||||
if test "x$enable_static_cryptsetup" = "xyes"; then
|
||||
saved_LIBS=$LIBS
|
||||
LIBS="$saved_LIBS $LIBGCRYPT_LIBS -static"
|
||||
AC_CHECK_LIB(gcrypt, gcry_check_version,,
|
||||
@@ -188,18 +270,17 @@ AC_DEFUN([CONFIGURE_OPENSSL], [
|
||||
CRYPTO_LIBS=$OPENSSL_LIBS
|
||||
use_internal_pbkdf2=0
|
||||
|
||||
if test x$enable_static_cryptsetup = xyes; then
|
||||
if test "x$enable_static_cryptsetup" = "xyes"; then
|
||||
saved_PKG_CONFIG=$PKG_CONFIG
|
||||
PKG_CONFIG="$PKG_CONFIG --static"
|
||||
PKG_CHECK_MODULES([OPENSSL_STATIC], [openssl])
|
||||
CRYPTO_STATIC_LIBS=$OPENSSL_STATIC_LIBS
|
||||
PKG_CONFIG=$saved_PKG_CONFIG
|
||||
fi
|
||||
NO_FIPS([])
|
||||
])
|
||||
|
||||
AC_DEFUN([CONFIGURE_NSS], [
|
||||
if test x$enable_static_cryptsetup = xyes; then
|
||||
if test "x$enable_static_cryptsetup" = "xyes"; then
|
||||
AC_MSG_ERROR([Static build of cryptsetup is not supported with NSS.])
|
||||
fi
|
||||
|
||||
@@ -232,6 +313,7 @@ AC_DEFUN([CONFIGURE_KERNEL], [
|
||||
AC_DEFUN([CONFIGURE_NETTLE], [
|
||||
AC_CHECK_HEADERS(nettle/sha.h,,
|
||||
[AC_MSG_ERROR([You need Nettle cryptographic library.])])
|
||||
AC_CHECK_HEADERS(nettle/version.h)
|
||||
|
||||
saved_LIBS=$LIBS
|
||||
AC_CHECK_LIB(nettle, nettle_pbkdf2_hmac_sha256,,
|
||||
@@ -248,33 +330,42 @@ dnl ==========================================================================
|
||||
saved_LIBS=$LIBS
|
||||
|
||||
AC_ARG_ENABLE([static-cryptsetup],
|
||||
AS_HELP_STRING([--enable-static-cryptsetup],
|
||||
[enable build of static cryptsetup binary]))
|
||||
if test x$enable_static_cryptsetup = xyes; then
|
||||
if test x$enable_static = xno; then
|
||||
AS_HELP_STRING([--enable-static-cryptsetup], [enable build of static version of tools]))
|
||||
if test "x$enable_static_cryptsetup" = "xyes"; then
|
||||
if test "x$enable_static" = "xno"; then
|
||||
AC_MSG_WARN([Requested static cryptsetup build, enabling static library.])
|
||||
enable_static=yes
|
||||
fi
|
||||
fi
|
||||
AM_CONDITIONAL(STATIC_TOOLS, test x$enable_static_cryptsetup = xyes)
|
||||
AM_CONDITIONAL(STATIC_TOOLS, test "x$enable_static_cryptsetup" = "xyes")
|
||||
|
||||
AC_ARG_ENABLE(veritysetup,
|
||||
AS_HELP_STRING([--disable-veritysetup],
|
||||
[disable veritysetup support]),[], [enable_veritysetup=yes])
|
||||
AM_CONDITIONAL(VERITYSETUP, test x$enable_veritysetup = xyes)
|
||||
AC_ARG_ENABLE([cryptsetup],
|
||||
AS_HELP_STRING([--disable-cryptsetup], [disable cryptsetup support]),
|
||||
[], [enable_cryptsetup=yes])
|
||||
AM_CONDITIONAL(CRYPTSETUP, test "x$enable_cryptsetup" = "xyes")
|
||||
|
||||
AC_ARG_ENABLE([veritysetup],
|
||||
AS_HELP_STRING([--disable-veritysetup], [disable veritysetup support]),
|
||||
[], [enable_veritysetup=yes])
|
||||
AM_CONDITIONAL(VERITYSETUP, test "x$enable_veritysetup" = "xyes")
|
||||
|
||||
AC_ARG_ENABLE([cryptsetup-reencrypt],
|
||||
AS_HELP_STRING([--enable-cryptsetup-reencrypt],
|
||||
[enable cryptsetup-reencrypt tool]))
|
||||
AM_CONDITIONAL(REENCRYPT, test x$enable_cryptsetup_reencrypt = xyes)
|
||||
AS_HELP_STRING([--disable-cryptsetup-reencrypt], [disable cryptsetup-reencrypt tool]),
|
||||
[], [enable_cryptsetup_reencrypt=yes])
|
||||
AM_CONDITIONAL(REENCRYPT, test "x$enable_cryptsetup_reencrypt" = "xyes")
|
||||
|
||||
AC_ARG_ENABLE(selinux,
|
||||
AS_HELP_STRING([--disable-selinux],
|
||||
[disable selinux support [default=auto]]),[], [])
|
||||
AC_ARG_ENABLE([integritysetup],
|
||||
AS_HELP_STRING([--disable-integritysetup], [disable integritysetup support]),
|
||||
[], [enable_integritysetup=yes])
|
||||
AM_CONDITIONAL(INTEGRITYSETUP, test "x$enable_integritysetup" = "xyes")
|
||||
|
||||
AC_ARG_ENABLE([selinux],
|
||||
AS_HELP_STRING([--disable-selinux], [disable selinux support [default=auto]]),
|
||||
[], [enable_selinux=yes])
|
||||
|
||||
AC_ARG_ENABLE([udev],
|
||||
AS_HELP_STRING([--disable-udev],
|
||||
[disable udev support]),[], enable_udev=yes)
|
||||
AS_HELP_STRING([--disable-udev], [disable udev support]),
|
||||
[], [enable_udev=yes])
|
||||
|
||||
dnl Try to use pkg-config for devmapper, but fallback to old detection
|
||||
PKG_CHECK_MODULES([DEVMAPPER], [devmapper >= 1.02.03],, [
|
||||
@@ -289,6 +380,11 @@ LIBS=$saved_LIBS
|
||||
LIBS="$LIBS $DEVMAPPER_LIBS"
|
||||
AC_CHECK_DECLS([dm_task_secure_data], [], [], [#include <libdevmapper.h>])
|
||||
AC_CHECK_DECLS([dm_task_retry_remove], [], [], [#include <libdevmapper.h>])
|
||||
AC_CHECK_DECLS([dm_task_deferred_remove], [], [], [#include <libdevmapper.h>])
|
||||
AC_CHECK_DECLS([dm_device_has_mounted_fs], [], [], [#include <libdevmapper.h>])
|
||||
AC_CHECK_DECLS([dm_device_has_holders], [], [], [#include <libdevmapper.h>])
|
||||
AC_CHECK_DECLS([dm_device_get_name], [], [], [#include <libdevmapper.h>])
|
||||
AC_CHECK_DECLS([DM_DEVICE_GET_TARGET_VERSION], [], [], [#include <libdevmapper.h>])
|
||||
AC_CHECK_DECLS([DM_UDEV_DISABLE_DISK_RULES_FLAG], [have_cookie=yes], [have_cookie=no], [#include <libdevmapper.h>])
|
||||
if test "x$enable_udev" = xyes; then
|
||||
if test "x$have_cookie" = xno; then
|
||||
@@ -299,19 +395,28 @@ if test "x$enable_udev" = xyes; then
|
||||
fi
|
||||
LIBS=$saved_LIBS
|
||||
|
||||
dnl Check for JSON-C used in LUKS2
|
||||
PKG_CHECK_MODULES([JSON_C], [json-c])
|
||||
AC_CHECK_DECLS([json_object_object_add_ex], [], [], [#include <json-c/json.h>])
|
||||
AC_CHECK_DECLS([json_object_deep_copy], [], [], [#include <json-c/json.h>])
|
||||
|
||||
dnl Check for libssh for SSH plugin
|
||||
if test "x$enable_ssh_token" = "xyes"; then
|
||||
PKG_CHECK_MODULES([LIBSSH], [libssh])
|
||||
AC_CHECK_DECLS([ssh_session_is_known_server], [], [], [#include <libssh/libssh.h>])
|
||||
fi
|
||||
|
||||
dnl Crypto backend configuration.
|
||||
AC_ARG_WITH([crypto_backend],
|
||||
AS_HELP_STRING([--with-crypto_backend=BACKEND], [crypto backend (gcrypt/openssl/nss/kernel/nettle) [gcrypt]]),
|
||||
[], with_crypto_backend=gcrypt
|
||||
)
|
||||
AS_HELP_STRING([--with-crypto_backend=BACKEND], [crypto backend (gcrypt/openssl/nss/kernel/nettle) [openssl]]),
|
||||
[], [with_crypto_backend=openssl])
|
||||
|
||||
dnl Kernel crypto API backend needed for benchmark and tcrypt
|
||||
AC_ARG_ENABLE([kernel_crypto], AS_HELP_STRING([--disable-kernel_crypto],
|
||||
[disable kernel userspace crypto (no benchmark and tcrypt)]),
|
||||
[with_kernel_crypto=$enableval],
|
||||
[with_kernel_crypto=yes])
|
||||
AC_ARG_ENABLE([kernel_crypto],
|
||||
AS_HELP_STRING([--disable-kernel_crypto], [disable kernel userspace crypto (no benchmark and tcrypt)]),
|
||||
[], [enable_kernel_crypto=yes])
|
||||
|
||||
if test "x$with_kernel_crypto" = "xyes"; then
|
||||
if test "x$enable_kernel_crypto" = "xyes"; then
|
||||
AC_CHECK_HEADERS(linux/if_alg.h,,
|
||||
[AC_MSG_ERROR([You need Linux kernel headers with userspace crypto interface. (Or use --disable-kernel_crypto.)])])
|
||||
AC_DEFINE(ENABLE_AF_ALG, 1, [Enable using of kernel userspace crypto])
|
||||
@@ -325,17 +430,88 @@ case $with_crypto_backend in
|
||||
nettle) CONFIGURE_NETTLE([]) ;;
|
||||
*) AC_MSG_ERROR([Unknown crypto backend.]) ;;
|
||||
esac
|
||||
AM_CONDITIONAL(CRYPTO_BACKEND_GCRYPT, test $with_crypto_backend = gcrypt)
|
||||
AM_CONDITIONAL(CRYPTO_BACKEND_OPENSSL, test $with_crypto_backend = openssl)
|
||||
AM_CONDITIONAL(CRYPTO_BACKEND_NSS, test $with_crypto_backend = nss)
|
||||
AM_CONDITIONAL(CRYPTO_BACKEND_KERNEL, test $with_crypto_backend = kernel)
|
||||
AM_CONDITIONAL(CRYPTO_BACKEND_NETTLE, test $with_crypto_backend = nettle)
|
||||
AM_CONDITIONAL(CRYPTO_BACKEND_GCRYPT, test "$with_crypto_backend" = "gcrypt")
|
||||
AM_CONDITIONAL(CRYPTO_BACKEND_OPENSSL, test "$with_crypto_backend" = "openssl")
|
||||
AM_CONDITIONAL(CRYPTO_BACKEND_NSS, test "$with_crypto_backend" = "nss")
|
||||
AM_CONDITIONAL(CRYPTO_BACKEND_KERNEL, test "$with_crypto_backend" = "kernel")
|
||||
AM_CONDITIONAL(CRYPTO_BACKEND_NETTLE, test "$with_crypto_backend" = "nettle")
|
||||
|
||||
AM_CONDITIONAL(CRYPTO_INTERNAL_PBKDF2, test $use_internal_pbkdf2 = 1)
|
||||
AC_DEFINE_UNQUOTED(USE_INTERNAL_PBKDF2, [$use_internal_pbkdf2], [Use internal PBKDF2])
|
||||
|
||||
dnl Argon2 implementation
|
||||
AC_ARG_ENABLE([internal-argon2],
|
||||
AS_HELP_STRING([--disable-internal-argon2], [disable internal implementation of Argon2 PBKDF]),
|
||||
[], [enable_internal_argon2=yes])
|
||||
|
||||
AC_ARG_ENABLE([libargon2],
|
||||
AS_HELP_STRING([--enable-libargon2], [enable external libargon2 (PHC) library (disables internal bundled version)]))
|
||||
|
||||
if test "x$enable_libargon2" = "xyes" ; then
|
||||
AC_CHECK_HEADERS(argon2.h,,
|
||||
[AC_MSG_ERROR([You need libargon2 development library installed.])])
|
||||
AC_CHECK_DECL(Argon2_id,,[AC_MSG_ERROR([You need more recent Argon2 library with support for Argon2id.])], [#include <argon2.h>])
|
||||
PKG_CHECK_MODULES([LIBARGON2], [libargon2],,[LIBARGON2_LIBS="-largon2"])
|
||||
enable_internal_argon2=no
|
||||
else
|
||||
AC_MSG_WARN([Argon2 bundled (slow) reference implementation will be used, please consider to use system library with --enable-libargon2.])
|
||||
|
||||
AC_ARG_ENABLE([internal-sse-argon2],
|
||||
AS_HELP_STRING([--enable-internal-sse-argon2], [enable internal SSE implementation of Argon2 PBKDF]))
|
||||
|
||||
if test "x$enable_internal_sse_argon2" = "xyes"; then
|
||||
AC_MSG_CHECKING(if Argon2 SSE optimization can be used)
|
||||
AC_LINK_IFELSE([AC_LANG_PROGRAM([[
|
||||
#include <emmintrin.h>
|
||||
__m128i testfunc(__m128i *a, __m128i *b) {
|
||||
return _mm_xor_si128(_mm_loadu_si128(a), _mm_loadu_si128(b));
|
||||
}
|
||||
]])],,[enable_internal_sse_argon2=no])
|
||||
AC_MSG_RESULT($enable_internal_sse_argon2)
|
||||
fi
|
||||
fi
|
||||
|
||||
if test "x$enable_internal_argon2" = "xyes"; then
|
||||
AC_DEFINE(USE_INTERNAL_ARGON2, 1, [Use internal Argon2])
|
||||
fi
|
||||
AM_CONDITIONAL(CRYPTO_INTERNAL_ARGON2, test "x$enable_internal_argon2" = "xyes")
|
||||
AM_CONDITIONAL(CRYPTO_INTERNAL_SSE_ARGON2, test "x$enable_internal_sse_argon2" = "xyes")
|
||||
|
||||
dnl Link with blkid to check for other device types
|
||||
AC_ARG_ENABLE([blkid],
|
||||
AS_HELP_STRING([--disable-blkid], [disable use of blkid for device signature detection and wiping]),
|
||||
[], [enable_blkid=yes])
|
||||
|
||||
if test "x$enable_blkid" = "xyes"; then
|
||||
PKG_CHECK_MODULES([BLKID], [blkid],[AC_DEFINE([HAVE_BLKID], 1, [Define to 1 to use blkid for detection of disk signatures.])],[LIBBLKID_LIBS="-lblkid"])
|
||||
|
||||
AC_CHECK_HEADERS(blkid/blkid.h,,[AC_MSG_ERROR([You need blkid development library installed.])])
|
||||
AC_CHECK_DECL([blkid_do_wipe],
|
||||
[ AC_DEFINE([HAVE_BLKID_WIPE], 1, [Define to 1 to use blkid_do_wipe.])
|
||||
enable_blkid_wipe=yes
|
||||
],,
|
||||
[#include <blkid/blkid.h>])
|
||||
AC_CHECK_DECL([blkid_probe_step_back],
|
||||
[ AC_DEFINE([HAVE_BLKID_STEP_BACK], 1, [Define to 1 to use blkid_probe_step_back.])
|
||||
enable_blkid_step_back=yes
|
||||
],,
|
||||
[#include <blkid/blkid.h>])
|
||||
AC_CHECK_DECLS([ blkid_reset_probe,
|
||||
blkid_probe_set_device,
|
||||
blkid_probe_filter_superblocks_type,
|
||||
blkid_do_safeprobe,
|
||||
blkid_do_probe,
|
||||
blkid_probe_lookup_value
|
||||
],,
|
||||
[AC_MSG_ERROR([Can not compile with blkid support, disable it by --disable-blkid.])],
|
||||
[#include <blkid/blkid.h>])
|
||||
fi
|
||||
AM_CONDITIONAL(HAVE_BLKID, test "x$enable_blkid" = "xyes")
|
||||
AM_CONDITIONAL(HAVE_BLKID_WIPE, test "x$enable_blkid_wipe" = "xyes")
|
||||
AM_CONDITIONAL(HAVE_BLKID_STEP_BACK, test "x$enable_blkid_step_back" = "xyes")
|
||||
|
||||
dnl Magic for cryptsetup.static build.
|
||||
if test x$enable_static_cryptsetup = xyes; then
|
||||
if test "x$enable_static_cryptsetup" = "xyes"; then
|
||||
saved_PKG_CONFIG=$PKG_CONFIG
|
||||
PKG_CONFIG="$PKG_CONFIG --static"
|
||||
|
||||
@@ -347,7 +523,7 @@ if test x$enable_static_cryptsetup = xyes; then
|
||||
LIBS="$saved_LIBS -static"
|
||||
PKG_CHECK_MODULES([DEVMAPPER_STATIC], [devmapper >= 1.02.27],,[
|
||||
DEVMAPPER_STATIC_LIBS=$DEVMAPPER_LIBS
|
||||
if test "x$enable_selinux" != xno; then
|
||||
if test "x$enable_selinux" = "xyes"; then
|
||||
AC_CHECK_LIB(sepol, sepol_bool_set)
|
||||
AC_CHECK_LIB(selinux, is_selinux_enabled)
|
||||
DEVMAPPER_STATIC_LIBS="$DEVMAPPER_STATIC_LIBS $LIBS"
|
||||
@@ -366,6 +542,10 @@ if test x$enable_static_cryptsetup = xyes; then
|
||||
PKG_CONFIG=$saved_PKG_CONFIG
|
||||
fi
|
||||
|
||||
AC_MSG_CHECKING([for systemd tmpfiles config directory])
|
||||
PKG_CHECK_VAR([systemd_tmpfilesdir], [systemd], [tmpfilesdir], [], [systemd_tmpfilesdir=no])
|
||||
AC_MSG_RESULT([$systemd_tmpfilesdir])
|
||||
|
||||
AC_SUBST([DEVMAPPER_LIBS])
|
||||
AC_SUBST([DEVMAPPER_STATIC_LIBS])
|
||||
|
||||
@@ -378,13 +558,23 @@ AC_SUBST([CRYPTO_CFLAGS])
|
||||
AC_SUBST([CRYPTO_LIBS])
|
||||
AC_SUBST([CRYPTO_STATIC_LIBS])
|
||||
|
||||
AC_SUBST([JSON_C_LIBS])
|
||||
AC_SUBST([LIBARGON2_LIBS])
|
||||
AC_SUBST([BLKID_LIBS])
|
||||
|
||||
AC_SUBST([LIBSSH_LIBS])
|
||||
|
||||
AC_SUBST([LIBCRYPTSETUP_VERSION])
|
||||
AC_SUBST([LIBCRYPTSETUP_VERSION_INFO])
|
||||
|
||||
dnl ==========================================================================
|
||||
AC_ARG_ENABLE([dev-random], AS_HELP_STRING([--enable-dev-random],
|
||||
[use blocking /dev/random by default for key generator (otherwise use /dev/urandom)]),
|
||||
[default_rng=/dev/random], [default_rng=/dev/urandom])
|
||||
AC_ARG_ENABLE([dev-random],
|
||||
AS_HELP_STRING([--enable-dev-random], [use /dev/random by default for key generation (otherwise use /dev/urandom)]))
|
||||
if test "x$enable_dev_random" = "xyes"; then
|
||||
default_rng=/dev/random
|
||||
else
|
||||
default_rng=/dev/urandom
|
||||
fi
|
||||
AC_DEFINE_UNQUOTED(DEFAULT_RNG, ["$default_rng"], [default RNG type for key generator])
|
||||
|
||||
dnl ==========================================================================
|
||||
@@ -404,30 +594,12 @@ AC_DEFUN([CS_NUM_WITH], [AC_ARG_WITH([$1],
|
||||
[CS_DEFINE([$1], [$3], [$2])]
|
||||
)])
|
||||
|
||||
dnl ==========================================================================
|
||||
dnl Python bindings
|
||||
AC_ARG_ENABLE([python], AS_HELP_STRING([--enable-python],[enable Python bindings]),
|
||||
[with_python=$enableval],
|
||||
[with_python=no])
|
||||
|
||||
AC_ARG_WITH([python_version],
|
||||
AS_HELP_STRING([--with-python_version=VERSION], [required Python version [2.6]]),
|
||||
[PYTHON_VERSION=$withval], [PYTHON_VERSION=2.6])
|
||||
|
||||
if test "x$with_python" = "xyes"; then
|
||||
AM_PATH_PYTHON([$PYTHON_VERSION])
|
||||
|
||||
if ! test -x "$PYTHON-config" ; then
|
||||
AC_MSG_ERROR([Cannot find python development packages to build bindings])
|
||||
fi
|
||||
|
||||
PYTHON_INCLUDES=$($PYTHON-config --includes)
|
||||
AC_SUBST(PYTHON_INCLUDES)
|
||||
|
||||
PYTHON_LIBS=$($PYTHON-config --libs)
|
||||
AC_SUBST(PYTHON_LIBS)
|
||||
fi
|
||||
AM_CONDITIONAL([PYTHON_CRYPTSETUP], [test "x$with_python" = "xyes"])
|
||||
AC_DEFUN([CS_ABSPATH], [
|
||||
case "$1" in
|
||||
/*) ;;
|
||||
*) AC_MSG_ERROR([$2 argument must be an absolute path.]);;
|
||||
esac
|
||||
])
|
||||
|
||||
dnl ==========================================================================
|
||||
CS_STR_WITH([plain-hash], [password hashing function for plain mode], [ripemd160])
|
||||
@@ -439,33 +611,83 @@ CS_STR_WITH([luks1-hash], [hash function for LUKS1 header], [sha256])
|
||||
CS_STR_WITH([luks1-cipher], [cipher for LUKS1], [aes])
|
||||
CS_STR_WITH([luks1-mode], [cipher mode for LUKS1], [xts-plain64])
|
||||
CS_NUM_WITH([luks1-keybits],[key length in bits for LUKS1], [256])
|
||||
CS_NUM_WITH([luks1-iter-time],[PBKDF2 iteration time for LUKS1 (in ms)], [2000])
|
||||
|
||||
AC_ARG_ENABLE([luks_adjust_xts_keysize], AS_HELP_STRING([--disable-luks-adjust-xts-keysize],
|
||||
[XTS mode requires two keys, double default LUKS keysize if needed]),
|
||||
[], [enable_luks_adjust_xts_keysize=yes])
|
||||
if test "x$enable_luks_adjust_xts_keysize" = "xyes"; then
|
||||
AC_DEFINE(ENABLE_LUKS_ADJUST_XTS_KEYSIZE, 1, [XTS mode - double default LUKS keysize if needed])
|
||||
fi
|
||||
|
||||
CS_STR_WITH([luks2-pbkdf], [Default PBKDF algorithm (pbkdf2 or argon2i/argon2id) for LUKS2], [argon2id])
|
||||
CS_NUM_WITH([luks1-iter-time], [PBKDF2 iteration time for LUKS1 (in ms)], [2000])
|
||||
CS_NUM_WITH([luks2-iter-time], [Argon2 PBKDF iteration time for LUKS2 (in ms)], [2000])
|
||||
CS_NUM_WITH([luks2-memory-kb], [Argon2 PBKDF memory cost for LUKS2 (in kB)], [1048576])
|
||||
CS_NUM_WITH([luks2-parallel-threads],[Argon2 PBKDF max parallel cost for LUKS2 (if CPUs available)], [4])
|
||||
|
||||
CS_STR_WITH([luks2-keyslot-cipher], [fallback cipher for LUKS2 keyslot (if data encryption is incompatible)], [aes-xts-plain64])
|
||||
CS_NUM_WITH([luks2-keyslot-keybits],[fallback key size for LUKS2 keyslot (if data encryption is incompatible)], [512])
|
||||
|
||||
CS_STR_WITH([loopaes-cipher], [cipher for loop-AES mode], [aes])
|
||||
CS_NUM_WITH([loopaes-keybits],[key length in bits for loop-AES mode], [256])
|
||||
|
||||
CS_NUM_WITH([keyfile-size-maxkb],[maximum keyfile size (in KiB)], [8192])
|
||||
CS_NUM_WITH([passphrase-size-max],[maximum keyfile size (in characters)], [512])
|
||||
CS_NUM_WITH([integrity-keyfile-size-maxkb],[maximum integritysetup keyfile size (in KiB)], [4])
|
||||
CS_NUM_WITH([passphrase-size-max],[maximum passphrase size (in characters)], [512])
|
||||
|
||||
CS_STR_WITH([verity-hash], [hash function for verity mode], [sha256])
|
||||
CS_NUM_WITH([verity-data-block], [data block size for verity mode], [4096])
|
||||
CS_NUM_WITH([verity-hash-block], [hash block size for verity mode], [4096])
|
||||
CS_NUM_WITH([verity-salt-size], [salt size for verity mode], [32])
|
||||
CS_NUM_WITH([verity-fec-roots], [parity bytes for verity FEC], [2])
|
||||
|
||||
CS_STR_WITH([tmpfilesdir], [override default path to directory with systemd temporary files], [])
|
||||
test -z "$with_tmpfilesdir" && with_tmpfilesdir=$systemd_tmpfilesdir
|
||||
test "x$with_tmpfilesdir" = "xno" || {
|
||||
CS_ABSPATH([${with_tmpfilesdir}],[with-tmpfilesdir])
|
||||
DEFAULT_TMPFILESDIR=$with_tmpfilesdir
|
||||
AC_SUBST(DEFAULT_TMPFILESDIR)
|
||||
}
|
||||
AM_CONDITIONAL(CRYPTSETUP_TMPFILE, test -n "$DEFAULT_TMPFILESDIR")
|
||||
|
||||
CS_STR_WITH([luks2-lock-path], [path to directory for LUKSv2 locks], [/run/cryptsetup])
|
||||
test -z "$with_luks2_lock_path" && with_luks2_lock_path=/run/cryptsetup
|
||||
CS_ABSPATH([${with_luks2_lock_path}],[with-luks2-lock-path])
|
||||
DEFAULT_LUKS2_LOCK_PATH=$with_luks2_lock_path
|
||||
AC_SUBST(DEFAULT_LUKS2_LOCK_PATH)
|
||||
|
||||
CS_NUM_WITH([luks2-lock-dir-perms], [default luks2 locking directory permissions], [0700])
|
||||
test -z "$with_luks2_lock_dir_perms" && with_luks2_lock_dir_perms=0700
|
||||
DEFAULT_LUKS2_LOCK_DIR_PERMS=$with_luks2_lock_dir_perms
|
||||
AC_SUBST(DEFAULT_LUKS2_LOCK_DIR_PERMS)
|
||||
|
||||
CS_STR_WITH([luks2-external-tokens-path], [path to directory with LUKSv2 external token handlers (plugins)], [LIBDIR/cryptsetup])
|
||||
if test -n "$with_luks2_external_tokens_path"; then
|
||||
CS_ABSPATH([${with_luks2_external_tokens_path}],[with-luks2-external-tokens-path])
|
||||
EXTERNAL_LUKS2_TOKENS_PATH=$with_luks2_external_tokens_path
|
||||
else
|
||||
EXTERNAL_LUKS2_TOKENS_PATH="\${libdir}/cryptsetup"
|
||||
fi
|
||||
AC_SUBST(EXTERNAL_LUKS2_TOKENS_PATH)
|
||||
|
||||
dnl Override default LUKS format version (for cryptsetup or cryptsetup-reencrypt format actions only).
|
||||
AC_ARG_WITH([default_luks_format],
|
||||
AS_HELP_STRING([--with-default-luks-format=FORMAT], [default LUKS format version (LUKS1/LUKS2) [LUKS2]]),
|
||||
[], [with_default_luks_format=LUKS2])
|
||||
|
||||
case $with_default_luks_format in
|
||||
LUKS1) default_luks=CRYPT_LUKS1 ;;
|
||||
LUKS2) default_luks=CRYPT_LUKS2 ;;
|
||||
*) AC_MSG_ERROR([Unknown default LUKS format. Use LUKS1 or LUKS2 only.]) ;;
|
||||
esac
|
||||
AC_DEFINE_UNQUOTED([DEFAULT_LUKS_FORMAT], [$default_luks], [default LUKS format version])
|
||||
|
||||
dnl ==========================================================================
|
||||
|
||||
AC_CONFIG_FILES([ Makefile
|
||||
lib/Makefile
|
||||
lib/libcryptsetup.pc
|
||||
lib/crypto_backend/Makefile
|
||||
lib/luks1/Makefile
|
||||
lib/loopaes/Makefile
|
||||
lib/verity/Makefile
|
||||
lib/tcrypt/Makefile
|
||||
src/Makefile
|
||||
po/Makefile.in
|
||||
man/Makefile
|
||||
scripts/cryptsetup.conf
|
||||
tests/Makefile
|
||||
python/Makefile
|
||||
])
|
||||
AC_OUTPUT
|
||||
|
||||
@@ -178,7 +178,7 @@
|
||||
* Document cryptsetup exit codes.
|
||||
|
||||
2011-03-18 Milan Broz <mbroz@redhat.com>
|
||||
* Respect maximum keyfile size paramater.
|
||||
* Respect maximum keyfile size parameter.
|
||||
* Introduce maximum default keyfile size, add configure option.
|
||||
* Require the whole key read from keyfile in create command (broken in 1.2.0).
|
||||
* Fix offset option for loopaesOpen.
|
||||
@@ -195,7 +195,7 @@
|
||||
|
||||
2011-03-05 Milan Broz <mbroz@redhat.com>
|
||||
* Add exception to COPYING for binary distribution linked with OpenSSL library.
|
||||
* Set secure data flag (wipe all ioclt buffers) if devmapper library supports it.
|
||||
* Set secure data flag (wipe all ioctl buffers) if devmapper library supports it.
|
||||
|
||||
2011-01-29 Milan Broz <mbroz@redhat.com>
|
||||
* Fix mapping removal if device disappeared but node still exists.
|
||||
@@ -334,13 +334,13 @@
|
||||
* Version 1.1.0.
|
||||
|
||||
2010-01-10 Milan Broz <mbroz@redhat.com>
|
||||
* Fix initialisation of gcrypt duting luksFormat.
|
||||
* Convert hash name to lower case in header (fix sha1 backward comatible header)
|
||||
* Fix initialisation of gcrypt during luksFormat.
|
||||
* Convert hash name to lower case in header (fix sha1 backward compatible header)
|
||||
* Check for minimum required gcrypt version.
|
||||
|
||||
2009-12-30 Milan Broz <mbroz@redhat.com>
|
||||
* Fix key slot iteration count calculation (small -i value was the same as default).
|
||||
* The slot and key digest iteration minimun is now 1000.
|
||||
* The slot and key digest iteration minimum is now 1000.
|
||||
* The key digest iteration # is calculated from iteration time (approx 1/8 of that).
|
||||
* Version 1.1.0-rc4.
|
||||
|
||||
@@ -395,16 +395,16 @@
|
||||
* Require device device-mapper to build and do not use backend wrapper for dm calls.
|
||||
* Move memory locking and dm initialization to command layer.
|
||||
* Increase priority of process if memory is locked.
|
||||
* Add log macros and make logging modre consitent.
|
||||
* Add log macros and make logging more consistent.
|
||||
* Move command successful messages to verbose level.
|
||||
* Introduce --debug parameter.
|
||||
* Move device utils code and provide context parameter (for log).
|
||||
* Keyfile now must be provided by path, only stdin file descriptor is used (api only).
|
||||
* Do not call isatty() on closed keyfile descriptor.
|
||||
* Run performance check for PBKDF2 from LUKS code, do not mix hash algoritms results.
|
||||
* Run performance check for PBKDF2 from LUKS code, do not mix hash algorithms results.
|
||||
* Add ability to provide pre-generated master key and UUID in LUKS header format.
|
||||
* Add LUKS function to verify master key digest.
|
||||
* Move key slot manuipulation function into LUKS specific code.
|
||||
* Move key slot manipulation function into LUKS specific code.
|
||||
* Replace global options struct with separate parameters in helper functions.
|
||||
* Add new libcryptsetup API (documented in libcryptsetup.h).
|
||||
* Implement old API calls using new functions.
|
||||
@@ -412,7 +412,7 @@
|
||||
* Add --master-key-file option for luksFormat and luksAddKey.
|
||||
|
||||
2009-08-17 Milan Broz <mbroz@redhat.com>
|
||||
* Fix PBKDF2 speed calculation for large passhrases.
|
||||
* Fix PBKDF2 speed calculation for large passphrases.
|
||||
* Allow using passphrase provided in options struct for LuksOpen.
|
||||
* Allow restrict keys size in LuksOpen.
|
||||
|
||||
@@ -424,7 +424,7 @@
|
||||
* Switch PBKDF2 from internal SHA1 to libgcrypt, make hash algorithm not hardcoded to SHA1 here.
|
||||
* Add required parameters for changing hash used in LUKS key setup scheme.
|
||||
* Do not export simple XOR helper now used only inside AF functions.
|
||||
* Completely remove internal SHA1 implementanion code, not needed anymore.
|
||||
* Completely remove internal SHA1 implementation code, not needed anymore.
|
||||
* Enable hash algorithm selection for LUKS through -h luksFormat option.
|
||||
|
||||
2009-07-28 Milan Broz <mbroz@redhat.com>
|
||||
@@ -636,7 +636,7 @@
|
||||
|
||||
2006-03-15 Clemens Fruhwirth <clemens@endorphin.org>
|
||||
|
||||
* configure.in: 1.0.3-rc3. Most unplease release ever.
|
||||
* configure.in: 1.0.3-rc3. Most displease release ever.
|
||||
* lib/setup.c (__crypt_create_device): More verbose error message.
|
||||
|
||||
2006-02-26 Clemens Fruhwirth <clemens@endorphin.org>
|
||||
@@ -705,7 +705,7 @@
|
||||
|
||||
2005-12-06 Clemens Fruhwirth <clemens@endorphin.org>
|
||||
|
||||
* man/cryptsetup.8: Correct "seconds" to "microseconds" in the explaination for -i.
|
||||
* man/cryptsetup.8: Correct "seconds" to "microseconds" in the explanation for -i.
|
||||
|
||||
2005-11-09 Clemens Fruhwirth <clemens@endorphin.org>
|
||||
|
||||
@@ -726,7 +726,7 @@
|
||||
|
||||
2005-09-08 Clemens Fruhwirth <clemens@endorphin.org>
|
||||
|
||||
* lib/setup.c (get_key): Fixed another incompatiblity with
|
||||
* lib/setup.c (get_key): Fixed another incompatibility with
|
||||
original cryptsetup.
|
||||
|
||||
2005-08-20 Clemens Fruhwirth <clemens@endorphin.org>
|
||||
@@ -816,7 +816,7 @@
|
||||
|
||||
* man/cryptsetup.1: Add man page.
|
||||
|
||||
* lib/setup.c: Remove unneccessary LUKS_write_phdr call, so the
|
||||
* lib/setup.c: Remove unnecessary LUKS_write_phdr call, so the
|
||||
phdr is written after passphrase reading, so the user can change
|
||||
his mind, and not have a partial written LUKS header on it's disk.
|
||||
|
||||
|
||||
56
docs/Keyring.txt
Normal file
56
docs/Keyring.txt
Normal file
@@ -0,0 +1,56 @@
|
||||
Integration with kernel keyring service
|
||||
---------------------------------------
|
||||
|
||||
We have two different use cases for kernel keyring service:
|
||||
|
||||
I) Volume keys
|
||||
|
||||
Since upstream kernel 4.10 dm-crypt device mapper target allows loading volume
|
||||
key (VK) in kernel keyring service. The key offloaded in kernel keyring service
|
||||
is only referenced (by key description) in dm-crypt target and the VK is therefore
|
||||
no longer stored directly in dm-crypt target. Starting with cryptsetup 2.0 we
|
||||
load VK in kernel keyring by default for LUKSv2 devices (when dm-crypt with the
|
||||
feature is available).
|
||||
|
||||
Currently cryptsetup loads VK in 'logon' type kernel key so that VK is passed in
|
||||
the kernel and can't be read from userspace afterward. Also cryptsetup loads VK in
|
||||
thread keyring (before passing the reference to dm-crypt target) so that the key
|
||||
lifetime is directly bound to the process that performs the dm-crypt setup. When
|
||||
cryptsetup process exits (for whatever reason) the key gets unlinked in kernel
|
||||
automatically. In summary, the key description visible in dm-crypt table line is
|
||||
a reference to VK that usually no longer exists in kernel keyring service if you
|
||||
used cryptsetup to for device activation.
|
||||
|
||||
Using this feature dm-crypt no longer maintains a direct key copy (but there's
|
||||
always at least one copy in kernel crypto layer).
|
||||
|
||||
II) Keyslot passphrase
|
||||
The second use case for kernel keyring is to allow cryptsetup reading the keyslot
|
||||
passphrase stored in kernel keyring instead. The user may load passphrase in kernel
|
||||
keyring and notify cryptsetup to read it from there later. Currently, cryptsetup
|
||||
cli supports kernel keyring for passphrase only via LUKS2 internal token
|
||||
(luks2-keyring). Library also provides a general method for device activation by
|
||||
reading passphrase from keyring: crypt_activate_by_keyring(). The key type
|
||||
for use case II) must always be 'user' since we need to read the actual key
|
||||
data from userspace unlike with VK in I). Ability to read keyslot passphrase
|
||||
from kernel keyring also allows easily auto-activate LUKS2 devices.
|
||||
|
||||
Simple example how to use kernel keyring for keyslot passphrase:
|
||||
|
||||
1) create LUKS2 keyring token for keyslot 0 (in LUKS2 device/image)
|
||||
cryptsetup token add --key-description my:key -S 0 /dev/device
|
||||
|
||||
2) Load keyslot passphrase in user keyring
|
||||
read -s -p "Keyslot passphrase: "; echo -n $REPLY | keyctl padd user my:key @u
|
||||
|
||||
3) Activate device using passphrase stored in kernel keyring
|
||||
cryptsetup open /dev/device my_unlocked_device
|
||||
|
||||
4a) unlink the key when no longer needed by
|
||||
keyctl unlink %user:my:key @u
|
||||
|
||||
4b) or revoke it immediately by
|
||||
keyctl revoke %user:my:key
|
||||
|
||||
If cryptsetup asks for passphrase in step 3) something went wrong with keyring
|
||||
activation. See --debug output then.
|
||||
61
docs/LUKS2-locking.txt
Normal file
61
docs/LUKS2-locking.txt
Normal file
@@ -0,0 +1,61 @@
|
||||
LUKS2 device locking overview
|
||||
=============================
|
||||
|
||||
Why
|
||||
~~~
|
||||
|
||||
LUKS2 format keeps two identical copies of metadata stored consecutively
|
||||
at the head of metadata device (file or bdev). The metadata
|
||||
area (both copies) must be updated in a single atomic operation to avoid
|
||||
header corruption during concurrent write.
|
||||
|
||||
While with LUKS1 users may have clear knowledge of when a LUKS header is
|
||||
being updated (written to) or when it's being read solely the need for
|
||||
locking with legacy format was not so obvious as it is with the LUKSv2 format.
|
||||
|
||||
With LUKS2 the boundary between read-only and read-write is blurry and what
|
||||
used to be the exclusively read-only operation (i.e., cryptsetup open command) may
|
||||
easily become read-update operation silently without user's knowledge.
|
||||
Major feature of LUKS2 format is resilience against accidental
|
||||
corruption of metadata (i.e., partial header overwrite by parted or cfdisk
|
||||
while creating partition on mistaken block device).
|
||||
Such header corruption is detected early on header read and auto-recovery
|
||||
procedure takes place (the corrupted header with checksum mismatch is being
|
||||
replaced by the secondary one if that one is intact).
|
||||
On current Linux systems header load operation may be triggered without user
|
||||
direct intervention for example by udev rule or from systemd service.
|
||||
Such clash of header read and auto-recovery procedure could have severe
|
||||
consequences with the worst case of having LUKS2 device unaccessible or being
|
||||
broken beyond repair.
|
||||
|
||||
The whole locking of LUKSv2 device headers split into two categories depending
|
||||
what backend the header is stored on:
|
||||
|
||||
I) block device
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
We perform flock() on file descriptors of files stored in a private
|
||||
directory (by default /run/lock/cryptsetup). The file name is derived
|
||||
from major:minor couple of affected block device. Note we recommend
|
||||
that access to private locking directory is supposed to be limited
|
||||
to superuser only. For this method to work the distribution needs
|
||||
to install the locking directory with appropriate access rights.
|
||||
|
||||
II) regular files
|
||||
~~~~~~~~~~~~~~~~~
|
||||
|
||||
First notable difference between headers stored in a file
|
||||
vs. headers stored in a block device is that headers in a file may be
|
||||
manipulated by the regular user unlike headers on block devices. Therefore
|
||||
we perform flock() protection on file with the luks2 header directly.
|
||||
|
||||
Limitations
|
||||
~~~~~~~~~~~
|
||||
|
||||
a) In general, the locking model provides serialization of I/Os targeting
|
||||
the header only. It means the header is always written or read at once
|
||||
while locking is enabled.
|
||||
We do not suppress any other negative effect that two or more concurrent
|
||||
writers of the same header may cause.
|
||||
|
||||
b) The locking is not cluster aware in any way.
|
||||
@@ -1,4 +1,4 @@
|
||||
# Doxyfile 1.7.4
|
||||
# Doxyfile 1.8.8
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Project related configuration options
|
||||
@@ -10,6 +10,7 @@ PROJECT_BRIEF = "Public cryptsetup API"
|
||||
PROJECT_LOGO =
|
||||
OUTPUT_DIRECTORY = doxygen_api_docs
|
||||
CREATE_SUBDIRS = NO
|
||||
ALLOW_UNICODE_NAMES = NO
|
||||
OUTPUT_LANGUAGE = English
|
||||
BRIEF_MEMBER_DESC = YES
|
||||
REPEAT_BRIEF = YES
|
||||
@@ -27,11 +28,14 @@ INHERIT_DOCS = YES
|
||||
SEPARATE_MEMBER_PAGES = NO
|
||||
TAB_SIZE = 8
|
||||
ALIASES =
|
||||
TCL_SUBST =
|
||||
OPTIMIZE_OUTPUT_FOR_C = YES
|
||||
OPTIMIZE_OUTPUT_JAVA = NO
|
||||
OPTIMIZE_FOR_FORTRAN = NO
|
||||
OPTIMIZE_OUTPUT_VHDL = NO
|
||||
EXTENSION_MAPPING =
|
||||
MARKDOWN_SUPPORT = YES
|
||||
AUTOLINK_SUPPORT = YES
|
||||
BUILTIN_STL_SUPPORT = NO
|
||||
CPP_CLI_SUPPORT = NO
|
||||
SIP_SUPPORT = NO
|
||||
@@ -39,13 +43,15 @@ IDL_PROPERTY_SUPPORT = YES
|
||||
DISTRIBUTE_GROUP_DOC = NO
|
||||
SUBGROUPING = YES
|
||||
INLINE_GROUPED_CLASSES = NO
|
||||
INLINE_SIMPLE_STRUCTS = NO
|
||||
TYPEDEF_HIDES_STRUCT = YES
|
||||
SYMBOL_CACHE_SIZE = 0
|
||||
LOOKUP_CACHE_SIZE = 0
|
||||
#---------------------------------------------------------------------------
|
||||
# Build related configuration options
|
||||
#---------------------------------------------------------------------------
|
||||
EXTRACT_ALL = NO
|
||||
EXTRACT_PRIVATE = NO
|
||||
EXTRACT_PACKAGE = NO
|
||||
EXTRACT_STATIC = NO
|
||||
EXTRACT_LOCAL_CLASSES = YES
|
||||
EXTRACT_LOCAL_METHODS = NO
|
||||
@@ -58,6 +64,7 @@ INTERNAL_DOCS = NO
|
||||
CASE_SENSE_NAMES = YES
|
||||
HIDE_SCOPE_NAMES = NO
|
||||
SHOW_INCLUDE_FILES = YES
|
||||
SHOW_GROUPED_MEMB_INC = NO
|
||||
FORCE_LOCAL_INCLUDES = NO
|
||||
INLINE_INFO = YES
|
||||
SORT_MEMBER_DOCS = YES
|
||||
@@ -73,13 +80,13 @@ GENERATE_DEPRECATEDLIST= YES
|
||||
ENABLED_SECTIONS =
|
||||
MAX_INITIALIZER_LINES = 30
|
||||
SHOW_USED_FILES = YES
|
||||
SHOW_DIRECTORIES = NO
|
||||
SHOW_FILES = YES
|
||||
SHOW_NAMESPACES = YES
|
||||
FILE_VERSION_FILTER =
|
||||
LAYOUT_FILE =
|
||||
CITE_BIB_FILES =
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to warning and progress messages
|
||||
# Configuration options related to warning and progress messages
|
||||
#---------------------------------------------------------------------------
|
||||
QUIET = NO
|
||||
WARNINGS = YES
|
||||
@@ -89,9 +96,10 @@ WARN_NO_PARAMDOC = NO
|
||||
WARN_FORMAT = "$file:$line: $text"
|
||||
WARN_LOGFILE =
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to the input files
|
||||
# Configuration options related to the input files
|
||||
#---------------------------------------------------------------------------
|
||||
INPUT = "doxygen_index" "../lib/libcryptsetup.h"
|
||||
INPUT = "doxygen_index.h" \
|
||||
"../lib/libcryptsetup.h"
|
||||
INPUT_ENCODING = UTF-8
|
||||
FILE_PATTERNS =
|
||||
RECURSIVE = NO
|
||||
@@ -107,8 +115,9 @@ INPUT_FILTER =
|
||||
FILTER_PATTERNS =
|
||||
FILTER_SOURCE_FILES = NO
|
||||
FILTER_SOURCE_PATTERNS =
|
||||
USE_MDFILE_AS_MAINPAGE =
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to source browsing
|
||||
# Configuration options related to source browsing
|
||||
#---------------------------------------------------------------------------
|
||||
SOURCE_BROWSER = NO
|
||||
INLINE_SOURCES = NO
|
||||
@@ -116,16 +125,19 @@ STRIP_CODE_COMMENTS = YES
|
||||
REFERENCED_BY_RELATION = NO
|
||||
REFERENCES_RELATION = NO
|
||||
REFERENCES_LINK_SOURCE = YES
|
||||
SOURCE_TOOLTIPS = YES
|
||||
USE_HTAGS = NO
|
||||
VERBATIM_HEADERS = YES
|
||||
CLANG_ASSISTED_PARSING = NO
|
||||
CLANG_OPTIONS =
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to the alphabetical class index
|
||||
# Configuration options related to the alphabetical class index
|
||||
#---------------------------------------------------------------------------
|
||||
ALPHABETICAL_INDEX = YES
|
||||
COLS_IN_ALPHA_INDEX = 5
|
||||
IGNORE_PREFIX =
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to the HTML output
|
||||
# Configuration options related to the HTML output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_HTML = YES
|
||||
HTML_OUTPUT = html
|
||||
@@ -133,13 +145,14 @@ HTML_FILE_EXTENSION = .html
|
||||
HTML_HEADER =
|
||||
HTML_FOOTER =
|
||||
HTML_STYLESHEET =
|
||||
HTML_EXTRA_STYLESHEET =
|
||||
HTML_EXTRA_FILES =
|
||||
HTML_COLORSTYLE_HUE = 220
|
||||
HTML_COLORSTYLE_SAT = 100
|
||||
HTML_COLORSTYLE_GAMMA = 80
|
||||
HTML_TIMESTAMP = YES
|
||||
HTML_ALIGN_MEMBERS = YES
|
||||
HTML_DYNAMIC_SECTIONS = NO
|
||||
HTML_INDEX_NUM_ENTRIES = 100
|
||||
GENERATE_DOCSET = NO
|
||||
DOCSET_FEEDNAME = "Doxygen generated docs"
|
||||
DOCSET_BUNDLE_ID = org.doxygen.Project
|
||||
@@ -163,19 +176,26 @@ QHG_LOCATION =
|
||||
GENERATE_ECLIPSEHELP = NO
|
||||
ECLIPSE_DOC_ID = org.doxygen.Project
|
||||
DISABLE_INDEX = NO
|
||||
ENUM_VALUES_PER_LINE = 4
|
||||
GENERATE_TREEVIEW = NO
|
||||
USE_INLINE_TREES = NO
|
||||
ENUM_VALUES_PER_LINE = 4
|
||||
TREEVIEW_WIDTH = 250
|
||||
EXT_LINKS_IN_WINDOW = NO
|
||||
FORMULA_FONTSIZE = 10
|
||||
FORMULA_TRANSPARENT = YES
|
||||
USE_MATHJAX = NO
|
||||
MATHJAX_FORMAT = HTML-CSS
|
||||
MATHJAX_RELPATH = http://www.mathjax.org/mathjax
|
||||
MATHJAX_EXTENSIONS =
|
||||
MATHJAX_CODEFILE =
|
||||
SEARCHENGINE = YES
|
||||
SERVER_BASED_SEARCH = NO
|
||||
EXTERNAL_SEARCH = NO
|
||||
SEARCHENGINE_URL =
|
||||
SEARCHDATA_FILE = searchdata.xml
|
||||
EXTERNAL_SEARCH_ID =
|
||||
EXTRA_SEARCH_MAPPINGS =
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to the LaTeX output
|
||||
# Configuration options related to the LaTeX output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_LATEX = YES
|
||||
LATEX_OUTPUT = latex
|
||||
@@ -186,13 +206,15 @@ PAPER_TYPE = a4
|
||||
EXTRA_PACKAGES =
|
||||
LATEX_HEADER =
|
||||
LATEX_FOOTER =
|
||||
LATEX_EXTRA_FILES =
|
||||
PDF_HYPERLINKS = YES
|
||||
USE_PDFLATEX = YES
|
||||
LATEX_BATCHMODE = NO
|
||||
LATEX_HIDE_INDICES = NO
|
||||
LATEX_SOURCE_CODE = NO
|
||||
LATEX_BIB_STYLE = plain
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to the RTF output
|
||||
# Configuration options related to the RTF output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_RTF = NO
|
||||
RTF_OUTPUT = rtf
|
||||
@@ -201,26 +223,31 @@ RTF_HYPERLINKS = NO
|
||||
RTF_STYLESHEET_FILE =
|
||||
RTF_EXTENSIONS_FILE =
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to the man page output
|
||||
# Configuration options related to the man page output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_MAN = NO
|
||||
MAN_OUTPUT = man
|
||||
MAN_EXTENSION = .3
|
||||
MAN_SUBDIR =
|
||||
MAN_LINKS = NO
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to the XML output
|
||||
# Configuration options related to the XML output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_XML = NO
|
||||
XML_OUTPUT = xml
|
||||
XML_SCHEMA =
|
||||
XML_DTD =
|
||||
XML_PROGRAMLISTING = YES
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options for the AutoGen Definitions output
|
||||
# Configuration options related to the DOCBOOK output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_DOCBOOK = NO
|
||||
DOCBOOK_OUTPUT = docbook
|
||||
DOCBOOK_PROGRAMLISTING = NO
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options for the AutoGen Definitions output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_AUTOGEN_DEF = NO
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to the Perl module output
|
||||
# Configuration options related to the Perl module output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_PERLMOD = NO
|
||||
PERLMOD_LATEX = NO
|
||||
@@ -239,18 +266,20 @@ PREDEFINED =
|
||||
EXPAND_AS_DEFINED =
|
||||
SKIP_FUNCTION_MACROS = YES
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration::additions related to external references
|
||||
# Configuration options related to external references
|
||||
#---------------------------------------------------------------------------
|
||||
TAGFILES =
|
||||
GENERATE_TAGFILE =
|
||||
ALLEXTERNALS = NO
|
||||
EXTERNAL_GROUPS = YES
|
||||
EXTERNAL_PAGES = YES
|
||||
PERL_PATH =
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the dot tool
|
||||
#---------------------------------------------------------------------------
|
||||
CLASS_DIAGRAMS = YES
|
||||
MSCGEN_PATH =
|
||||
DIA_PATH =
|
||||
HIDE_UNDOC_RELATIONS = YES
|
||||
HAVE_DOT = NO
|
||||
DOT_NUM_THREADS = 0
|
||||
@@ -261,6 +290,7 @@ CLASS_GRAPH = YES
|
||||
COLLABORATION_GRAPH = YES
|
||||
GROUP_GRAPHS = YES
|
||||
UML_LOOK = NO
|
||||
UML_LIMIT_NUM_FIELDS = 10
|
||||
TEMPLATE_RELATIONS = NO
|
||||
INCLUDE_GRAPH = YES
|
||||
INCLUDED_BY_GRAPH = YES
|
||||
@@ -269,9 +299,12 @@ CALLER_GRAPH = NO
|
||||
GRAPHICAL_HIERARCHY = YES
|
||||
DIRECTORY_GRAPH = YES
|
||||
DOT_IMAGE_FORMAT = png
|
||||
INTERACTIVE_SVG = NO
|
||||
DOT_PATH =
|
||||
DOTFILE_DIRS =
|
||||
MSCFILE_DIRS =
|
||||
DIAFILE_DIRS =
|
||||
PLANTUML_JAR_PATH =
|
||||
DOT_GRAPH_MAX_NODES = 50
|
||||
MAX_DOT_GRAPH_DEPTH = 0
|
||||
DOT_TRANSPARENT = NO
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
/**
|
||||
* @mainpage Cryptsetup API
|
||||
/*! \mainpage Cryptsetup API
|
||||
*
|
||||
* The documentation covers public parts of cryptsetup API. In the following sections you'll find
|
||||
* <b>The</b> documentation covers public parts of cryptsetup API. In the following sections you'll find
|
||||
* the examples that describe some features of cryptsetup API.
|
||||
* For more info about libcryptsetup API versions see
|
||||
* <a href="http://upstream-tracker.org/versions/libcryptsetup.html">Upstream Tracker</a>.
|
||||
* <a href="https://gitlab.com/cryptsetup/cryptsetup/wikis/ABI-tracker/timeline/libcryptsetup/index.html">API Tracker</a>.
|
||||
*
|
||||
* <OL type="A">
|
||||
* <LI>@ref cexamples "Cryptsetup API examples"</LI>
|
||||
@@ -32,18 +31,16 @@
|
||||
* @section cexamples Cryptsetup API examples
|
||||
* @section cluks crypt_luks_usage - cryptsetup LUKS device type usage
|
||||
* @subsection cinit crypt_init()
|
||||
*
|
||||
* Every time you need to do something with cryptsetup or dmcrypt device
|
||||
* Every time you need to do something with cryptsetup or dmcrypt device
|
||||
* you need a valid context. The first step to start your work is
|
||||
* @ref crypt_init call. You can call it either with path
|
||||
* to the block device or path to the regular file. If you don't supply the path,
|
||||
* empty context is initialized.
|
||||
*
|
||||
* @subsection cformat crypt_format() - header and payload on mutual device
|
||||
*
|
||||
* This section covers basic use cases for formatting LUKS devices. Format operation
|
||||
* sets device type in context and in case of LUKS header is written at the beginning
|
||||
* of block device. In the example bellow we use the scenario where LUKS header and data
|
||||
* of block device. In the example below we use the scenario where LUKS header and data
|
||||
* are both stored on the same device. There's also a possibility to store header and
|
||||
* data separately.
|
||||
*
|
||||
@@ -51,7 +48,6 @@
|
||||
* overwrites part of the backing block device.
|
||||
*
|
||||
* @subsection ckeys Keyslot operations examples
|
||||
*
|
||||
* After successful @ref crypt_format of LUKS device, volume key is not stored
|
||||
* in a persistent way on the device. Keyslot area is an array beyond LUKS header, where
|
||||
* volume key is stored in the encrypted form using user input passphrase. For more info about
|
||||
@@ -60,33 +56,27 @@
|
||||
* There are two basic methods to create a new keyslot:
|
||||
*
|
||||
* @subsection ckeyslot_vol crypt_keyslot_add_by_volume_key()
|
||||
*
|
||||
* Creates a new keyslot directly by encrypting volume_key stored in the device
|
||||
* context. Passphrase should be supplied or user is prompted if passphrase param is
|
||||
* NULL.
|
||||
*
|
||||
* @subsection ckeyslot_pass crypt_keyslot_add_by_passphrase()
|
||||
*
|
||||
* Creates a new keyslot for the volume key by opening existing active keyslot,
|
||||
* extracting volume key from it and storing it into a new keyslot
|
||||
* protected by a new passphrase
|
||||
*
|
||||
* @subsection cload crypt_load()
|
||||
*
|
||||
* Function loads header from backing block device into device context.
|
||||
*
|
||||
* @subsection cactivate crypt_activate_by_passphrase()
|
||||
*
|
||||
* Activates crypt device by user supplied password for keyslot containing the volume_key.
|
||||
* If <I>keyslot</I> parameter is set to <I>CRYPT_ANY_SLOT</I> then all active keyslots
|
||||
* are tried one by one until the volume key is found.
|
||||
*
|
||||
* @subsection cactive_pars crypt_get_active_device()
|
||||
*
|
||||
* This call returns structure containing runtime attributes of active device.
|
||||
*
|
||||
* @subsection cinit_by_name crypt_init_by_name()
|
||||
*
|
||||
* In case you need to do operations with active device (device which already
|
||||
* has its corresponding mapping) and you miss valid device context stored in
|
||||
* *crypt_device reference, you should use this call. Function tries to
|
||||
@@ -94,22 +84,18 @@
|
||||
* header.
|
||||
*
|
||||
* @subsection cdeactivate crypt_deactivate()
|
||||
*
|
||||
* Deactivates crypt device (removes DM mapping and safely erases volume key from kernel).
|
||||
*
|
||||
* @subsection cluks_ex crypt_luks_usage.c - Complex example
|
||||
*
|
||||
* To compile and run use following commands in examples directory:
|
||||
*
|
||||
* @code
|
||||
* make
|
||||
* ./crypt_luks_usage _path_to_[block_device]_file
|
||||
* @endcode
|
||||
*
|
||||
* Note that you need to have the cryptsetup library compiled. @include crypt_luks_usage.c
|
||||
*
|
||||
* @section clog crypt_log_usage - cryptsetup logging API example
|
||||
*
|
||||
* Example describes basic use case for cryptsetup logging. To compile and run
|
||||
* use following commands in examples directory:
|
||||
*
|
||||
@@ -117,7 +103,6 @@
|
||||
* make
|
||||
* ./crypt_log_usage
|
||||
* @endcode
|
||||
*
|
||||
* Note that you need to have the cryptsetup library compiled. @include crypt_log_usage.c
|
||||
*
|
||||
* @example crypt_luks_usage.c
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* An example of using logging through libcryptsetup API
|
||||
* libcryptsetup API log example
|
||||
*
|
||||
* Copyright (C) 2011, Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2011-2021 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
@@ -25,10 +25,8 @@
|
||||
#include <libcryptsetup.h>
|
||||
|
||||
/*
|
||||
* This is an example of function that can be registered using crypt_set_log_callback API.
|
||||
* This is an example of crypt_set_log_callback API callback.
|
||||
*
|
||||
* Its prototype is void (*log)(int level, const char *msg, void *usrptr) as defined
|
||||
* in crypt_set_log_callback
|
||||
*/
|
||||
static void simple_syslog_wrapper(int level, const char *msg, void *usrptr)
|
||||
{
|
||||
@@ -71,7 +69,7 @@ int main(void)
|
||||
return 2;
|
||||
}
|
||||
|
||||
/* crypt_set_log_callback() - register a log function for crypt context */
|
||||
/* crypt_set_log_callback() - register a log callback for crypt context */
|
||||
crypt_set_log_callback(cd, &simple_syslog_wrapper, (void *)usrprefix);
|
||||
|
||||
/* send messages ithrough the crypt_log() interface */
|
||||
@@ -83,7 +81,7 @@ int main(void)
|
||||
/* release crypt context */
|
||||
crypt_free(cd);
|
||||
|
||||
/* Initialize default (global) log function */
|
||||
/* Initialize default (global) log callback */
|
||||
crypt_set_log_callback(NULL, &simple_syslog_wrapper, NULL);
|
||||
|
||||
crypt_log(NULL, CRYPT_LOG_NORMAL, "This is normal log message");
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* An example of using LUKS device through libcryptsetup API
|
||||
* libcryptsetup API - using LUKS device example
|
||||
*
|
||||
* Copyright (C) 2011, Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2011-2021 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
@@ -29,23 +29,18 @@
|
||||
static int format_and_add_keyslots(const char *path)
|
||||
{
|
||||
struct crypt_device *cd;
|
||||
struct crypt_params_luks1 params;
|
||||
int r;
|
||||
|
||||
/*
|
||||
* crypt_init() call precedes most of operations of cryptsetup API. The call is used
|
||||
* to initialize crypt device context stored in structure referenced by _cd_ in
|
||||
* the example. Second parameter is used to pass underlaying device path.
|
||||
* The crypt_init() call is used to initialize crypt_device context,
|
||||
* The path parameter specifies a device path.
|
||||
*
|
||||
* Note:
|
||||
* If path refers to a regular file it'll be attached to a first free loop device.
|
||||
* crypt_init() operation fails in case there's no more loop device available.
|
||||
* Also, loop device will have the AUTOCLEAR flag set, so the file loopback will
|
||||
* be detached automatically.
|
||||
* For path, you can use either link to a file or block device.
|
||||
* The loopback device will be detached automatically.
|
||||
*/
|
||||
|
||||
r = crypt_init(&cd, path);
|
||||
if (r < 0 ) {
|
||||
if (r < 0) {
|
||||
printf("crypt_init() failed for %s.\n", path);
|
||||
return r;
|
||||
}
|
||||
@@ -53,73 +48,37 @@ static int format_and_add_keyslots(const char *path)
|
||||
printf("Context is attached to block device %s.\n", crypt_get_device_name(cd));
|
||||
|
||||
/*
|
||||
* So far no data were written on your device. This will change with call of
|
||||
* crypt_format() only if you specify CRYPT_LUKS1 as device type.
|
||||
* So far, no data were written to the device.
|
||||
*/
|
||||
printf("Device %s will be formatted to LUKS device after 5 seconds.\n"
|
||||
printf("Device %s will be formatted as a LUKS device after 5 seconds.\n"
|
||||
"Press CTRL+C now if you want to cancel this operation.\n", path);
|
||||
sleep(5);
|
||||
|
||||
|
||||
/*
|
||||
* Prepare LUKS format parameters
|
||||
*
|
||||
* hash parameter defines PBKDF2 hash algorithm used in LUKS header.
|
||||
* For compatibility reason we use SHA1 here.
|
||||
*/
|
||||
params.hash = "sha1";
|
||||
|
||||
/*
|
||||
* data_alignment parameter is relevant only in case of the luks header
|
||||
* and the payload are both stored on same device.
|
||||
*
|
||||
* if you set data_alignment = 0, cryptsetup will autodetect
|
||||
* data_alignment according to underlaying device topology.
|
||||
*/
|
||||
params.data_alignment = 0;
|
||||
|
||||
/*
|
||||
* data_device parameter defines that no external device
|
||||
* for luks header will be used
|
||||
*/
|
||||
params.data_device = NULL;
|
||||
|
||||
/*
|
||||
* NULLs for uuid and volume_key means that these attributes will be
|
||||
* generated during crypt_format(). Volume key is generated with respect
|
||||
* to key size parameter passed to function.
|
||||
*
|
||||
* crypt_format() checks device size (LUKS header must fit there).
|
||||
* generated during crypt_format().
|
||||
*/
|
||||
r = crypt_format(cd, /* crypt context */
|
||||
CRYPT_LUKS1, /* LUKS1 is standard LUKS header */
|
||||
CRYPT_LUKS2, /* LUKS2 is a new LUKS format; use CRYPT_LUKS1 for LUKS1 */
|
||||
"aes", /* used cipher */
|
||||
"xts-plain64", /* used block mode and IV generator*/
|
||||
"xts-plain64", /* used block mode and IV */
|
||||
NULL, /* generate UUID */
|
||||
NULL, /* generate volume key from RNG */
|
||||
256 / 8, /* 256bit key - here AES-128 in XTS mode, size is in bytes */
|
||||
¶ms); /* parameters above */
|
||||
512 / 8, /* 512bit key - here AES-256 in XTS mode, size is in bytes */
|
||||
NULL); /* default parameters */
|
||||
|
||||
if(r < 0) {
|
||||
if (r < 0) {
|
||||
printf("crypt_format() failed on device %s\n", crypt_get_device_name(cd));
|
||||
crypt_free(cd);
|
||||
return r;
|
||||
}
|
||||
|
||||
/*
|
||||
* The device now contains LUKS1 header, but there is
|
||||
* no active keyslot with encrypted volume key yet.
|
||||
*/
|
||||
|
||||
/*
|
||||
* cryptt_kesylot_add_* call stores volume_key in encrypted form into keyslot.
|
||||
* Without keyslot you can't manipulate with LUKS device after the context will be freed.
|
||||
* The device now contains a LUKS header, but there is no active keyslot.
|
||||
*
|
||||
* To create a new keyslot you need to supply the existing one (to get the volume key from) or
|
||||
* you need to supply the volume key.
|
||||
* crypt_keyslot_add_* call stores the volume_key in the encrypted form into the keyslot.
|
||||
*
|
||||
* After format, we have volume key stored internally in context so add new keyslot
|
||||
* using this internal volume key.
|
||||
* After format, the volume key is stored internally.
|
||||
*/
|
||||
r = crypt_keyslot_add_by_volume_key(cd, /* crypt context */
|
||||
CRYPT_ANY_SLOT, /* just use first free slot */
|
||||
@@ -137,8 +96,8 @@ static int format_and_add_keyslots(const char *path)
|
||||
printf("The first keyslot is initialized.\n");
|
||||
|
||||
/*
|
||||
* Add another keyslot, now using the first keyslot.
|
||||
* It will decrypt volume key from the first keyslot and creates new one with another passphrase.
|
||||
* Add another keyslot, now authenticating with the first keyslot.
|
||||
* It decrypts the volume key from the first keyslot and creates a new one with the specified passphrase.
|
||||
*/
|
||||
r = crypt_keyslot_add_by_passphrase(cd, /* crypt context */
|
||||
CRYPT_ANY_SLOT, /* just use first free slot */
|
||||
@@ -164,21 +123,18 @@ static int activate_and_check_status(const char *path, const char *device_name)
|
||||
|
||||
/*
|
||||
* LUKS device activation example.
|
||||
* It's sequence of sub-steps: device initialization, LUKS header load
|
||||
* and the device activation itself.
|
||||
*/
|
||||
r = crypt_init(&cd, path);
|
||||
if (r < 0 ) {
|
||||
if (r < 0) {
|
||||
printf("crypt_init() failed for %s.\n", path);
|
||||
return r;
|
||||
}
|
||||
|
||||
/*
|
||||
* crypt_load() is used to load the LUKS header from block device
|
||||
* into crypt_device context.
|
||||
* crypt_load() is used to load existing LUKS header from a block device
|
||||
*/
|
||||
r = crypt_load(cd, /* crypt context */
|
||||
CRYPT_LUKS1, /* requested type */
|
||||
CRYPT_LUKS, /* requested type - here LUKS of any type */
|
||||
NULL); /* additional parameters (not used) */
|
||||
|
||||
if (r < 0) {
|
||||
@@ -188,11 +144,11 @@ static int activate_and_check_status(const char *path, const char *device_name)
|
||||
}
|
||||
|
||||
/*
|
||||
* Device activation creates device-mapper devie mapping with name device_name.
|
||||
* Device activation creates a device-mapper device with the specified name.
|
||||
*/
|
||||
r = crypt_activate_by_passphrase(cd, /* crypt context */
|
||||
device_name, /* device name to activate */
|
||||
CRYPT_ANY_SLOT,/* which slot use (ANY - try all) */
|
||||
CRYPT_ANY_SLOT,/* the keyslot use (try all here) */
|
||||
"foo", 3, /* passphrase */
|
||||
CRYPT_ACTIVATE_READONLY); /* flags */
|
||||
if (r < 0) {
|
||||
@@ -201,13 +157,13 @@ static int activate_and_check_status(const char *path, const char *device_name)
|
||||
return r;
|
||||
}
|
||||
|
||||
printf("LUKS device %s/%s is active.\n", crypt_get_dir(), device_name);
|
||||
printf("%s device %s/%s is active.\n", crypt_get_type(cd), crypt_get_dir(), device_name);
|
||||
printf("\tcipher used: %s\n", crypt_get_cipher(cd));
|
||||
printf("\tcipher mode: %s\n", crypt_get_cipher_mode(cd));
|
||||
printf("\tdevice UUID: %s\n", crypt_get_uuid(cd));
|
||||
|
||||
/*
|
||||
* Get info about active device (query DM backend)
|
||||
* Get info about the active device.
|
||||
*/
|
||||
r = crypt_get_active_device(cd, device_name, &cad);
|
||||
if (r < 0) {
|
||||
@@ -235,7 +191,7 @@ static int handle_active_device(const char *device_name)
|
||||
int r;
|
||||
|
||||
/*
|
||||
* crypt_init_by_name() initializes device context and loads LUKS header from backing device
|
||||
* crypt_init_by_name() initializes context by an active device-mapper name
|
||||
*/
|
||||
r = crypt_init_by_name(&cd, device_name);
|
||||
if (r < 0) {
|
||||
@@ -252,7 +208,7 @@ static int handle_active_device(const char *device_name)
|
||||
}
|
||||
|
||||
/*
|
||||
* crypt_deactivate() is used to deactivate device
|
||||
* crypt_deactivate() is used to deactivate a device
|
||||
*/
|
||||
r = crypt_deactivate(cd, device_name);
|
||||
if (r < 0) {
|
||||
|
||||
BIN
docs/on-disk-format-luks2.pdf
Normal file
BIN
docs/on-disk-format-luks2.pdf
Normal file
Binary file not shown.
Binary file not shown.
@@ -15,7 +15,7 @@ Important changes
|
||||
* NSS (because of missing ripemd160 it cannot provide full backward compatibility)
|
||||
* kernel userspace API (provided by kernel 2.6.38 and above)
|
||||
(Note that kernel userspace backend is very slow for this type of operation.
|
||||
But it can be usefull for embedded systems, because you can avoid userspace
|
||||
But it can be useful for embedded systems, because you can avoid userspace
|
||||
crypto library completely.)
|
||||
|
||||
Backend is selected during configure time, using --with-crypto_backend option.
|
||||
|
||||
@@ -89,7 +89,7 @@ WARNING: This release removes old deprecated API from libcryptsetup
|
||||
(It can be used to simulate trivial hidden disk concepts.)
|
||||
|
||||
libcryptsetup API changes:
|
||||
* Added options to suport detached metadata device
|
||||
* Added options to support detached metadata device
|
||||
crypt_init_by_name_and_header()
|
||||
crypt_set_data_device()
|
||||
* Add crypt_last_error() API call.
|
||||
|
||||
@@ -46,7 +46,7 @@ Side effect of reencryption is that final device will contain
|
||||
only ciphertext (for all sectors) so even if device was not properly
|
||||
wiped by random data, after reencryption you cannot distinguish
|
||||
which sectors are used.
|
||||
(Reecryption is done always for the whole device.)
|
||||
(Reencryption is done always for the whole device.)
|
||||
|
||||
There are for sure bugs, please TEST IT IN TEST ENVIRONMENT before
|
||||
use for your data.
|
||||
|
||||
36
docs/v1.7.1-ReleaseNotes
Normal file
36
docs/v1.7.1-ReleaseNotes
Normal file
@@ -0,0 +1,36 @@
|
||||
Cryptsetup 1.7.1 Release Notes
|
||||
==============================
|
||||
|
||||
Changes since version 1.7.0
|
||||
|
||||
* Code now uses kernel crypto API backend according to new
|
||||
changes introduced in mainline kernel
|
||||
|
||||
While mainline kernel should contain backward compatible
|
||||
changes, some stable series kernels do not contain fully
|
||||
backported compatibility patches.
|
||||
Without these patches most of cryptsetup operations
|
||||
(like unlocking device) fail.
|
||||
|
||||
This change in cryptsetup ensures that all operations using
|
||||
kernel crypto API works even on these kernels.
|
||||
|
||||
* The cryptsetup-reencrypt utility now properly detects removal
|
||||
of underlying link to block device and does not remove
|
||||
ongoing re-encryption log.
|
||||
This allows proper recovery (resume) of reencrypt operation later.
|
||||
|
||||
NOTE: Never use /dev/disk/by-uuid/ path for reencryption utility,
|
||||
this link disappears once the device metadata is temporarily
|
||||
removed from device.
|
||||
|
||||
* Cryptsetup now allows special "-" (standard input) keyfile handling
|
||||
even for TCRYPT (TrueCrypt and VeraCrypt compatible) devices.
|
||||
|
||||
* Cryptsetup now fails if there are more keyfiles specified
|
||||
for non-TCRYPT device.
|
||||
|
||||
* The luksKillSlot command now does not suppress provided password
|
||||
in batch mode (if password is wrong slot is not destroyed).
|
||||
Note that not providing password in batch mode means that keyslot
|
||||
is destroyed unconditionally.
|
||||
37
docs/v1.7.2-ReleaseNotes
Normal file
37
docs/v1.7.2-ReleaseNotes
Normal file
@@ -0,0 +1,37 @@
|
||||
Cryptsetup 1.7.2 Release Notes
|
||||
==============================
|
||||
|
||||
Changes since version 1.7.1
|
||||
|
||||
* Update LUKS documentation format.
|
||||
Clarify fixed sector size and keyslots alignment.
|
||||
|
||||
* Support activation options for error handling modes in Linux kernel
|
||||
dm-verity module:
|
||||
|
||||
--ignore-corruption - dm-verity just logs detected corruption
|
||||
|
||||
--restart-on-corruption - dm-verity restarts the kernel if corruption is detected
|
||||
|
||||
If the options above are not specified, default behavior for dm-verity remains.
|
||||
Default is that I/O operation fails with I/O error if corrupted block is detected.
|
||||
|
||||
--ignore-zero-blocks - Instructs dm-verity to not verify blocks that are expected
|
||||
to contain zeroes and always return zeroes directly instead.
|
||||
|
||||
NOTE that these options could have security or functional impacts,
|
||||
do not use them without assessing the risks!
|
||||
|
||||
* Fix help text for cipher benchmark specification (mention --cipher option).
|
||||
|
||||
* Fix off-by-one error in maximum keyfile size.
|
||||
Allow keyfiles up to compiled-in default and not that value minus one.
|
||||
|
||||
* Support resume of interrupted decryption in cryptsetup-reencrypt utility.
|
||||
To resume decryption, LUKS device UUID (--uuid option) option must be used.
|
||||
|
||||
* Do not use direct-io for LUKS header with unaligned keyslots.
|
||||
Such headers were used only by the first cryptsetup-luks-1.0.0 release (2005).
|
||||
|
||||
* Fix device block size detection to properly work on particular file-based
|
||||
containers over underlying devices with 4k sectors.
|
||||
20
docs/v1.7.3-ReleaseNotes
Normal file
20
docs/v1.7.3-ReleaseNotes
Normal file
@@ -0,0 +1,20 @@
|
||||
Cryptsetup 1.7.3 Release Notes
|
||||
==============================
|
||||
|
||||
Changes since version 1.7.2
|
||||
|
||||
* Fix device access to hash offsets located beyond the 2GB device boundary in veritysetup.
|
||||
|
||||
* Set configured (compile-time) default iteration time for devices created directly through
|
||||
libcryptsetup (default was hardcoded 1 second, the configured value applied only
|
||||
for cryptsetup application).
|
||||
|
||||
* Fix PBKDF2 benchmark to not double iteration count for specific corner case.
|
||||
If the measurement function returns exactly 500 ms, the iteration calculation loop
|
||||
doubled iteration count but instead of repeating measurement it used this value directly.
|
||||
|
||||
* OpenSSL backend: fix memory leak if hash context was repeatedly reused.
|
||||
|
||||
* OpenSSL backend: add support for OpenSSL 1.1.0.
|
||||
|
||||
* Fix several minor spelling errors.
|
||||
22
docs/v1.7.4-ReleaseNotes
Normal file
22
docs/v1.7.4-ReleaseNotes
Normal file
@@ -0,0 +1,22 @@
|
||||
Cryptsetup 1.7.4 Release Notes
|
||||
==============================
|
||||
|
||||
Changes since version 1.7.3
|
||||
|
||||
* Allow to specify LUKS1 hash algorithm in Python luksFormat wrapper.
|
||||
|
||||
* Use LUKS1 compiled-in defaults also in Python wrapper.
|
||||
|
||||
* OpenSSL backend: Fix OpenSSL 1.1.0 support without backward compatible API.
|
||||
|
||||
* OpenSSL backend: Fix LibreSSL compatibility.
|
||||
|
||||
* Check for data device and hash device area overlap in veritysetup.
|
||||
|
||||
* Fix a possible race while allocating a free loop device.
|
||||
|
||||
* Fix possible file descriptor leaks if libcryptsetup is run from a forked process.
|
||||
|
||||
* Fix missing same_cpu_crypt flag in status command.
|
||||
|
||||
* Various updates to FAQ and man pages.
|
||||
22
docs/v1.7.5-ReleaseNotes
Normal file
22
docs/v1.7.5-ReleaseNotes
Normal file
@@ -0,0 +1,22 @@
|
||||
Cryptsetup 1.7.5 Release Notes
|
||||
==============================
|
||||
|
||||
Changes since version 1.7.4
|
||||
|
||||
* Fixes to luksFormat to properly support recent kernel running in FIPS mode.
|
||||
|
||||
Cryptsetup must never use a weak key even if it is just used for testing
|
||||
of algorithm availability. In FIPS mode, weak keys are always rejected.
|
||||
|
||||
A weak key is for example detected if the XTS encryption mode use
|
||||
the same key for the tweak and the encryption part.
|
||||
|
||||
* Fixes accesses to unaligned hidden legacy TrueCrypt header.
|
||||
|
||||
On a native 4k-sector device the old hidden TrueCrypt header is not
|
||||
aligned with the hw sector size (this problem was fixed in later TrueCrypt
|
||||
on-disk format versions).
|
||||
|
||||
Cryptsetup now properly aligns the read so it does not fail.
|
||||
|
||||
* Fixes to optional dracut ramdisk scripts for offline re-encryption on initial boot.
|
||||
605
docs/v2.0.0-ReleaseNotes
Normal file
605
docs/v2.0.0-ReleaseNotes
Normal file
@@ -0,0 +1,605 @@
|
||||
Cryptsetup 2.0.0 Release Notes
|
||||
==============================
|
||||
Stable release with experimental features.
|
||||
|
||||
This version introduces a new on-disk LUKS2 format.
|
||||
|
||||
The legacy LUKS (referenced as LUKS1) will be fully supported
|
||||
forever as well as a traditional and fully backward compatible format.
|
||||
|
||||
NOTE: This version changes soname of libcryptsetup library and increases
|
||||
major version for all public symbols.
|
||||
Most of the old functions are fully backward compatible, so only
|
||||
recompilation of programs should be needed.
|
||||
|
||||
Please note that authenticated disk encryption, non-cryptographic
|
||||
data integrity protection (dm-integrity), use of Argon2 Password-Based
|
||||
Key Derivation Function and the LUKS2 on-disk format itself are new
|
||||
features and can contain some bugs.
|
||||
|
||||
To provide all security features of authenticated encryption we need
|
||||
better nonce-reuse resistant algorithm in kernel (see note below).
|
||||
For now, please use authenticated encryption as experimental feature.
|
||||
|
||||
Please do not use LUKS2 without properly configured backup or in
|
||||
production systems that need to be compatible with older systems.
|
||||
|
||||
Changes since version 2.0.0-RC1
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* Limit KDF requested (for format) memory by available physical memory.
|
||||
On some systems too high requested amount of memory causes OOM killer
|
||||
to kill the process (instead of returning ENOMEM).
|
||||
We never try to use more than half of available physical memory.
|
||||
|
||||
* Ignore device alignment if it is not multiple of minimal-io.
|
||||
Some USB enclosures seems to report bogus topology info that
|
||||
prevents to use LUKS detached header.
|
||||
|
||||
Changes since version 2.0.0-RC0
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
* Enable to use system libargon2 instead of bundled version.
|
||||
Renames --disable-argon2 to --disable-internal-argon2 option
|
||||
and adds --enable-libargon2 flag to allow system libargon2.
|
||||
|
||||
* Changes in build system (Automake)
|
||||
- The build system now uses non-recursive automake (except for tests).
|
||||
(Tools binaries are now located in buildroot directory.)
|
||||
- New --disable-cryptsetup option to disable build of cryptsetup tool.
|
||||
- Enable build of cryptsetup-reencrypt by default.
|
||||
|
||||
* Install tmpfiles.d configuration for LUKS2 locking directory.
|
||||
You can overwrite this using --with-tmpfilesdir configure option.
|
||||
If your distro does not support tmpfiles.d directory, you have
|
||||
to create locking directory (/run/lock/cryptsetup) in cryptsetup
|
||||
package (or init scripts).
|
||||
|
||||
* Adds limited support for offline reencryption of LUKS2 format.
|
||||
|
||||
* Decrease size of testing images (and the whole release archive).
|
||||
|
||||
* Fixes for several memory leaks found by Valgrind and Coverity tools.
|
||||
|
||||
* Fixes for several typos in man pages and error messages.
|
||||
|
||||
* LUKS header file in luksFormat is now automatically created
|
||||
if it does not exist.
|
||||
|
||||
* Do not allow resize if device size is not aligned to sector size.
|
||||
|
||||
Cryptsetup 2.0.0 RC0 Release Notes
|
||||
==================================
|
||||
|
||||
Important features
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
|
||||
* New command integritysetup: support for the new dm-integrity kernel target.
|
||||
|
||||
The dm-integrity is a new kernel device-mapper target that introduces
|
||||
software emulation of per-sector integrity fields on the disk sector level.
|
||||
It is available since Linux kernel version 4.12.
|
||||
|
||||
The provided per-sector metadata fields can be used for storing a data
|
||||
integrity checksum (for example CRC32).
|
||||
The dm-integrity implements data journal that enforces atomic update
|
||||
of a sector and its integrity metadata.
|
||||
|
||||
Integritysetup is a CLI utility that can setup standalone dm-integrity
|
||||
devices (that internally check integrity of data).
|
||||
|
||||
Integritysetup is intended to be used for settings that require
|
||||
non-cryptographic data integrity protection with no data encryption.
|
||||
Fo setting integrity protected encrypted devices, see disk authenticated
|
||||
encryption below.
|
||||
|
||||
Note that after formatting the checksums need to be initialized;
|
||||
otherwise device reads will fail because of integrity errors.
|
||||
Integritysetup by default tries to wipe the device with zero blocks
|
||||
to avoid this problem. Device wipe can be time-consuming, you can skip
|
||||
this step by specifying --no-wipe option.
|
||||
(But note that not wiping device can cause some operations to fail
|
||||
if a write is not multiple of page size and kernel page cache tries
|
||||
to read sectors with not yet initialized checksums.)
|
||||
|
||||
The default setting is tag size 4 bytes per-sector and CRC32C protection.
|
||||
To format device with these defaults:
|
||||
$ integritysetup format <device>
|
||||
$ integritysetup open <device> <name>
|
||||
|
||||
Note that used algorithm (unlike tag size) is NOT stored in device
|
||||
kernel superblock and if you use different algorithm, you MUST specify
|
||||
it in every open command, for example:
|
||||
$ integritysetup format <device> --tag-size 32 --integrity sha256
|
||||
$ integritysetup open <device> <name> --integrity sha256
|
||||
|
||||
For more info, see integrity man page.
|
||||
|
||||
* Veritysetup command can now format and activate dm-verity devices
|
||||
that contain Forward Error Correction (FEC) (Reed-Solomon code is used).
|
||||
This feature is used on most of Android devices already (available since
|
||||
Linux kernel 4.5).
|
||||
|
||||
There are new options --fec-device, --fec-offset to specify data area
|
||||
with correction code and --fec-roots that set Redd-Solomon generator roots.
|
||||
This setting can be used for format command (veritysetup will calculate
|
||||
and store RS codes) or open command (veritysetup configures kernel
|
||||
dm-verity to use RS codes).
|
||||
|
||||
For more info see veritysetup man page.
|
||||
|
||||
* Support for larger sector sizes for crypt devices.
|
||||
|
||||
LUKS2 and plain crypt devices can be now configured with larger encryption
|
||||
sector (typically 4096 bytes, sector size must be the power of two,
|
||||
maximal sector size is 4096 bytes for portability).
|
||||
Large sector size can decrease encryption overhead and can also help
|
||||
with some specific crypto hardware accelerators that perform very
|
||||
badly with 512 bytes sectors.
|
||||
|
||||
Note that if you configure such a larger sector of the device that does use
|
||||
smaller physical sector, there is a possibility of a data corruption during
|
||||
power fail (partial sector writes).
|
||||
|
||||
WARNING: If you use different sector size for a plain device after data were
|
||||
stored, the decryption will produce garbage.
|
||||
|
||||
For LUKS2, the sector size is stored in metadata and cannot be changed later.
|
||||
|
||||
LUKS2 format and features
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
The LUKS2 is an on-disk storage format designed to provide simple key
|
||||
management, primarily intended for Full Disk Encryption based on dm-crypt.
|
||||
|
||||
The LUKS2 is inspired by LUKS1 format and in some specific situations (most
|
||||
of the default configurations) can be converted in-place from LUKS1.
|
||||
|
||||
The LUKS2 format is designed to allow future updates of various
|
||||
parts without the need to modify binary structures and internally
|
||||
uses JSON text format for metadata. Compilation now requires the json-c library
|
||||
that is used for JSON data processing.
|
||||
|
||||
On-disk format provides redundancy of metadata, detection
|
||||
of metadata corruption and automatic repair from metadata copy.
|
||||
|
||||
NOTE: For security reasons, there is no redundancy in keyslots binary data
|
||||
(encrypted keys) but the format allows adding such a feature in future.
|
||||
|
||||
NOTE: to operate correctly, LUKS2 requires locking of metadata.
|
||||
Locking is performed by using flock() system call for images in file
|
||||
and for block device by using a specific lock file in /run/lock/cryptsetup.
|
||||
|
||||
This directory must be created by distribution (do not rely on internal
|
||||
fallback). For systemd-based distribution, you can simply install
|
||||
scripts/cryptsetup.conf into tmpfiles.d directory.
|
||||
|
||||
For more details see LUKS2-format.txt and LUKS2-locking.txt in the docs
|
||||
directory. (Please note this is just overview, there will be more formal
|
||||
documentation later.)
|
||||
|
||||
LUKS2 use
|
||||
~~~~~~~~~
|
||||
|
||||
LUKS2 allows using all possible configurations as LUKS1.
|
||||
|
||||
To format device as LUKS2, you have to add "--type luks2" during format:
|
||||
|
||||
$ cryptsetup luksFormat --type luks2 <device>
|
||||
|
||||
All commands issued later will recognize the new format automatically.
|
||||
|
||||
The newly added features in LUKS2 include:
|
||||
|
||||
* Authenticated disk (sector) encryption (EXPERIMENTAL)
|
||||
|
||||
Legacy Full disk encryption (FDE), for example, LUKS1, is a length-preserving
|
||||
encryption (plaintext is the same size as a ciphertext).
|
||||
Such FDE can provide data confidentiality, but cannot provide sound data
|
||||
integrity protection.
|
||||
|
||||
Full disk authenticated encryption is a way how to provide both
|
||||
confidentiality and data integrity protection. Integrity protection here means
|
||||
not only detection of random data corruption (silent data corruption) but also
|
||||
prevention of an unauthorized intentional change of disk sector content.
|
||||
|
||||
NOTE: Integrity protection of this type cannot prevent a replay attack.
|
||||
An attacker can replace the device or its part of the old content, and it
|
||||
cannot be detected.
|
||||
If you need such protection, better use integrity protection on a higher layer.
|
||||
|
||||
For data integrity protection on the sector level, we need additional
|
||||
per-sector metadata space. In LUKS2 this space is provided by a new
|
||||
device-mapper dm-integrity target (available since kernel 4.12).
|
||||
Here the integrity target provides only reliable per-sector metadata store,
|
||||
and the whole authenticated encryption is performed inside dm-crypt stacked
|
||||
over the dm-integrity device.
|
||||
|
||||
For encryption, Authenticated Encryption with Additional Data (AEAD) is used.
|
||||
Every sector is processed as a encryption request of this format:
|
||||
|
||||
|----- AAD -------|------ DATA -------|-- AUTH TAG --|
|
||||
| (authenticated) | (auth+encryption) | |
|
||||
| sector_LE | IV | sector in/out | tag in/out |
|
||||
|
||||
AEAD encrypts the whole sector and also authenticates sector number
|
||||
(to detect sector relocation) and also authenticates Initialization Vector.
|
||||
|
||||
AEAD encryption produces encrypted data and authentication tag.
|
||||
The authenticated tag is then stored in per-sector metadata space provided
|
||||
by dm-integrity.
|
||||
|
||||
Most of the current AEAD algorithms requires IV as a nonce, value that is
|
||||
never reused. Because sector number, as an IV, cannot be used in this
|
||||
environment, we use a new random IV (IV is a random value generated by system
|
||||
RNG on every write). This random IV is then stored in the per-sector metadata
|
||||
as well.
|
||||
|
||||
Because the authentication tag (and IV) requires additional space, the device
|
||||
provided for a user has less capacity. Also, the data journalling means that
|
||||
writes are performed twice, decreasing throughput.
|
||||
|
||||
This integrity protection works better with SSDs. If you want to ignore
|
||||
dm-integrity data journal (because journalling is performed on some higher
|
||||
layer or you just want to trade-off performance to safe recovery), you can
|
||||
switch journal off with --integrity-no-journal option.
|
||||
(This flag can be stored persistently as well.)
|
||||
|
||||
Note that (similar to integritysetup) the device read will fail if
|
||||
authentication tag is not initialized (no previous write).
|
||||
By default cryptsetup run wipe of a device (writing zeroes) to initialize
|
||||
authentication tags. This operation can be very time-consuming.
|
||||
You can skip device wipe using --integrity-no-wipe option.
|
||||
|
||||
To format LUKS2 device with integrity protection, use new --integrity option.
|
||||
|
||||
For now, there are very few AEAD algorithms that can be used, and some
|
||||
of them are known to be problematic. In this release we support only
|
||||
a few of AEAD algorithms (options are for now hard coded), later this
|
||||
extension will be completely algorithm-agnostic.
|
||||
|
||||
For testing of authenticated encryption, these algorithms work for now:
|
||||
|
||||
1) aes-xts-plain64 with hmac-sha256 or hmac-sha512 as the authentication tag.
|
||||
(Common FDE mode + independent authentication tag. Authentication key
|
||||
for HMAC is independently generated. This mode is very slow.)
|
||||
$ cryptsetup luksFormat --type luks2 <device> --cipher aes-xts-plain64 --integrity hmac-sha256
|
||||
|
||||
2) aes-gcm-random (native AEAD mode)
|
||||
DO NOT USE in production! The GCM mode uses only 96-bit nonce,
|
||||
and possible collision means fatal security problem.
|
||||
GCM mode has very good hardware support through AES-NI, so it is useful
|
||||
for performance testing.
|
||||
$ cryptsetup luksFormat --type luks2 <device> --cipher aes-gcm-random --integrity aead
|
||||
|
||||
3) ChaCha20 with Poly1305 authenticator (according to RFC7539)
|
||||
$ cryptsetup luksFormat --type luks2 <device> --cipher chacha20-random --integrity poly1305
|
||||
|
||||
To specify AES128/AES256 just specify proper key size (without possible
|
||||
authentication key). Other symmetric ciphers, like Serpent or Twofish,
|
||||
should work as well. The mode 1) and 2) should be compatible with IEEE 1619.1
|
||||
standard recommendation.
|
||||
|
||||
There will be better suitable authenticated modes available soon
|
||||
For now we are just preparing framework to enable it (and hopefully improve security of FDE).
|
||||
|
||||
FDE authenticated encryption is not a replacement for filesystem layer
|
||||
authenticated encryption. The goal is to provide at least something because
|
||||
data integrity protection is often completely ignored in today systems.
|
||||
|
||||
* New memory-hard PBKDF
|
||||
|
||||
LUKS1 introduced Password-Based Key Derivation Function v2 as a tool to
|
||||
increase attacker cost for a dictionary and brute force attacks.
|
||||
The PBKDF2 uses iteration count to increase time of key derivation.
|
||||
Unfortunately, with modern GPUs, the PBKDF2 calculations can be run
|
||||
in parallel and PBKDF2 can no longer provide the best available protection.
|
||||
Increasing iteration count just cannot prevent massive parallel dictionary
|
||||
password attacks in long-term.
|
||||
|
||||
To solve this problem, a new PBKDF, based on so-called memory-hard functions
|
||||
can be used. Key derivation with memory-hard function requires a certain
|
||||
amount of memory to compute its output. The memory requirement is very
|
||||
costly for GPUs and prevents these systems to operate effectively,
|
||||
increasing cost for attackers.
|
||||
|
||||
LUKS2 introduces support for Argon2i and Argon2id as a PBKDF.
|
||||
Argon2 is the winner of Password Hashing Competition and is currently
|
||||
in final RFC draft specification.
|
||||
|
||||
For now, libcryptsetup contains the embedded copy of reference implementation
|
||||
of Argon2 (that is easily portable to all architectures).
|
||||
Later, once this function is available in common crypto libraries, it will
|
||||
switch to external implementation. (This happened for LUKS1 and PBKDF2
|
||||
as well years ago.)
|
||||
With using reference implementation (that is not optimized for speed), there
|
||||
is some performance penalty. However, using memory-hard PBKDF should still
|
||||
significantly complicate GPU-optimized dictionary and brute force attacks.
|
||||
|
||||
The Argon2 uses three costs: memory, time (number of iterations) and parallel
|
||||
(number of threads).
|
||||
Note that time and memory cost highly influences each other (accessing a lot
|
||||
of memory takes more time).
|
||||
|
||||
There is a new benchmark that tries to calculate costs to take similar way as
|
||||
in LUKS1 (where iteration is measured to take 1-2 seconds on user system).
|
||||
Because now there are more cost variables, it prefers time cost (iterations)
|
||||
and tries to find required memory that fits. (IOW required memory cost can be
|
||||
lower if the benchmarks are not able to find required parameters.)
|
||||
The benchmark cannot run too long, so it tries to approximate next step
|
||||
for benchmarking.
|
||||
|
||||
For now, default LUKS2 PBKDF algorithm is Argon2i (data independent variant)
|
||||
with memory cost set to 128MB, time to 800ms and parallel thread according
|
||||
to available CPU cores but no more than 4.
|
||||
|
||||
All default parameters can be set during compile time and also set on
|
||||
the command line by using --pbkdf, --pbkdf-memory, --pbkdf-parallel and
|
||||
--iter-time options.
|
||||
(Or without benchmark directly by using --pbkdf-force-iterations, see below.)
|
||||
|
||||
You can still use PBKDF2 even for LUKS2 by specifying --pbkdf pbkdf2 option.
|
||||
(Then only iteration count is applied.)
|
||||
|
||||
* Use of kernel keyring
|
||||
|
||||
Kernel keyring is a storage for sensitive material (like cryptographic keys)
|
||||
inside Linux kernel.
|
||||
|
||||
LUKS2 uses keyring for two major functions:
|
||||
|
||||
- To store volume key for dm-crypt where it avoids sending volume key in
|
||||
every device-mapper ioctl structure. Volume key is also no longer directly
|
||||
visible in a dm-crypt mapping table. The key is not available for the user
|
||||
after dm-crypt configuration (obviously except direct memory scan).
|
||||
Use of kernel keyring can be disabled in runtime by --disable-keyring option.
|
||||
|
||||
- As a tool to automatically unlock LUKS device if a passphrase is put into
|
||||
kernel keyring and proper keyring token is configured.
|
||||
|
||||
This allows storing a secret (passphrase) to kernel per-user keyring by
|
||||
some external tool (for example some TPM handler) and LUKS2, if configured,
|
||||
will automatically search in the keyring and unlock the system.
|
||||
For more info see Tokens section below.
|
||||
|
||||
* Persistent flags
|
||||
The activation flags (like allow-discards) can be stored in metadata and used
|
||||
automatically by all later activations (even without using crypttab).
|
||||
|
||||
To store activation flags permanently, use activation command with required
|
||||
flags and add --persistent option.
|
||||
|
||||
For example, to mark device to always activate with TRIM enabled,
|
||||
use (for LUKS2 type):
|
||||
|
||||
$ cryptsetup open <device> <name> --allow-discards --persistent
|
||||
|
||||
You can check persistent flags in dump command output:
|
||||
|
||||
$ cryptsetup luksDump <device>
|
||||
|
||||
* Tokens and auto-activation
|
||||
|
||||
A LUKS2 token is an object that can be described "how to get passphrase or key"
|
||||
to unlock particular keyslot.
|
||||
(Also it can be used to store any additional metadata, and with
|
||||
the libcryptsetup interface it can be used to define user token types.)
|
||||
|
||||
Cryptsetup internally implements keyring token. Cryptsetup tries to use
|
||||
available tokens before asking for the passphrase. For keyring token,
|
||||
it means that if the passphrase is available under specified identifier
|
||||
inside kernel keyring, the device is automatically activated using this
|
||||
stored passphrase.
|
||||
|
||||
Example of using LUKS2 keyring token:
|
||||
|
||||
# Adding token to metadata with "my_token" identifier (by default it applies to all keyslots).
|
||||
$ cryptsetup token add --key-description "my_token" <device>
|
||||
|
||||
# Storing passphrase to user keyring (this can be done by an external application)
|
||||
$ echo -n <passphrase> | keyctl padd user my_token @u
|
||||
|
||||
# Now cryptsetup activates automatically if it finds correct passphrase
|
||||
$ cryptsetup open <device> <name>
|
||||
|
||||
The main reason to use tokens this way is to separate possible hardware
|
||||
handlers from cryptsetup code.
|
||||
|
||||
* Keyslot priorities
|
||||
|
||||
LUKS2 keyslot can have a new priority attribute.
|
||||
The default is "normal". The "prefer" priority tell the keyslot to be tried
|
||||
before other keyslots. Priority "ignore" means that keyslot will never be
|
||||
used if not specified explicitly (it can be used for backup administrator
|
||||
passwords that are used only situations when a user forgets own passphrase).
|
||||
|
||||
The priority of keyslot can be set with new config command, for example
|
||||
$ cryptsetup config <device> --key-slot 1 --priority prefer
|
||||
|
||||
Setting priority to normal will reset slot to normal state.
|
||||
|
||||
* LUKS2 label and subsystem
|
||||
|
||||
The header now contains additional fields for label and subsystem (additional
|
||||
label). These fields can be used similar to filesystem label and will be
|
||||
visible in udev rules to possible filtering. (Note that blkid do not yet
|
||||
contain the LUKS scanning code).
|
||||
|
||||
By default both labels are empty. Label and subsystem are always set together
|
||||
(no option means clear the label) with the config command:
|
||||
|
||||
$ cryptsetup config <device> --label my_device --subsystem ""
|
||||
|
||||
* In-place conversion form LUKS1
|
||||
|
||||
To allow easy testing and transition to the new LUKS2 format, there is a new
|
||||
convert command that allows in-place conversion from the LUKS1 format and,
|
||||
if there are no incompatible options, also conversion back from LUKS2
|
||||
to LUKS1 format.
|
||||
|
||||
Note this command can be used only on some LUKS1 devices (some device header
|
||||
sizes are not supported).
|
||||
This command is dangerous, never run it without header backup!
|
||||
If something fails in the middle of conversion (IO error), the header
|
||||
is destroyed. (Note that conversion requires move of keyslot data area to
|
||||
a different offset.)
|
||||
|
||||
To convert header in-place to LUKS2 format, use
|
||||
$ cryptsetup convert <device> --type luks2
|
||||
|
||||
To convert it back to LUKS1 format, use
|
||||
$ cryptsetup convert <device> --type luks1
|
||||
|
||||
You can verify LUKS version with luksDump command.
|
||||
$ cryptsetup luksDump <device>
|
||||
|
||||
Note that some LUKS2 features will make header incompatible with LUKS1 and
|
||||
conversion will be rejected (for example using new Argon2 PBKDF or integrity
|
||||
extensions). Some minor attributes can be lost in conversion.
|
||||
|
||||
Other changes
|
||||
~~~~~~~~~~~~~
|
||||
|
||||
* Explicit KDF iterations count setting
|
||||
|
||||
With new PBKDF interface, there is also the possibility to setup PBKDF costs
|
||||
directly, avoiding benchmarks. This can be useful if device is formatted to be
|
||||
primarily used on a different system.
|
||||
|
||||
The option --pbkdf-force-iterations is available for both LUKS1 and LUKS2
|
||||
format. Using this option can cause device to have either very low or very
|
||||
high PBKDF costs.
|
||||
In the first case it means bad protection to dictionary attacks, in the second
|
||||
case, it can mean extremely high unlocking time or memory requirements.
|
||||
Use only if you are sure what you are doing!
|
||||
|
||||
Not that this setting also affects iteration count for the key digest.
|
||||
For LUKS1 iteration count for digest will be approximately 1/8 of requested
|
||||
value, for LUKS2 and "pbkdf2" digest minimal PBKDF2 iteration count (1000)
|
||||
will be used. You cannot set lower iteration count than the internal minimum
|
||||
(1000 for PBKDF2).
|
||||
|
||||
To format LUKS1 device with forced iteration count (and no benchmarking), use
|
||||
$ cryptsetup luksFormat <device> --pbkdf-force-iterations 22222
|
||||
|
||||
For LUKS2 it is always better to specify full settings (do not rely on default
|
||||
cost values).
|
||||
For example, we can set to use Argon2id with iteration cost 5, memory 128000
|
||||
and parallel set 1:
|
||||
$ cryptsetup luksFormat --type luks2 <device> \
|
||||
--pbkdf argon2id --pbkdf-force-iterations 5 --pbkdf-memory 128000 --pbkdf-parallel 1
|
||||
|
||||
* VeraCrypt PIM
|
||||
|
||||
Cryptsetup can now also open VeraCrypt device that uses Personal Iteration
|
||||
Multiplier (PIM). PIM is an integer value that user must remember additionally
|
||||
to passphrase and influences PBKDF2 iteration count (without it VeraCrypt uses
|
||||
a fixed number of iterations).
|
||||
|
||||
To open VeraCrypt device with PIM settings, use --veracrypt-pim (to specify
|
||||
PIM on the command line) or --veracrypt-query-pim to query PIM interactively.
|
||||
|
||||
* Support for plain64be IV
|
||||
|
||||
The plain64be is big-endian variant of plain64 Initialization Vector. It is
|
||||
used in some images of hardware-based disk encryption systems. Supporting this
|
||||
variant allows using dm-crypt to map such images through cryptsetup.
|
||||
|
||||
* Deferral removal
|
||||
|
||||
Cryptsetup now can mark device for deferred removal by using a new option
|
||||
--deferred. This means that close command will not fail if the device is still
|
||||
in use, but will instruct the kernel to remove the device automatically after
|
||||
use count drops to zero (for example, once the filesystem is unmounted).
|
||||
|
||||
* A lot of updates to man pages and many minor changes that would make this
|
||||
release notes too long ;-)
|
||||
|
||||
Libcryptsetup API changes
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
These API functions were removed, libcryptsetup no longer handles password
|
||||
retries from terminal (application should handle terminal operations itself):
|
||||
crypt_set_password_callback;
|
||||
crypt_set_timeout;
|
||||
crypt_set_password_retry;
|
||||
crypt_set_password_verify;
|
||||
|
||||
This call is removed (no need to keep typo backward compatibility,
|
||||
the proper function is crypt_set_iteration_time :-)
|
||||
crypt_set_iterarion_time;
|
||||
|
||||
These calls were removed because are not safe, use per-context
|
||||
error callbacks instead:
|
||||
crypt_last_error;
|
||||
crypt_get_error;
|
||||
|
||||
The PBKDF benchmark was replaced by a new function that uses new KDF structure
|
||||
crypt_benchmark_kdf; (removed)
|
||||
crypt_benchmark_pbkdf; (new API call)
|
||||
|
||||
These new calls are now exported, for details see libcryptsetup.h:
|
||||
crypt_keyslot_add_by_key;
|
||||
crypt_keyslot_set_priority;
|
||||
crypt_keyslot_get_priority;
|
||||
|
||||
crypt_token_json_get;
|
||||
crypt_token_json_set;
|
||||
crypt_token_status;
|
||||
crypt_token_luks2_keyring_get;
|
||||
crypt_token_luks2_keyring_set;
|
||||
crypt_token_assign_keyslot;
|
||||
crypt_token_unassign_keyslot;
|
||||
crypt_token_register;
|
||||
|
||||
crypt_activate_by_token;
|
||||
crypt_activate_by_keyring;
|
||||
crypt_deactivate_by_name;
|
||||
|
||||
crypt_metadata_locking;
|
||||
crypt_volume_key_keyring;
|
||||
crypt_get_integrity_info;
|
||||
crypt_get_sector_size;
|
||||
crypt_persistent_flags_set;
|
||||
crypt_persistent_flags_get;
|
||||
crypt_set_pbkdf_type;
|
||||
crypt_get_pbkdf_type;
|
||||
|
||||
crypt_convert;
|
||||
crypt_keyfile_read;
|
||||
crypt_wipe;
|
||||
|
||||
Unfinished things & TODO for next releases
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* There will be better documentation and examples.
|
||||
|
||||
* There will be some more formal definition of the threat model for integrity
|
||||
protection. (And a link to some papers discussing integrity protection,
|
||||
once it is, hopefully, accepted and published.)
|
||||
|
||||
* Offline re-encrypt tool LUKS2 support is currently limited.
|
||||
There will be online LUKS2 re-encryption tool in future.
|
||||
|
||||
* Authenticated encryption will use new algorithms from CAESAR competition
|
||||
(https://competitions.cr.yp.to/caesar.html) once these algorithms are available
|
||||
in kernel (more on this later).
|
||||
NOTE: Currently available authenticated modes (GCM, Chacha20-poly1305)
|
||||
in kernel have too small 96-bit nonces that are problematic with
|
||||
randomly generated IVs (the collison probability is not negligible).
|
||||
For the GCM, nonce collision is a fatal problem.
|
||||
|
||||
* Authenticated encryption do not set encryption for dm-integrity journal.
|
||||
|
||||
While it does not influence data confidentiality or integrity protection,
|
||||
an attacker can get some more information from data journal or cause that
|
||||
system will corrupt sectors after journal replay. (That corruption will be
|
||||
detected though.)
|
||||
|
||||
* Some utilities (blkid, systemd-cryptsetup) have already support for LUKS
|
||||
but not yet in released version (support in crypttab etc).
|
||||
|
||||
* There are some examples of user-defined tokens inside misc/luks2_keyslot_example
|
||||
directory (like a simple external program that uses libssh to unlock LUKS2
|
||||
using remote keyfile).
|
||||
|
||||
* The python binding (pycryptsetup) contains only basic functionality for LUKS1
|
||||
(it is not updated for new features) and will be deprecated soon in favor
|
||||
of python bindings to libblockdev library (that can already handle LUKS1 devices).
|
||||
109
docs/v2.0.1-ReleaseNotes
Normal file
109
docs/v2.0.1-ReleaseNotes
Normal file
@@ -0,0 +1,109 @@
|
||||
Cryptsetup 2.0.1 Release Notes
|
||||
==============================
|
||||
Stable and bug-fix release with experimental features.
|
||||
|
||||
This version introduces a new on-disk LUKS2 format.
|
||||
|
||||
The legacy LUKS (referenced as LUKS1) will be fully supported
|
||||
forever as well as a traditional and fully backward compatible format.
|
||||
|
||||
Please note that authenticated disk encryption, non-cryptographic
|
||||
data integrity protection (dm-integrity), use of Argon2 Password-Based
|
||||
Key Derivation Function and the LUKS2 on-disk format itself are new
|
||||
features and can contain some bugs.
|
||||
|
||||
To provide all security features of authenticated encryption we need
|
||||
a better nonce-reuse resistant algorithm in the kernel (see note below).
|
||||
For now, please use authenticated encryption as an experimental feature.
|
||||
|
||||
Please do not use LUKS2 without properly configured backup or in
|
||||
production systems that need to be compatible with older systems.
|
||||
|
||||
Changes since version 2.0.0
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
* To store volume key into kernel keyring, kernel 4.15 with dm-crypt 1.18.1
|
||||
is required. If a volume key is stored in keyring (LUKS2 only),
|
||||
the dm-crypt v1.15.0 through v1.18.0 contains a serious bug that may cause
|
||||
data corruption for ciphers with ESSIV.
|
||||
(The key for ESSIV is zeroed because of code misplacement.)
|
||||
This bug is not present for LUKS1 or any other IVs used in LUKS modes.
|
||||
This change is not visible to the user (except dmsetup output).
|
||||
|
||||
* Increase maximum allowed PBKDF memory-cost limit to 4 GiB.
|
||||
The Argon2 PBKDF uses 1GiB by default; this is also limited by the amount
|
||||
of physical memory available (maximum is half of the physical memory).
|
||||
|
||||
* Use /run/cryptsetup as default for cryptsetup locking dir.
|
||||
There were problems with sharing /run/lock with lockdev, and in the early
|
||||
boot, the directory was missing.
|
||||
The directory can be changed with --with-luks2-lock-path and
|
||||
--with-luks2-lock-dir-perms configure switches.
|
||||
|
||||
* Introduce new 64-bit byte-offset *keyfile_device_offset functions.
|
||||
|
||||
The keyfile interface was designed, well, for keyfiles. Unfortunately,
|
||||
there are user cases where a keyfile can be placed on a device, and
|
||||
size_t offset can overflow on 32-bit systems.
|
||||
|
||||
New set of functions that allow 64-bit offsets even on 32bit systems
|
||||
are now available:
|
||||
|
||||
- crypt_resume_by_keyfile_device_offset
|
||||
- crypt_keyslot_add_by_keyfile_device_offset
|
||||
- crypt_activate_by_keyfile_device_offset
|
||||
- crypt_keyfile_device_read
|
||||
|
||||
The new functions have added the _device_ in name.
|
||||
Old functions are just internal wrappers around these.
|
||||
|
||||
Also cryptsetup --keyfile-offset and --new-keyfile-offset now allows
|
||||
64-bit offsets as parameters.
|
||||
|
||||
* Add error hint for wrongly formatted cipher strings in LUKS1 and
|
||||
properly fail in luksFormat if cipher format is missing required IV.
|
||||
For now, crypto API quietly used cipher without IV if a cipher
|
||||
algorithm without IV specification was used (e.g., aes-xts).
|
||||
This caused fail later during activation.
|
||||
|
||||
* Configure check for a recent Argon2 lib to support mandatory Argon2id.
|
||||
|
||||
* Fix for the cryptsetup-reencrypt static build if pwquality is enabled.
|
||||
|
||||
* Update LUKS1 standard doc (https links in the bibliography).
|
||||
|
||||
|
||||
Unfinished things & TODO for next releases
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* There will be better documentation and examples.
|
||||
|
||||
* There will be some more formal definition of the threat model for integrity
|
||||
protection. (And a link to some papers discussing integrity protection,
|
||||
once it is, hopefully, accepted and published.)
|
||||
|
||||
* Offline re-encrypt tool LUKS2 support is currently limited.
|
||||
There will be online LUKS2 re-encryption tool in future.
|
||||
|
||||
* Authenticated encryption will use new algorithms from CAESAR competition
|
||||
(https://competitions.cr.yp.to/caesar.html) once these algorithms are
|
||||
available in the kernel (more on this later).
|
||||
NOTE: Currently available authenticated modes (GCM, Chacha20-poly1305)
|
||||
in the kernel have too small 96-bit nonces that are problematic with
|
||||
randomly generated IVs (the collision probability is not negligible).
|
||||
For the GCM, nonce collision is a fatal problem.
|
||||
|
||||
* Authenticated encryption do not set encryption for a dm-integrity journal.
|
||||
|
||||
While it does not influence data confidentiality or integrity protection,
|
||||
an attacker can get some more information from data journal or cause that
|
||||
system will corrupt sectors after journal replay. (That corruption will be
|
||||
detected though.)
|
||||
|
||||
* There are examples of user-defined tokens inside misc/luks2_keyslot_example
|
||||
directory (like a simple external program that uses libssh to unlock LUKS2
|
||||
using remote keyfile).
|
||||
|
||||
* The python binding (pycryptsetup) contains only basic functionality for LUKS1
|
||||
(it is not updated for new features) and will be deprecated soon in favor
|
||||
of python bindings to the libblockdev library (that can already handle LUKS1
|
||||
devices).
|
||||
93
docs/v2.0.2-ReleaseNotes
Normal file
93
docs/v2.0.2-ReleaseNotes
Normal file
@@ -0,0 +1,93 @@
|
||||
Cryptsetup 2.0.2 Release Notes
|
||||
==============================
|
||||
Stable and bug-fix release with experimental features.
|
||||
|
||||
Cryptsetup 2.x version introduces a new on-disk LUKS2 format.
|
||||
|
||||
The legacy LUKS (referenced as LUKS1) will be fully supported
|
||||
forever as well as a traditional and fully backward compatible format.
|
||||
|
||||
Please note that authenticated disk encryption, non-cryptographic
|
||||
data integrity protection (dm-integrity), use of Argon2 Password-Based
|
||||
Key Derivation Function and the LUKS2 on-disk format itself are new
|
||||
features and can contain some bugs.
|
||||
|
||||
To provide all security features of authenticated encryption, we need
|
||||
a better nonce-reuse resistant algorithm in the kernel (see note below).
|
||||
For now, please use authenticated encryption as an experimental feature.
|
||||
|
||||
Please do not use LUKS2 without properly configured backup or in
|
||||
production systems that need to be compatible with older systems.
|
||||
|
||||
Changes since version 2.0.1
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
* Fix a regression in early detection of inactive keyslot for luksKillSlot.
|
||||
It tried to ask for passphrase even for already erased keyslot.
|
||||
|
||||
* Fix a regression in loopaesOpen processing for keyfile on standard input.
|
||||
Use of "-" argument was not working properly.
|
||||
|
||||
* Add LUKS2 specific options for cryptsetup-reencrypt.
|
||||
Tokens and persistent flags are now transferred during reencryption;
|
||||
change of PBKDF keyslot parameters is now supported and allows
|
||||
to set precalculated values (no benchmarks).
|
||||
|
||||
* Do not allow LUKS2 --persistent and --test-passphrase cryptsetup flags
|
||||
combination. Persistent flags are now stored only if the device was
|
||||
successfully activated with the specified flags.
|
||||
|
||||
* Fix integritysetup format after recent Linux kernel changes that
|
||||
requires to setup key for HMAC in all cases.
|
||||
Previously integritysetup allowed HMAC with zero key that behaves
|
||||
like a plain hash.
|
||||
|
||||
* Fix VeraCrypt PIM handling that modified internal iteration counts
|
||||
even for subsequent activations. The PIM count is no longer printed
|
||||
in debug log as it is sensitive information.
|
||||
Also, the code now skips legacy TrueCrypt algorithms if a PIM
|
||||
is specified (they cannot be used with PIM anyway).
|
||||
|
||||
* PBKDF values cannot be set (even with force parameters) below
|
||||
hardcoded minimums. For PBKDF2 is it 1000 iterations, for Argon2
|
||||
it is 4 iterations and 32 KiB of memory cost.
|
||||
|
||||
* Introduce new crypt_token_is_assigned() API function for reporting
|
||||
the binding between token and keyslots.
|
||||
|
||||
* Allow crypt_token_json_set() API function to create internal token types.
|
||||
Do not allow unknown fields in internal token objects.
|
||||
|
||||
* Print message in cryptsetup that about was aborted if a user did not
|
||||
answer YES in a query.
|
||||
|
||||
Unfinished things & TODO for next releases
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* There will be better documentation and examples.
|
||||
|
||||
* There will be some more formal definition of the threat model for integrity
|
||||
protection. (And a link to some papers discussing integrity protection,
|
||||
once it is, hopefully, accepted and published.)
|
||||
|
||||
* Authenticated encryption will use new algorithms from CAESAR competition
|
||||
https://competitions.cr.yp.to/caesar-submissions.html.
|
||||
We plan to use AEGIS and MORUS, as CAESAR finalists.
|
||||
|
||||
NOTE: Currently available authenticated modes (GCM, Chacha20-poly1305)
|
||||
in the kernel have too small 96-bit nonces that are problematic with
|
||||
randomly generated IVs (the collision probability is not negligible).
|
||||
|
||||
* Authenticated encryption do not set encryption for a dm-integrity journal.
|
||||
|
||||
While it does not influence data confidentiality or integrity protection,
|
||||
an attacker can get some more information from data journal or cause that
|
||||
system will corrupt sectors after journal replay. (That corruption will be
|
||||
detected though.)
|
||||
|
||||
* There are examples of user-defined tokens inside misc/luks2_keyslot_example
|
||||
directory (like a simple external program that uses libssh to unlock LUKS2
|
||||
using remote keyfile).
|
||||
|
||||
* The python binding (pycryptsetup) contains only basic functionality for LUKS1
|
||||
(it is not updated for new features) and will be deprecated in version 2.1
|
||||
in favor of python bindings to the libblockdev library.
|
||||
121
docs/v2.0.3-ReleaseNotes
Normal file
121
docs/v2.0.3-ReleaseNotes
Normal file
@@ -0,0 +1,121 @@
|
||||
Cryptsetup 2.0.3 Release Notes
|
||||
==============================
|
||||
Stable bug-fix release with new features.
|
||||
|
||||
Cryptsetup 2.x version introduces a new on-disk LUKS2 format.
|
||||
|
||||
The legacy LUKS (referenced as LUKS1) will be fully supported
|
||||
forever as well as a traditional and fully backward compatible format.
|
||||
|
||||
Please note that authenticated disk encryption, non-cryptographic
|
||||
data integrity protection (dm-integrity), use of Argon2 Password-Based
|
||||
Key Derivation Function and the LUKS2 on-disk format itself are new
|
||||
features and can contain some bugs.
|
||||
|
||||
To provide all security features of authenticated encryption, we need
|
||||
a better nonce-reuse resistant algorithm in the kernel (see note below).
|
||||
For now, please use authenticated encryption as an experimental feature.
|
||||
|
||||
Please do not use LUKS2 without properly configured backup or in
|
||||
production systems that need to be compatible with older systems.
|
||||
|
||||
Changes since version 2.0.2
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
* Expose interface to unbound LUKS2 keyslots.
|
||||
Unbound LUKS2 keyslot allows storing a key material that is independent
|
||||
of master volume key (it is not bound to encrypted data segment).
|
||||
|
||||
* New API extensions for unbound keyslots (LUKS2 only)
|
||||
crypt_keyslot_get_key_size() and crypt_volume_key_get()
|
||||
These functions allow to get key and key size for unbound keyslots.
|
||||
|
||||
* New enum value CRYPT_SLOT_UNBOUND for keyslot status (LUKS2 only).
|
||||
|
||||
* Add --unbound keyslot option to the cryptsetup luksAddKey command.
|
||||
|
||||
* Add crypt_get_active_integrity_failures() call to get integrity
|
||||
failure count for dm-integrity devices.
|
||||
|
||||
* Add crypt_get_pbkdf_default() function to get per-type PBKDF default
|
||||
setting.
|
||||
|
||||
* Add new flag to crypt_keyslot_add_by_key() to force update device
|
||||
volume key. This call is mainly intended for a wrapped key change.
|
||||
|
||||
* Allow volume key store in a file with cryptsetup.
|
||||
The --dump-master-key together with --master-key-file allows cryptsetup
|
||||
to store the binary volume key to a file instead of standard output.
|
||||
|
||||
* Add support detached header for cryptsetup-reencrypt command.
|
||||
|
||||
* Fix VeraCrypt PIM handling - use proper iterations count formula
|
||||
for PBKDF2-SHA512 and PBKDF2-Whirlpool used in system volumes.
|
||||
|
||||
* Fix cryptsetup tcryptDump for VeraCrypt PIM (support --veracrypt-pim).
|
||||
|
||||
* Add --with-default-luks-format configure time option.
|
||||
(Option to override default LUKS format version.)
|
||||
|
||||
* Fix LUKS version conversion for detached (and trimmed) LUKS headers.
|
||||
|
||||
* Add luksConvertKey cryptsetup command that converts specific keyslot
|
||||
from one PBKDF to another.
|
||||
|
||||
* Do not allow conversion to LUKS2 if LUKSMETA (external tool metadata)
|
||||
header is detected.
|
||||
|
||||
* More cleanup and hardening of LUKS2 keyslot specific validation options.
|
||||
Add more checks for cipher validity before writing metadata on-disk.
|
||||
|
||||
* Do not allow LUKS1 version downconversion if the header contains tokens.
|
||||
|
||||
* Add "paes" family ciphers (AES wrapped key scheme for mainframes)
|
||||
to allowed ciphers.
|
||||
Specific wrapped ley configuration logic must be done by 3rd party tool,
|
||||
LUKS2 stores only keyslot material and allow activation of the device.
|
||||
|
||||
* Add support for --check-at-most-once option (kernel 4.17) to veritysetup.
|
||||
This flag can be dangerous; if you can control underlying device
|
||||
(you can change its content after it was verified) it will no longer
|
||||
prevent reading tampered data and also it does not prevent silent
|
||||
data corruptions that appear after the block was once read.
|
||||
|
||||
* Fix return code (EPERM instead of EINVAL) and retry count for bad
|
||||
passphrase on non-tty input.
|
||||
|
||||
* Enable support for FEC decoding in veritysetup to check dm-verity devices
|
||||
with additional Reed-Solomon code in userspace (verify command).
|
||||
|
||||
Unfinished things & TODO for next releases
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* There will be better documentation and examples (planned for 2.0.4).
|
||||
|
||||
* There will be some more formal definition of the threat model for integrity
|
||||
protection. (And a link to some papers discussing integrity protection,
|
||||
once it is, hopefully, accepted and published.)
|
||||
|
||||
* Authenticated encryption will use new algorithms from CAESAR competition
|
||||
https://competitions.cr.yp.to/caesar-submissions.html.
|
||||
We plan to use AEGIS and MORUS, as CAESAR finalists.
|
||||
|
||||
NOTE: Currently available authenticated modes (GCM, Chacha20-poly1305)
|
||||
in the kernel have too small 96-bit nonces that are problematic with
|
||||
randomly generated IVs (the collision probability is not negligible).
|
||||
|
||||
* Authenticated encryption do not set encryption for a dm-integrity journal.
|
||||
|
||||
While it does not influence data confidentiality or integrity protection,
|
||||
an attacker can get some more information from data journal or cause that
|
||||
system will corrupt sectors after journal replay. (That corruption will be
|
||||
detected though.)
|
||||
|
||||
* There are examples of user-defined tokens inside misc/luks2_keyslot_example
|
||||
directory (like a simple external program that uses libssh to unlock LUKS2
|
||||
using remote keyfile).
|
||||
|
||||
* The python binding (pycryptsetup) contains only basic functionality for LUKS1
|
||||
(it is not updated for new features) and will be REMOVED in version 2.1
|
||||
in favor of python bindings to the libblockdev library.
|
||||
See https://github.com/storaged-project/libblockdev/releases/tag/2.17-1 that
|
||||
already supports LUKS2 and VeraCrypt devices handling through libcryptsetup.
|
||||
119
docs/v2.0.4-ReleaseNotes
Normal file
119
docs/v2.0.4-ReleaseNotes
Normal file
@@ -0,0 +1,119 @@
|
||||
Cryptsetup 2.0.4 Release Notes
|
||||
==============================
|
||||
Stable bug-fix release with new features.
|
||||
|
||||
Cryptsetup 2.x version introduces a new on-disk LUKS2 format.
|
||||
|
||||
The legacy LUKS (referenced as LUKS1) will be fully supported
|
||||
forever as well as a traditional and fully backward compatible format.
|
||||
|
||||
Please note that authenticated disk encryption, non-cryptographic
|
||||
data integrity protection (dm-integrity), use of Argon2 Password-Based
|
||||
Key Derivation Function and the LUKS2 on-disk format itself are new
|
||||
features and can contain some bugs.
|
||||
|
||||
To provide all security features of authenticated encryption, we need
|
||||
a better nonce-reuse resistant algorithm in the kernel (see note below).
|
||||
For now, please use authenticated encryption as an experimental feature.
|
||||
|
||||
Please do not use LUKS2 without properly configured backup or in
|
||||
production systems that need to be compatible with older systems.
|
||||
|
||||
Changes since version 2.0.3
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
* Use the libblkid (blockid) library to detect foreign signatures
|
||||
on a device before LUKS format and LUKS2 auto-recovery.
|
||||
|
||||
This change fixes an unexpected recovery using the secondary
|
||||
LUKS2 header after a device was already overwritten with
|
||||
another format (filesystem or LVM physical volume).
|
||||
|
||||
LUKS2 will not recreate a primary header if it detects a valid
|
||||
foreign signature. In this situation, a user must always
|
||||
use cryptsetup repair command for the recovery.
|
||||
|
||||
Note that libcryptsetup and utilities are now linked to libblkid
|
||||
as a new dependence.
|
||||
|
||||
To compile code without blockid support (strongly discouraged),
|
||||
use --disable-blkid configure switch.
|
||||
|
||||
* Add prompt for format and repair actions in cryptsetup and
|
||||
integritysetup if foreign signatures are detected on the device
|
||||
through the blockid library.
|
||||
|
||||
After the confirmation, all known signatures are then wiped as
|
||||
part of the format or repair procedure.
|
||||
|
||||
* Print consistent verbose message about keyslot and token numbers.
|
||||
For keyslot actions: Key slot <number> unlocked/created/removed.
|
||||
For token actions: Token <number> created/removed.
|
||||
|
||||
* Print error, if a non-existent token is tried to be removed.
|
||||
|
||||
* Add support for LUKS2 token definition export and import.
|
||||
|
||||
The token command now can export/import customized token JSON file
|
||||
directly from command line. See the man page for more details.
|
||||
|
||||
* Add support for new dm-integrity superblock version 2.
|
||||
|
||||
* Add an error message when nothing was read from a key file.
|
||||
|
||||
* Update cryptsetup man pages, including --type option usage.
|
||||
|
||||
* Add a snapshot of LUKS2 format specification to documentation
|
||||
and accordingly fix supported secondary header offsets.
|
||||
|
||||
* Add bundled optimized Argon2 SSE (X86_64 platform) code.
|
||||
|
||||
If the bundled Argon2 code is used and the new configure switch
|
||||
--enable-internal-sse-argon2 option is present, and compiler flags
|
||||
support required optimization, the code will try to use optimized
|
||||
and faster variant.
|
||||
|
||||
Always use the shared library (--enable-libargon2) if possible.
|
||||
|
||||
This option was added because an enterprise distribution
|
||||
rejected to support the shared Argon2 library and native support
|
||||
in generic cryptographic libraries is not ready yet.
|
||||
|
||||
* Fix compilation with crypto backend for LibreSSL >= 2.7.0.
|
||||
LibreSSL introduced OpenSSL 1.1.x API functions, so compatibility
|
||||
wrapper must be commented out.
|
||||
|
||||
* Fix on-disk header size calculation for LUKS2 format if a specific
|
||||
data alignment is requested. Until now, the code used default size
|
||||
that could be wrong for converted devices.
|
||||
|
||||
Unfinished things & TODO for next releases
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* Authenticated encryption will use new algorithms from CAESAR competition
|
||||
https://competitions.cr.yp.to/caesar-submissions.html.
|
||||
We plan to use AEGIS and MORUS (in kernel 4.18), as CAESAR finalists.
|
||||
|
||||
NOTE: Currently available authenticated modes (GCM, Chacha20-poly1305)
|
||||
in the kernel have too small 96-bit nonces that are problematic with
|
||||
randomly generated IVs (the collision probability is not negligible).
|
||||
|
||||
For more info about LUKS2 authenticated encryption, please see our paper
|
||||
https://arxiv.org/abs/1807.00309
|
||||
|
||||
* Authenticated encryption do not set encryption for a dm-integrity journal.
|
||||
|
||||
While it does not influence data confidentiality or integrity protection,
|
||||
an attacker can get some more information from data journal or cause that
|
||||
system will corrupt sectors after journal replay. (That corruption will be
|
||||
detected though.)
|
||||
|
||||
* There are examples of user-defined tokens inside misc/luks2_keyslot_example
|
||||
directory (like a simple external program that uses libssh to unlock LUKS2
|
||||
using remote keyfile).
|
||||
|
||||
* The python binding (pycryptsetup) contains only basic functionality for LUKS1
|
||||
(it is not updated for new features) and will be REMOVED in version 2.1
|
||||
in favor of python bindings to the libblockdev library.
|
||||
See https://github.com/storaged-project/libblockdev/releases that
|
||||
already supports LUKS2 and VeraCrypt devices handling through libcryptsetup.
|
||||
|
||||
102
docs/v2.0.5-ReleaseNotes
Normal file
102
docs/v2.0.5-ReleaseNotes
Normal file
@@ -0,0 +1,102 @@
|
||||
Cryptsetup 2.0.5 Release Notes
|
||||
==============================
|
||||
Stable bug-fix release with new features.
|
||||
|
||||
Cryptsetup 2.x version introduces a new on-disk LUKS2 format.
|
||||
|
||||
The legacy LUKS (referenced as LUKS1) will be fully supported
|
||||
forever as well as a traditional and fully backward compatible format.
|
||||
|
||||
Please note that authenticated disk encryption, non-cryptographic
|
||||
data integrity protection (dm-integrity), use of Argon2 Password-Based
|
||||
Key Derivation Function and the LUKS2 on-disk format itself are new
|
||||
features and can contain some bugs.
|
||||
|
||||
Please do not use LUKS2 without properly configured backup or in
|
||||
production systems that need to be compatible with older systems.
|
||||
|
||||
Changes since version 2.0.4
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
* Wipe full header areas (including unused) during LUKS format.
|
||||
|
||||
Since this version, the whole area up to the data offset is zeroed,
|
||||
and subsequently, all keyslots areas are wiped with random data.
|
||||
This ensures that no remaining old data remains in the LUKS header
|
||||
areas, but it could slow down format operation on some devices.
|
||||
Previously only first 4k (or 32k for LUKS2) and the used keyslot
|
||||
was overwritten in the format operation.
|
||||
|
||||
* Several fixes to error messages that were unintentionally replaced
|
||||
in previous versions with a silent exit code.
|
||||
More descriptive error messages were added, including error
|
||||
messages if
|
||||
- a device is unusable (not a block device, no access, etc.),
|
||||
- a LUKS device is not detected,
|
||||
- LUKS header load code detects unsupported version,
|
||||
- a keyslot decryption fails (also happens in the cipher check),
|
||||
- converting an inactive keyslot.
|
||||
|
||||
* Device activation fails if data area overlaps with LUKS header.
|
||||
|
||||
* Code now uses explicit_bzero to wipe memory if available
|
||||
(instead of own implementation).
|
||||
|
||||
* Additional VeraCrypt modes are now supported, including Camellia
|
||||
and Kuznyechik symmetric ciphers (and cipher chains) and Streebog
|
||||
hash function. These were introduced in a recent VeraCrypt upstream.
|
||||
|
||||
Note that Kuznyechik requires out-of-tree kernel module and
|
||||
Streebog hash function is available only with the gcrypt cryptographic
|
||||
backend for now.
|
||||
|
||||
* Fixes static build for integritysetup if the pwquality library is used.
|
||||
|
||||
* Allows passphrase change for unbound keyslots.
|
||||
|
||||
* Fixes removed keyslot number in verbose message for luksKillSlot,
|
||||
luksRemoveKey and erase command.
|
||||
|
||||
* Adds blkid scan when attempting to open a plain device and warn the user
|
||||
about existing device signatures in a ciphertext device.
|
||||
|
||||
* Remove LUKS header signature if luksFormat fails to add the first keyslot.
|
||||
|
||||
* Remove O_SYNC from device open and use fsync() to speed up
|
||||
wipe operation considerably.
|
||||
|
||||
* Create --master-key-file in luksDump and fail if the file already exists.
|
||||
|
||||
* Fixes a bug when LUKS2 authenticated encryption with a detached header
|
||||
wiped the header device instead of dm-integrity data device area (causing
|
||||
unnecessary LUKS2 header auto recovery).
|
||||
|
||||
Unfinished things & TODO for next releases
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* Authenticated encryption should use new algorithms from CAESAR competition
|
||||
https://competitions.cr.yp.to/caesar-submissions.html.
|
||||
AEGIS and MORUS are already available in kernel 4.18.
|
||||
|
||||
For more info about LUKS2 authenticated encryption, please see our paper
|
||||
https://arxiv.org/abs/1807.00309
|
||||
|
||||
Please note that authenticated encryption is still an experimental feature
|
||||
and can have performance problems for hish-speed devices and device
|
||||
with larger IO blocks (like RAID).
|
||||
|
||||
* Authenticated encryption do not set encryption for a dm-integrity journal.
|
||||
|
||||
While it does not influence data confidentiality or integrity protection,
|
||||
an attacker can get some more information from data journal or cause that
|
||||
system will corrupt sectors after journal replay. (That corruption will be
|
||||
detected though.)
|
||||
|
||||
* There are examples of user-defined tokens inside misc/luks2_keyslot_example
|
||||
directory (like a simple external program that uses libssh to unlock LUKS2
|
||||
using remote keyfile).
|
||||
|
||||
* The python binding (pycryptsetup) contains only basic functionality for LUKS1
|
||||
(it is not updated for new features) and will be REMOVED in version 2.1
|
||||
in favor of python bindings to the libblockdev library.
|
||||
See https://github.com/storaged-project/libblockdev/releases that
|
||||
already supports LUKS2 and VeraCrypt devices handling through libcryptsetup.
|
||||
97
docs/v2.0.6-ReleaseNotes
Normal file
97
docs/v2.0.6-ReleaseNotes
Normal file
@@ -0,0 +1,97 @@
|
||||
Cryptsetup 2.0.6 Release Notes
|
||||
==============================
|
||||
Stable bug-fix release.
|
||||
All users of cryptsetup 2.0.x should upgrade to this version.
|
||||
|
||||
Cryptsetup 2.x version introduces a new on-disk LUKS2 format.
|
||||
|
||||
The legacy LUKS (referenced as LUKS1) will be fully supported
|
||||
forever as well as a traditional and fully backward compatible format.
|
||||
|
||||
Please note that authenticated disk encryption, non-cryptographic
|
||||
data integrity protection (dm-integrity), use of Argon2 Password-Based
|
||||
Key Derivation Function and the LUKS2 on-disk format itself are new
|
||||
features and can contain some bugs.
|
||||
|
||||
Please do not use LUKS2 without properly configured backup or in
|
||||
production systems that need to be compatible with older systems.
|
||||
|
||||
Changes since version 2.0.5
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
* Fix support of larger metadata areas in LUKS2 header.
|
||||
|
||||
This release properly supports all specified metadata areas, as documented
|
||||
in LUKS2 format description (see docs/on-disk-format-luks2.pdf in archive).
|
||||
|
||||
Currently, only default metadata area size is used (in format or convert).
|
||||
Later cryptsetup versions will allow increasing this metadata area size.
|
||||
|
||||
* If AEAD (authenticated encryption) is used, cryptsetup now tries to check
|
||||
if the requested AEAD algorithm with specified key size is available
|
||||
in kernel crypto API.
|
||||
This change avoids formatting a device that cannot be later activated.
|
||||
|
||||
For this function, the kernel must be compiled with the
|
||||
CONFIG_CRYPTO_USER_API_AEAD option enabled.
|
||||
Note that kernel user crypto API options (CONFIG_CRYPTO_USER_API and
|
||||
CONFIG_CRYPTO_USER_API_SKCIPHER) are already mandatory for LUKS2.
|
||||
|
||||
* Fix setting of integrity no-journal flag.
|
||||
Now you can store this flag to metadata using --persistent option.
|
||||
|
||||
* Fix cryptsetup-reencrypt to not keep temporary reencryption headers
|
||||
if interrupted during initial password prompt.
|
||||
|
||||
* Adds early check to plain and LUKS2 formats to disallow device format
|
||||
if device size is not aligned to requested sector size.
|
||||
Previously it was possible, and the device was rejected to activate by
|
||||
kernel later.
|
||||
|
||||
* Fix checking of hash algorithms availability for PBKDF early.
|
||||
Previously LUKS2 format allowed non-existent hash algorithm with
|
||||
invalid keyslot preventing the device from activation.
|
||||
|
||||
* Allow Adiantum cipher construction (a non-authenticated length-preserving
|
||||
fast encryption scheme), so it can be used both for data encryption and
|
||||
keyslot encryption in LUKS1/2 devices.
|
||||
|
||||
For benchmark, use:
|
||||
# cryptsetup benchmark -c xchacha12,aes-adiantum
|
||||
# cryptsetup benchmark -c xchacha20,aes-adiantum
|
||||
|
||||
For LUKS format:
|
||||
# cryptsetup luksFormat -c xchacha20,aes-adiantum-plain64 -s 256 <device>
|
||||
|
||||
The support for Adiantum will be merged in Linux kernel 4.21.
|
||||
For more info see the paper https://eprint.iacr.org/2018/720.
|
||||
|
||||
Unfinished things & TODO for next releases
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* Authenticated encryption should use new algorithms from CAESAR competition
|
||||
https://competitions.cr.yp.to/caesar-submissions.html.
|
||||
AEGIS and MORUS are already available in kernel 4.18.
|
||||
|
||||
For more info about LUKS2 authenticated encryption, please see our paper
|
||||
https://arxiv.org/abs/1807.00309
|
||||
|
||||
Please note that authenticated encryption is still an experimental feature
|
||||
and can have performance problems for high-speed devices and device
|
||||
with larger IO blocks (like RAID).
|
||||
|
||||
* Authenticated encryption do not set encryption for a dm-integrity journal.
|
||||
|
||||
While it does not influence data confidentiality or integrity protection,
|
||||
an attacker can get some more information from data journal or cause that
|
||||
system will corrupt sectors after journal replay. (That corruption will be
|
||||
detected though.)
|
||||
|
||||
* There are examples of user-defined tokens inside misc/luks2_keyslot_example
|
||||
directory (like a simple external program that uses libssh to unlock LUKS2
|
||||
using remote keyfile).
|
||||
|
||||
* The python binding (pycryptsetup) contains only basic functionality for LUKS1
|
||||
(it is not updated for new features) and will be REMOVED in version 2.1
|
||||
in favor of python bindings to the libblockdev library.
|
||||
See https://github.com/storaged-project/libblockdev/releases that
|
||||
already supports LUKS2 and VeraCrypt devices handling through libcryptsetup.
|
||||
210
docs/v2.1.0-ReleaseNotes
Normal file
210
docs/v2.1.0-ReleaseNotes
Normal file
@@ -0,0 +1,210 @@
|
||||
Cryptsetup 2.1.0 Release Notes
|
||||
==============================
|
||||
Stable release with new features and bug fixes.
|
||||
|
||||
Cryptsetup 2.1 version uses a new on-disk LUKS2 format as the default
|
||||
LUKS format and increases default LUKS2 header size.
|
||||
|
||||
The legacy LUKS (referenced as LUKS1) will be fully supported forever
|
||||
as well as a traditional and fully backward compatible format.
|
||||
|
||||
When upgrading a stable distribution, please use configure option
|
||||
--with-default-luks-format=LUKS1 to maintain backward compatibility.
|
||||
|
||||
This release also switches to OpenSSL as a default cryptographic
|
||||
backend for LUKS header processing. Use --with-crypto_backend=gcrypt
|
||||
configure option if you need to preserve legacy libgcrypt backend.
|
||||
|
||||
Please do not use LUKS2 without properly configured backup or
|
||||
in production systems that need to be compatible with older systems.
|
||||
|
||||
Changes since version 2.0.6
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
* The default for cryptsetup LUKS format action is now LUKS2.
|
||||
You can use LUKS1 with cryptsetup option --type luks1.
|
||||
|
||||
* The default size of the LUKS2 header is increased to 16 MB.
|
||||
It includes metadata and the area used for binary keyslots;
|
||||
it means that LUKS header backup is now 16MB in size.
|
||||
|
||||
Note, that used keyslot area is much smaller, but this increase
|
||||
of reserved space allows implementation of later extensions
|
||||
(like online reencryption).
|
||||
It is fully compatible with older cryptsetup 2.0.x versions.
|
||||
If you require to create LUKS2 header with the same size as
|
||||
in the 2.0.x version, use --offset 8192 option for luksFormat
|
||||
(units are in 512-bytes sectors; see notes below).
|
||||
|
||||
* Cryptsetup now doubles LUKS default key size if XTS mode is used
|
||||
(XTS mode uses two internal keys). This does not apply if key size
|
||||
is explicitly specified on the command line and it does not apply
|
||||
for the plain mode.
|
||||
This fixes a confusion with AES and 256bit key in XTS mode where
|
||||
code used AES128 and not AES256 as often expected.
|
||||
|
||||
Also, the default keyslot encryption algorithm (if cannot be derived
|
||||
from data encryption algorithm) is now available as configure
|
||||
options --with-luks2-keyslot-cipher and --with-luks2-keyslot-keybits.
|
||||
The default is aes-xts-plain64 with 2 * 256-bits key.
|
||||
|
||||
* Default cryptographic backend used for LUKS header processing is now
|
||||
OpenSSL. For years, OpenSSL provided better performance for PBKDF.
|
||||
|
||||
NOTE: Cryptsetup/libcryptsetup supports several cryptographic
|
||||
library backends. The fully supported are libgcrypt, OpenSSL and
|
||||
kernel crypto API. FIPS mode extensions are maintained only for
|
||||
libgcrypt and OpenSSL. Nettle and NSS are usable only for some
|
||||
subset of algorithms and cannot provide full backward compatibility.
|
||||
You can always switch to other backends by using a configure switch,
|
||||
for libgcrypt (compatibility for older distributions) use:
|
||||
--with-crypto_backend=gcrypt
|
||||
|
||||
* The Python bindings are no longer supported and the code was removed
|
||||
from cryptsetup distribution. Please use the libblockdev project
|
||||
that already covers most of the libcryptsetup functionality
|
||||
including LUKS2.
|
||||
|
||||
* Cryptsetup now allows using --offset option also for luksFormat.
|
||||
It means that the specified offset value is used for data offset.
|
||||
LUKS2 header areas are automatically adjusted according to this value.
|
||||
(Note units are in 512-byte sectors due to the previous definition
|
||||
of this option in plain mode.)
|
||||
This option can replace --align-payload with absolute alignment value.
|
||||
|
||||
* Cryptsetup now supports new refresh action (that is the alias for
|
||||
"open --refresh").
|
||||
It allows changes of parameters for an active device (like root
|
||||
device mapping), for example, it can enable or disable TRIM support
|
||||
on-the-fly.
|
||||
It is supported for LUKS1, LUKS2, plain and loop-AES devices.
|
||||
|
||||
* Integritysetup now supports mode with detached data device through
|
||||
new --data-device option.
|
||||
Since kernel 4.18 there is a possibility to specify external data
|
||||
device for dm-integrity that stores all integrity tags.
|
||||
|
||||
* Integritysetup now supports automatic integrity recalculation
|
||||
through new --integrity-recalculate option.
|
||||
Linux kernel since version 4.18 supports automatic background
|
||||
recalculation of integrity tags for dm-integrity.
|
||||
|
||||
Other changes and fixes
|
||||
~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
* Fix for crypt_wipe call to allocate space if the header is backed
|
||||
by a file. This means that if you use detached header file, it will
|
||||
now have always the full size after luksFormat, even if only
|
||||
a few keyslots are used.
|
||||
|
||||
* Fixes to offline cryptsetup-reencrypt to preserve LUKS2 keyslots
|
||||
area sizes after reencryption and fixes for some other issues when
|
||||
creating temporary reencryption headers.
|
||||
|
||||
* Added some FIPS mode workarounds. We cannot (yet) use Argon2 in
|
||||
FIPS mode, libcryptsetup now fallbacks to use PBKDF2 in FIPS mode.
|
||||
|
||||
* Rejects conversion to LUKS1 if PBKDF2 hash algorithms
|
||||
in keyslots differ.
|
||||
|
||||
* The hash setting on command line now applies also to LUKS2 PBKDF2
|
||||
digest. In previous versions, the LUKS2 key digest used PBKDF2-SHA256
|
||||
(except for converted headers).
|
||||
|
||||
* Allow LUKS2 keyslots area to increase if data offset allows it.
|
||||
Cryptsetup can fine-tune LUKS2 metadata area sizes through
|
||||
--luks2-metadata-size=BYTES and --luks2-keyslots-size=BYTES.
|
||||
Please DO NOT use these low-level options until you need it for
|
||||
some very specific additional feature.
|
||||
Also, the code now prints these LUKS2 header area sizes in dump
|
||||
command.
|
||||
|
||||
* For LUKS2, keyslot can use different encryption that data with
|
||||
new options --keyslot-key-size=BITS and --keyslot-cipher=STRING
|
||||
in all commands that create new LUKS keyslot.
|
||||
Please DO NOT use these low-level options until you need it for
|
||||
some very specific additional feature.
|
||||
|
||||
* Code now avoids data flush when reading device status through
|
||||
device-mapper.
|
||||
|
||||
* The Nettle crypto backend and the userspace kernel crypto API
|
||||
backend were enhanced to allow more available hash functions
|
||||
(like SHA3 variants).
|
||||
|
||||
* Upstream code now does not require libgcrypt-devel
|
||||
for autoconfigure, because OpenSSL is the default.
|
||||
The libgcrypt does not use standard pkgconfig detection and
|
||||
requires specific macro (part of libgcrypt development files)
|
||||
to be always present during autoconfigure.
|
||||
With other crypto backends, like OpenSSL, this makes no sense,
|
||||
so this part of autoconfigure is now optional.
|
||||
|
||||
* Cryptsetup now understands new --debug-json option that allows
|
||||
an additional dump of some JSON information. These are no longer
|
||||
present in standard debug output because it could contain some
|
||||
specific LUKS header parameters.
|
||||
|
||||
* The luksDump contains the hash algorithm used in Anti-Forensic
|
||||
function.
|
||||
|
||||
* All debug messages are now sent through configured log callback
|
||||
functions, so an application can easily use own debug messages
|
||||
handling. In previous versions debug messages were printed directly
|
||||
to standard output.)
|
||||
|
||||
Libcryptsetup API additions
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
These new calls are now exported, for details see libcryptsetup.h:
|
||||
|
||||
* crypt_init_data_device
|
||||
* crypt_get_metadata_device_name
|
||||
functions to init devices with separate metadata and data device
|
||||
before a format function is called.
|
||||
|
||||
* crypt_set_data_offset
|
||||
sets the data offset for LUKS to the specified value
|
||||
in 512-byte sectors.
|
||||
It should replace alignment calculation in LUKS param structures.
|
||||
|
||||
* crypt_get_metadata_size
|
||||
* crypt_set_metadata_size
|
||||
allows to set/get area sizes in LUKS header
|
||||
(according to specification).
|
||||
|
||||
* crypt_get_default_type
|
||||
get default compiled-in LUKS type (version).
|
||||
|
||||
* crypt_get_pbkdf_type_params
|
||||
allows to get compiled-in PBKDF parameters.
|
||||
|
||||
* crypt_keyslot_set_encryption
|
||||
* crypt_keyslot_get_encryption
|
||||
allows to set/get per-keyslot encryption algorithm for LUKS2.
|
||||
|
||||
* crypt_keyslot_get_pbkdf
|
||||
allows to get PBKDF parameters per-keyslot.
|
||||
|
||||
and these new defines:
|
||||
* CRYPT_LOG_DEBUG_JSON (message type for JSON debug)
|
||||
* CRYPT_DEBUG_JSON (log level for JSON debug)
|
||||
* CRYPT_ACTIVATE_RECALCULATE (dm-integrity recalculate flag)
|
||||
* CRYPT_ACTIVATE_REFRESH (new open with refresh flag)
|
||||
|
||||
All existing API calls should remain backward compatible.
|
||||
|
||||
Unfinished things & TODO for next releases
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* Optional authenticated encryption is still an experimental feature
|
||||
and can have performance problems for high-speed devices and device
|
||||
with larger IO blocks (like RAID).
|
||||
|
||||
* Authenticated encryption does not use encryption for a dm-integrity
|
||||
journal. While it does not influence data confidentiality or
|
||||
integrity protection, an attacker can get some more information
|
||||
from data journal or cause that system will corrupt sectors after
|
||||
journal replay. (That corruption will be detected though.)
|
||||
|
||||
* The LUKS2 metadata area increase is mainly needed for the new online
|
||||
reencryption as the major feature for the next release.
|
||||
279
docs/v2.2.0-ReleaseNotes
Normal file
279
docs/v2.2.0-ReleaseNotes
Normal file
@@ -0,0 +1,279 @@
|
||||
Cryptsetup 2.2.0 Release Notes
|
||||
==============================
|
||||
Stable release with new experimental features and bug fixes.
|
||||
|
||||
Cryptsetup 2.2 version introduces a new LUKS2 online reencryption
|
||||
extension that allows reencryption of mounted LUKS2 devices
|
||||
(device in use) in the background.
|
||||
|
||||
Online reencryption is a complex feature. Please be sure you
|
||||
have a full data backup before using this feature.
|
||||
|
||||
Changes since version 2.1.0
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
LUKS2 online reencryption
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The reencryption is intended to provide a reliable way to change
|
||||
volume key or an algorithm change while the encrypted device is still
|
||||
in use.
|
||||
|
||||
It is based on userspace-only approach (no kernel changes needed)
|
||||
that uses the device-mapper subsystem to remap active devices on-the-fly
|
||||
dynamically. The device is split into several segments (encrypted by old
|
||||
key, new key and so-called hotzone, where reencryption is actively running).
|
||||
|
||||
The flexible LUKS2 metadata format is used to store intermediate states
|
||||
(segment mappings) and both version of keyslots (old and new keys).
|
||||
Also, it provides a binary area (in the unused keyslot area space)
|
||||
to provide recovery metadata in the case of unexpected failure during
|
||||
reencryption. LUKS2 header is during the reencryption marked with
|
||||
"online-reencryption" keyword. After the reencryption is finished,
|
||||
this keyword is removed, and the device is backward compatible with all
|
||||
older cryptsetup tools (that support LUKS2).
|
||||
|
||||
The recovery supports three resilience modes:
|
||||
|
||||
- checksum: default mode, where individual checksums of ciphertext hotzone
|
||||
sectors are stored, so the recovery process can detect which sectors were
|
||||
already reencrypted. It requires that the device sector write is atomic.
|
||||
|
||||
- journal: the hotzone is journaled in the binary area
|
||||
(so the data are written twice)
|
||||
|
||||
- none: performance mode; there is no protection
|
||||
(similar to old offline reencryption)
|
||||
|
||||
These resilience modes are not available if reencryption uses data shift.
|
||||
|
||||
Note: until we have full documentation (both of the process and metadata),
|
||||
please refer to Ondrej's slides (some slight details are no longer relevant)
|
||||
https://okozina.fedorapeople.org/online-disk-reencryption-with-luks2-compact.pdf
|
||||
|
||||
The offline reencryption tool (cryptsetup-reencrypt) is still supported
|
||||
for both LUKS1 and LUKS2 format.
|
||||
|
||||
Cryptsetup examples for reencryption
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The reencryption feature is integrated directly into cryptsetup utility
|
||||
as the new "reencrypt" action (command).
|
||||
|
||||
There are three basic modes - to perform reencryption (change of already
|
||||
existing LUKS2 device), to add encryption to plaintext device and to remove
|
||||
encryption from a device (decryption).
|
||||
|
||||
In all cases, if existing LUKS2 metadata contains information about
|
||||
the ongoing reencryption process, following reencrypt command continues
|
||||
with the ongoing reencryption process until it is finished.
|
||||
|
||||
You can activate a device with ongoing reencryption as the standard LUKS2
|
||||
device, but the reencryption process will not continue until the cryptsetup
|
||||
reencrypt command is issued.
|
||||
|
||||
|
||||
1) Reencryption
|
||||
~~~~~~~~~~~~~~~
|
||||
This mode is intended to change any attribute of the data encryption
|
||||
(change of the volume key, algorithm or sector size).
|
||||
Note that authenticated encryption is not yet supported.
|
||||
|
||||
You can start the reencryption process by specifying a LUKS2 device or with
|
||||
a detached LUKS2 header.
|
||||
The code should automatically recognize if the device is in use (and if it
|
||||
should use online mode of reencryption).
|
||||
|
||||
If you do not specify parameters, only volume key is changed
|
||||
(a new random key is generated).
|
||||
|
||||
# cryptsetup reencrypt <device> [--header <hdr>]
|
||||
|
||||
You can also start reencryption using active mapped device name:
|
||||
# cryptsetup reencrypt --active-name <name>
|
||||
|
||||
You can also specify the resilience mode (none, checksum, journal) with
|
||||
--resilience=<mode> option, for checksum mode also the hash algorithm with
|
||||
--resilience-hash=<alg> (only hash algorithms supported by cryptographic
|
||||
backend are available).
|
||||
|
||||
The maximal size of reencryption hotzone can be limited by
|
||||
--hotzone-size=<size> option and applies to all reencryption modes.
|
||||
Note that for checksum and journal mode hotzone size is also limited
|
||||
by available space in binary keyslot area.
|
||||
|
||||
2) Encryption
|
||||
~~~~~~~~~~~~~
|
||||
This mode provides a way to encrypt a plaintext device to LUKS2 format.
|
||||
This option requires reduction of device size (for LUKS2 header) or new
|
||||
detached header.
|
||||
|
||||
# cryptsetup reencrypt <device> --encrypt --reduce-device-size <size>
|
||||
|
||||
Or with detached header:
|
||||
# cryptsetup reencrypt <device> --encrypt --header <hdr>
|
||||
|
||||
3) Decryption
|
||||
~~~~~~~~~~~~~
|
||||
This mode provides the removal of existing LUKS2 encryption and replacing
|
||||
a device with plaintext content only.
|
||||
For now, we support only decryption with a detached header.
|
||||
|
||||
# cryptsetup reencrypt <device> --decrypt --header <hdr>
|
||||
|
||||
For all three modes, you can split the process to metadata initialization
|
||||
(prepare keyslots and segments but do not run reencryption yet) and the data
|
||||
reencryption step by using --init-only option.
|
||||
|
||||
Prepares metadata:
|
||||
# cryptsetup reencrypt --init-only <parameters>
|
||||
|
||||
Starts the data processing:
|
||||
# cryptsetup reencrypt <device>
|
||||
|
||||
Please note, that due to the Linux kernel limitation, the encryption or
|
||||
decryption process cannot be run entirely online - there must be at least
|
||||
short offline window where operation adds/removes device-mapper crypt (LUKS2) layer.
|
||||
This step should also include modification of /etc/crypttab and fstab UUIDs,
|
||||
but it is out of the scope of cryptsetup tools.
|
||||
|
||||
Limitations
|
||||
~~~~~~~~~~~
|
||||
Most of these limitations will be (hopefully) fixed in next versions.
|
||||
|
||||
* Only one active keyslot is supported (all old keyslots will be removed
|
||||
after reencryption).
|
||||
|
||||
* Only block devices are now supported as parameters. As a workaround
|
||||
for images in a file, please explicitly map a loop device over the image
|
||||
and use the loop device as the parameter.
|
||||
|
||||
* Devices with authenticated encryption are not supported. (Later it will
|
||||
be limited by the fixed per-sector metadata, per-sector metadata size
|
||||
cannot be changed without a new device format operation.)
|
||||
|
||||
* The reencryption uses userspace crypto library, with fallback to
|
||||
the kernel (if available). There can be some specific configurations
|
||||
where the fallback does not provide optimal performance.
|
||||
|
||||
* There are no translations of error messages until the final release
|
||||
(some messages can be rephrased as well).
|
||||
|
||||
* The repair command is not finished; the recovery of interrupted
|
||||
reencryption is made automatically on the first device activation.
|
||||
|
||||
* Reencryption triggers too many udev scans on metadata updates (on closing
|
||||
write enabled file descriptors). This has a negative performance impact on the whole
|
||||
reencryption and generates excessive I/O load on the system.
|
||||
|
||||
New libcryptsetup reencryption API
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
The libcryptsetup contains new API calls that are used to setup and
|
||||
run the reencryption.
|
||||
|
||||
Note that there can be some changes in API implementation of these functions
|
||||
and/or some new function can be introduced in final cryptsetup 2.2 release.
|
||||
|
||||
New API symbols (see documentation in libcryptsetup.h)
|
||||
* struct crypt_params_reencrypt - reencryption parameters
|
||||
|
||||
* crypt_reencrypt_init_by_passphrase
|
||||
* crypt_reencrypt_init_by_keyring
|
||||
- function to configure LUKS2 metadata for reencryption;
|
||||
if metadata already exists, it configures the context from this metadata
|
||||
|
||||
* crypt_reencrypt
|
||||
- run the reencryption process (processing the data)
|
||||
- the optional callback function can be used to interrupt the reencryption
|
||||
or report the progress.
|
||||
|
||||
* crypt_reencrypt_status
|
||||
- function to query LUKS2 metadata about the reencryption state
|
||||
|
||||
Other changes and fixes
|
||||
~~~~~~~~~~~~~~~~~~~~~~~
|
||||
* Add optional global serialization lock for memory hard PBKDF.
|
||||
(The --serialize-memory-hard-pbkdf option in cryptsetup and
|
||||
CRYPT_ACTIVATE_SERIALIZE_MEMORY_HARD_PBKDF in activation flag.)
|
||||
|
||||
This is an "ugly" optional workaround for a situation when multiple devices
|
||||
are being activated in parallel (like systemd crypttab activation).
|
||||
The system instead of returning ENOMEM (no memory available) starts
|
||||
out-of-memory (OOM) killer to kill processes randomly.
|
||||
|
||||
Until we find a reliable way how to work with memory-hard function
|
||||
in these situations, cryptsetup provide a way how to serialize memory-hard
|
||||
unlocking among parallel cryptsetup instances to workaround this problem.
|
||||
This flag is intended to be used only in very specific situations,
|
||||
never use it directly :-)
|
||||
|
||||
* Abort conversion to LUKS1 with incompatible sector size that is
|
||||
not supported in LUKS1.
|
||||
|
||||
* Report error (-ENOENT) if no LUKS keyslots are available. User can now
|
||||
distinguish between a wrong passphrase and no keyslot available.
|
||||
|
||||
* Fix a possible segfault in detached header handling (double free).
|
||||
|
||||
* Add integritysetup support for bitmap mode introduced in Linux kernel 5.2.
|
||||
Integritysetup now supports --integrity-bitmap-mode option and
|
||||
--bitmap-sector-per-bit and --bitmap-flush-time commandline options.
|
||||
|
||||
In the bitmap operation mode, if a bit in the bitmap is 1, the corresponding
|
||||
region's data and integrity tags are not synchronized - if the machine
|
||||
crashes, the unsynchronized regions will be recalculated.
|
||||
The bitmap mode is faster than the journal mode because we don't have
|
||||
to write the data twice, but it is also less reliable, because if data
|
||||
corruption happens when the machine crashes, it may not be detected.
|
||||
This can be used only for standalone devices, not with dm-crypt.
|
||||
|
||||
* The libcryptsetup now keeps all file descriptors to underlying device
|
||||
open during the whole lifetime of crypt device context to avoid excessive
|
||||
scanning in udev (udev run scan on every descriptor close).
|
||||
|
||||
* The luksDump command now prints more info for reencryption keyslot
|
||||
(when a device is in-reencryption).
|
||||
|
||||
* New --device-size parameter is supported for LUKS2 reencryption.
|
||||
It may be used to encrypt/reencrypt only the initial part of the data
|
||||
device if the user is aware that the rest of the device is empty.
|
||||
|
||||
Note: This change causes API break since the last rc0 release
|
||||
(crypt_params_reencrypt structure contains additional field).
|
||||
|
||||
* New --resume-only parameter is supported for LUKS2 reencryption.
|
||||
This flag resumes reencryption process if it exists (not starting
|
||||
new reencryption).
|
||||
|
||||
* The repair command now tries LUKS2 reencryption recovery if needed.
|
||||
|
||||
* If reencryption device is a file image, an interactive dialog now
|
||||
asks if reencryption should be run safely in offline mode
|
||||
(if autodetection of active devices failed).
|
||||
|
||||
* Fix activation through a token where dm-crypt volume key was not
|
||||
set through keyring (but using old device-mapper table parameter mode).
|
||||
|
||||
* Online reencryption can now retain all keyslots (if all passphrases
|
||||
are provided). Note that keyslot numbers will change in this case.
|
||||
|
||||
* Allow volume key file to be used if no LUKS2 keyslots are present.
|
||||
If all keyslots are removed, LUKS2 has no longer information about
|
||||
the volume key size (there is only key digest present).
|
||||
Please use --key-size option to open the device or add a new keyslot
|
||||
in these cases.
|
||||
|
||||
* Print a warning if online reencrypt is called over LUKS1 (not supported).
|
||||
|
||||
* Fix TCRYPT KDF failure in FIPS mode.
|
||||
Some crypto backends support plain hash in FIPS mode but not for PBKDF2.
|
||||
|
||||
* Remove FIPS mode restriction for crypt_volume_key_get.
|
||||
It is an application responsibility to use this API in the proper context.
|
||||
|
||||
* Reduce keyslots area size in luksFormat when the header device is too small.
|
||||
Unless user explicitly asks for keyslots areas size (either via
|
||||
--luks2-keyslots-size or --offset) reduce keyslots size so that it fits
|
||||
in metadata device.
|
||||
|
||||
* Make resize action accept --device-size parameter (supports units suffix).
|
||||
36
docs/v2.2.1-ReleaseNotes
Normal file
36
docs/v2.2.1-ReleaseNotes
Normal file
@@ -0,0 +1,36 @@
|
||||
Cryptsetup 2.2.1 Release Notes
|
||||
==============================
|
||||
Stable bug-fix release.
|
||||
|
||||
This version contains a fix for a possible data corruption bug
|
||||
on 32-bit platforms.
|
||||
All users of cryptsetup 2.1 and 2.2 should upgrade to this version.
|
||||
|
||||
Changes since version 2.2.0
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
* Fix possible data length and IV offset overflow on 32bit architectures.
|
||||
Other 64-bit architectures are not affected.
|
||||
|
||||
The flawed helper function prototypes (introduced in version 2.1.0) used
|
||||
size_t type, that is 32-bit integer on 32-bit systems.
|
||||
This patch fixes the problem to properly use 64-bit types.
|
||||
|
||||
If the offset parameter addresses devices larger than 2TB, the value
|
||||
overflows and stores incorrect information in the metadata.
|
||||
For example, integrity device is smaller than expected size if used
|
||||
over large disk on 32-bit architecture.
|
||||
|
||||
This issue is not present with the standard LUKS1/LUKS2 devices without
|
||||
integrity extensions.
|
||||
|
||||
* Fix a regression in TrueCrypt/VeraCrypt system partition activation.
|
||||
|
||||
* Reinstate missing backing file hint for loop device.
|
||||
|
||||
If the encrypted device is backed by a file (loopback), cryptsetup now
|
||||
shows the path to the backing file in passphrase query (as in 1.x version).
|
||||
|
||||
* LUKS2 reencryption block size is now aligned to reported optimal IO size.
|
||||
This change eliminates possible non-aligned device warnings in kernel log
|
||||
during reencryption.
|
||||
56
docs/v2.2.2-ReleaseNotes
Normal file
56
docs/v2.2.2-ReleaseNotes
Normal file
@@ -0,0 +1,56 @@
|
||||
Cryptsetup 2.2.2 Release Notes
|
||||
==============================
|
||||
Stable bug-fix release.
|
||||
|
||||
All users of cryptsetup 2.1 and 2.2 should upgrade to this version.
|
||||
|
||||
Changes since version 2.2.1
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
* Print error message if a keyslot open failed for a different reason
|
||||
than wrong passwords (for example there is not enough memory).
|
||||
Only an exit code was present in this case.
|
||||
|
||||
* The progress function switches unit sizes (B/s to GiB/s) according
|
||||
to the actual speed. Also, it properly calculates speed in the case
|
||||
of a resumed reencryption operation.
|
||||
|
||||
* The --version now supports short -V short option and better handles
|
||||
common option priorities.
|
||||
|
||||
* If cryptsetup wipes signatures during format actions through blkid,
|
||||
it also prints signature device offsets.
|
||||
|
||||
* Compilation now properly uses LTLIBINTL gettext setting in Makefiles.
|
||||
|
||||
* Device-mapper backend now supports new DM_GET_TARGET_VERSION ioctl
|
||||
(available since Linux kernel 5.4).
|
||||
This should help to detect some kernel/userspace incompatibilities
|
||||
earlier later after a failed device activation.
|
||||
|
||||
* Fixes LUKS2 reencryption on systems without kernel keyring.
|
||||
|
||||
* Fixes unlocking prompt for partitions mapped through loop devices
|
||||
(to properly show the backing device).
|
||||
|
||||
* For LUKS2 decryption, a device is now marked for deferred removal
|
||||
to be automatically deactivated.
|
||||
|
||||
* Reencryption now limits hotzone size to be maximal 1 GiB or 1/4
|
||||
system memory (if lower).
|
||||
|
||||
* Reencryption now retains activation flags during online reencryption.
|
||||
|
||||
* Reencryption now allows LUKS2 device to activate device right after
|
||||
LUKS2 encryption is initialized through optional active device name
|
||||
for cryptsetup reencrypt --encrypt command.
|
||||
This could help with automated encryption during boot.
|
||||
|
||||
NOTE: It means that part of the device is still not encrypted during
|
||||
activation. Use with care!
|
||||
|
||||
* Fixes failure in resize and plain format activation if activated device
|
||||
size was not aligned to underlying logical device size.
|
||||
|
||||
* Fixes conversion to LUKS2 format with detached header if a detached
|
||||
header size was smaller than the expected aligned LUKS1 header size.
|
||||
209
docs/v2.3.0-ReleaseNotes
Normal file
209
docs/v2.3.0-ReleaseNotes
Normal file
@@ -0,0 +1,209 @@
|
||||
Cryptsetup 2.3.0 Release Notes
|
||||
==============================
|
||||
Stable release with new experimental features and bug fixes.
|
||||
|
||||
Cryptsetup 2.3 version introduces support for BitLocker-compatible
|
||||
devices (BITLK format). This format is used in Windows systems,
|
||||
and in combination with a filesystem driver, cryptsetup now provides
|
||||
native read-write access to BitLocker Full Disk Encryption devices.
|
||||
|
||||
The BITLK implementation is based on publicly available information
|
||||
and it is an independent and opensource implementation that allows
|
||||
to access this proprietary disk encryption.
|
||||
|
||||
Changes since version 2.2.2
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
* BITLK (Windows BitLocker compatible) device access
|
||||
|
||||
BITLK userspace implementation is based on the master thesis and code
|
||||
provided by Vojtech Trefny. Also, thanks to other opensource projects
|
||||
like libbde (that provide alternative approach to decode this format)
|
||||
we were able to verify cryptsetup implementation.
|
||||
|
||||
NOTE: Support for the BITLK device is EXPERIMENTAL and will require
|
||||
a lot of testing. If you get some error message (mainly unsupported
|
||||
metadata in the on-disk header), please help us by submitting an issue
|
||||
to cryptsetup project, so we can fix it. Thank you!
|
||||
|
||||
Cryptsetup supports BITLK activation through passphrase or recovery
|
||||
passphrase for existing devices (BitLocker and Bitlocker to Go).
|
||||
|
||||
Activation through TPM, SmartCard, or any other key protector
|
||||
is not supported. And in some situations, mainly for TPM bind to some
|
||||
PCR registers, it could be even impossible on Linux in the future.
|
||||
|
||||
All metadata (key protectors) are handled read-only, cryptsetup cannot
|
||||
create or modify them. Except for old devices (created in old Vista
|
||||
systems), all format variants should be recognized.
|
||||
|
||||
Data devices can be activated read-write (followed by mounting through
|
||||
the proper filesystem driver). To access filesystem on the decrypted device
|
||||
you need properly installed driver (vfat, NTFS or exFAT).
|
||||
|
||||
Foe AES-XTS, activation is supported on all recent Linux kernels.
|
||||
|
||||
For older AES-CBC encryption, Linux Kernel version 5.3 is required
|
||||
(support for special IV variant); for AES-CBC with Elephant diffuser,
|
||||
Linux Kernel 5.6 is required.
|
||||
|
||||
Please note that CBC variants are legacy, and we provide it only
|
||||
for backward compatibility (to be able to access old drives).
|
||||
|
||||
Cryptsetup command now supports the new "bitlk" format and implement dump,
|
||||
open, status, and close actions.
|
||||
|
||||
To activate a BITLK device, use
|
||||
|
||||
# cryptsetup open --type bitlk <device> <name>
|
||||
or with alias
|
||||
# cryptsetup bitlkOpen <device> <name>
|
||||
|
||||
Then with properly installed fs driver (usually NTFS, vfat or exFAT),
|
||||
you can mount the plaintext device /dev/mapper<name> device as a common
|
||||
filesystem.
|
||||
|
||||
To print metadata information about BITLK device, use
|
||||
# crypotsetup bitlkDump <device>
|
||||
|
||||
To print information about the active device, use
|
||||
# cryptsetup status <name>
|
||||
|
||||
Example (activation of disk image):
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
# Recent blkid recognizes BitLocker device,just to verity
|
||||
# blkid bitlocker_xts_ntfs.img
|
||||
bitlocker_xts_ntfs.img: TYPE="BitLocker"
|
||||
|
||||
# Print visible metadata information (on-disk, form the image)
|
||||
# cryptsetup bitlkDump bitlocker_xts_ntfs.img
|
||||
Info for BITLK device bitlocker_xts_ntfs.img.
|
||||
Version: 2
|
||||
GUID: ...
|
||||
Created: Wed Oct 23 17:38:15 2019
|
||||
Description: DESKTOP-xxxxxxx E: 23.10.2019
|
||||
Cipher name: aes
|
||||
Cipher mode: xts-plain64
|
||||
Cipher key: 128 bits
|
||||
|
||||
Keyslots:
|
||||
0: VMK
|
||||
GUID: ...
|
||||
Protection: VMK protected with passphrase
|
||||
Salt: ...
|
||||
Key data size: 44 [bytes]
|
||||
1: VMK
|
||||
GUID: ...
|
||||
Protection: VMK protected with recovery passphrase
|
||||
Salt: ...
|
||||
Key data size: 44 [bytes]
|
||||
2: FVEK
|
||||
Key data size: 44 [bytes]
|
||||
|
||||
# Activation (recovery passphrase works the same as password)
|
||||
# cryptsetup bitlkOpen bitlocker_xts_ntfs.img test -v
|
||||
Enter passphrase for bitlocker_xts_ntfs.img:
|
||||
Command successful.
|
||||
|
||||
# Information about the active device
|
||||
# cryptsetup status test
|
||||
/dev/mapper/test is active.
|
||||
type: BITLK
|
||||
cipher: aes-xts-plain64
|
||||
keysize: 128 bits
|
||||
...
|
||||
|
||||
# Plaintext device should now contain decrypted NTFS filesystem
|
||||
# blkid /dev/mapper/test
|
||||
/dev/mapper/test: UUID="..." TYPE="ntfs"
|
||||
|
||||
# And can be mounted
|
||||
# mount /dev/mapper/test /mnt/tst
|
||||
|
||||
# Deactivation
|
||||
# umount /mnt/tst
|
||||
# cryptsetup close test
|
||||
|
||||
* Veritysetup now supports activation with additional PKCS7 signature
|
||||
of root hash through --root-hash-signature option.
|
||||
The signature uses an in-kernel trusted key to validate the signature
|
||||
of the root hash during activation. This option requires Linux kernel
|
||||
5.4 with DM_VERITY_VERIFY_ROOTHASH_SIG option.
|
||||
|
||||
Verity devices activated with signature now has a special flag
|
||||
(with signature) active in device status (veritysetup status <name>).
|
||||
|
||||
Usage:
|
||||
# veritysetup open <data_device> name <hash_device> <root_hash> \
|
||||
--root-hash-signature=<roothash_p7_sig_file>
|
||||
|
||||
* Integritysetup now calculates hash integrity size according to algorithm
|
||||
instead of requiring an explicit tag size.
|
||||
|
||||
Previously, when integritysetup formats a device with hash or
|
||||
HMAC integrity checksums, it required explicitly tag size entry from
|
||||
a user (or used default value).
|
||||
This led to confusion and unexpected shortened tag sizes.
|
||||
|
||||
Now, libcryptsetup calculates tag size according to real hash output.
|
||||
Tag size can also be specified, then it warns if these values differ.
|
||||
|
||||
* Integritysetup now supports fixed padding for dm-integrity devices.
|
||||
|
||||
There was an in-kernel bug that wasted a lot of space when using metadata
|
||||
areas for integrity-protected devices if a larger sector size than
|
||||
512 bytes was used.
|
||||
This problem affects both stand-alone dm-integrity and also LUKS2 with
|
||||
authenticated encryption and larger sector size.
|
||||
|
||||
The new extension to dm-integrity superblock is needed, so devices
|
||||
with the new optimal padding cannot be activated on older systems.
|
||||
|
||||
Integritysetup/Cryptsetup will use new padding automatically if it
|
||||
detects the proper kernel. To create a compatible device with
|
||||
the old padding, use --integrity-legacy-padding option.
|
||||
|
||||
* A lot of fixes to online LUKS2 reecryption.
|
||||
|
||||
* Add crypt_resume_by_volume_key() function to libcryptsetup.
|
||||
If a user has a volume key available, the LUKS device can be resumed
|
||||
directly using the provided volume key.
|
||||
No keyslot derivation is needed, only the key digest is checked.
|
||||
|
||||
* Implement active device suspend info.
|
||||
Add CRYPT_ACTIVATE_SUSPENDED bit to crypt_get_active_device() flags
|
||||
that informs the caller that device is suspended (luksSuspend).
|
||||
|
||||
* Allow --test-passphrase for a detached header.
|
||||
Before this fix, we required a data device specified on the command
|
||||
line even though it was not necessary for the passphrase check.
|
||||
|
||||
* Allow --key-file option in legacy offline encryption.
|
||||
The option was ignored for LUKS1 encryption initialization.
|
||||
|
||||
* Export memory safe functions.
|
||||
To make developing of some extensions simpler, we now export
|
||||
functions to handle memory with proper wipe on deallocation.
|
||||
|
||||
* Fail crypt_keyslot_get_pbkdf for inactive LUKS1 keyslot.
|
||||
|
||||
Libcryptsetup API extensions
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
The libcryptsetup API is backward compatible for existing symbols.
|
||||
|
||||
New symbols
|
||||
crypt_set_compatibility
|
||||
crypt_get_compatibility;
|
||||
crypt_resume_by_volume_key;
|
||||
crypt_activate_by_signed_key;
|
||||
crypt_safe_alloc;
|
||||
crypt_safe_realloc;
|
||||
crypt_safe_free;
|
||||
crypt_safe_memzero;
|
||||
|
||||
New defines introduced :
|
||||
CRYPT_BITLK "BITLK" - BITLK (BitLocker-compatible mode
|
||||
CRYPT_COMPAT_LEGACY_INTEGRITY_PADDING - dm-integrity legacy padding
|
||||
CRYPT_VERITY_ROOT_HASH_SIGNATURE - dm-verity root hash signature
|
||||
CRYPT_ACTIVATE_SUSPENDED - device suspended info flag
|
||||
45
docs/v2.3.1-ReleaseNotes
Normal file
45
docs/v2.3.1-ReleaseNotes
Normal file
@@ -0,0 +1,45 @@
|
||||
Cryptsetup 2.3.1 Release Notes
|
||||
==============================
|
||||
Stable bug-fix release.
|
||||
|
||||
All users of cryptsetup 2.x should upgrade to this version.
|
||||
|
||||
Changes since version 2.3.0
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
* Support VeraCrypt 128 bytes passwords.
|
||||
VeraCrypt now allows passwords of maximal length 128 bytes
|
||||
(compared to legacy TrueCrypt where it was limited by 64 bytes).
|
||||
|
||||
* Strip extra newline from BitLocker recovery keys
|
||||
There might be a trailing newline added by the text editor when
|
||||
the recovery passphrase was passed using the --key-file option.
|
||||
|
||||
* Detect separate libiconv library.
|
||||
It should fix compilation issues on distributions with iconv
|
||||
implemented in a separate library.
|
||||
|
||||
* Various fixes and workarounds to build on old Linux distributions.
|
||||
|
||||
* Split lines with hexadecimal digest printing for large key-sizes.
|
||||
|
||||
* Do not wipe the device with no integrity profile.
|
||||
With --integrity none we performed useless full device wipe.
|
||||
|
||||
* Workaround for dm-integrity kernel table bug.
|
||||
Some kernels show an invalid dm-integrity mapping table
|
||||
if superblock contains the "recalculate" bit. This causes
|
||||
integritysetup to not recognize the dm-integrity device.
|
||||
Integritysetup now specifies kernel options such a way that
|
||||
even on unpatched kernels mapping table is correct.
|
||||
|
||||
* Print error message if LUKS1 keyslot cannot be processed.
|
||||
If the crypto backend is missing support for hash algorithms
|
||||
used in PBKDF2, the error message was not visible.
|
||||
|
||||
* Properly align LUKS2 keyslots area on conversion.
|
||||
If the LUKS1 payload offset (data offset) is not aligned
|
||||
to 4 KiB boundary, new LUKS2 keyslots area in now aligned properly.
|
||||
|
||||
* Validate LUKS2 earlier on conversion to not corrupt the device
|
||||
if binary keyslots areas metadata are not correct.
|
||||
42
docs/v2.3.2-ReleaseNotes
Normal file
42
docs/v2.3.2-ReleaseNotes
Normal file
@@ -0,0 +1,42 @@
|
||||
Cryptsetup 2.3.2 Release Notes
|
||||
==============================
|
||||
Stable bug-fix release.
|
||||
|
||||
All users of cryptsetup 2.x should upgrade to this version.
|
||||
|
||||
Changes since version 2.3.1
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
* Support compilation with json-c library version 0.14.
|
||||
|
||||
* Update FAQ document for some LUKS2 specific information.
|
||||
|
||||
* Add option to dump content of LUKS2 unbound keyslot:
|
||||
cryptsetup luksDump --unbound -S <slot> <device>
|
||||
or optionally with --master-key-file option.
|
||||
|
||||
The slot number --key-slot (-S) option is mandatory here.
|
||||
|
||||
An unbound keyslot store a key is that is not assigned to data
|
||||
area on disk (LUKS2 allows to store arbitrary keys).
|
||||
|
||||
* Rephrase some error messages and remove redundant end-of-lines.
|
||||
|
||||
* Add support for discards (TRIM) for standalone dm-integrity devices.
|
||||
Linux kernel 5.7 adds support for optional discard/TRIM operation
|
||||
over dm-integrity devices.
|
||||
|
||||
It is now supported through --allow-discards integritysetup option.
|
||||
Note you need to add this flag in all activation calls.
|
||||
|
||||
Note that this option cannot be used for LUKS2 authenticated encryption
|
||||
(that uses dm-integrity for storing additional per-sector metadata).
|
||||
|
||||
* Fix cryptsetup-reencrypt to work on devices that do not allow
|
||||
direct-io device access.
|
||||
|
||||
* Fix a crash in the BitLocker-compatible code error path.
|
||||
|
||||
* Fix Veracrypt compatible support for longer (>64 bytes) passphrases.
|
||||
It allows some older images to be correctly opened again.
|
||||
The issue was introduced in version 2.3.1.
|
||||
42
docs/v2.3.3-ReleaseNotes
Normal file
42
docs/v2.3.3-ReleaseNotes
Normal file
@@ -0,0 +1,42 @@
|
||||
Cryptsetup 2.3.3 Release Notes
|
||||
==============================
|
||||
Stable bug-fix release.
|
||||
|
||||
All users of cryptsetup 2.x should upgrade to this version.
|
||||
|
||||
Changes since version 2.3.2
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
* Fix BitLocker compatible device access that uses native 4kB sectors.
|
||||
|
||||
Devices formatted with storage that natively support 4096-bytes
|
||||
sectors can also use this sector size for encryption units.
|
||||
|
||||
* Support large IV count (--iv-large-sectors) cryptsetup option
|
||||
for plain device mapping.
|
||||
|
||||
The large IV count is supported in dm-crypt together with larger
|
||||
sector encryption. It counts the Initialization Vector (IV) in
|
||||
a larger sector size instead of 512-bytes sectors.
|
||||
|
||||
This option does not have any performance or security impact,
|
||||
but it can be used for accessing incompatible existing disk images
|
||||
from other systems.
|
||||
|
||||
Only open action with plain device type and sector size > 512 bytes
|
||||
are supported.
|
||||
|
||||
* Fix a memory leak in BitLocker compatible handling.
|
||||
|
||||
* Allow EBOIV (Initialization Vector algorithm) use.
|
||||
|
||||
The EBOIV initialization vector is intended to be used internally
|
||||
with BitLocker devices (for CBC mode). It can now be used also
|
||||
outside of the BitLocker compatible code.
|
||||
|
||||
* Require both keyslot cipher and key size options.
|
||||
|
||||
If these LUKS2 keyslot parameters were not specified together,
|
||||
cryptsetup silently failed.
|
||||
|
||||
* Update to man pages and FAQ.
|
||||
112
docs/v2.3.4-ReleaseNotes
Normal file
112
docs/v2.3.4-ReleaseNotes
Normal file
@@ -0,0 +1,112 @@
|
||||
Cryptsetup 2.3.4 Release Notes
|
||||
==============================
|
||||
Stable bug-fix release with a security fix (32-bit only).
|
||||
|
||||
All users of cryptsetup 2.2.x and later should upgrade to this version.
|
||||
|
||||
Changes since version 2.3.3
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
* Fix a possible out-of-bounds memory write while validating LUKS2 data
|
||||
segments metadata (CVE-2020-14382).
|
||||
|
||||
This problem can be triggered only on 32-bit builds (64-bit systems
|
||||
are not affected).
|
||||
|
||||
LUKS2 format validation code contains a bug in segments validation code
|
||||
where the code does not check for possible overflow on memory allocation.
|
||||
|
||||
Due to the bug, the libcryptsetup can be tricked to expect such allocation
|
||||
was successful. Later it may read data from image crafted by an attacker and
|
||||
actually write such data beyond allocated memory.
|
||||
|
||||
The bug was introduced in cryptsetup 2.2.0. All later releases until 2.3.4
|
||||
are affected.
|
||||
|
||||
If you only backport the fix for this CVE, these master branch git commits
|
||||
should be backported:
|
||||
52f5cb8cedf22fb3e14c744814ec8af7614146c7
|
||||
46ee71edcd13e1dad50815ad65c28779aa6f7503
|
||||
752c9a52798f11d3b765b673ebaa3058eb25316e
|
||||
|
||||
Thanks to Tobias Stoeckmann for discovering this issue.
|
||||
|
||||
* Ignore reported optimal IO size if not aligned to minimal page size.
|
||||
|
||||
Some USB enclosures report bogus block device topology (see lsblk -t) that
|
||||
prevents LUKS2 format with 4k sector size (reported values are not correctly
|
||||
aligned). The code now ignores such values and uses the default alignment.
|
||||
|
||||
* Added support for new no_read/write_wrokqueue dm-crypt options (kernel 5.9).
|
||||
|
||||
These performance options, introduced in kernel 5.9, configure dm-crypt
|
||||
to bypass read or write workqueues and run encryption synchronously.
|
||||
|
||||
Use --perf-no_read_workqueue or --perf-no_write_workqueue cryptsetup arguments
|
||||
to use these dm-crypt flags.
|
||||
|
||||
These options are available only for low-level dm-crypt performance tuning,
|
||||
use only if you need a change to default dm-crypt behavior.
|
||||
|
||||
For LUKS2, these flags can be persistently stored in metadata with
|
||||
the --persistent option.
|
||||
|
||||
* Added support panic_on_corruption option for dm-verity devices (kernel 5.9).
|
||||
|
||||
Veritysetup now supports --panic-on-corruption argument that configures
|
||||
the dm-verity device to panics kernel if a corruption is detected.
|
||||
|
||||
This option is intended for specific configurations, do not use it in
|
||||
standard configurations.
|
||||
|
||||
* Support --master-key-file option for online LUKS2 reencryption
|
||||
|
||||
This can be used for reencryption of devices that uses protected key AES cipher
|
||||
on some mainframes crypto accelerators.
|
||||
|
||||
* Always return EEXIST error code if a device already exists.
|
||||
|
||||
Some libcryptsetup functions (activate_by*) now return EEXIST error code,
|
||||
so the caller can distinguish that call fails because some parallel process
|
||||
already activated the device.
|
||||
Previously all fails returned EINVAL (invalid value).
|
||||
|
||||
* Fix a problem in integritysetup if a hash algorithm has dash in the name.
|
||||
|
||||
If users want to use blake2b/blake2s, the kernel algorithm name includes
|
||||
a dash (like "blake2s-256").
|
||||
Theses algorithms can now be used for integritysetup devices.
|
||||
|
||||
* Fix crypto backend to properly handle ECB mode.
|
||||
|
||||
Even though it should never be used, it should still work for testing :)
|
||||
This fixes a bug introduced in cryptsetup version 2.3.2.
|
||||
|
||||
* TrueCrypt/VeraCrypt compatible mode now supports the activation of devices
|
||||
with a larger sector.
|
||||
|
||||
TrueCrypt/VeraCrypt always uses 512-byte sector for encryption, but for devices
|
||||
with a larger native sector, it stores this value in the header.
|
||||
|
||||
This patch allows activation of such devices, basically ignoring
|
||||
the mentioned sector size.
|
||||
|
||||
* LUKS2: Do not create excessively large headers.
|
||||
|
||||
When creating a LUKS2 header with a specified --offset larger than
|
||||
the LUKS2 header size, do not create a larger file than needed.
|
||||
|
||||
* Fix unspecified sector size for BitLocker compatible mode.
|
||||
|
||||
Some BitLocker devices can contain zeroed sector size in the header.
|
||||
In this case, the 512-byte sector should be used.
|
||||
The bug was introduced in version 2.3.3.
|
||||
|
||||
* Fix reading key data size in metadata for BitLocker compatible mode.
|
||||
|
||||
Such devices with an unexpected entry in metadata can now be activated.
|
||||
|
||||
Thanks to all users reporting these problems, BitLocker metadata documentation
|
||||
is not publicly available, and we depend only on these reports.
|
||||
|
||||
* Fix typos in documentation.
|
||||
181
docs/v2.3.5-ReleaseNotes
Normal file
181
docs/v2.3.5-ReleaseNotes
Normal file
@@ -0,0 +1,181 @@
|
||||
Cryptsetup 2.3.5 Release Notes
|
||||
==============================
|
||||
Stable bug-fix release with minor extensions.
|
||||
|
||||
All users of cryptsetup 2.x and later should upgrade to this version.
|
||||
|
||||
Changes since version 2.3.4
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
* Fix partial reads of passphrase from an interactive terminal.
|
||||
Some stable kernels (5.3.11) started to return buffer from a terminal
|
||||
in parts of maximal size 64 bytes.
|
||||
This breaks the reading of passphrases longer than 64 characters
|
||||
entered through an interactive terminal. The change is already fixed
|
||||
in later kernel releases, but tools now support such partial read from
|
||||
terminal properly.
|
||||
|
||||
* Fix maximal length of password entered through a terminal.
|
||||
Now the maximal interactive passphrase length is exactly
|
||||
512 characters (not 511).
|
||||
|
||||
* integritysetup: support new dm-integrity HMAC recalculation options.
|
||||
|
||||
In older kernels (since version 4.19), an attacker can force
|
||||
an automatic recalculation of integrity tags by modifying
|
||||
the dm-integrity superblock.
|
||||
This is a problem with a keyed algorithms (HMAC), where it expects
|
||||
nobody can trigger such recalculation without the key.
|
||||
(Automatic recalculation will start after the next activation.)
|
||||
|
||||
Note that dm-integrity in standalone mode was *not* supposed
|
||||
to provide cryptographic data integrity protection.
|
||||
Despite that, we try to keep the system secure if keyed algorithms
|
||||
are used.
|
||||
Thank Daniel Glöckner for the original report of this problem.
|
||||
|
||||
Authenticated encryption that provides data integrity protection (in
|
||||
combination with dm-crypt and LUKS2) is not affected by this problem.
|
||||
|
||||
The fix in the kernel for this problem contains two parts.
|
||||
|
||||
Firstly, the dm-integrity kernel module disables integrity
|
||||
recalculation if keyed algorithms (HMAC) are used.
|
||||
This change is included in long-term stable kernels.
|
||||
|
||||
Secondly, since the kernel version 5.11, dm-integrity introduces
|
||||
modified protection where a journal-integrity algorithm guards
|
||||
superblock; also, journal sections are protected. An attacker cannot
|
||||
copy sectors from one journal section to another, and the superblock
|
||||
also contains salt to prevent header replacement from another device.
|
||||
|
||||
If you want to protect data with HMAC, you should always also use HMAC
|
||||
for --journal-integrity. Keys can be independent.
|
||||
If HMAC is used for data but not for the journal, the recalculation
|
||||
option is disabled.
|
||||
|
||||
If you need to use (insecure) backward compatibility implementation,
|
||||
two new integritysetup options are introduced:
|
||||
- Use --integrity-legacy-recalc (instead of --integrity-recalc)
|
||||
to allow recalculation on legacy devices.
|
||||
- Use --integrity-legacy-hmac in format action to force old insecure
|
||||
HMAC format.
|
||||
|
||||
Libcryptsetup API also introduces flags
|
||||
CRYPT_COMPAT_LEGACY_INTEGRITY_HMAC and
|
||||
CRYPT_COMPAT_LEGACY_INTEGRITY_RECALC
|
||||
to set these through crypt_set_compatibility() call.
|
||||
|
||||
* integritysetup: display of recalculating sector in dump command.
|
||||
|
||||
* veritysetup: fix verity FEC if stored in the same image with hashes.
|
||||
|
||||
Optional FEC (Forward Error Correction) data should cover the whole
|
||||
data area, hashes (Merkle tree), and optionally additional metadata
|
||||
(located after hash area).
|
||||
|
||||
Unfortunately, if FEC data is stored in the same file as hash,
|
||||
the calculation wrongly used the whole file size, thus overlaps with
|
||||
the FEC area itself. This produced unusable and too large FEC data.
|
||||
There is no problem if the FEC image is a separate image.
|
||||
|
||||
The problem is now fixed, introducing FEC blocks calculation as:
|
||||
- If the hash device is in a separate image, metadata covers the
|
||||
whole rest of the image after the hash area. (Unchanged behavior.)
|
||||
- If hash and FEC device is in the image, metadata ends on the FEC
|
||||
area offset.
|
||||
|
||||
Note: there is also a fix for FEC in the dm-verity kernel (on the way
|
||||
to stable kernels) that fixes error correction with larger RS roots.
|
||||
|
||||
* veritysetup: run FEC repair check even if root hash fails.
|
||||
|
||||
Note: The userspace FEC verify command reports are only informational
|
||||
for now. Code does not check verity hash after FEC recovery in
|
||||
userspace. The Reed-Solomon decoder can then report the possibility
|
||||
that it fixed data even if parity is too damaged.
|
||||
This will be fixed in the next major release.
|
||||
|
||||
* veritysetup: do not process hash image if hash area is empty.
|
||||
|
||||
Sometimes the device is so small that there is only a root hash
|
||||
needed, and the hash area is not used.
|
||||
Also, the size of the hash image is not increased for hash block
|
||||
alignment in this case.
|
||||
|
||||
* veritysetup: store verity hash algorithm in superblock in lowercase.
|
||||
|
||||
Otherwise, the kernel could refuse the activation of the device.
|
||||
|
||||
* bitlk: fix a crash if the device disappears during BitLocker scan.
|
||||
|
||||
* bitlk: show a better error when trying to open an NTFS device.
|
||||
|
||||
Both BitLocker version 1 and NTFS have the same signature.
|
||||
If a user opens an NTFS device without BitLocker, it now correctly
|
||||
informs that it is not a BITLK device.
|
||||
|
||||
* bitlk: add support for startup key protected VMKs.
|
||||
|
||||
The startup key can be provided in --key-file option for open command.
|
||||
|
||||
* Fix LUKS1 repair code (regression since version 1.7.x).
|
||||
|
||||
We cannot trust possibly broken keyslots metadata in repair, so the
|
||||
code recalculates them instead.
|
||||
This makes the repair code working again when the master boot record
|
||||
signature overwrites the LUKS header.
|
||||
|
||||
* Fix luksKeyChange for LUKS2 with assigned tokens.
|
||||
|
||||
The token references are now correctly assigned to the new keyslot
|
||||
number.
|
||||
|
||||
* Fix cryptsetup resize using LUKS2 tokens.
|
||||
|
||||
Code needlessly asked for passphrase even though volume key was
|
||||
already unlocked via LUKS2 token.
|
||||
|
||||
* Print a visible error if device resize is not supported.
|
||||
|
||||
* Add error message when suspending wrong non-LUKS device.
|
||||
|
||||
* Fix default XTS mode key size in reencryption.
|
||||
|
||||
The same luksFormat logic (double key size because XTS uses two keys)
|
||||
is applied in the reencryption code.
|
||||
|
||||
* Rephrase missing locking directory warning and move it to debug level.
|
||||
|
||||
The system should later provide a safe transition to tempdir
|
||||
configuration, so creating locking directory inside libcryptsetup
|
||||
call is safe.
|
||||
|
||||
* Many fixes for the use of cipher_null (empty debug cipher).
|
||||
|
||||
Support for this empty cipher was intended as a debug feature and for
|
||||
measuring performance overhead. Unfortunately, many systems started to
|
||||
use it as an "empty shell" for LUKS (to enable encryption later).
|
||||
|
||||
This use is very dangerous and it creates a false sense of security.
|
||||
|
||||
Anyway, to not break such systems, we try to support these
|
||||
configurations.
|
||||
Using cipher_null in any production system is strongly discouraged!
|
||||
|
||||
Fixes include:
|
||||
- allow LUKS resume for a device with cipher_null.
|
||||
- do not upload key in keyring when data cipher is null.
|
||||
- switch to default cipher when reencrypting cipher_null device.
|
||||
- replace possible bogus cipher_null keyslots before reencryption.
|
||||
- fix broken detection of null cipher in LUKS2.
|
||||
cipher_null is no longer possible to be used in keyslot encryption
|
||||
in LUKS2, it can be used only for data for debugging purposes.
|
||||
|
||||
* Fixes for libpasswdqc 2.0.x (optional passphrase quality check).
|
||||
|
||||
* Fixes for problems discovered by various tools for code analysis.
|
||||
|
||||
Fixes include a rework of libpopt command line option string leaks.
|
||||
|
||||
* Various fixes to man pages.
|
||||
56
docs/v2.3.6-ReleaseNotes
Normal file
56
docs/v2.3.6-ReleaseNotes
Normal file
@@ -0,0 +1,56 @@
|
||||
Cryptsetup 2.3.6 Release Notes
|
||||
==============================
|
||||
Stable bug-fix release with minor extensions.
|
||||
|
||||
All users of cryptsetup 2.x and later should upgrade to this version.
|
||||
|
||||
Changes since version 2.3.5
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
* integritysetup: Fix possible dm-integrity mapping table truncation.
|
||||
|
||||
While integritysetup in standalone mode (no encryption) was not
|
||||
designed to provide keyed (and cryptographically strong) data
|
||||
integrity protection, some options can use such algorithms (HMAC).
|
||||
|
||||
If a key is used, it is directly sent to the kernel dm-integrity as
|
||||
a mapping table option (no key derivation is performed).
|
||||
For HMAC, such a key could be quite long (up to 4096 bytes in
|
||||
integritysetup CLI).
|
||||
|
||||
Unfortunately, due to fixed buffers and not correctly checking string
|
||||
truncation, some parameter combinations could cause truncation
|
||||
of the dm-integrity mapping table.
|
||||
In most cases, the table was rejected by the kernel.
|
||||
The worst possible case was key truncation for HMAC options
|
||||
(internal_hash and journal_mac dm-integrity table options).
|
||||
|
||||
This release fixes possible truncation and also adds more sanity
|
||||
checks to reject truncated options.
|
||||
Also, integritysetup now mentions maximal allowed key size
|
||||
in --help output.
|
||||
|
||||
For old standalone dm-integrity devices where the key length was
|
||||
truncated, you have to modify (shorten) --integrity-key-size
|
||||
resp. --journal-integrity-key-size option now.
|
||||
|
||||
This bug is _not_ present for dm-crypt/LUKS, LUKS2 (including
|
||||
integrity protection), or dm-verity devices; it affects only
|
||||
standalone dm-integrity with HMAC integrity protection.
|
||||
|
||||
* cryptsetup: Backup header can be used to activate TCRYPT device.
|
||||
Use --header option to specify the header.
|
||||
|
||||
* cryptsetup: Avoid LUKS2 decryption without detached header.
|
||||
This feature will be added later and is currently not supported.
|
||||
|
||||
* Additional fixes and workarounds for common warnings produced
|
||||
by some static analysis tools (like gcc-11 analyzer) and additional
|
||||
code hardening.
|
||||
|
||||
* Fix standalone libintl detection for compiled tests.
|
||||
|
||||
* Add Blake2b and Blake2s hash support for crypto backends.
|
||||
Kernel and gcrypt crypto backend support all variants.
|
||||
OpenSSL supports only Blake2b-512 and Blake2s-256.
|
||||
Crypto backend supports kernel notation e.g. "blake2b-512".
|
||||
302
docs/v2.4.0-ReleaseNotes
Normal file
302
docs/v2.4.0-ReleaseNotes
Normal file
@@ -0,0 +1,302 @@
|
||||
Cryptsetup 2.4.0 Release Notes
|
||||
==============================
|
||||
Stable release candidate with new features and bug fixes.
|
||||
|
||||
This version introduces support for external libraries
|
||||
(plugins) for handling LUKS2 token objects.
|
||||
|
||||
Changes since version 2.3.6
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
* External LUKS token plugins
|
||||
|
||||
A LUKS2 token is an object that can describe how to get a passphrase
|
||||
to unlock a particular keyslot. The generic metadata format is part
|
||||
of the LUKS2 specification.
|
||||
|
||||
Cryptsetup 2.4 adds the possibility to implement token handlers
|
||||
in external libraries (possibly provided by other projects).
|
||||
|
||||
A token library allows cryptsetup to understand metadata and provide
|
||||
basic operations. Currently external tokens may be used to unlock
|
||||
keyslots for following CLI actions: open (luksOpen),
|
||||
refresh (open --refresh), resize and dump (prints token specific
|
||||
content).
|
||||
|
||||
LUKS2 devices cannot be resumed (luksResume action) via tokens yet.
|
||||
Support for resume and other actions will be added later.
|
||||
|
||||
The library now provides an interface that automatically tries to load
|
||||
an external library for a token object in LUKS2 metadata.
|
||||
|
||||
Token libraries should be installed in the cryptsetup subdirectory
|
||||
(usually /lib*/cryptsetup). This path is configurable through
|
||||
--with-luks2-external-tokens-path configure option.
|
||||
|
||||
The external plugin loading can be compiled entirely out if
|
||||
--disable-external-tokens configure option is used. The external token
|
||||
interface can also be disabled runtime on the command line by
|
||||
--disable-external-tokens cryptsetup switch or by calling
|
||||
crypt_token_external_disable() API function.
|
||||
|
||||
The name of the loaded token library is determined from the JSON LUKS
|
||||
metadata token object type. For example, "ssh" token will load library
|
||||
"libcryptsetup-token-ssh.so".
|
||||
|
||||
External projects can use this interface to handle specific hardware
|
||||
without introducing additional dependencies to libcryptsetup core.
|
||||
|
||||
As of cryptsetup 2.4.0 release systemd project already merged upstream
|
||||
native cryptsetup token handler for its systemd-tpm2 LUKS2 token
|
||||
released originally in systemd-v248. The token can be created using
|
||||
systemd-cryptenroll utility and devices may be manipulated either by
|
||||
systemd-cryptsetup cli or by cryptsetup for actions listed above.
|
||||
|
||||
Other tokens like systemd-fido2 and systemd-pkcs11 are currently
|
||||
in-review.
|
||||
|
||||
* Experimental SSH token
|
||||
|
||||
As a demonstration of the external LUKS2 token interface, a new SSH
|
||||
token handler and cryptsetup-ssh utility is now provided and compiled
|
||||
by default.
|
||||
|
||||
Crypsetup SSH token allows using remote keyfile through SSH protocol
|
||||
(it will authenticate through SSH certificates).
|
||||
|
||||
You can disable the build of this token library with
|
||||
--disable-ssh-token configure option.
|
||||
|
||||
To configure the token metadata, you need cryptsetup-ssh utility.
|
||||
|
||||
Activation of the device is then performed by the cryptsetup utility.
|
||||
|
||||
Example (how to activate LUKS2 through remote keyfile):
|
||||
|
||||
- configure existing LUKS2 device with keyslot activated by a keyfile
|
||||
# cryptsetup luksAddKey <device> keyfile --key-slot 2
|
||||
|
||||
- store that keyfile on a remote system accessible through SSH
|
||||
|
||||
- configure SSH to use certificate for authentication
|
||||
|
||||
- add a LUKS2 token with cryptsetup-ssh utility:
|
||||
# cryptsetup-ssh add <device>1 --key-slot 2 \
|
||||
--ssh-server test-vm \
|
||||
--ssh-user test \
|
||||
--ssh-path /home/test/keyfile \
|
||||
--ssh-keypath /home/test/.ssh/test_rsa_key
|
||||
|
||||
- you should see token metadata now with "cryptsetup luksDump ..."
|
||||
...
|
||||
Tokens:
|
||||
0: ssh
|
||||
ssh_server: test-vm
|
||||
ssh_user: test
|
||||
ssh_path: /home/test/keyfile
|
||||
ssh_key_path: /home/test/.ssh/test_rsa_key
|
||||
Keyslot: 2
|
||||
|
||||
|
||||
- activation now should be automatic
|
||||
# cryptsetup open <device> test --verbose
|
||||
SSH token initiating ssh session.
|
||||
Key slot 2 unlocked.
|
||||
Command successful.
|
||||
|
||||
- to remove a token, you can use "cryptsetup token remove" command
|
||||
(no plugin library required)
|
||||
|
||||
Please note SSH token is just demonstration of plugin interface API,
|
||||
it is an EXPERIMENTAL feature.
|
||||
|
||||
* Add cryptsetup --token-type parameter.
|
||||
|
||||
It restricts token type to the parameter value in case no specific
|
||||
token-id is selected.
|
||||
|
||||
* Support for token based activation with PIN.
|
||||
|
||||
If specific token requires PIN to unlock keyslot passphrase and
|
||||
--token-only parameter was used cryptsetup asks for additional
|
||||
token PIN.
|
||||
|
||||
* Respect keyslot priority with token-based activation.
|
||||
|
||||
* Default LUKS2 PBKDF is now Argon2id
|
||||
|
||||
Cryptsetup LUKS2 was using Argon2 while there were two versions,
|
||||
data-independent (Argon2i) suitable for the KDF use case and
|
||||
Argon2d (data-dependent). Later Argon2id was introduced as a new
|
||||
mandatory algorithm.
|
||||
|
||||
We switched the password-based key derivation algorithms
|
||||
following the latest version of Argon2 RFC draft
|
||||
(https://datatracker.ietf.org/doc/draft-irtf-cfrg-argon2/) to Argon2id
|
||||
(from Argon2i) as it is the mandatory and primary version
|
||||
of the Argon2 algorithm.
|
||||
|
||||
There is no need to modify older containers; the main reason is that
|
||||
RFC makes Argon2id the primary variant, while Argon2i subvariant is
|
||||
only optional.
|
||||
Argon2id provides better protection to side-channel attacks while
|
||||
still providing protection to time-memory tradeoffs.
|
||||
|
||||
We will switch to OpenSSL implementation once it is available.
|
||||
With a crystal ball as a reference, it could happen early in
|
||||
OpenSSL 3.1 release.
|
||||
Watch https://github.com/openssl/openssl/issues/4091.
|
||||
|
||||
* Increase minimal memory cost for Argon2 benchmark to 64MiB.
|
||||
|
||||
This patch increases the benchmarking value to 64 MiB (as minimal
|
||||
suggested values in Argon2 RFC). For compatibility reasons, we still
|
||||
allow older limits if set by a parameter.
|
||||
|
||||
NOTE: Argon2 RFC draft defines suggested parameters for disk
|
||||
encryption, but the LUKS2 approach is slightly different. We need to
|
||||
provide platform-independent values. The values in the draft expect
|
||||
64bit systems (suggesting using 6 GiB of RAM). In comparison, we need
|
||||
to provide compatibility with all 32bit systems, so allocating more
|
||||
than 4GiB memory is not an option for LUKS2.
|
||||
|
||||
The maximal limit in LUKS2 stays for 4 GiB, and by default LUKS2 PBKDF
|
||||
benchmarking sets maximum to 1 GIB, preferring an increase of CPU cost
|
||||
while running benchmark
|
||||
|
||||
* Autodetect optimal encryption sector size on LUKS2 format.
|
||||
|
||||
While the support for larger encryption sectors is supported
|
||||
for several releases, it required an additional parameter.
|
||||
|
||||
Code now uses automatic detection of 4096-bytes native sector devices
|
||||
and automatically enables 4096-bytes encryption size for LUKS2.
|
||||
|
||||
If no setor size option is used, sector size is detected
|
||||
automatically by cryptsetup. For libcryptsetup API, autodetection
|
||||
happens once you specify sector_size to 0.
|
||||
|
||||
NOTE: crypt_format() function runs autodetection ONLY if you
|
||||
recompile your application to the new API symbol version.
|
||||
For backward compatibility, older applications ignore this parameter.
|
||||
|
||||
* Use VeraCrypt option by default and add --disable-veracrypt option.
|
||||
|
||||
While TrueCrypt is no longer developed and supported since 2014,
|
||||
VeraCrypt devices (a successor of TrueCrypt) are much more used today.
|
||||
|
||||
Default is now to support VeraCrypt format (in addition to TrueCrypt),
|
||||
making the --veracrypt option obsolete (ignored as it is the default).
|
||||
|
||||
If you need to disable VeraCrypt support, use the new option
|
||||
--disable-veracrypt.
|
||||
|
||||
This option increases the time to recognize wrong passwords because
|
||||
some VeraCrypt modes use a high PBKDF2 iteration count, and the code
|
||||
must try all variants. This could be limited by using --hash and
|
||||
--cipher options mentioned below.
|
||||
|
||||
* Support --hash and --cipher to limit opening time for TCRYPT type
|
||||
|
||||
If a user knows which particular PBKDF2 hash or cipher is used for
|
||||
TrueCrypt/VeraCrypt container, TCRYPT format now supports --hash and
|
||||
--cipher option.
|
||||
|
||||
Note the value means substring (all cipher chains containing
|
||||
the cipher substring are tried).
|
||||
|
||||
For example, you can use
|
||||
# cryptsetup tcryptDump --hash sha512 <container>
|
||||
|
||||
Note: to speed up the scan, the hash option (used for PBKDF)2 matters.
|
||||
Cipher variants are scanned very quickly.
|
||||
|
||||
Use with care.
|
||||
It can reveal some sensitive attributes of the container!
|
||||
|
||||
* Fixed default OpenSSL crypt backend support for OpenSSL3.
|
||||
|
||||
For OpenSSL version 3, we need to load legacy provider for older hash
|
||||
and ciphers. For example, RIPEMD160 and Whirlpool hash algorithms are
|
||||
no longer available by default.
|
||||
|
||||
NOTE: the plain format still uses RIPEMD160 for password hashing by
|
||||
default. Changing the default would cause incompatibilities for many
|
||||
old systems. Nevertheless, such a change will be needed very soon.
|
||||
|
||||
* integritysetup: add integrity-recalculate-reset flag.
|
||||
|
||||
The new dm-integrity option in kernel 5.13 can restart recalculation
|
||||
from the beginning of the device.
|
||||
It can be used to change the integrity checksum function.
|
||||
|
||||
New integritysetup --integrity-recalculate-reset option is added to
|
||||
integritysetup, and CRYPT_ACTIVATE_RECALCULATE_RESET flag to API.
|
||||
|
||||
* cryptsetup: retains keyslot number in luksChangeKey for LUKS2.
|
||||
|
||||
In LUKS1, any change in keyslot means keyslot number change.
|
||||
|
||||
In LUKS2, we can retain the keyslot number.
|
||||
Now luksKeyChange and crypt_keyslot_change_by_passphrase() API
|
||||
retains keyslot number for LUKS2 by default.
|
||||
|
||||
* Fix cryptsetup resize using LUKS2 tokens.
|
||||
|
||||
Fix a bug where cryptsetup needlessly asked for a passphrase even
|
||||
though the volume key was already unlocked via LUKS2 token.
|
||||
|
||||
* Add close --deferred and --cancel-deferred options.
|
||||
|
||||
All command-line utilities now understand deferred options for the
|
||||
close command. Deferred close means that the device is removed
|
||||
automagically after the last user closed the device.
|
||||
Cancel deferred means to cancel this operation (so the device remains
|
||||
active even if there a no longer active users).
|
||||
|
||||
CRYPT_DEACTIVATE_DEFERRED and CRYPT_DEACTIVATE_DEFERRED_CANCEL flags
|
||||
are now available for API.
|
||||
|
||||
* Rewritten command-line option parsing to avoid libpopt arguments
|
||||
memory leaks.
|
||||
|
||||
Note: some distributions use patched lipopt that still leaks memory
|
||||
inside internal code (see Debian bug 941814).
|
||||
|
||||
* Add --test-args option.
|
||||
|
||||
New --test-args option can be used for syntax checking for valid
|
||||
command-line arguments with no actions performed.
|
||||
Note that it cannot detect unknown algorithm names and similar where
|
||||
we need call API functions.
|
||||
|
||||
* veritysetup: add --root-hash-file option
|
||||
Allow passing the root hash via a file, rather than verbatim on
|
||||
the command line, for the open, verify, and format actions.
|
||||
|
||||
* libcryptsetup C API extensions (see libcryptsetup.h for details)
|
||||
|
||||
- crypt_logf - a printf like log function
|
||||
- crypt_dump_json - dump LUKS2 metadata in JSON format
|
||||
- crypt_header_is_detached - check if context use detached header
|
||||
- crypt_token_max - get maximal tokens number
|
||||
- crypt_token_external_path - get path for plugins (or NULL)
|
||||
- crypt_token_external_disable - disable runtime support for plugins
|
||||
- crypt_activate_by_token_pin - activate by token with additional PIN
|
||||
- crypt_reencrypt_run - fixed API for deprecated crypt_reencrypt
|
||||
|
||||
The token plugin library interface cosists from these versioned
|
||||
exported symbols (for details see header file and SSH token example):
|
||||
cryptsetup_token_open
|
||||
cryptsetup_token_open_pin
|
||||
cryptsetup_token_buffer_free
|
||||
cryptsetup_token_validate
|
||||
cryptsetup_token_dump
|
||||
cryptsetup_token_version
|
||||
|
||||
Since version 2.4 libcryptsetup uses exact symbol versioning
|
||||
Newly introduced functions have CRYPTSETUP_2.4 namespace (the old
|
||||
symbol always used CRYPTSETUP_2.0).
|
||||
There is no change in soname (the library is backward compatible).
|
||||
|
||||
* Many fixes and additions to documentation and man pages.
|
||||
@@ -1,70 +0,0 @@
|
||||
SUBDIRS = crypto_backend luks1 loopaes verity tcrypt
|
||||
|
||||
moduledir = $(libdir)/cryptsetup
|
||||
|
||||
pkgconfigdir = $(libdir)/pkgconfig
|
||||
pkgconfig_DATA = libcryptsetup.pc
|
||||
|
||||
AM_CPPFLAGS = -include config.h \
|
||||
-I$(top_srcdir) \
|
||||
-I$(top_srcdir)/lib/crypto_backend \
|
||||
-I$(top_srcdir)/lib/luks1 \
|
||||
-I$(top_srcdir)/lib/loopaes \
|
||||
-I$(top_srcdir)/lib/verity \
|
||||
-I$(top_srcdir)/lib/tcrypt \
|
||||
-DDATADIR=\""$(datadir)"\" \
|
||||
-DLIBDIR=\""$(libdir)"\" \
|
||||
-DPREFIX=\""$(prefix)"\" \
|
||||
-DSYSCONFDIR=\""$(sysconfdir)"\" \
|
||||
-DVERSION=\""$(VERSION)"\"
|
||||
|
||||
lib_LTLIBRARIES = libcryptsetup.la
|
||||
|
||||
common_ldadd = \
|
||||
crypto_backend/libcrypto_backend.la \
|
||||
luks1/libluks1.la \
|
||||
loopaes/libloopaes.la \
|
||||
verity/libverity.la \
|
||||
tcrypt/libtcrypt.la
|
||||
|
||||
libcryptsetup_la_DEPENDENCIES = $(common_ldadd) libcryptsetup.sym
|
||||
|
||||
libcryptsetup_la_LDFLAGS = $(AM_LDFLAGS) -no-undefined \
|
||||
-Wl,--version-script=$(top_srcdir)/lib/libcryptsetup.sym \
|
||||
-version-info @LIBCRYPTSETUP_VERSION_INFO@
|
||||
|
||||
libcryptsetup_la_CFLAGS = -Wall $(AM_CFLAGS) @CRYPTO_CFLAGS@
|
||||
|
||||
libcryptsetup_la_LIBADD = \
|
||||
@UUID_LIBS@ \
|
||||
@DEVMAPPER_LIBS@ \
|
||||
@CRYPTO_LIBS@ \
|
||||
$(common_ldadd)
|
||||
|
||||
|
||||
libcryptsetup_la_SOURCES = \
|
||||
setup.c \
|
||||
internal.h \
|
||||
bitops.h \
|
||||
nls.h \
|
||||
libcryptsetup.h \
|
||||
utils.c \
|
||||
utils_benchmark.c \
|
||||
utils_crypt.c \
|
||||
utils_crypt.h \
|
||||
utils_loop.c \
|
||||
utils_loop.h \
|
||||
utils_devpath.c \
|
||||
utils_wipe.c \
|
||||
utils_fips.c \
|
||||
utils_fips.h \
|
||||
utils_device.c \
|
||||
libdevmapper.c \
|
||||
utils_dm.h \
|
||||
volumekey.c \
|
||||
random.c \
|
||||
crypt_plain.c
|
||||
|
||||
include_HEADERS = libcryptsetup.h
|
||||
|
||||
EXTRA_DIST = libcryptsetup.pc.in libcryptsetup.sym
|
||||
109
lib/Makemodule.am
Normal file
109
lib/Makemodule.am
Normal file
@@ -0,0 +1,109 @@
|
||||
pkgconfigdir = $(libdir)/pkgconfig
|
||||
pkgconfig_DATA += lib/libcryptsetup.pc
|
||||
|
||||
lib_LTLIBRARIES += libcryptsetup.la
|
||||
|
||||
noinst_LTLIBRARIES += libutils_io.la
|
||||
|
||||
include_HEADERS += lib/libcryptsetup.h
|
||||
|
||||
EXTRA_DIST += lib/libcryptsetup.pc.in lib/libcryptsetup.sym
|
||||
|
||||
libutils_io_la_CFLAGS = $(AM_CFLAGS)
|
||||
|
||||
libutils_io_la_SOURCES = \
|
||||
lib/utils_io.c \
|
||||
lib/utils_io.h
|
||||
|
||||
libcryptsetup_la_CPPFLAGS = $(AM_CPPFLAGS)
|
||||
|
||||
libcryptsetup_la_DEPENDENCIES = libutils_io.la libcrypto_backend.la lib/libcryptsetup.sym
|
||||
|
||||
libcryptsetup_la_LDFLAGS = $(AM_LDFLAGS) -no-undefined \
|
||||
-Wl,--version-script=$(top_srcdir)/lib/libcryptsetup.sym \
|
||||
-version-info @LIBCRYPTSETUP_VERSION_INFO@
|
||||
|
||||
libcryptsetup_la_CFLAGS = $(AM_CFLAGS) @CRYPTO_CFLAGS@
|
||||
|
||||
libcryptsetup_la_LIBADD = \
|
||||
@UUID_LIBS@ \
|
||||
@DEVMAPPER_LIBS@ \
|
||||
@CRYPTO_LIBS@ \
|
||||
@LIBARGON2_LIBS@ \
|
||||
@JSON_C_LIBS@ \
|
||||
@BLKID_LIBS@ \
|
||||
$(LTLIBICONV) \
|
||||
libcrypto_backend.la \
|
||||
libutils_io.la
|
||||
|
||||
libcryptsetup_la_SOURCES = \
|
||||
lib/setup.c \
|
||||
lib/internal.h \
|
||||
lib/bitops.h \
|
||||
lib/nls.h \
|
||||
lib/libcryptsetup.h \
|
||||
lib/libcryptsetup_macros.h \
|
||||
lib/libcryptsetup_symver.h \
|
||||
lib/utils.c \
|
||||
lib/utils_benchmark.c \
|
||||
lib/utils_crypt.c \
|
||||
lib/utils_crypt.h \
|
||||
lib/utils_loop.c \
|
||||
lib/utils_loop.h \
|
||||
lib/utils_devpath.c \
|
||||
lib/utils_wipe.c \
|
||||
lib/utils_fips.c \
|
||||
lib/utils_fips.h \
|
||||
lib/utils_device.c \
|
||||
lib/utils_keyring.c \
|
||||
lib/utils_keyring.h \
|
||||
lib/utils_device_locking.c \
|
||||
lib/utils_device_locking.h \
|
||||
lib/utils_pbkdf.c \
|
||||
lib/utils_safe_memory.c \
|
||||
lib/utils_storage_wrappers.c \
|
||||
lib/utils_storage_wrappers.h \
|
||||
lib/libdevmapper.c \
|
||||
lib/utils_dm.h \
|
||||
lib/volumekey.c \
|
||||
lib/random.c \
|
||||
lib/crypt_plain.c \
|
||||
lib/base64.h \
|
||||
lib/base64.c \
|
||||
lib/integrity/integrity.h \
|
||||
lib/integrity/integrity.c \
|
||||
lib/loopaes/loopaes.h \
|
||||
lib/loopaes/loopaes.c \
|
||||
lib/tcrypt/tcrypt.h \
|
||||
lib/tcrypt/tcrypt.c \
|
||||
lib/luks1/af.h \
|
||||
lib/luks1/af.c \
|
||||
lib/luks1/keyencryption.c \
|
||||
lib/luks1/keymanage.c \
|
||||
lib/luks1/luks.h \
|
||||
lib/verity/verity_hash.c \
|
||||
lib/verity/verity_fec.c \
|
||||
lib/verity/verity.c \
|
||||
lib/verity/verity.h \
|
||||
lib/verity/rs_encode_char.c \
|
||||
lib/verity/rs_decode_char.c \
|
||||
lib/verity/rs.h \
|
||||
lib/luks2/luks2_disk_metadata.c \
|
||||
lib/luks2/luks2_json_format.c \
|
||||
lib/luks2/luks2_json_metadata.c \
|
||||
lib/luks2/luks2_luks1_convert.c \
|
||||
lib/luks2/luks2_digest.c \
|
||||
lib/luks2/luks2_digest_pbkdf2.c \
|
||||
lib/luks2/luks2_keyslot.c \
|
||||
lib/luks2/luks2_keyslot_luks2.c \
|
||||
lib/luks2/luks2_keyslot_reenc.c \
|
||||
lib/luks2/luks2_reencrypt.c \
|
||||
lib/luks2/luks2_segment.c \
|
||||
lib/luks2/luks2_token_keyring.c \
|
||||
lib/luks2/luks2_token.c \
|
||||
lib/luks2/luks2_internal.h \
|
||||
lib/luks2/luks2.h \
|
||||
lib/utils_blkid.c \
|
||||
lib/utils_blkid.h \
|
||||
lib/bitlk/bitlk.h \
|
||||
lib/bitlk/bitlk.c
|
||||
605
lib/base64.c
Normal file
605
lib/base64.c
Normal file
@@ -0,0 +1,605 @@
|
||||
/* base64.c -- Encode binary data using printable characters.
|
||||
Copyright (C) 1999-2001, 2004-2006, 2009-2019 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, see <https://www.gnu.org/licenses/>. */
|
||||
|
||||
/* Written by Simon Josefsson. Partially adapted from GNU MailUtils
|
||||
* (mailbox/filter_trans.c, as of 2004-11-28). Improved by review
|
||||
* from Paul Eggert, Bruno Haible, and Stepan Kasal.
|
||||
*
|
||||
* See also RFC 4648 <https://www.ietf.org/rfc/rfc4648.txt>.
|
||||
*
|
||||
* Be careful with error checking. Here is how you would typically
|
||||
* use these functions:
|
||||
*
|
||||
* bool ok = base64_decode_alloc (in, inlen, &out, &outlen);
|
||||
* if (!ok)
|
||||
* FAIL: input was not valid base64
|
||||
* if (out == NULL)
|
||||
* FAIL: memory allocation error
|
||||
* OK: data in OUT/OUTLEN
|
||||
*
|
||||
* size_t outlen = base64_encode_alloc (in, inlen, &out);
|
||||
* if (out == NULL && outlen == 0 && inlen != 0)
|
||||
* FAIL: input too long
|
||||
* if (out == NULL)
|
||||
* FAIL: memory allocation error
|
||||
* OK: data in OUT/OUTLEN.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
/* Get prototype. */
|
||||
#include "base64.h"
|
||||
|
||||
/* Get malloc. */
|
||||
#include <stdlib.h>
|
||||
|
||||
/* Get UCHAR_MAX. */
|
||||
#include <limits.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
/* C89 compliant way to cast 'char' to 'unsigned char'. */
|
||||
static unsigned char
|
||||
to_uchar (char ch)
|
||||
{
|
||||
return ch;
|
||||
}
|
||||
|
||||
static const char b64c[64] =
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
|
||||
/* Base64 encode IN array of size INLEN into OUT array. OUT needs
|
||||
to be of length >= BASE64_LENGTH(INLEN), and INLEN needs to be
|
||||
a multiple of 3. */
|
||||
static void
|
||||
base64_encode_fast (const char *restrict in, size_t inlen, char *restrict out)
|
||||
{
|
||||
while (inlen)
|
||||
{
|
||||
*out++ = b64c[(to_uchar (in[0]) >> 2) & 0x3f];
|
||||
*out++ = b64c[((to_uchar (in[0]) << 4) + (to_uchar (in[1]) >> 4)) & 0x3f];
|
||||
*out++ = b64c[((to_uchar (in[1]) << 2) + (to_uchar (in[2]) >> 6)) & 0x3f];
|
||||
*out++ = b64c[to_uchar (in[2]) & 0x3f];
|
||||
|
||||
inlen -= 3;
|
||||
in += 3;
|
||||
}
|
||||
}
|
||||
|
||||
/* Base64 encode IN array of size INLEN into OUT array of size OUTLEN.
|
||||
If OUTLEN is less than BASE64_LENGTH(INLEN), write as many bytes as
|
||||
possible. If OUTLEN is larger than BASE64_LENGTH(INLEN), also zero
|
||||
terminate the output buffer. */
|
||||
void
|
||||
base64_encode (const char *restrict in, size_t inlen,
|
||||
char *restrict out, size_t outlen)
|
||||
{
|
||||
/* Note this outlen constraint can be enforced at compile time.
|
||||
I.E. that the output buffer is exactly large enough to hold
|
||||
the encoded inlen bytes. The inlen constraints (of corresponding
|
||||
to outlen, and being a multiple of 3) can change at runtime
|
||||
at the end of input. However the common case when reading
|
||||
large inputs is to have both constraints satisfied, so we depend
|
||||
on both in base_encode_fast(). */
|
||||
if (outlen % 4 == 0 && inlen == outlen / 4 * 3)
|
||||
{
|
||||
base64_encode_fast (in, inlen, out);
|
||||
return;
|
||||
}
|
||||
|
||||
while (inlen && outlen)
|
||||
{
|
||||
*out++ = b64c[(to_uchar (in[0]) >> 2) & 0x3f];
|
||||
if (!--outlen)
|
||||
break;
|
||||
*out++ = b64c[((to_uchar (in[0]) << 4)
|
||||
+ (--inlen ? to_uchar (in[1]) >> 4 : 0))
|
||||
& 0x3f];
|
||||
if (!--outlen)
|
||||
break;
|
||||
*out++ =
|
||||
(inlen
|
||||
? b64c[((to_uchar (in[1]) << 2)
|
||||
+ (--inlen ? to_uchar (in[2]) >> 6 : 0))
|
||||
& 0x3f]
|
||||
: '=');
|
||||
if (!--outlen)
|
||||
break;
|
||||
*out++ = inlen ? b64c[to_uchar (in[2]) & 0x3f] : '=';
|
||||
if (!--outlen)
|
||||
break;
|
||||
if (inlen)
|
||||
inlen--;
|
||||
if (inlen)
|
||||
in += 3;
|
||||
}
|
||||
|
||||
if (outlen)
|
||||
*out = '\0';
|
||||
}
|
||||
|
||||
/* Allocate a buffer and store zero terminated base64 encoded data
|
||||
from array IN of size INLEN, returning BASE64_LENGTH(INLEN), i.e.,
|
||||
the length of the encoded data, excluding the terminating zero. On
|
||||
return, the OUT variable will hold a pointer to newly allocated
|
||||
memory that must be deallocated by the caller. If output string
|
||||
length would overflow, 0 is returned and OUT is set to NULL. If
|
||||
memory allocation failed, OUT is set to NULL, and the return value
|
||||
indicates length of the requested memory block, i.e.,
|
||||
BASE64_LENGTH(inlen) + 1. */
|
||||
size_t
|
||||
base64_encode_alloc (const char *in, size_t inlen, char **out)
|
||||
{
|
||||
size_t outlen = 1 + BASE64_LENGTH (inlen);
|
||||
|
||||
/* Check for overflow in outlen computation.
|
||||
*
|
||||
* If there is no overflow, outlen >= inlen.
|
||||
*
|
||||
* If the operation (inlen + 2) overflows then it yields at most +1, so
|
||||
* outlen is 0.
|
||||
*
|
||||
* If the multiplication overflows, we lose at least half of the
|
||||
* correct value, so the result is < ((inlen + 2) / 3) * 2, which is
|
||||
* less than (inlen + 2) * 0.66667, which is less than inlen as soon as
|
||||
* (inlen > 4).
|
||||
*/
|
||||
if (inlen > outlen)
|
||||
{
|
||||
*out = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
*out = malloc (outlen);
|
||||
if (!*out)
|
||||
return outlen;
|
||||
|
||||
base64_encode (in, inlen, *out, outlen);
|
||||
|
||||
return outlen - 1;
|
||||
}
|
||||
|
||||
/* With this approach this file works independent of the charset used
|
||||
(think EBCDIC). However, it does assume that the characters in the
|
||||
Base64 alphabet (A-Za-z0-9+/) are encoded in 0..255. POSIX
|
||||
1003.1-2001 require that char and unsigned char are 8-bit
|
||||
quantities, though, taking care of that problem. But this may be a
|
||||
potential problem on non-POSIX C99 platforms.
|
||||
|
||||
IBM C V6 for AIX mishandles "#define B64(x) ...'x'...", so use "_"
|
||||
as the formal parameter rather than "x". */
|
||||
#define B64(_) \
|
||||
((_) == 'A' ? 0 \
|
||||
: (_) == 'B' ? 1 \
|
||||
: (_) == 'C' ? 2 \
|
||||
: (_) == 'D' ? 3 \
|
||||
: (_) == 'E' ? 4 \
|
||||
: (_) == 'F' ? 5 \
|
||||
: (_) == 'G' ? 6 \
|
||||
: (_) == 'H' ? 7 \
|
||||
: (_) == 'I' ? 8 \
|
||||
: (_) == 'J' ? 9 \
|
||||
: (_) == 'K' ? 10 \
|
||||
: (_) == 'L' ? 11 \
|
||||
: (_) == 'M' ? 12 \
|
||||
: (_) == 'N' ? 13 \
|
||||
: (_) == 'O' ? 14 \
|
||||
: (_) == 'P' ? 15 \
|
||||
: (_) == 'Q' ? 16 \
|
||||
: (_) == 'R' ? 17 \
|
||||
: (_) == 'S' ? 18 \
|
||||
: (_) == 'T' ? 19 \
|
||||
: (_) == 'U' ? 20 \
|
||||
: (_) == 'V' ? 21 \
|
||||
: (_) == 'W' ? 22 \
|
||||
: (_) == 'X' ? 23 \
|
||||
: (_) == 'Y' ? 24 \
|
||||
: (_) == 'Z' ? 25 \
|
||||
: (_) == 'a' ? 26 \
|
||||
: (_) == 'b' ? 27 \
|
||||
: (_) == 'c' ? 28 \
|
||||
: (_) == 'd' ? 29 \
|
||||
: (_) == 'e' ? 30 \
|
||||
: (_) == 'f' ? 31 \
|
||||
: (_) == 'g' ? 32 \
|
||||
: (_) == 'h' ? 33 \
|
||||
: (_) == 'i' ? 34 \
|
||||
: (_) == 'j' ? 35 \
|
||||
: (_) == 'k' ? 36 \
|
||||
: (_) == 'l' ? 37 \
|
||||
: (_) == 'm' ? 38 \
|
||||
: (_) == 'n' ? 39 \
|
||||
: (_) == 'o' ? 40 \
|
||||
: (_) == 'p' ? 41 \
|
||||
: (_) == 'q' ? 42 \
|
||||
: (_) == 'r' ? 43 \
|
||||
: (_) == 's' ? 44 \
|
||||
: (_) == 't' ? 45 \
|
||||
: (_) == 'u' ? 46 \
|
||||
: (_) == 'v' ? 47 \
|
||||
: (_) == 'w' ? 48 \
|
||||
: (_) == 'x' ? 49 \
|
||||
: (_) == 'y' ? 50 \
|
||||
: (_) == 'z' ? 51 \
|
||||
: (_) == '0' ? 52 \
|
||||
: (_) == '1' ? 53 \
|
||||
: (_) == '2' ? 54 \
|
||||
: (_) == '3' ? 55 \
|
||||
: (_) == '4' ? 56 \
|
||||
: (_) == '5' ? 57 \
|
||||
: (_) == '6' ? 58 \
|
||||
: (_) == '7' ? 59 \
|
||||
: (_) == '8' ? 60 \
|
||||
: (_) == '9' ? 61 \
|
||||
: (_) == '+' ? 62 \
|
||||
: (_) == '/' ? 63 \
|
||||
: -1)
|
||||
|
||||
static const signed char b64[0x100] = {
|
||||
B64 (0), B64 (1), B64 (2), B64 (3),
|
||||
B64 (4), B64 (5), B64 (6), B64 (7),
|
||||
B64 (8), B64 (9), B64 (10), B64 (11),
|
||||
B64 (12), B64 (13), B64 (14), B64 (15),
|
||||
B64 (16), B64 (17), B64 (18), B64 (19),
|
||||
B64 (20), B64 (21), B64 (22), B64 (23),
|
||||
B64 (24), B64 (25), B64 (26), B64 (27),
|
||||
B64 (28), B64 (29), B64 (30), B64 (31),
|
||||
B64 (32), B64 (33), B64 (34), B64 (35),
|
||||
B64 (36), B64 (37), B64 (38), B64 (39),
|
||||
B64 (40), B64 (41), B64 (42), B64 (43),
|
||||
B64 (44), B64 (45), B64 (46), B64 (47),
|
||||
B64 (48), B64 (49), B64 (50), B64 (51),
|
||||
B64 (52), B64 (53), B64 (54), B64 (55),
|
||||
B64 (56), B64 (57), B64 (58), B64 (59),
|
||||
B64 (60), B64 (61), B64 (62), B64 (63),
|
||||
B64 (64), B64 (65), B64 (66), B64 (67),
|
||||
B64 (68), B64 (69), B64 (70), B64 (71),
|
||||
B64 (72), B64 (73), B64 (74), B64 (75),
|
||||
B64 (76), B64 (77), B64 (78), B64 (79),
|
||||
B64 (80), B64 (81), B64 (82), B64 (83),
|
||||
B64 (84), B64 (85), B64 (86), B64 (87),
|
||||
B64 (88), B64 (89), B64 (90), B64 (91),
|
||||
B64 (92), B64 (93), B64 (94), B64 (95),
|
||||
B64 (96), B64 (97), B64 (98), B64 (99),
|
||||
B64 (100), B64 (101), B64 (102), B64 (103),
|
||||
B64 (104), B64 (105), B64 (106), B64 (107),
|
||||
B64 (108), B64 (109), B64 (110), B64 (111),
|
||||
B64 (112), B64 (113), B64 (114), B64 (115),
|
||||
B64 (116), B64 (117), B64 (118), B64 (119),
|
||||
B64 (120), B64 (121), B64 (122), B64 (123),
|
||||
B64 (124), B64 (125), B64 (126), B64 (127),
|
||||
B64 (128), B64 (129), B64 (130), B64 (131),
|
||||
B64 (132), B64 (133), B64 (134), B64 (135),
|
||||
B64 (136), B64 (137), B64 (138), B64 (139),
|
||||
B64 (140), B64 (141), B64 (142), B64 (143),
|
||||
B64 (144), B64 (145), B64 (146), B64 (147),
|
||||
B64 (148), B64 (149), B64 (150), B64 (151),
|
||||
B64 (152), B64 (153), B64 (154), B64 (155),
|
||||
B64 (156), B64 (157), B64 (158), B64 (159),
|
||||
B64 (160), B64 (161), B64 (162), B64 (163),
|
||||
B64 (164), B64 (165), B64 (166), B64 (167),
|
||||
B64 (168), B64 (169), B64 (170), B64 (171),
|
||||
B64 (172), B64 (173), B64 (174), B64 (175),
|
||||
B64 (176), B64 (177), B64 (178), B64 (179),
|
||||
B64 (180), B64 (181), B64 (182), B64 (183),
|
||||
B64 (184), B64 (185), B64 (186), B64 (187),
|
||||
B64 (188), B64 (189), B64 (190), B64 (191),
|
||||
B64 (192), B64 (193), B64 (194), B64 (195),
|
||||
B64 (196), B64 (197), B64 (198), B64 (199),
|
||||
B64 (200), B64 (201), B64 (202), B64 (203),
|
||||
B64 (204), B64 (205), B64 (206), B64 (207),
|
||||
B64 (208), B64 (209), B64 (210), B64 (211),
|
||||
B64 (212), B64 (213), B64 (214), B64 (215),
|
||||
B64 (216), B64 (217), B64 (218), B64 (219),
|
||||
B64 (220), B64 (221), B64 (222), B64 (223),
|
||||
B64 (224), B64 (225), B64 (226), B64 (227),
|
||||
B64 (228), B64 (229), B64 (230), B64 (231),
|
||||
B64 (232), B64 (233), B64 (234), B64 (235),
|
||||
B64 (236), B64 (237), B64 (238), B64 (239),
|
||||
B64 (240), B64 (241), B64 (242), B64 (243),
|
||||
B64 (244), B64 (245), B64 (246), B64 (247),
|
||||
B64 (248), B64 (249), B64 (250), B64 (251),
|
||||
B64 (252), B64 (253), B64 (254), B64 (255)
|
||||
};
|
||||
|
||||
#if UCHAR_MAX == 255
|
||||
# define uchar_in_range(c) true
|
||||
#else
|
||||
# define uchar_in_range(c) ((c) <= 255)
|
||||
#endif
|
||||
|
||||
/* Return true if CH is a character from the Base64 alphabet, and
|
||||
false otherwise. Note that '=' is padding and not considered to be
|
||||
part of the alphabet. */
|
||||
bool
|
||||
isbase64 (char ch)
|
||||
{
|
||||
return uchar_in_range (to_uchar (ch)) && 0 <= b64[to_uchar (ch)];
|
||||
}
|
||||
|
||||
/* Initialize decode-context buffer, CTX. */
|
||||
void
|
||||
base64_decode_ctx_init (struct base64_decode_context *ctx)
|
||||
{
|
||||
ctx->i = 0;
|
||||
}
|
||||
|
||||
/* If CTX->i is 0 or 4, there are four or more bytes in [*IN..IN_END), and
|
||||
none of those four is a newline, then return *IN. Otherwise, copy up to
|
||||
4 - CTX->i non-newline bytes from that range into CTX->buf, starting at
|
||||
index CTX->i and setting CTX->i to reflect the number of bytes copied,
|
||||
and return CTX->buf. In either case, advance *IN to point to the byte
|
||||
after the last one processed, and set *N_NON_NEWLINE to the number of
|
||||
verified non-newline bytes accessible through the returned pointer. */
|
||||
static const char *
|
||||
get_4 (struct base64_decode_context *ctx,
|
||||
char const *restrict *in, char const *restrict in_end,
|
||||
size_t *n_non_newline)
|
||||
{
|
||||
if (ctx->i == 4)
|
||||
ctx->i = 0;
|
||||
|
||||
if (ctx->i == 0)
|
||||
{
|
||||
char const *t = *in;
|
||||
if (4 <= in_end - *in && memchr (t, '\n', 4) == NULL)
|
||||
{
|
||||
/* This is the common case: no newline. */
|
||||
*in += 4;
|
||||
*n_non_newline = 4;
|
||||
return (const char *) t;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
/* Copy non-newline bytes into BUF. */
|
||||
char const *p = *in;
|
||||
while (p < in_end)
|
||||
{
|
||||
char c = *p++;
|
||||
if (c != '\n')
|
||||
{
|
||||
ctx->buf[ctx->i++] = c;
|
||||
if (ctx->i == 4)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
*in = p;
|
||||
*n_non_newline = ctx->i;
|
||||
return ctx->buf;
|
||||
}
|
||||
}
|
||||
|
||||
#define return_false \
|
||||
do \
|
||||
{ \
|
||||
*outp = out; \
|
||||
return false; \
|
||||
} \
|
||||
while (false)
|
||||
|
||||
/* Decode up to four bytes of base64-encoded data, IN, of length INLEN
|
||||
into the output buffer, *OUT, of size *OUTLEN bytes. Return true if
|
||||
decoding is successful, false otherwise. If *OUTLEN is too small,
|
||||
as many bytes as possible are written to *OUT. On return, advance
|
||||
*OUT to point to the byte after the last one written, and decrement
|
||||
*OUTLEN to reflect the number of bytes remaining in *OUT. */
|
||||
static bool
|
||||
decode_4 (char const *restrict in, size_t inlen,
|
||||
char *restrict *outp, size_t *outleft)
|
||||
{
|
||||
char *out = *outp;
|
||||
if (inlen < 2)
|
||||
return false;
|
||||
|
||||
if (!isbase64 (in[0]) || !isbase64 (in[1]))
|
||||
return false;
|
||||
|
||||
if (*outleft)
|
||||
{
|
||||
*out++ = ((b64[to_uchar (in[0])] << 2)
|
||||
| (b64[to_uchar (in[1])] >> 4));
|
||||
--*outleft;
|
||||
}
|
||||
|
||||
if (inlen == 2)
|
||||
return_false;
|
||||
|
||||
if (in[2] == '=')
|
||||
{
|
||||
if (inlen != 4)
|
||||
return_false;
|
||||
|
||||
if (in[3] != '=')
|
||||
return_false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!isbase64 (in[2]))
|
||||
return_false;
|
||||
|
||||
if (*outleft)
|
||||
{
|
||||
*out++ = (((b64[to_uchar (in[1])] << 4) & 0xf0)
|
||||
| (b64[to_uchar (in[2])] >> 2));
|
||||
--*outleft;
|
||||
}
|
||||
|
||||
if (inlen == 3)
|
||||
return_false;
|
||||
|
||||
if (in[3] == '=')
|
||||
{
|
||||
if (inlen != 4)
|
||||
return_false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!isbase64 (in[3]))
|
||||
return_false;
|
||||
|
||||
if (*outleft)
|
||||
{
|
||||
*out++ = (((b64[to_uchar (in[2])] << 6) & 0xc0)
|
||||
| b64[to_uchar (in[3])]);
|
||||
--*outleft;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*outp = out;
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Decode base64-encoded input array IN of length INLEN to output array
|
||||
OUT that can hold *OUTLEN bytes. The input data may be interspersed
|
||||
with newlines. Return true if decoding was successful, i.e. if the
|
||||
input was valid base64 data, false otherwise. If *OUTLEN is too
|
||||
small, as many bytes as possible will be written to OUT. On return,
|
||||
*OUTLEN holds the length of decoded bytes in OUT. Note that as soon
|
||||
as any non-alphabet, non-newline character is encountered, decoding
|
||||
is stopped and false is returned. If INLEN is zero, then process
|
||||
only whatever data is stored in CTX.
|
||||
|
||||
Initially, CTX must have been initialized via base64_decode_ctx_init.
|
||||
Subsequent calls to this function must reuse whatever state is recorded
|
||||
in that buffer. It is necessary for when a quadruple of base64 input
|
||||
bytes spans two input buffers.
|
||||
|
||||
If CTX is NULL then newlines are treated as garbage and the input
|
||||
buffer is processed as a unit. */
|
||||
|
||||
bool
|
||||
base64_decode_ctx (struct base64_decode_context *ctx,
|
||||
const char *restrict in, size_t inlen,
|
||||
char *restrict out, size_t *outlen)
|
||||
{
|
||||
size_t outleft = *outlen;
|
||||
bool ignore_newlines = ctx != NULL;
|
||||
bool flush_ctx = false;
|
||||
unsigned int ctx_i = 0;
|
||||
|
||||
if (ignore_newlines)
|
||||
{
|
||||
ctx_i = ctx->i;
|
||||
flush_ctx = inlen == 0;
|
||||
}
|
||||
|
||||
|
||||
while (true)
|
||||
{
|
||||
size_t outleft_save = outleft;
|
||||
if (ctx_i == 0 && !flush_ctx)
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
/* Save a copy of outleft, in case we need to re-parse this
|
||||
block of four bytes. */
|
||||
outleft_save = outleft;
|
||||
if (!decode_4 (in, inlen, &out, &outleft))
|
||||
break;
|
||||
|
||||
in += 4;
|
||||
inlen -= 4;
|
||||
}
|
||||
}
|
||||
|
||||
if (inlen == 0 && !flush_ctx)
|
||||
break;
|
||||
|
||||
/* Handle the common case of 72-byte wrapped lines.
|
||||
This also handles any other multiple-of-4-byte wrapping. */
|
||||
if (inlen && *in == '\n' && ignore_newlines)
|
||||
{
|
||||
++in;
|
||||
--inlen;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Restore OUT and OUTLEFT. */
|
||||
out -= outleft_save - outleft;
|
||||
outleft = outleft_save;
|
||||
|
||||
{
|
||||
char const *in_end = in + inlen;
|
||||
char const *non_nl;
|
||||
|
||||
if (ignore_newlines)
|
||||
non_nl = get_4 (ctx, &in, in_end, &inlen);
|
||||
else
|
||||
non_nl = in; /* Might have nl in this case. */
|
||||
|
||||
/* If the input is empty or consists solely of newlines (0 non-newlines),
|
||||
then we're done. Likewise if there are fewer than 4 bytes when not
|
||||
flushing context and not treating newlines as garbage. */
|
||||
if (inlen == 0 || (inlen < 4 && !flush_ctx && ignore_newlines))
|
||||
{
|
||||
inlen = 0;
|
||||
break;
|
||||
}
|
||||
if (!decode_4 (non_nl, inlen, &out, &outleft))
|
||||
break;
|
||||
|
||||
inlen = in_end - in;
|
||||
}
|
||||
}
|
||||
|
||||
*outlen -= outleft;
|
||||
|
||||
return inlen == 0;
|
||||
}
|
||||
|
||||
/* Allocate an output buffer in *OUT, and decode the base64 encoded
|
||||
data stored in IN of size INLEN to the *OUT buffer. On return, the
|
||||
size of the decoded data is stored in *OUTLEN. OUTLEN may be NULL,
|
||||
if the caller is not interested in the decoded length. *OUT may be
|
||||
NULL to indicate an out of memory error, in which case *OUTLEN
|
||||
contains the size of the memory block needed. The function returns
|
||||
true on successful decoding and memory allocation errors. (Use the
|
||||
*OUT and *OUTLEN parameters to differentiate between successful
|
||||
decoding and memory error.) The function returns false if the
|
||||
input was invalid, in which case *OUT is NULL and *OUTLEN is
|
||||
undefined. */
|
||||
bool
|
||||
base64_decode_alloc_ctx (struct base64_decode_context *ctx,
|
||||
const char *in, size_t inlen, char **out,
|
||||
size_t *outlen)
|
||||
{
|
||||
/* This may allocate a few bytes too many, depending on input,
|
||||
but it's not worth the extra CPU time to compute the exact size.
|
||||
The exact size is 3 * (inlen + (ctx ? ctx->i : 0)) / 4, minus 1 if the
|
||||
input ends with "=" and minus another 1 if the input ends with "==".
|
||||
Dividing before multiplying avoids the possibility of overflow. */
|
||||
size_t needlen = 3 * (inlen / 4) + 3;
|
||||
|
||||
*out = malloc (needlen);
|
||||
if (!*out)
|
||||
return true;
|
||||
|
||||
if (!base64_decode_ctx (ctx, in, inlen, *out, &needlen))
|
||||
{
|
||||
free (*out);
|
||||
*out = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (outlen)
|
||||
*outlen = needlen;
|
||||
|
||||
return true;
|
||||
}
|
||||
68
lib/base64.h
Normal file
68
lib/base64.h
Normal file
@@ -0,0 +1,68 @@
|
||||
/* base64.h -- Encode binary data using printable characters.
|
||||
Copyright (C) 2004-2006, 2009-2019 Free Software Foundation, Inc.
|
||||
Written by Simon Josefsson.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, see <https://www.gnu.org/licenses/>. */
|
||||
|
||||
#ifndef BASE64_H
|
||||
# define BASE64_H
|
||||
|
||||
/* Get size_t. */
|
||||
# include <stddef.h>
|
||||
|
||||
/* Get bool. */
|
||||
# include <stdbool.h>
|
||||
|
||||
# ifdef __cplusplus
|
||||
extern "C" {
|
||||
# endif
|
||||
|
||||
/* This uses that the expression (n+(k-1))/k means the smallest
|
||||
integer >= n/k, i.e., the ceiling of n/k. */
|
||||
# define BASE64_LENGTH(inlen) ((((inlen) + 2) / 3) * 4)
|
||||
|
||||
struct base64_decode_context
|
||||
{
|
||||
unsigned int i;
|
||||
char buf[4];
|
||||
};
|
||||
|
||||
extern bool isbase64 (char ch) __attribute__ ((__const__));
|
||||
|
||||
extern void base64_encode (const char *restrict in, size_t inlen,
|
||||
char *restrict out, size_t outlen);
|
||||
|
||||
extern size_t base64_encode_alloc (const char *in, size_t inlen, char **out);
|
||||
|
||||
extern void base64_decode_ctx_init (struct base64_decode_context *ctx);
|
||||
|
||||
extern bool base64_decode_ctx (struct base64_decode_context *ctx,
|
||||
const char *restrict in, size_t inlen,
|
||||
char *restrict out, size_t *outlen);
|
||||
|
||||
extern bool base64_decode_alloc_ctx (struct base64_decode_context *ctx,
|
||||
const char *in, size_t inlen,
|
||||
char **out, size_t *outlen);
|
||||
|
||||
#define base64_decode(in, inlen, out, outlen) \
|
||||
base64_decode_ctx (NULL, in, inlen, out, outlen)
|
||||
|
||||
#define base64_decode_alloc(in, inlen, out, outlen) \
|
||||
base64_decode_alloc_ctx (NULL, in, inlen, out, outlen)
|
||||
|
||||
# ifdef __cplusplus
|
||||
}
|
||||
# endif
|
||||
|
||||
#endif /* BASE64_H */
|
||||
1443
lib/bitlk/bitlk.c
Normal file
1443
lib/bitlk/bitlk.c
Normal file
File diff suppressed because it is too large
Load Diff
145
lib/bitlk/bitlk.h
Normal file
145
lib/bitlk/bitlk.h
Normal file
@@ -0,0 +1,145 @@
|
||||
/*
|
||||
* BITLK (BitLocker-compatible) header definition
|
||||
*
|
||||
* Copyright (C) 2019-2021 Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2019-2021 Milan Broz
|
||||
* Copyright (C) 2019-2021 Vojtech Trefny
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This file is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this file; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef _CRYPTSETUP_BITLK_H
|
||||
#define _CRYPTSETUP_BITLK_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
struct crypt_device;
|
||||
struct device;
|
||||
struct volume_key;
|
||||
|
||||
#define BITLK_NONCE_SIZE 12
|
||||
#define BITLK_SALT_SIZE 16
|
||||
#define BITLK_VMK_MAC_TAG_SIZE 16
|
||||
|
||||
#define BITLK_STATE_NORMAL 0x0004
|
||||
|
||||
typedef enum {
|
||||
BITLK_ENCRYPTION_TYPE_NORMAL = 0,
|
||||
BITLK_ENCRYPTION_TYPE_EOW,
|
||||
BITLK_ENCRYPTION_TYPE_UNKNOWN,
|
||||
} BITLKEncryptionType;
|
||||
|
||||
typedef enum {
|
||||
BITLK_PROTECTION_CLEAR_KEY = 0,
|
||||
BITLK_PROTECTION_TPM,
|
||||
BITLK_PROTECTION_STARTUP_KEY,
|
||||
BITLK_PROTECTION_TPM_PIN,
|
||||
BITLK_PROTECTION_RECOVERY_PASSPHRASE,
|
||||
BITLK_PROTECTION_PASSPHRASE,
|
||||
BITLK_PROTECTION_SMART_CARD,
|
||||
BITLK_PROTECTION_UNKNOWN,
|
||||
} BITLKVMKProtection;
|
||||
|
||||
typedef enum {
|
||||
BITLK_ENTRY_TYPE_PROPERTY = 0x0000,
|
||||
BITLK_ENTRY_TYPE_VMK = 0x0002,
|
||||
BITLK_ENTRY_TYPE_FVEK = 0x0003,
|
||||
BITLK_ENTRY_TYPE_STARTUP_KEY = 0x0006,
|
||||
BITLK_ENTRY_TYPE_DESCRIPTION = 0x0007,
|
||||
BITLK_ENTRY_TYPE_VOLUME_HEADER = 0x000f,
|
||||
} BITLKFVEEntryType;
|
||||
|
||||
typedef enum {
|
||||
BITLK_ENTRY_VALUE_ERASED = 0x0000,
|
||||
BITLK_ENTRY_VALUE_KEY = 0x0001,
|
||||
BITLK_ENTRY_VALUE_STRING = 0x0002,
|
||||
BITLK_ENTRY_VALUE_STRETCH_KEY = 0x0003,
|
||||
BITLK_ENTRY_VALUE_USE_KEY = 0x0004,
|
||||
BITLK_ENTRY_VALUE_ENCRYPTED_KEY = 0x0005,
|
||||
BITLK_ENTRY_VALUE_TPM_KEY = 0x0006,
|
||||
BITLK_ENTRY_VALUE_VALIDATION = 0x0007,
|
||||
BITLK_ENTRY_VALUE_VMK = 0x0008,
|
||||
BITLK_ENTRY_VALUE_EXTERNAL_KEY = 0x0009,
|
||||
BITLK_ENTRY_VALUE_OFFSET_SIZE = 0x000f,
|
||||
BITLK_ENTRY_VALUE_RECOVERY_TIME = 0x015,
|
||||
} BITLKFVEEntryValue;
|
||||
|
||||
struct bitlk_vmk {
|
||||
char *guid;
|
||||
char *name;
|
||||
BITLKVMKProtection protection;
|
||||
uint8_t salt[BITLK_SALT_SIZE];
|
||||
uint8_t mac_tag[BITLK_VMK_MAC_TAG_SIZE];
|
||||
uint8_t nonce[BITLK_NONCE_SIZE];
|
||||
struct volume_key *vk;
|
||||
struct bitlk_vmk *next;
|
||||
};
|
||||
|
||||
struct bitlk_fvek {
|
||||
uint8_t mac_tag[BITLK_VMK_MAC_TAG_SIZE];
|
||||
uint8_t nonce[BITLK_NONCE_SIZE];
|
||||
struct volume_key *vk;
|
||||
};
|
||||
|
||||
struct bitlk_metadata {
|
||||
uint16_t sector_size;
|
||||
bool togo;
|
||||
bool state;
|
||||
BITLKEncryptionType type;
|
||||
const char *cipher;
|
||||
const char *cipher_mode;
|
||||
uint16_t key_size;
|
||||
char *guid;
|
||||
uint64_t creation_time;
|
||||
char *description;
|
||||
uint64_t metadata_offset[3];
|
||||
uint32_t metadata_version;
|
||||
uint64_t volume_header_offset;
|
||||
uint64_t volume_header_size;
|
||||
struct bitlk_vmk *vmks;
|
||||
struct bitlk_fvek *fvek;
|
||||
};
|
||||
|
||||
int BITLK_read_sb(struct crypt_device *cd, struct bitlk_metadata *params);
|
||||
|
||||
int BITLK_dump(struct crypt_device *cd, struct device *device, struct bitlk_metadata *params);
|
||||
|
||||
int BITLK_get_volume_key(struct crypt_device *cd,
|
||||
const char *password,
|
||||
size_t passwordLen,
|
||||
const struct bitlk_metadata *params,
|
||||
struct volume_key **open_fvek_key);
|
||||
|
||||
int BITLK_activate_by_passphrase(struct crypt_device *cd,
|
||||
const char *name,
|
||||
const char *password,
|
||||
size_t passwordLen,
|
||||
const struct bitlk_metadata *params,
|
||||
uint32_t flags);
|
||||
|
||||
int BITLK_activate_by_volume_key(struct crypt_device *cd,
|
||||
const char *name,
|
||||
const char *volume_key,
|
||||
size_t volume_key_size,
|
||||
const struct bitlk_metadata *params,
|
||||
uint32_t flags);
|
||||
|
||||
void BITLK_bitlk_fvek_free(struct bitlk_fvek *fvek);
|
||||
void BITLK_bitlk_vmk_free(struct bitlk_vmk *vmk);
|
||||
void BITLK_bitlk_metadata_free(struct bitlk_metadata *params);
|
||||
|
||||
#endif
|
||||
@@ -1,9 +1,9 @@
|
||||
/*
|
||||
* cryptsetup plain device helper functions
|
||||
*
|
||||
* Copyright (C) 2004, Jana Saout <jana@saout.de>
|
||||
* Copyright (C) 2010-2012 Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2010-2012, Milan Broz
|
||||
* Copyright (C) 2004 Jana Saout <jana@saout.de>
|
||||
* Copyright (C) 2010-2021 Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2010-2021 Milan Broz
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@@ -64,7 +64,7 @@ static int hash(const char *hash_name, size_t key_size, char *key,
|
||||
|
||||
#define PLAIN_HASH_LEN_MAX 256
|
||||
|
||||
int crypt_plain_hash(struct crypt_device *ctx __attribute__((unused)),
|
||||
int crypt_plain_hash(struct crypt_device *cd,
|
||||
const char *hash_name,
|
||||
char *key, size_t key_size,
|
||||
const char *passphrase, size_t passphrase_size)
|
||||
@@ -73,7 +73,7 @@ int crypt_plain_hash(struct crypt_device *ctx __attribute__((unused)),
|
||||
size_t hash_size, pad_size;
|
||||
int r;
|
||||
|
||||
log_dbg("Plain: hashing passphrase using %s.", hash_name);
|
||||
log_dbg(cd, "Plain: hashing passphrase using %s.", hash_name);
|
||||
|
||||
if (strlen(hash_name) >= PLAIN_HASH_LEN_MAX)
|
||||
return -EINVAL;
|
||||
@@ -85,11 +85,11 @@ int crypt_plain_hash(struct crypt_device *ctx __attribute__((unused)),
|
||||
*s = '\0';
|
||||
s++;
|
||||
if (!*s || sscanf(s, "%zd", &hash_size) != 1) {
|
||||
log_dbg("Hash length is not a number");
|
||||
log_dbg(cd, "Hash length is not a number");
|
||||
return -EINVAL;
|
||||
}
|
||||
if (hash_size > key_size) {
|
||||
log_dbg("Hash length %zd > key length %zd",
|
||||
log_dbg(cd, "Hash length %zd > key length %zd",
|
||||
hash_size, key_size);
|
||||
return -EINVAL;
|
||||
}
|
||||
@@ -102,7 +102,7 @@ int crypt_plain_hash(struct crypt_device *ctx __attribute__((unused)),
|
||||
/* No hash, copy passphrase directly */
|
||||
if (!strcmp(hash_name_buf, "plain")) {
|
||||
if (passphrase_size < hash_size) {
|
||||
log_dbg("Too short plain passphrase.");
|
||||
log_dbg(cd, "Too short plain passphrase.");
|
||||
return -EINVAL;
|
||||
}
|
||||
memcpy(key, passphrase, hash_size);
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
moduledir = $(libdir)/cryptsetup
|
||||
|
||||
noinst_LTLIBRARIES = libcrypto_backend.la
|
||||
|
||||
libcrypto_backend_la_CFLAGS = $(AM_CFLAGS) -Wall @CRYPTO_CFLAGS@
|
||||
|
||||
libcrypto_backend_la_SOURCES = crypto_backend.h \
|
||||
crypto_cipher_kernel.c crypto_storage.c pbkdf_check.c crc32.c
|
||||
|
||||
if CRYPTO_BACKEND_GCRYPT
|
||||
libcrypto_backend_la_SOURCES += crypto_gcrypt.c
|
||||
endif
|
||||
if CRYPTO_BACKEND_OPENSSL
|
||||
libcrypto_backend_la_SOURCES += crypto_openssl.c
|
||||
endif
|
||||
if CRYPTO_BACKEND_NSS
|
||||
libcrypto_backend_la_SOURCES += crypto_nss.c
|
||||
endif
|
||||
if CRYPTO_BACKEND_KERNEL
|
||||
libcrypto_backend_la_SOURCES += crypto_kernel.c
|
||||
endif
|
||||
if CRYPTO_BACKEND_NETTLE
|
||||
libcrypto_backend_la_SOURCES += crypto_nettle.c
|
||||
endif
|
||||
|
||||
if CRYPTO_INTERNAL_PBKDF2
|
||||
libcrypto_backend_la_SOURCES += pbkdf2_generic.c
|
||||
endif
|
||||
|
||||
AM_CPPFLAGS = -include config.h -I$(top_srcdir)/lib
|
||||
39
lib/crypto_backend/Makemodule.am
Normal file
39
lib/crypto_backend/Makemodule.am
Normal file
@@ -0,0 +1,39 @@
|
||||
noinst_LTLIBRARIES += libcrypto_backend.la
|
||||
|
||||
libcrypto_backend_la_CFLAGS = $(AM_CFLAGS) @CRYPTO_CFLAGS@
|
||||
|
||||
libcrypto_backend_la_SOURCES = \
|
||||
lib/crypto_backend/crypto_backend.h \
|
||||
lib/crypto_backend/crypto_backend_internal.h \
|
||||
lib/crypto_backend/crypto_cipher_kernel.c \
|
||||
lib/crypto_backend/crypto_storage.c \
|
||||
lib/crypto_backend/pbkdf_check.c \
|
||||
lib/crypto_backend/crc32.c \
|
||||
lib/crypto_backend/argon2_generic.c \
|
||||
lib/crypto_backend/cipher_generic.c \
|
||||
lib/crypto_backend/cipher_check.c
|
||||
|
||||
if CRYPTO_BACKEND_GCRYPT
|
||||
libcrypto_backend_la_SOURCES += lib/crypto_backend/crypto_gcrypt.c
|
||||
endif
|
||||
if CRYPTO_BACKEND_OPENSSL
|
||||
libcrypto_backend_la_SOURCES += lib/crypto_backend/crypto_openssl.c
|
||||
endif
|
||||
if CRYPTO_BACKEND_NSS
|
||||
libcrypto_backend_la_SOURCES += lib/crypto_backend/crypto_nss.c
|
||||
endif
|
||||
if CRYPTO_BACKEND_KERNEL
|
||||
libcrypto_backend_la_SOURCES += lib/crypto_backend/crypto_kernel.c
|
||||
endif
|
||||
if CRYPTO_BACKEND_NETTLE
|
||||
libcrypto_backend_la_SOURCES += lib/crypto_backend/crypto_nettle.c
|
||||
endif
|
||||
|
||||
if CRYPTO_INTERNAL_PBKDF2
|
||||
libcrypto_backend_la_SOURCES += lib/crypto_backend/pbkdf2_generic.c
|
||||
endif
|
||||
|
||||
if CRYPTO_INTERNAL_ARGON2
|
||||
libcrypto_backend_la_DEPENDENCIES = libargon2.la
|
||||
libcrypto_backend_la_LIBADD = libargon2.la
|
||||
endif
|
||||
30
lib/crypto_backend/argon2/LICENSE
Normal file
30
lib/crypto_backend/argon2/LICENSE
Normal file
@@ -0,0 +1,30 @@
|
||||
CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED HEREUNDER.
|
||||
|
||||
Statement of Purpose
|
||||
|
||||
The laws of most jurisdictions throughout the world automatically confer exclusive Copyright and Related Rights (defined below) upon the creator and subsequent owner(s) (each and all, an "owner") of an original work of authorship and/or a database (each, a "Work").
|
||||
|
||||
Certain owners wish to permanently relinquish those rights to a Work for the purpose of contributing to a commons of creative, cultural and scientific works ("Commons") that the public can reliably and without fear of later claims of infringement build upon, modify, incorporate in other works, reuse and redistribute as freely as possible in any form whatsoever and for any purposes, including without limitation commercial purposes. These owners may contribute to the Commons to promote the ideal of a free culture and the further production of creative, cultural and scientific works, or to gain reputation or greater distribution for their Work in part through the use and efforts of others.
|
||||
|
||||
For these and/or other purposes and motivations, and without any expectation of additional consideration or compensation, the person associating CC0 with a Work (the "Affirmer"), to the extent that he or she is an owner of Copyright and Related Rights in the Work, voluntarily elects to apply CC0 to the Work and publicly distribute the Work under its terms, with knowledge of his or her Copyright and Related Rights in the Work and the meaning and intended legal effect of CC0 on those rights.
|
||||
|
||||
1. Copyright and Related Rights. A Work made available under CC0 may be protected by copyright and related or neighboring rights ("Copyright and Related Rights"). Copyright and Related Rights include, but are not limited to, the following:
|
||||
|
||||
the right to reproduce, adapt, distribute, perform, display, communicate, and translate a Work;
|
||||
moral rights retained by the original author(s) and/or performer(s);
|
||||
publicity and privacy rights pertaining to a person's image or likeness depicted in a Work;
|
||||
rights protecting against unfair competition in regards to a Work, subject to the limitations in paragraph 4(a), below;
|
||||
rights protecting the extraction, dissemination, use and reuse of data in a Work;
|
||||
database rights (such as those arising under Directive 96/9/EC of the European Parliament and of the Council of 11 March 1996 on the legal protection of databases, and under any national implementation thereof, including any amended or successor version of such directive); and
|
||||
other similar, equivalent or corresponding rights throughout the world based on applicable law or treaty, and any national implementations thereof.
|
||||
|
||||
2. Waiver. To the greatest extent permitted by, but not in contravention of, applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and unconditionally waives, abandons, and surrenders all of Affirmer's Copyright and Related Rights and associated claims and causes of action, whether now known or unknown (including existing as well as future claims and causes of action), in the Work (i) in all territories worldwide, (ii) for the maximum duration provided by applicable law or treaty (including future time extensions), (iii) in any current or future medium and for any number of copies, and (iv) for any purpose whatsoever, including without limitation commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each member of the public at large and to the detriment of Affirmer's heirs and successors, fully intending that such Waiver shall not be subject to revocation, rescission, cancellation, termination, or any other legal or equitable action to disrupt the quiet enjoyment of the Work by the public as contemplated by Affirmer's express Statement of Purpose.
|
||||
|
||||
3. Public License Fallback. Should any part of the Waiver for any reason be judged legally invalid or ineffective under applicable law, then the Waiver shall be preserved to the maximum extent permitted taking into account Affirmer's express Statement of Purpose. In addition, to the extent the Waiver is so judged Affirmer hereby grants to each affected person a royalty-free, non transferable, non sublicensable, non exclusive, irrevocable and unconditional license to exercise Affirmer's Copyright and Related Rights in the Work (i) in all territories worldwide, (ii) for the maximum duration provided by applicable law or treaty (including future time extensions), (iii) in any current or future medium and for any number of copies, and (iv) for any purpose whatsoever, including without limitation commercial, advertising or promotional purposes (the "License"). The License shall be deemed effective as of the date CC0 was applied by Affirmer to the Work. Should any part of the License for any reason be judged legally invalid or ineffective under applicable law, such partial invalidity or ineffectiveness shall not invalidate the remainder of the License, and in such case Affirmer hereby affirms that he or she will not (i) exercise any of his or her remaining Copyright and Related Rights in the Work or (ii) assert any associated claims and causes of action with respect to the Work, in either case contrary to Affirmer's express Statement of Purpose.
|
||||
|
||||
4. Limitations and Disclaimers.
|
||||
|
||||
No trademark or patent rights held by Affirmer are waived, abandoned, surrendered, licensed or otherwise affected by this document.
|
||||
Affirmer offers the Work as-is and makes no representations or warranties of any kind concerning the Work, express, implied, statutory or otherwise, including without limitation warranties of title, merchantability, fitness for a particular purpose, non infringement, or the absence of latent or other defects, accuracy, or the present or absence of errors, whether or not discoverable, all to the greatest extent permissible under applicable law.
|
||||
Affirmer disclaims responsibility for clearing rights of other persons that may apply to the Work or any use thereof, including without limitation any person's Copyright and Related Rights in the Work. Further, Affirmer disclaims responsibility for obtaining any necessary consents, permissions or other rights required for any use of the Work.
|
||||
Affirmer understands and acknowledges that Creative Commons is not a party to this document and has no duty or obligation with respect to this CC0 or use of the Work.
|
||||
30
lib/crypto_backend/argon2/Makemodule.am
Normal file
30
lib/crypto_backend/argon2/Makemodule.am
Normal file
@@ -0,0 +1,30 @@
|
||||
noinst_LTLIBRARIES += libargon2.la
|
||||
|
||||
libargon2_la_CFLAGS = $(AM_CFLAGS) -std=c89 -pthread -O3
|
||||
libargon2_la_CPPFLAGS = $(AM_CPPFLAGS) \
|
||||
-I lib/crypto_backend/argon2 \
|
||||
-I lib/crypto_backend/argon2/blake2
|
||||
|
||||
libargon2_la_SOURCES = \
|
||||
lib/crypto_backend/argon2/blake2/blake2b.c \
|
||||
lib/crypto_backend/argon2/blake2/blake2.h \
|
||||
lib/crypto_backend/argon2/blake2/blake2-impl.h \
|
||||
lib/crypto_backend/argon2/argon2.c \
|
||||
lib/crypto_backend/argon2/argon2.h \
|
||||
lib/crypto_backend/argon2/core.c \
|
||||
lib/crypto_backend/argon2/core.h \
|
||||
lib/crypto_backend/argon2/encoding.c \
|
||||
lib/crypto_backend/argon2/encoding.h \
|
||||
lib/crypto_backend/argon2/thread.c \
|
||||
lib/crypto_backend/argon2/thread.h
|
||||
|
||||
if CRYPTO_INTERNAL_SSE_ARGON2
|
||||
libargon2_la_SOURCES += lib/crypto_backend/argon2/blake2/blamka-round-opt.h \
|
||||
lib/crypto_backend/argon2/opt.c
|
||||
else
|
||||
libargon2_la_SOURCES += lib/crypto_backend/argon2/blake2/blamka-round-ref.h \
|
||||
lib/crypto_backend/argon2/ref.c
|
||||
endif
|
||||
|
||||
EXTRA_DIST += lib/crypto_backend/argon2/LICENSE
|
||||
EXTRA_DIST += lib/crypto_backend/argon2/README
|
||||
5
lib/crypto_backend/argon2/README
Normal file
5
lib/crypto_backend/argon2/README
Normal file
@@ -0,0 +1,5 @@
|
||||
This is bundled Argon2 algorithm library, copied from
|
||||
https://github.com/P-H-C/phc-winner-argon2
|
||||
|
||||
For more info see Password Hashing Competition site:
|
||||
https://password-hashing.net/
|
||||
458
lib/crypto_backend/argon2/argon2.c
Normal file
458
lib/crypto_backend/argon2/argon2.c
Normal file
@@ -0,0 +1,458 @@
|
||||
/*
|
||||
* Argon2 reference source code package - reference C implementations
|
||||
*
|
||||
* Copyright 2015
|
||||
* Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves
|
||||
*
|
||||
* You may use this work under the terms of a Creative Commons CC0 1.0
|
||||
* License/Waiver or the Apache Public License 2.0, at your option. The terms of
|
||||
* these licenses can be found at:
|
||||
*
|
||||
* - CC0 1.0 Universal : https://creativecommons.org/publicdomain/zero/1.0
|
||||
* - Apache 2.0 : https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* You should have received a copy of both of these licenses along with this
|
||||
* software. If not, they may be obtained at the above URLs.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "argon2.h"
|
||||
#include "encoding.h"
|
||||
#include "core.h"
|
||||
|
||||
/* to silent gcc -Wcast-qual for const cast */
|
||||
#define CONST_CAST(x) (x)(uintptr_t)
|
||||
|
||||
const char *argon2_type2string(argon2_type type, int uppercase) {
|
||||
switch (type) {
|
||||
case Argon2_d:
|
||||
return uppercase ? "Argon2d" : "argon2d";
|
||||
case Argon2_i:
|
||||
return uppercase ? "Argon2i" : "argon2i";
|
||||
case Argon2_id:
|
||||
return uppercase ? "Argon2id" : "argon2id";
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int argon2_ctx(argon2_context *context, argon2_type type) {
|
||||
/* 1. Validate all inputs */
|
||||
int result = validate_inputs(context);
|
||||
uint32_t memory_blocks, segment_length;
|
||||
argon2_instance_t instance;
|
||||
|
||||
if (ARGON2_OK != result) {
|
||||
return result;
|
||||
}
|
||||
|
||||
if (Argon2_d != type && Argon2_i != type && Argon2_id != type) {
|
||||
return ARGON2_INCORRECT_TYPE;
|
||||
}
|
||||
|
||||
/* 2. Align memory size */
|
||||
/* Minimum memory_blocks = 8L blocks, where L is the number of lanes */
|
||||
memory_blocks = context->m_cost;
|
||||
|
||||
if (memory_blocks < 2 * ARGON2_SYNC_POINTS * context->lanes) {
|
||||
memory_blocks = 2 * ARGON2_SYNC_POINTS * context->lanes;
|
||||
}
|
||||
|
||||
segment_length = memory_blocks / (context->lanes * ARGON2_SYNC_POINTS);
|
||||
/* Ensure that all segments have equal length */
|
||||
memory_blocks = segment_length * (context->lanes * ARGON2_SYNC_POINTS);
|
||||
|
||||
instance.version = context->version;
|
||||
instance.memory = NULL;
|
||||
instance.passes = context->t_cost;
|
||||
instance.memory_blocks = memory_blocks;
|
||||
instance.segment_length = segment_length;
|
||||
instance.lane_length = segment_length * ARGON2_SYNC_POINTS;
|
||||
instance.lanes = context->lanes;
|
||||
instance.threads = context->threads;
|
||||
instance.type = type;
|
||||
|
||||
if (instance.threads > instance.lanes) {
|
||||
instance.threads = instance.lanes;
|
||||
}
|
||||
|
||||
/* 3. Initialization: Hashing inputs, allocating memory, filling first
|
||||
* blocks
|
||||
*/
|
||||
result = initialize(&instance, context);
|
||||
|
||||
if (ARGON2_OK != result) {
|
||||
return result;
|
||||
}
|
||||
|
||||
/* 4. Filling memory */
|
||||
result = fill_memory_blocks(&instance);
|
||||
|
||||
if (ARGON2_OK != result) {
|
||||
return result;
|
||||
}
|
||||
/* 5. Finalization */
|
||||
finalize(context, &instance);
|
||||
|
||||
return ARGON2_OK;
|
||||
}
|
||||
|
||||
int argon2_hash(const uint32_t t_cost, const uint32_t m_cost,
|
||||
const uint32_t parallelism, const void *pwd,
|
||||
const size_t pwdlen, const void *salt, const size_t saltlen,
|
||||
void *hash, const size_t hashlen, char *encoded,
|
||||
const size_t encodedlen, argon2_type type,
|
||||
const uint32_t version){
|
||||
|
||||
argon2_context context;
|
||||
int result;
|
||||
uint8_t *out;
|
||||
|
||||
if (pwdlen > ARGON2_MAX_PWD_LENGTH) {
|
||||
return ARGON2_PWD_TOO_LONG;
|
||||
}
|
||||
|
||||
if (saltlen > ARGON2_MAX_SALT_LENGTH) {
|
||||
return ARGON2_SALT_TOO_LONG;
|
||||
}
|
||||
|
||||
if (hashlen > ARGON2_MAX_OUTLEN) {
|
||||
return ARGON2_OUTPUT_TOO_LONG;
|
||||
}
|
||||
|
||||
if (hashlen < ARGON2_MIN_OUTLEN) {
|
||||
return ARGON2_OUTPUT_TOO_SHORT;
|
||||
}
|
||||
|
||||
out = malloc(hashlen);
|
||||
if (!out) {
|
||||
return ARGON2_MEMORY_ALLOCATION_ERROR;
|
||||
}
|
||||
|
||||
context.out = (uint8_t *)out;
|
||||
context.outlen = (uint32_t)hashlen;
|
||||
context.pwd = CONST_CAST(uint8_t *)pwd;
|
||||
context.pwdlen = (uint32_t)pwdlen;
|
||||
context.salt = CONST_CAST(uint8_t *)salt;
|
||||
context.saltlen = (uint32_t)saltlen;
|
||||
context.secret = NULL;
|
||||
context.secretlen = 0;
|
||||
context.ad = NULL;
|
||||
context.adlen = 0;
|
||||
context.t_cost = t_cost;
|
||||
context.m_cost = m_cost;
|
||||
context.lanes = parallelism;
|
||||
context.threads = parallelism;
|
||||
context.allocate_cbk = NULL;
|
||||
context.free_cbk = NULL;
|
||||
context.flags = ARGON2_DEFAULT_FLAGS;
|
||||
context.version = version;
|
||||
|
||||
result = argon2_ctx(&context, type);
|
||||
|
||||
if (result != ARGON2_OK) {
|
||||
clear_internal_memory(out, hashlen);
|
||||
free(out);
|
||||
return result;
|
||||
}
|
||||
|
||||
/* if raw hash requested, write it */
|
||||
if (hash) {
|
||||
memcpy(hash, out, hashlen);
|
||||
}
|
||||
|
||||
/* if encoding requested, write it */
|
||||
if (encoded && encodedlen) {
|
||||
if (encode_string(encoded, encodedlen, &context, type) != ARGON2_OK) {
|
||||
clear_internal_memory(out, hashlen); /* wipe buffers if error */
|
||||
clear_internal_memory(encoded, encodedlen);
|
||||
free(out);
|
||||
return ARGON2_ENCODING_FAIL;
|
||||
}
|
||||
}
|
||||
clear_internal_memory(out, hashlen);
|
||||
free(out);
|
||||
|
||||
return ARGON2_OK;
|
||||
}
|
||||
|
||||
int argon2i_hash_encoded(const uint32_t t_cost, const uint32_t m_cost,
|
||||
const uint32_t parallelism, const void *pwd,
|
||||
const size_t pwdlen, const void *salt,
|
||||
const size_t saltlen, const size_t hashlen,
|
||||
char *encoded, const size_t encodedlen) {
|
||||
|
||||
return argon2_hash(t_cost, m_cost, parallelism, pwd, pwdlen, salt, saltlen,
|
||||
NULL, hashlen, encoded, encodedlen, Argon2_i,
|
||||
ARGON2_VERSION_NUMBER);
|
||||
}
|
||||
|
||||
int argon2i_hash_raw(const uint32_t t_cost, const uint32_t m_cost,
|
||||
const uint32_t parallelism, const void *pwd,
|
||||
const size_t pwdlen, const void *salt,
|
||||
const size_t saltlen, void *hash, const size_t hashlen) {
|
||||
|
||||
return argon2_hash(t_cost, m_cost, parallelism, pwd, pwdlen, salt, saltlen,
|
||||
hash, hashlen, NULL, 0, Argon2_i, ARGON2_VERSION_NUMBER);
|
||||
}
|
||||
|
||||
int argon2d_hash_encoded(const uint32_t t_cost, const uint32_t m_cost,
|
||||
const uint32_t parallelism, const void *pwd,
|
||||
const size_t pwdlen, const void *salt,
|
||||
const size_t saltlen, const size_t hashlen,
|
||||
char *encoded, const size_t encodedlen) {
|
||||
|
||||
return argon2_hash(t_cost, m_cost, parallelism, pwd, pwdlen, salt, saltlen,
|
||||
NULL, hashlen, encoded, encodedlen, Argon2_d,
|
||||
ARGON2_VERSION_NUMBER);
|
||||
}
|
||||
|
||||
int argon2d_hash_raw(const uint32_t t_cost, const uint32_t m_cost,
|
||||
const uint32_t parallelism, const void *pwd,
|
||||
const size_t pwdlen, const void *salt,
|
||||
const size_t saltlen, void *hash, const size_t hashlen) {
|
||||
|
||||
return argon2_hash(t_cost, m_cost, parallelism, pwd, pwdlen, salt, saltlen,
|
||||
hash, hashlen, NULL, 0, Argon2_d, ARGON2_VERSION_NUMBER);
|
||||
}
|
||||
|
||||
int argon2id_hash_encoded(const uint32_t t_cost, const uint32_t m_cost,
|
||||
const uint32_t parallelism, const void *pwd,
|
||||
const size_t pwdlen, const void *salt,
|
||||
const size_t saltlen, const size_t hashlen,
|
||||
char *encoded, const size_t encodedlen) {
|
||||
|
||||
return argon2_hash(t_cost, m_cost, parallelism, pwd, pwdlen, salt, saltlen,
|
||||
NULL, hashlen, encoded, encodedlen, Argon2_id,
|
||||
ARGON2_VERSION_NUMBER);
|
||||
}
|
||||
|
||||
int argon2id_hash_raw(const uint32_t t_cost, const uint32_t m_cost,
|
||||
const uint32_t parallelism, const void *pwd,
|
||||
const size_t pwdlen, const void *salt,
|
||||
const size_t saltlen, void *hash, const size_t hashlen) {
|
||||
return argon2_hash(t_cost, m_cost, parallelism, pwd, pwdlen, salt, saltlen,
|
||||
hash, hashlen, NULL, 0, Argon2_id,
|
||||
ARGON2_VERSION_NUMBER);
|
||||
}
|
||||
|
||||
static int argon2_compare(const uint8_t *b1, const uint8_t *b2, size_t len) {
|
||||
size_t i;
|
||||
uint8_t d = 0U;
|
||||
|
||||
for (i = 0U; i < len; i++) {
|
||||
d |= b1[i] ^ b2[i];
|
||||
}
|
||||
return (int)((1 & ((d - 1) >> 8)) - 1);
|
||||
}
|
||||
|
||||
int argon2_verify(const char *encoded, const void *pwd, const size_t pwdlen,
|
||||
argon2_type type) {
|
||||
|
||||
argon2_context ctx;
|
||||
uint8_t *desired_result = NULL;
|
||||
|
||||
int ret = ARGON2_OK;
|
||||
|
||||
size_t encoded_len;
|
||||
uint32_t max_field_len;
|
||||
|
||||
if (pwdlen > ARGON2_MAX_PWD_LENGTH) {
|
||||
return ARGON2_PWD_TOO_LONG;
|
||||
}
|
||||
|
||||
if (encoded == NULL) {
|
||||
return ARGON2_DECODING_FAIL;
|
||||
}
|
||||
|
||||
encoded_len = strlen(encoded);
|
||||
if (encoded_len > UINT32_MAX) {
|
||||
return ARGON2_DECODING_FAIL;
|
||||
}
|
||||
|
||||
/* No field can be longer than the encoded length */
|
||||
/* coverity[strlen_assign] */
|
||||
max_field_len = (uint32_t)encoded_len;
|
||||
|
||||
ctx.saltlen = max_field_len;
|
||||
ctx.outlen = max_field_len;
|
||||
|
||||
ctx.salt = malloc(ctx.saltlen);
|
||||
ctx.out = malloc(ctx.outlen);
|
||||
if (!ctx.salt || !ctx.out) {
|
||||
ret = ARGON2_MEMORY_ALLOCATION_ERROR;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ctx.pwd = CONST_CAST(uint8_t *)pwd;
|
||||
ctx.pwdlen = (uint32_t)pwdlen;
|
||||
|
||||
ret = decode_string(&ctx, encoded, type);
|
||||
if (ret != ARGON2_OK) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Set aside the desired result, and get a new buffer. */
|
||||
desired_result = ctx.out;
|
||||
ctx.out = malloc(ctx.outlen);
|
||||
if (!ctx.out) {
|
||||
ret = ARGON2_MEMORY_ALLOCATION_ERROR;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ret = argon2_verify_ctx(&ctx, (char *)desired_result, type);
|
||||
if (ret != ARGON2_OK) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
fail:
|
||||
free(ctx.salt);
|
||||
free(ctx.out);
|
||||
free(desired_result);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int argon2i_verify(const char *encoded, const void *pwd, const size_t pwdlen) {
|
||||
|
||||
return argon2_verify(encoded, pwd, pwdlen, Argon2_i);
|
||||
}
|
||||
|
||||
int argon2d_verify(const char *encoded, const void *pwd, const size_t pwdlen) {
|
||||
|
||||
return argon2_verify(encoded, pwd, pwdlen, Argon2_d);
|
||||
}
|
||||
|
||||
int argon2id_verify(const char *encoded, const void *pwd, const size_t pwdlen) {
|
||||
|
||||
return argon2_verify(encoded, pwd, pwdlen, Argon2_id);
|
||||
}
|
||||
|
||||
int argon2d_ctx(argon2_context *context) {
|
||||
return argon2_ctx(context, Argon2_d);
|
||||
}
|
||||
|
||||
int argon2i_ctx(argon2_context *context) {
|
||||
return argon2_ctx(context, Argon2_i);
|
||||
}
|
||||
|
||||
int argon2id_ctx(argon2_context *context) {
|
||||
return argon2_ctx(context, Argon2_id);
|
||||
}
|
||||
|
||||
int argon2_verify_ctx(argon2_context *context, const char *hash,
|
||||
argon2_type type) {
|
||||
int ret = argon2_ctx(context, type);
|
||||
if (ret != ARGON2_OK) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (argon2_compare(CONST_CAST(uint8_t *)hash, context->out, context->outlen)) {
|
||||
return ARGON2_VERIFY_MISMATCH;
|
||||
}
|
||||
|
||||
return ARGON2_OK;
|
||||
}
|
||||
|
||||
int argon2d_verify_ctx(argon2_context *context, const char *hash) {
|
||||
return argon2_verify_ctx(context, hash, Argon2_d);
|
||||
}
|
||||
|
||||
int argon2i_verify_ctx(argon2_context *context, const char *hash) {
|
||||
return argon2_verify_ctx(context, hash, Argon2_i);
|
||||
}
|
||||
|
||||
int argon2id_verify_ctx(argon2_context *context, const char *hash) {
|
||||
return argon2_verify_ctx(context, hash, Argon2_id);
|
||||
}
|
||||
|
||||
const char *argon2_error_message(int error_code) {
|
||||
switch (error_code) {
|
||||
case ARGON2_OK:
|
||||
return "OK";
|
||||
case ARGON2_OUTPUT_PTR_NULL:
|
||||
return "Output pointer is NULL";
|
||||
case ARGON2_OUTPUT_TOO_SHORT:
|
||||
return "Output is too short";
|
||||
case ARGON2_OUTPUT_TOO_LONG:
|
||||
return "Output is too long";
|
||||
case ARGON2_PWD_TOO_SHORT:
|
||||
return "Password is too short";
|
||||
case ARGON2_PWD_TOO_LONG:
|
||||
return "Password is too long";
|
||||
case ARGON2_SALT_TOO_SHORT:
|
||||
return "Salt is too short";
|
||||
case ARGON2_SALT_TOO_LONG:
|
||||
return "Salt is too long";
|
||||
case ARGON2_AD_TOO_SHORT:
|
||||
return "Associated data is too short";
|
||||
case ARGON2_AD_TOO_LONG:
|
||||
return "Associated data is too long";
|
||||
case ARGON2_SECRET_TOO_SHORT:
|
||||
return "Secret is too short";
|
||||
case ARGON2_SECRET_TOO_LONG:
|
||||
return "Secret is too long";
|
||||
case ARGON2_TIME_TOO_SMALL:
|
||||
return "Time cost is too small";
|
||||
case ARGON2_TIME_TOO_LARGE:
|
||||
return "Time cost is too large";
|
||||
case ARGON2_MEMORY_TOO_LITTLE:
|
||||
return "Memory cost is too small";
|
||||
case ARGON2_MEMORY_TOO_MUCH:
|
||||
return "Memory cost is too large";
|
||||
case ARGON2_LANES_TOO_FEW:
|
||||
return "Too few lanes";
|
||||
case ARGON2_LANES_TOO_MANY:
|
||||
return "Too many lanes";
|
||||
case ARGON2_PWD_PTR_MISMATCH:
|
||||
return "Password pointer is NULL, but password length is not 0";
|
||||
case ARGON2_SALT_PTR_MISMATCH:
|
||||
return "Salt pointer is NULL, but salt length is not 0";
|
||||
case ARGON2_SECRET_PTR_MISMATCH:
|
||||
return "Secret pointer is NULL, but secret length is not 0";
|
||||
case ARGON2_AD_PTR_MISMATCH:
|
||||
return "Associated data pointer is NULL, but ad length is not 0";
|
||||
case ARGON2_MEMORY_ALLOCATION_ERROR:
|
||||
return "Memory allocation error";
|
||||
case ARGON2_FREE_MEMORY_CBK_NULL:
|
||||
return "The free memory callback is NULL";
|
||||
case ARGON2_ALLOCATE_MEMORY_CBK_NULL:
|
||||
return "The allocate memory callback is NULL";
|
||||
case ARGON2_INCORRECT_PARAMETER:
|
||||
return "Argon2_Context context is NULL";
|
||||
case ARGON2_INCORRECT_TYPE:
|
||||
return "There is no such version of Argon2";
|
||||
case ARGON2_OUT_PTR_MISMATCH:
|
||||
return "Output pointer mismatch";
|
||||
case ARGON2_THREADS_TOO_FEW:
|
||||
return "Not enough threads";
|
||||
case ARGON2_THREADS_TOO_MANY:
|
||||
return "Too many threads";
|
||||
case ARGON2_MISSING_ARGS:
|
||||
return "Missing arguments";
|
||||
case ARGON2_ENCODING_FAIL:
|
||||
return "Encoding failed";
|
||||
case ARGON2_DECODING_FAIL:
|
||||
return "Decoding failed";
|
||||
case ARGON2_THREAD_FAIL:
|
||||
return "Threading failure";
|
||||
case ARGON2_DECODING_LENGTH_FAIL:
|
||||
return "Some of encoded parameters are too long or too short";
|
||||
case ARGON2_VERIFY_MISMATCH:
|
||||
return "The password does not match the supplied hash";
|
||||
default:
|
||||
return "Unknown error code";
|
||||
}
|
||||
}
|
||||
|
||||
size_t argon2_encodedlen(uint32_t t_cost, uint32_t m_cost, uint32_t parallelism,
|
||||
uint32_t saltlen, uint32_t hashlen, argon2_type type) {
|
||||
if (!argon2_type2string(type, 0))
|
||||
return 0;
|
||||
return strlen("$$v=$m=,t=,p=$$") + strlen(argon2_type2string(type, 0)) +
|
||||
numlen(t_cost) + numlen(m_cost) + numlen(parallelism) +
|
||||
b64len(saltlen) + b64len(hashlen) + numlen(ARGON2_VERSION_NUMBER) + 1;
|
||||
}
|
||||
437
lib/crypto_backend/argon2/argon2.h
Normal file
437
lib/crypto_backend/argon2/argon2.h
Normal file
@@ -0,0 +1,437 @@
|
||||
/*
|
||||
* Argon2 reference source code package - reference C implementations
|
||||
*
|
||||
* Copyright 2015
|
||||
* Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves
|
||||
*
|
||||
* You may use this work under the terms of a Creative Commons CC0 1.0
|
||||
* License/Waiver or the Apache Public License 2.0, at your option. The terms of
|
||||
* these licenses can be found at:
|
||||
*
|
||||
* - CC0 1.0 Universal : https://creativecommons.org/publicdomain/zero/1.0
|
||||
* - Apache 2.0 : https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* You should have received a copy of both of these licenses along with this
|
||||
* software. If not, they may be obtained at the above URLs.
|
||||
*/
|
||||
|
||||
#ifndef ARGON2_H
|
||||
#define ARGON2_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <limits.h>
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Symbols visibility control */
|
||||
#ifdef A2_VISCTL
|
||||
#define ARGON2_PUBLIC __attribute__((visibility("default")))
|
||||
#define ARGON2_LOCAL __attribute__ ((visibility ("hidden")))
|
||||
#elif _MSC_VER
|
||||
#define ARGON2_PUBLIC __declspec(dllexport)
|
||||
#define ARGON2_LOCAL
|
||||
#else
|
||||
#define ARGON2_PUBLIC
|
||||
#define ARGON2_LOCAL
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Argon2 input parameter restrictions
|
||||
*/
|
||||
|
||||
/* Minimum and maximum number of lanes (degree of parallelism) */
|
||||
#define ARGON2_MIN_LANES UINT32_C(1)
|
||||
#define ARGON2_MAX_LANES UINT32_C(0xFFFFFF)
|
||||
|
||||
/* Minimum and maximum number of threads */
|
||||
#define ARGON2_MIN_THREADS UINT32_C(1)
|
||||
#define ARGON2_MAX_THREADS UINT32_C(0xFFFFFF)
|
||||
|
||||
/* Number of synchronization points between lanes per pass */
|
||||
#define ARGON2_SYNC_POINTS UINT32_C(4)
|
||||
|
||||
/* Minimum and maximum digest size in bytes */
|
||||
#define ARGON2_MIN_OUTLEN UINT32_C(4)
|
||||
#define ARGON2_MAX_OUTLEN UINT32_C(0xFFFFFFFF)
|
||||
|
||||
/* Minimum and maximum number of memory blocks (each of BLOCK_SIZE bytes) */
|
||||
#define ARGON2_MIN_MEMORY (2 * ARGON2_SYNC_POINTS) /* 2 blocks per slice */
|
||||
|
||||
#define ARGON2_MIN(a, b) ((a) < (b) ? (a) : (b))
|
||||
/* Max memory size is addressing-space/2, topping at 2^32 blocks (4 TB) */
|
||||
#define ARGON2_MAX_MEMORY_BITS \
|
||||
ARGON2_MIN(UINT32_C(32), (sizeof(void *) * CHAR_BIT - 10 - 1))
|
||||
#define ARGON2_MAX_MEMORY \
|
||||
ARGON2_MIN(UINT32_C(0xFFFFFFFF), UINT64_C(1) << ARGON2_MAX_MEMORY_BITS)
|
||||
|
||||
/* Minimum and maximum number of passes */
|
||||
#define ARGON2_MIN_TIME UINT32_C(1)
|
||||
#define ARGON2_MAX_TIME UINT32_C(0xFFFFFFFF)
|
||||
|
||||
/* Minimum and maximum password length in bytes */
|
||||
#define ARGON2_MIN_PWD_LENGTH UINT32_C(0)
|
||||
#define ARGON2_MAX_PWD_LENGTH UINT32_C(0xFFFFFFFF)
|
||||
|
||||
/* Minimum and maximum associated data length in bytes */
|
||||
#define ARGON2_MIN_AD_LENGTH UINT32_C(0)
|
||||
#define ARGON2_MAX_AD_LENGTH UINT32_C(0xFFFFFFFF)
|
||||
|
||||
/* Minimum and maximum salt length in bytes */
|
||||
#define ARGON2_MIN_SALT_LENGTH UINT32_C(8)
|
||||
#define ARGON2_MAX_SALT_LENGTH UINT32_C(0xFFFFFFFF)
|
||||
|
||||
/* Minimum and maximum key length in bytes */
|
||||
#define ARGON2_MIN_SECRET UINT32_C(0)
|
||||
#define ARGON2_MAX_SECRET UINT32_C(0xFFFFFFFF)
|
||||
|
||||
/* Flags to determine which fields are securely wiped (default = no wipe). */
|
||||
#define ARGON2_DEFAULT_FLAGS UINT32_C(0)
|
||||
#define ARGON2_FLAG_CLEAR_PASSWORD (UINT32_C(1) << 0)
|
||||
#define ARGON2_FLAG_CLEAR_SECRET (UINT32_C(1) << 1)
|
||||
|
||||
/* Global flag to determine if we are wiping internal memory buffers. This flag
|
||||
* is defined in core.c and defaults to 1 (wipe internal memory). */
|
||||
extern int FLAG_clear_internal_memory;
|
||||
|
||||
/* Error codes */
|
||||
typedef enum Argon2_ErrorCodes {
|
||||
ARGON2_OK = 0,
|
||||
|
||||
ARGON2_OUTPUT_PTR_NULL = -1,
|
||||
|
||||
ARGON2_OUTPUT_TOO_SHORT = -2,
|
||||
ARGON2_OUTPUT_TOO_LONG = -3,
|
||||
|
||||
ARGON2_PWD_TOO_SHORT = -4,
|
||||
ARGON2_PWD_TOO_LONG = -5,
|
||||
|
||||
ARGON2_SALT_TOO_SHORT = -6,
|
||||
ARGON2_SALT_TOO_LONG = -7,
|
||||
|
||||
ARGON2_AD_TOO_SHORT = -8,
|
||||
ARGON2_AD_TOO_LONG = -9,
|
||||
|
||||
ARGON2_SECRET_TOO_SHORT = -10,
|
||||
ARGON2_SECRET_TOO_LONG = -11,
|
||||
|
||||
ARGON2_TIME_TOO_SMALL = -12,
|
||||
ARGON2_TIME_TOO_LARGE = -13,
|
||||
|
||||
ARGON2_MEMORY_TOO_LITTLE = -14,
|
||||
ARGON2_MEMORY_TOO_MUCH = -15,
|
||||
|
||||
ARGON2_LANES_TOO_FEW = -16,
|
||||
ARGON2_LANES_TOO_MANY = -17,
|
||||
|
||||
ARGON2_PWD_PTR_MISMATCH = -18, /* NULL ptr with non-zero length */
|
||||
ARGON2_SALT_PTR_MISMATCH = -19, /* NULL ptr with non-zero length */
|
||||
ARGON2_SECRET_PTR_MISMATCH = -20, /* NULL ptr with non-zero length */
|
||||
ARGON2_AD_PTR_MISMATCH = -21, /* NULL ptr with non-zero length */
|
||||
|
||||
ARGON2_MEMORY_ALLOCATION_ERROR = -22,
|
||||
|
||||
ARGON2_FREE_MEMORY_CBK_NULL = -23,
|
||||
ARGON2_ALLOCATE_MEMORY_CBK_NULL = -24,
|
||||
|
||||
ARGON2_INCORRECT_PARAMETER = -25,
|
||||
ARGON2_INCORRECT_TYPE = -26,
|
||||
|
||||
ARGON2_OUT_PTR_MISMATCH = -27,
|
||||
|
||||
ARGON2_THREADS_TOO_FEW = -28,
|
||||
ARGON2_THREADS_TOO_MANY = -29,
|
||||
|
||||
ARGON2_MISSING_ARGS = -30,
|
||||
|
||||
ARGON2_ENCODING_FAIL = -31,
|
||||
|
||||
ARGON2_DECODING_FAIL = -32,
|
||||
|
||||
ARGON2_THREAD_FAIL = -33,
|
||||
|
||||
ARGON2_DECODING_LENGTH_FAIL = -34,
|
||||
|
||||
ARGON2_VERIFY_MISMATCH = -35
|
||||
} argon2_error_codes;
|
||||
|
||||
/* Memory allocator types --- for external allocation */
|
||||
typedef int (*allocate_fptr)(uint8_t **memory, size_t bytes_to_allocate);
|
||||
typedef void (*deallocate_fptr)(uint8_t *memory, size_t bytes_to_allocate);
|
||||
|
||||
/* Argon2 external data structures */
|
||||
|
||||
/*
|
||||
*****
|
||||
* Context: structure to hold Argon2 inputs:
|
||||
* output array and its length,
|
||||
* password and its length,
|
||||
* salt and its length,
|
||||
* secret and its length,
|
||||
* associated data and its length,
|
||||
* number of passes, amount of used memory (in KBytes, can be rounded up a bit)
|
||||
* number of parallel threads that will be run.
|
||||
* All the parameters above affect the output hash value.
|
||||
* Additionally, two function pointers can be provided to allocate and
|
||||
* deallocate the memory (if NULL, memory will be allocated internally).
|
||||
* Also, three flags indicate whether to erase password, secret as soon as they
|
||||
* are pre-hashed (and thus not needed anymore), and the entire memory
|
||||
*****
|
||||
* Simplest situation: you have output array out[8], password is stored in
|
||||
* pwd[32], salt is stored in salt[16], you do not have keys nor associated
|
||||
* data. You need to spend 1 GB of RAM and you run 5 passes of Argon2d with
|
||||
* 4 parallel lanes.
|
||||
* You want to erase the password, but you're OK with last pass not being
|
||||
* erased. You want to use the default memory allocator.
|
||||
* Then you initialize:
|
||||
Argon2_Context(out,8,pwd,32,salt,16,NULL,0,NULL,0,5,1<<20,4,4,NULL,NULL,true,false,false,false)
|
||||
*/
|
||||
typedef struct Argon2_Context {
|
||||
uint8_t *out; /* output array */
|
||||
uint32_t outlen; /* digest length */
|
||||
|
||||
uint8_t *pwd; /* password array */
|
||||
uint32_t pwdlen; /* password length */
|
||||
|
||||
uint8_t *salt; /* salt array */
|
||||
uint32_t saltlen; /* salt length */
|
||||
|
||||
uint8_t *secret; /* key array */
|
||||
uint32_t secretlen; /* key length */
|
||||
|
||||
uint8_t *ad; /* associated data array */
|
||||
uint32_t adlen; /* associated data length */
|
||||
|
||||
uint32_t t_cost; /* number of passes */
|
||||
uint32_t m_cost; /* amount of memory requested (KB) */
|
||||
uint32_t lanes; /* number of lanes */
|
||||
uint32_t threads; /* maximum number of threads */
|
||||
|
||||
uint32_t version; /* version number */
|
||||
|
||||
allocate_fptr allocate_cbk; /* pointer to memory allocator */
|
||||
deallocate_fptr free_cbk; /* pointer to memory deallocator */
|
||||
|
||||
uint32_t flags; /* array of bool options */
|
||||
} argon2_context;
|
||||
|
||||
/* Argon2 primitive type */
|
||||
typedef enum Argon2_type {
|
||||
Argon2_d = 0,
|
||||
Argon2_i = 1,
|
||||
Argon2_id = 2
|
||||
} argon2_type;
|
||||
|
||||
/* Version of the algorithm */
|
||||
typedef enum Argon2_version {
|
||||
ARGON2_VERSION_10 = 0x10,
|
||||
ARGON2_VERSION_13 = 0x13,
|
||||
ARGON2_VERSION_NUMBER = ARGON2_VERSION_13
|
||||
} argon2_version;
|
||||
|
||||
/*
|
||||
* Function that gives the string representation of an argon2_type.
|
||||
* @param type The argon2_type that we want the string for
|
||||
* @param uppercase Whether the string should have the first letter uppercase
|
||||
* @return NULL if invalid type, otherwise the string representation.
|
||||
*/
|
||||
ARGON2_PUBLIC const char *argon2_type2string(argon2_type type, int uppercase);
|
||||
|
||||
/*
|
||||
* Function that performs memory-hard hashing with certain degree of parallelism
|
||||
* @param context Pointer to the Argon2 internal structure
|
||||
* @return Error code if smth is wrong, ARGON2_OK otherwise
|
||||
*/
|
||||
ARGON2_PUBLIC int argon2_ctx(argon2_context *context, argon2_type type);
|
||||
|
||||
/**
|
||||
* Hashes a password with Argon2i, producing an encoded hash
|
||||
* @param t_cost Number of iterations
|
||||
* @param m_cost Sets memory usage to m_cost kibibytes
|
||||
* @param parallelism Number of threads and compute lanes
|
||||
* @param pwd Pointer to password
|
||||
* @param pwdlen Password size in bytes
|
||||
* @param salt Pointer to salt
|
||||
* @param saltlen Salt size in bytes
|
||||
* @param hashlen Desired length of the hash in bytes
|
||||
* @param encoded Buffer where to write the encoded hash
|
||||
* @param encodedlen Size of the buffer (thus max size of the encoded hash)
|
||||
* @pre Different parallelism levels will give different results
|
||||
* @pre Returns ARGON2_OK if successful
|
||||
*/
|
||||
ARGON2_PUBLIC int argon2i_hash_encoded(const uint32_t t_cost,
|
||||
const uint32_t m_cost,
|
||||
const uint32_t parallelism,
|
||||
const void *pwd, const size_t pwdlen,
|
||||
const void *salt, const size_t saltlen,
|
||||
const size_t hashlen, char *encoded,
|
||||
const size_t encodedlen);
|
||||
|
||||
/**
|
||||
* Hashes a password with Argon2i, producing a raw hash at @hash
|
||||
* @param t_cost Number of iterations
|
||||
* @param m_cost Sets memory usage to m_cost kibibytes
|
||||
* @param parallelism Number of threads and compute lanes
|
||||
* @param pwd Pointer to password
|
||||
* @param pwdlen Password size in bytes
|
||||
* @param salt Pointer to salt
|
||||
* @param saltlen Salt size in bytes
|
||||
* @param hash Buffer where to write the raw hash - updated by the function
|
||||
* @param hashlen Desired length of the hash in bytes
|
||||
* @pre Different parallelism levels will give different results
|
||||
* @pre Returns ARGON2_OK if successful
|
||||
*/
|
||||
ARGON2_PUBLIC int argon2i_hash_raw(const uint32_t t_cost, const uint32_t m_cost,
|
||||
const uint32_t parallelism, const void *pwd,
|
||||
const size_t pwdlen, const void *salt,
|
||||
const size_t saltlen, void *hash,
|
||||
const size_t hashlen);
|
||||
|
||||
ARGON2_PUBLIC int argon2d_hash_encoded(const uint32_t t_cost,
|
||||
const uint32_t m_cost,
|
||||
const uint32_t parallelism,
|
||||
const void *pwd, const size_t pwdlen,
|
||||
const void *salt, const size_t saltlen,
|
||||
const size_t hashlen, char *encoded,
|
||||
const size_t encodedlen);
|
||||
|
||||
ARGON2_PUBLIC int argon2d_hash_raw(const uint32_t t_cost, const uint32_t m_cost,
|
||||
const uint32_t parallelism, const void *pwd,
|
||||
const size_t pwdlen, const void *salt,
|
||||
const size_t saltlen, void *hash,
|
||||
const size_t hashlen);
|
||||
|
||||
ARGON2_PUBLIC int argon2id_hash_encoded(const uint32_t t_cost,
|
||||
const uint32_t m_cost,
|
||||
const uint32_t parallelism,
|
||||
const void *pwd, const size_t pwdlen,
|
||||
const void *salt, const size_t saltlen,
|
||||
const size_t hashlen, char *encoded,
|
||||
const size_t encodedlen);
|
||||
|
||||
ARGON2_PUBLIC int argon2id_hash_raw(const uint32_t t_cost,
|
||||
const uint32_t m_cost,
|
||||
const uint32_t parallelism, const void *pwd,
|
||||
const size_t pwdlen, const void *salt,
|
||||
const size_t saltlen, void *hash,
|
||||
const size_t hashlen);
|
||||
|
||||
/* generic function underlying the above ones */
|
||||
ARGON2_PUBLIC int argon2_hash(const uint32_t t_cost, const uint32_t m_cost,
|
||||
const uint32_t parallelism, const void *pwd,
|
||||
const size_t pwdlen, const void *salt,
|
||||
const size_t saltlen, void *hash,
|
||||
const size_t hashlen, char *encoded,
|
||||
const size_t encodedlen, argon2_type type,
|
||||
const uint32_t version);
|
||||
|
||||
/**
|
||||
* Verifies a password against an encoded string
|
||||
* Encoded string is restricted as in validate_inputs()
|
||||
* @param encoded String encoding parameters, salt, hash
|
||||
* @param pwd Pointer to password
|
||||
* @pre Returns ARGON2_OK if successful
|
||||
*/
|
||||
ARGON2_PUBLIC int argon2i_verify(const char *encoded, const void *pwd,
|
||||
const size_t pwdlen);
|
||||
|
||||
ARGON2_PUBLIC int argon2d_verify(const char *encoded, const void *pwd,
|
||||
const size_t pwdlen);
|
||||
|
||||
ARGON2_PUBLIC int argon2id_verify(const char *encoded, const void *pwd,
|
||||
const size_t pwdlen);
|
||||
|
||||
/* generic function underlying the above ones */
|
||||
ARGON2_PUBLIC int argon2_verify(const char *encoded, const void *pwd,
|
||||
const size_t pwdlen, argon2_type type);
|
||||
|
||||
/**
|
||||
* Argon2d: Version of Argon2 that picks memory blocks depending
|
||||
* on the password and salt. Only for side-channel-free
|
||||
* environment!!
|
||||
*****
|
||||
* @param context Pointer to current Argon2 context
|
||||
* @return Zero if successful, a non zero error code otherwise
|
||||
*/
|
||||
ARGON2_PUBLIC int argon2d_ctx(argon2_context *context);
|
||||
|
||||
/**
|
||||
* Argon2i: Version of Argon2 that picks memory blocks
|
||||
* independent on the password and salt. Good for side-channels,
|
||||
* but worse w.r.t. tradeoff attacks if only one pass is used.
|
||||
*****
|
||||
* @param context Pointer to current Argon2 context
|
||||
* @return Zero if successful, a non zero error code otherwise
|
||||
*/
|
||||
ARGON2_PUBLIC int argon2i_ctx(argon2_context *context);
|
||||
|
||||
/**
|
||||
* Argon2id: Version of Argon2 where the first half-pass over memory is
|
||||
* password-independent, the rest are password-dependent (on the password and
|
||||
* salt). OK against side channels (they reduce to 1/2-pass Argon2i), and
|
||||
* better with w.r.t. tradeoff attacks (similar to Argon2d).
|
||||
*****
|
||||
* @param context Pointer to current Argon2 context
|
||||
* @return Zero if successful, a non zero error code otherwise
|
||||
*/
|
||||
ARGON2_PUBLIC int argon2id_ctx(argon2_context *context);
|
||||
|
||||
/**
|
||||
* Verify if a given password is correct for Argon2d hashing
|
||||
* @param context Pointer to current Argon2 context
|
||||
* @param hash The password hash to verify. The length of the hash is
|
||||
* specified by the context outlen member
|
||||
* @return Zero if successful, a non zero error code otherwise
|
||||
*/
|
||||
ARGON2_PUBLIC int argon2d_verify_ctx(argon2_context *context, const char *hash);
|
||||
|
||||
/**
|
||||
* Verify if a given password is correct for Argon2i hashing
|
||||
* @param context Pointer to current Argon2 context
|
||||
* @param hash The password hash to verify. The length of the hash is
|
||||
* specified by the context outlen member
|
||||
* @return Zero if successful, a non zero error code otherwise
|
||||
*/
|
||||
ARGON2_PUBLIC int argon2i_verify_ctx(argon2_context *context, const char *hash);
|
||||
|
||||
/**
|
||||
* Verify if a given password is correct for Argon2id hashing
|
||||
* @param context Pointer to current Argon2 context
|
||||
* @param hash The password hash to verify. The length of the hash is
|
||||
* specified by the context outlen member
|
||||
* @return Zero if successful, a non zero error code otherwise
|
||||
*/
|
||||
ARGON2_PUBLIC int argon2id_verify_ctx(argon2_context *context,
|
||||
const char *hash);
|
||||
|
||||
/* generic function underlying the above ones */
|
||||
ARGON2_PUBLIC int argon2_verify_ctx(argon2_context *context, const char *hash,
|
||||
argon2_type type);
|
||||
|
||||
/**
|
||||
* Get the associated error message for given error code
|
||||
* @return The error message associated with the given error code
|
||||
*/
|
||||
ARGON2_PUBLIC const char *argon2_error_message(int error_code);
|
||||
|
||||
/**
|
||||
* Returns the encoded hash length for the given input parameters
|
||||
* @param t_cost Number of iterations
|
||||
* @param m_cost Memory usage in kibibytes
|
||||
* @param parallelism Number of threads; used to compute lanes
|
||||
* @param saltlen Salt size in bytes
|
||||
* @param hashlen Hash size in bytes
|
||||
* @param type The argon2_type that we want the encoded length for
|
||||
* @return The encoded hash length in bytes
|
||||
*/
|
||||
ARGON2_PUBLIC size_t argon2_encodedlen(uint32_t t_cost, uint32_t m_cost,
|
||||
uint32_t parallelism, uint32_t saltlen,
|
||||
uint32_t hashlen, argon2_type type);
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
154
lib/crypto_backend/argon2/blake2/blake2-impl.h
Normal file
154
lib/crypto_backend/argon2/blake2/blake2-impl.h
Normal file
@@ -0,0 +1,154 @@
|
||||
/*
|
||||
* Argon2 reference source code package - reference C implementations
|
||||
*
|
||||
* Copyright 2015
|
||||
* Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves
|
||||
*
|
||||
* You may use this work under the terms of a Creative Commons CC0 1.0
|
||||
* License/Waiver or the Apache Public License 2.0, at your option. The terms of
|
||||
* these licenses can be found at:
|
||||
*
|
||||
* - CC0 1.0 Universal : https://creativecommons.org/publicdomain/zero/1.0
|
||||
* - Apache 2.0 : https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* You should have received a copy of both of these licenses along with this
|
||||
* software. If not, they may be obtained at the above URLs.
|
||||
*/
|
||||
|
||||
#ifndef PORTABLE_BLAKE2_IMPL_H
|
||||
#define PORTABLE_BLAKE2_IMPL_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#define BLAKE2_INLINE __inline
|
||||
#elif defined(__GNUC__) || defined(__clang__)
|
||||
#define BLAKE2_INLINE __inline__
|
||||
#else
|
||||
#define BLAKE2_INLINE
|
||||
#endif
|
||||
|
||||
/* Argon2 Team - Begin Code */
|
||||
/*
|
||||
Not an exhaustive list, but should cover the majority of modern platforms
|
||||
Additionally, the code will always be correct---this is only a performance
|
||||
tweak.
|
||||
*/
|
||||
#if (defined(__BYTE_ORDER__) && \
|
||||
(__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)) || \
|
||||
defined(__LITTLE_ENDIAN__) || defined(__ARMEL__) || defined(__MIPSEL__) || \
|
||||
defined(__AARCH64EL__) || defined(__amd64__) || defined(__i386__) || \
|
||||
defined(_M_IX86) || defined(_M_X64) || defined(_M_AMD64) || \
|
||||
defined(_M_ARM)
|
||||
#define NATIVE_LITTLE_ENDIAN
|
||||
#endif
|
||||
/* Argon2 Team - End Code */
|
||||
|
||||
static BLAKE2_INLINE uint32_t load32(const void *src) {
|
||||
#if defined(NATIVE_LITTLE_ENDIAN)
|
||||
uint32_t w;
|
||||
memcpy(&w, src, sizeof w);
|
||||
return w;
|
||||
#else
|
||||
const uint8_t *p = (const uint8_t *)src;
|
||||
uint32_t w = *p++;
|
||||
w |= (uint32_t)(*p++) << 8;
|
||||
w |= (uint32_t)(*p++) << 16;
|
||||
w |= (uint32_t)(*p++) << 24;
|
||||
return w;
|
||||
#endif
|
||||
}
|
||||
|
||||
static BLAKE2_INLINE uint64_t load64(const void *src) {
|
||||
#if defined(NATIVE_LITTLE_ENDIAN)
|
||||
uint64_t w;
|
||||
memcpy(&w, src, sizeof w);
|
||||
return w;
|
||||
#else
|
||||
const uint8_t *p = (const uint8_t *)src;
|
||||
uint64_t w = *p++;
|
||||
w |= (uint64_t)(*p++) << 8;
|
||||
w |= (uint64_t)(*p++) << 16;
|
||||
w |= (uint64_t)(*p++) << 24;
|
||||
w |= (uint64_t)(*p++) << 32;
|
||||
w |= (uint64_t)(*p++) << 40;
|
||||
w |= (uint64_t)(*p++) << 48;
|
||||
w |= (uint64_t)(*p++) << 56;
|
||||
return w;
|
||||
#endif
|
||||
}
|
||||
|
||||
static BLAKE2_INLINE void store32(void *dst, uint32_t w) {
|
||||
#if defined(NATIVE_LITTLE_ENDIAN)
|
||||
memcpy(dst, &w, sizeof w);
|
||||
#else
|
||||
uint8_t *p = (uint8_t *)dst;
|
||||
*p++ = (uint8_t)w;
|
||||
w >>= 8;
|
||||
*p++ = (uint8_t)w;
|
||||
w >>= 8;
|
||||
*p++ = (uint8_t)w;
|
||||
w >>= 8;
|
||||
*p++ = (uint8_t)w;
|
||||
#endif
|
||||
}
|
||||
|
||||
static BLAKE2_INLINE void store64(void *dst, uint64_t w) {
|
||||
#if defined(NATIVE_LITTLE_ENDIAN)
|
||||
memcpy(dst, &w, sizeof w);
|
||||
#else
|
||||
uint8_t *p = (uint8_t *)dst;
|
||||
*p++ = (uint8_t)w;
|
||||
w >>= 8;
|
||||
*p++ = (uint8_t)w;
|
||||
w >>= 8;
|
||||
*p++ = (uint8_t)w;
|
||||
w >>= 8;
|
||||
*p++ = (uint8_t)w;
|
||||
w >>= 8;
|
||||
*p++ = (uint8_t)w;
|
||||
w >>= 8;
|
||||
*p++ = (uint8_t)w;
|
||||
w >>= 8;
|
||||
*p++ = (uint8_t)w;
|
||||
w >>= 8;
|
||||
*p++ = (uint8_t)w;
|
||||
#endif
|
||||
}
|
||||
|
||||
static BLAKE2_INLINE uint64_t load48(const void *src) {
|
||||
const uint8_t *p = (const uint8_t *)src;
|
||||
uint64_t w = *p++;
|
||||
w |= (uint64_t)(*p++) << 8;
|
||||
w |= (uint64_t)(*p++) << 16;
|
||||
w |= (uint64_t)(*p++) << 24;
|
||||
w |= (uint64_t)(*p++) << 32;
|
||||
w |= (uint64_t)(*p++) << 40;
|
||||
return w;
|
||||
}
|
||||
|
||||
static BLAKE2_INLINE void store48(void *dst, uint64_t w) {
|
||||
uint8_t *p = (uint8_t *)dst;
|
||||
*p++ = (uint8_t)w;
|
||||
w >>= 8;
|
||||
*p++ = (uint8_t)w;
|
||||
w >>= 8;
|
||||
*p++ = (uint8_t)w;
|
||||
w >>= 8;
|
||||
*p++ = (uint8_t)w;
|
||||
w >>= 8;
|
||||
*p++ = (uint8_t)w;
|
||||
w >>= 8;
|
||||
*p++ = (uint8_t)w;
|
||||
}
|
||||
|
||||
static BLAKE2_INLINE uint32_t rotr32(const uint32_t w, const unsigned c) {
|
||||
return (w >> c) | (w << (32 - c));
|
||||
}
|
||||
|
||||
static BLAKE2_INLINE uint64_t rotr64(const uint64_t w, const unsigned c) {
|
||||
return (w >> c) | (w << (64 - c));
|
||||
}
|
||||
|
||||
#endif
|
||||
89
lib/crypto_backend/argon2/blake2/blake2.h
Normal file
89
lib/crypto_backend/argon2/blake2/blake2.h
Normal file
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* Argon2 reference source code package - reference C implementations
|
||||
*
|
||||
* Copyright 2015
|
||||
* Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves
|
||||
*
|
||||
* You may use this work under the terms of a Creative Commons CC0 1.0
|
||||
* License/Waiver or the Apache Public License 2.0, at your option. The terms of
|
||||
* these licenses can be found at:
|
||||
*
|
||||
* - CC0 1.0 Universal : https://creativecommons.org/publicdomain/zero/1.0
|
||||
* - Apache 2.0 : https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* You should have received a copy of both of these licenses along with this
|
||||
* software. If not, they may be obtained at the above URLs.
|
||||
*/
|
||||
|
||||
#ifndef PORTABLE_BLAKE2_H
|
||||
#define PORTABLE_BLAKE2_H
|
||||
|
||||
#include "../argon2.h"
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
enum blake2b_constant {
|
||||
BLAKE2B_BLOCKBYTES = 128,
|
||||
BLAKE2B_OUTBYTES = 64,
|
||||
BLAKE2B_KEYBYTES = 64,
|
||||
BLAKE2B_SALTBYTES = 16,
|
||||
BLAKE2B_PERSONALBYTES = 16
|
||||
};
|
||||
|
||||
#pragma pack(push, 1)
|
||||
typedef struct __blake2b_param {
|
||||
uint8_t digest_length; /* 1 */
|
||||
uint8_t key_length; /* 2 */
|
||||
uint8_t fanout; /* 3 */
|
||||
uint8_t depth; /* 4 */
|
||||
uint32_t leaf_length; /* 8 */
|
||||
uint64_t node_offset; /* 16 */
|
||||
uint8_t node_depth; /* 17 */
|
||||
uint8_t inner_length; /* 18 */
|
||||
uint8_t reserved[14]; /* 32 */
|
||||
uint8_t salt[BLAKE2B_SALTBYTES]; /* 48 */
|
||||
uint8_t personal[BLAKE2B_PERSONALBYTES]; /* 64 */
|
||||
} blake2b_param;
|
||||
#pragma pack(pop)
|
||||
|
||||
typedef struct __blake2b_state {
|
||||
uint64_t h[8];
|
||||
uint64_t t[2];
|
||||
uint64_t f[2];
|
||||
uint8_t buf[BLAKE2B_BLOCKBYTES];
|
||||
unsigned buflen;
|
||||
unsigned outlen;
|
||||
uint8_t last_node;
|
||||
} blake2b_state;
|
||||
|
||||
/* Ensure param structs have not been wrongly padded */
|
||||
/* Poor man's static_assert */
|
||||
enum {
|
||||
blake2_size_check_0 = 1 / !!(CHAR_BIT == 8),
|
||||
blake2_size_check_2 =
|
||||
1 / !!(sizeof(blake2b_param) == sizeof(uint64_t) * CHAR_BIT)
|
||||
};
|
||||
|
||||
/* Streaming API */
|
||||
ARGON2_LOCAL int blake2b_init(blake2b_state *S, size_t outlen);
|
||||
ARGON2_LOCAL int blake2b_init_key(blake2b_state *S, size_t outlen, const void *key,
|
||||
size_t keylen);
|
||||
ARGON2_LOCAL int blake2b_init_param(blake2b_state *S, const blake2b_param *P);
|
||||
ARGON2_LOCAL int blake2b_update(blake2b_state *S, const void *in, size_t inlen);
|
||||
ARGON2_LOCAL int blake2b_final(blake2b_state *S, void *out, size_t outlen);
|
||||
|
||||
/* Simple API */
|
||||
ARGON2_LOCAL int blake2b(void *out, size_t outlen, const void *in, size_t inlen,
|
||||
const void *key, size_t keylen);
|
||||
|
||||
/* Argon2 Team - Begin Code */
|
||||
ARGON2_LOCAL int blake2b_long(void *out, size_t outlen, const void *in, size_t inlen);
|
||||
/* Argon2 Team - End Code */
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
392
lib/crypto_backend/argon2/blake2/blake2b.c
Normal file
392
lib/crypto_backend/argon2/blake2/blake2b.c
Normal file
@@ -0,0 +1,392 @@
|
||||
/*
|
||||
* Argon2 reference source code package - reference C implementations
|
||||
*
|
||||
* Copyright 2015
|
||||
* Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves
|
||||
*
|
||||
* You may use this work under the terms of a Creative Commons CC0 1.0
|
||||
* License/Waiver or the Apache Public License 2.0, at your option. The terms of
|
||||
* these licenses can be found at:
|
||||
*
|
||||
* - CC0 1.0 Universal : https://creativecommons.org/publicdomain/zero/1.0
|
||||
* - Apache 2.0 : https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* You should have received a copy of both of these licenses along with this
|
||||
* software. If not, they may be obtained at the above URLs.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "blake2.h"
|
||||
#include "blake2-impl.h"
|
||||
|
||||
void clear_internal_memory(void *v, size_t n);
|
||||
|
||||
static const uint64_t blake2b_IV[8] = {
|
||||
UINT64_C(0x6a09e667f3bcc908), UINT64_C(0xbb67ae8584caa73b),
|
||||
UINT64_C(0x3c6ef372fe94f82b), UINT64_C(0xa54ff53a5f1d36f1),
|
||||
UINT64_C(0x510e527fade682d1), UINT64_C(0x9b05688c2b3e6c1f),
|
||||
UINT64_C(0x1f83d9abfb41bd6b), UINT64_C(0x5be0cd19137e2179)};
|
||||
|
||||
static const unsigned int blake2b_sigma[12][16] = {
|
||||
{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15},
|
||||
{14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3},
|
||||
{11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4},
|
||||
{7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8},
|
||||
{9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13},
|
||||
{2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9},
|
||||
{12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11},
|
||||
{13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10},
|
||||
{6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5},
|
||||
{10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0},
|
||||
{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15},
|
||||
{14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3},
|
||||
};
|
||||
|
||||
static BLAKE2_INLINE void blake2b_set_lastnode(blake2b_state *S) {
|
||||
S->f[1] = (uint64_t)-1;
|
||||
}
|
||||
|
||||
static BLAKE2_INLINE void blake2b_set_lastblock(blake2b_state *S) {
|
||||
if (S->last_node) {
|
||||
blake2b_set_lastnode(S);
|
||||
}
|
||||
S->f[0] = (uint64_t)-1;
|
||||
}
|
||||
|
||||
static BLAKE2_INLINE void blake2b_increment_counter(blake2b_state *S,
|
||||
uint64_t inc) {
|
||||
S->t[0] += inc;
|
||||
S->t[1] += (S->t[0] < inc);
|
||||
}
|
||||
|
||||
static BLAKE2_INLINE void blake2b_invalidate_state(blake2b_state *S) {
|
||||
clear_internal_memory(S, sizeof(*S)); /* wipe */
|
||||
blake2b_set_lastblock(S); /* invalidate for further use */
|
||||
}
|
||||
|
||||
static BLAKE2_INLINE void blake2b_init0(blake2b_state *S) {
|
||||
memset(S, 0, sizeof(*S));
|
||||
memcpy(S->h, blake2b_IV, sizeof(S->h));
|
||||
}
|
||||
|
||||
int blake2b_init_param(blake2b_state *S, const blake2b_param *P) {
|
||||
const unsigned char *p = (const unsigned char *)P;
|
||||
unsigned int i;
|
||||
|
||||
if (NULL == P || NULL == S) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
blake2b_init0(S);
|
||||
/* IV XOR Parameter Block */
|
||||
for (i = 0; i < 8; ++i) {
|
||||
S->h[i] ^= load64(&p[i * sizeof(S->h[i])]);
|
||||
}
|
||||
S->outlen = P->digest_length;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Sequential blake2b initialization */
|
||||
int blake2b_init(blake2b_state *S, size_t outlen) {
|
||||
blake2b_param P;
|
||||
|
||||
if (S == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((outlen == 0) || (outlen > BLAKE2B_OUTBYTES)) {
|
||||
blake2b_invalidate_state(S);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Setup Parameter Block for unkeyed BLAKE2 */
|
||||
P.digest_length = (uint8_t)outlen;
|
||||
P.key_length = 0;
|
||||
P.fanout = 1;
|
||||
P.depth = 1;
|
||||
P.leaf_length = 0;
|
||||
P.node_offset = 0;
|
||||
P.node_depth = 0;
|
||||
P.inner_length = 0;
|
||||
memset(P.reserved, 0, sizeof(P.reserved));
|
||||
memset(P.salt, 0, sizeof(P.salt));
|
||||
memset(P.personal, 0, sizeof(P.personal));
|
||||
|
||||
return blake2b_init_param(S, &P);
|
||||
}
|
||||
|
||||
int blake2b_init_key(blake2b_state *S, size_t outlen, const void *key,
|
||||
size_t keylen) {
|
||||
blake2b_param P;
|
||||
|
||||
if (S == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((outlen == 0) || (outlen > BLAKE2B_OUTBYTES)) {
|
||||
blake2b_invalidate_state(S);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((key == 0) || (keylen == 0) || (keylen > BLAKE2B_KEYBYTES)) {
|
||||
blake2b_invalidate_state(S);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Setup Parameter Block for keyed BLAKE2 */
|
||||
P.digest_length = (uint8_t)outlen;
|
||||
P.key_length = (uint8_t)keylen;
|
||||
P.fanout = 1;
|
||||
P.depth = 1;
|
||||
P.leaf_length = 0;
|
||||
P.node_offset = 0;
|
||||
P.node_depth = 0;
|
||||
P.inner_length = 0;
|
||||
memset(P.reserved, 0, sizeof(P.reserved));
|
||||
memset(P.salt, 0, sizeof(P.salt));
|
||||
memset(P.personal, 0, sizeof(P.personal));
|
||||
|
||||
if (blake2b_init_param(S, &P) < 0) {
|
||||
blake2b_invalidate_state(S);
|
||||
return -1;
|
||||
}
|
||||
|
||||
{
|
||||
uint8_t block[BLAKE2B_BLOCKBYTES];
|
||||
memset(block, 0, BLAKE2B_BLOCKBYTES);
|
||||
memcpy(block, key, keylen);
|
||||
blake2b_update(S, block, BLAKE2B_BLOCKBYTES);
|
||||
/* Burn the key from stack */
|
||||
clear_internal_memory(block, BLAKE2B_BLOCKBYTES);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void blake2b_compress(blake2b_state *S, const uint8_t *block) {
|
||||
uint64_t m[16];
|
||||
uint64_t v[16];
|
||||
unsigned int i, r;
|
||||
|
||||
for (i = 0; i < 16; ++i) {
|
||||
m[i] = load64(block + i * sizeof(m[i]));
|
||||
}
|
||||
|
||||
for (i = 0; i < 8; ++i) {
|
||||
v[i] = S->h[i];
|
||||
}
|
||||
|
||||
v[8] = blake2b_IV[0];
|
||||
v[9] = blake2b_IV[1];
|
||||
v[10] = blake2b_IV[2];
|
||||
v[11] = blake2b_IV[3];
|
||||
v[12] = blake2b_IV[4] ^ S->t[0];
|
||||
v[13] = blake2b_IV[5] ^ S->t[1];
|
||||
v[14] = blake2b_IV[6] ^ S->f[0];
|
||||
v[15] = blake2b_IV[7] ^ S->f[1];
|
||||
|
||||
#define G(r, i, a, b, c, d) \
|
||||
do { \
|
||||
a = a + b + m[blake2b_sigma[r][2 * i + 0]]; \
|
||||
d = rotr64(d ^ a, 32); \
|
||||
c = c + d; \
|
||||
b = rotr64(b ^ c, 24); \
|
||||
a = a + b + m[blake2b_sigma[r][2 * i + 1]]; \
|
||||
d = rotr64(d ^ a, 16); \
|
||||
c = c + d; \
|
||||
b = rotr64(b ^ c, 63); \
|
||||
} while ((void)0, 0)
|
||||
|
||||
#define ROUND(r) \
|
||||
do { \
|
||||
G(r, 0, v[0], v[4], v[8], v[12]); \
|
||||
G(r, 1, v[1], v[5], v[9], v[13]); \
|
||||
G(r, 2, v[2], v[6], v[10], v[14]); \
|
||||
G(r, 3, v[3], v[7], v[11], v[15]); \
|
||||
G(r, 4, v[0], v[5], v[10], v[15]); \
|
||||
G(r, 5, v[1], v[6], v[11], v[12]); \
|
||||
G(r, 6, v[2], v[7], v[8], v[13]); \
|
||||
G(r, 7, v[3], v[4], v[9], v[14]); \
|
||||
} while ((void)0, 0)
|
||||
|
||||
for (r = 0; r < 12; ++r) {
|
||||
ROUND(r);
|
||||
}
|
||||
|
||||
for (i = 0; i < 8; ++i) {
|
||||
S->h[i] = S->h[i] ^ v[i] ^ v[i + 8];
|
||||
}
|
||||
|
||||
#undef G
|
||||
#undef ROUND
|
||||
}
|
||||
|
||||
int blake2b_update(blake2b_state *S, const void *in, size_t inlen) {
|
||||
const uint8_t *pin = (const uint8_t *)in;
|
||||
|
||||
if (inlen == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Sanity check */
|
||||
if (S == NULL || in == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Is this a reused state? */
|
||||
if (S->f[0] != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (S->buflen + inlen > BLAKE2B_BLOCKBYTES) {
|
||||
/* Complete current block */
|
||||
size_t left = S->buflen;
|
||||
size_t fill = BLAKE2B_BLOCKBYTES - left;
|
||||
memcpy(&S->buf[left], pin, fill);
|
||||
blake2b_increment_counter(S, BLAKE2B_BLOCKBYTES);
|
||||
blake2b_compress(S, S->buf);
|
||||
S->buflen = 0;
|
||||
inlen -= fill;
|
||||
pin += fill;
|
||||
/* Avoid buffer copies when possible */
|
||||
while (inlen > BLAKE2B_BLOCKBYTES) {
|
||||
blake2b_increment_counter(S, BLAKE2B_BLOCKBYTES);
|
||||
blake2b_compress(S, pin);
|
||||
inlen -= BLAKE2B_BLOCKBYTES;
|
||||
pin += BLAKE2B_BLOCKBYTES;
|
||||
}
|
||||
}
|
||||
memcpy(&S->buf[S->buflen], pin, inlen);
|
||||
S->buflen += (unsigned int)inlen;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int blake2b_final(blake2b_state *S, void *out, size_t outlen) {
|
||||
uint8_t buffer[BLAKE2B_OUTBYTES] = {0};
|
||||
unsigned int i;
|
||||
|
||||
/* Sanity checks */
|
||||
if (S == NULL || out == NULL || outlen < S->outlen) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Is this a reused state? */
|
||||
if (S->f[0] != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
blake2b_increment_counter(S, S->buflen);
|
||||
blake2b_set_lastblock(S);
|
||||
memset(&S->buf[S->buflen], 0, BLAKE2B_BLOCKBYTES - S->buflen); /* Padding */
|
||||
blake2b_compress(S, S->buf);
|
||||
|
||||
for (i = 0; i < 8; ++i) { /* Output full hash to temp buffer */
|
||||
store64(buffer + sizeof(S->h[i]) * i, S->h[i]);
|
||||
}
|
||||
|
||||
memcpy(out, buffer, S->outlen);
|
||||
clear_internal_memory(buffer, sizeof(buffer));
|
||||
clear_internal_memory(S->buf, sizeof(S->buf));
|
||||
clear_internal_memory(S->h, sizeof(S->h));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int blake2b(void *out, size_t outlen, const void *in, size_t inlen,
|
||||
const void *key, size_t keylen) {
|
||||
blake2b_state S;
|
||||
int ret = -1;
|
||||
|
||||
/* Verify parameters */
|
||||
if (NULL == in && inlen > 0) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (NULL == out || outlen == 0 || outlen > BLAKE2B_OUTBYTES) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if ((NULL == key && keylen > 0) || keylen > BLAKE2B_KEYBYTES) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (keylen > 0) {
|
||||
if (blake2b_init_key(&S, outlen, key, keylen) < 0) {
|
||||
goto fail;
|
||||
}
|
||||
} else {
|
||||
if (blake2b_init(&S, outlen) < 0) {
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
if (blake2b_update(&S, in, inlen) < 0) {
|
||||
goto fail;
|
||||
}
|
||||
ret = blake2b_final(&S, out, outlen);
|
||||
|
||||
fail:
|
||||
clear_internal_memory(&S, sizeof(S));
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Argon2 Team - Begin Code */
|
||||
int blake2b_long(void *pout, size_t outlen, const void *in, size_t inlen) {
|
||||
uint8_t *out = (uint8_t *)pout;
|
||||
blake2b_state blake_state;
|
||||
uint8_t outlen_bytes[sizeof(uint32_t)] = {0};
|
||||
int ret = -1;
|
||||
|
||||
if (outlen > UINT32_MAX) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Ensure little-endian byte order! */
|
||||
store32(outlen_bytes, (uint32_t)outlen);
|
||||
|
||||
#define TRY(statement) \
|
||||
do { \
|
||||
ret = statement; \
|
||||
if (ret < 0) { \
|
||||
goto fail; \
|
||||
} \
|
||||
} while ((void)0, 0)
|
||||
|
||||
if (outlen <= BLAKE2B_OUTBYTES) {
|
||||
TRY(blake2b_init(&blake_state, outlen));
|
||||
TRY(blake2b_update(&blake_state, outlen_bytes, sizeof(outlen_bytes)));
|
||||
TRY(blake2b_update(&blake_state, in, inlen));
|
||||
TRY(blake2b_final(&blake_state, out, outlen));
|
||||
} else {
|
||||
uint32_t toproduce;
|
||||
uint8_t out_buffer[BLAKE2B_OUTBYTES];
|
||||
uint8_t in_buffer[BLAKE2B_OUTBYTES];
|
||||
TRY(blake2b_init(&blake_state, BLAKE2B_OUTBYTES));
|
||||
TRY(blake2b_update(&blake_state, outlen_bytes, sizeof(outlen_bytes)));
|
||||
TRY(blake2b_update(&blake_state, in, inlen));
|
||||
TRY(blake2b_final(&blake_state, out_buffer, BLAKE2B_OUTBYTES));
|
||||
memcpy(out, out_buffer, BLAKE2B_OUTBYTES / 2);
|
||||
out += BLAKE2B_OUTBYTES / 2;
|
||||
toproduce = (uint32_t)outlen - BLAKE2B_OUTBYTES / 2;
|
||||
|
||||
while (toproduce > BLAKE2B_OUTBYTES) {
|
||||
memcpy(in_buffer, out_buffer, BLAKE2B_OUTBYTES);
|
||||
TRY(blake2b(out_buffer, BLAKE2B_OUTBYTES, in_buffer,
|
||||
BLAKE2B_OUTBYTES, NULL, 0));
|
||||
memcpy(out, out_buffer, BLAKE2B_OUTBYTES / 2);
|
||||
out += BLAKE2B_OUTBYTES / 2;
|
||||
toproduce -= BLAKE2B_OUTBYTES / 2;
|
||||
}
|
||||
|
||||
memcpy(in_buffer, out_buffer, BLAKE2B_OUTBYTES);
|
||||
TRY(blake2b(out_buffer, toproduce, in_buffer, BLAKE2B_OUTBYTES, NULL,
|
||||
0));
|
||||
memcpy(out, out_buffer, toproduce);
|
||||
}
|
||||
fail:
|
||||
clear_internal_memory(&blake_state, sizeof(blake_state));
|
||||
return ret;
|
||||
#undef TRY
|
||||
}
|
||||
/* Argon2 Team - End Code */
|
||||
471
lib/crypto_backend/argon2/blake2/blamka-round-opt.h
Normal file
471
lib/crypto_backend/argon2/blake2/blamka-round-opt.h
Normal file
@@ -0,0 +1,471 @@
|
||||
/*
|
||||
* Argon2 reference source code package - reference C implementations
|
||||
*
|
||||
* Copyright 2015
|
||||
* Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves
|
||||
*
|
||||
* You may use this work under the terms of a Creative Commons CC0 1.0
|
||||
* License/Waiver or the Apache Public License 2.0, at your option. The terms of
|
||||
* these licenses can be found at:
|
||||
*
|
||||
* - CC0 1.0 Universal : https://creativecommons.org/publicdomain/zero/1.0
|
||||
* - Apache 2.0 : https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* You should have received a copy of both of these licenses along with this
|
||||
* software. If not, they may be obtained at the above URLs.
|
||||
*/
|
||||
|
||||
#ifndef BLAKE_ROUND_MKA_OPT_H
|
||||
#define BLAKE_ROUND_MKA_OPT_H
|
||||
|
||||
#include "blake2-impl.h"
|
||||
|
||||
#include <emmintrin.h>
|
||||
#if defined(__SSSE3__)
|
||||
#include <tmmintrin.h> /* for _mm_shuffle_epi8 and _mm_alignr_epi8 */
|
||||
#endif
|
||||
|
||||
#if defined(__XOP__) && (defined(__GNUC__) || defined(__clang__))
|
||||
#include <x86intrin.h>
|
||||
#endif
|
||||
|
||||
#if !defined(__AVX512F__)
|
||||
#if !defined(__AVX2__)
|
||||
#if !defined(__XOP__)
|
||||
#if defined(__SSSE3__)
|
||||
#define r16 \
|
||||
(_mm_setr_epi8(2, 3, 4, 5, 6, 7, 0, 1, 10, 11, 12, 13, 14, 15, 8, 9))
|
||||
#define r24 \
|
||||
(_mm_setr_epi8(3, 4, 5, 6, 7, 0, 1, 2, 11, 12, 13, 14, 15, 8, 9, 10))
|
||||
#define _mm_roti_epi64(x, c) \
|
||||
(-(c) == 32) \
|
||||
? _mm_shuffle_epi32((x), _MM_SHUFFLE(2, 3, 0, 1)) \
|
||||
: (-(c) == 24) \
|
||||
? _mm_shuffle_epi8((x), r24) \
|
||||
: (-(c) == 16) \
|
||||
? _mm_shuffle_epi8((x), r16) \
|
||||
: (-(c) == 63) \
|
||||
? _mm_xor_si128(_mm_srli_epi64((x), -(c)), \
|
||||
_mm_add_epi64((x), (x))) \
|
||||
: _mm_xor_si128(_mm_srli_epi64((x), -(c)), \
|
||||
_mm_slli_epi64((x), 64 - (-(c))))
|
||||
#else /* defined(__SSE2__) */
|
||||
#define _mm_roti_epi64(r, c) \
|
||||
_mm_xor_si128(_mm_srli_epi64((r), -(c)), _mm_slli_epi64((r), 64 - (-(c))))
|
||||
#endif
|
||||
#else
|
||||
#endif
|
||||
|
||||
static BLAKE2_INLINE __m128i fBlaMka(__m128i x, __m128i y) {
|
||||
const __m128i z = _mm_mul_epu32(x, y);
|
||||
return _mm_add_epi64(_mm_add_epi64(x, y), _mm_add_epi64(z, z));
|
||||
}
|
||||
|
||||
#define G1(A0, B0, C0, D0, A1, B1, C1, D1) \
|
||||
do { \
|
||||
A0 = fBlaMka(A0, B0); \
|
||||
A1 = fBlaMka(A1, B1); \
|
||||
\
|
||||
D0 = _mm_xor_si128(D0, A0); \
|
||||
D1 = _mm_xor_si128(D1, A1); \
|
||||
\
|
||||
D0 = _mm_roti_epi64(D0, -32); \
|
||||
D1 = _mm_roti_epi64(D1, -32); \
|
||||
\
|
||||
C0 = fBlaMka(C0, D0); \
|
||||
C1 = fBlaMka(C1, D1); \
|
||||
\
|
||||
B0 = _mm_xor_si128(B0, C0); \
|
||||
B1 = _mm_xor_si128(B1, C1); \
|
||||
\
|
||||
B0 = _mm_roti_epi64(B0, -24); \
|
||||
B1 = _mm_roti_epi64(B1, -24); \
|
||||
} while ((void)0, 0)
|
||||
|
||||
#define G2(A0, B0, C0, D0, A1, B1, C1, D1) \
|
||||
do { \
|
||||
A0 = fBlaMka(A0, B0); \
|
||||
A1 = fBlaMka(A1, B1); \
|
||||
\
|
||||
D0 = _mm_xor_si128(D0, A0); \
|
||||
D1 = _mm_xor_si128(D1, A1); \
|
||||
\
|
||||
D0 = _mm_roti_epi64(D0, -16); \
|
||||
D1 = _mm_roti_epi64(D1, -16); \
|
||||
\
|
||||
C0 = fBlaMka(C0, D0); \
|
||||
C1 = fBlaMka(C1, D1); \
|
||||
\
|
||||
B0 = _mm_xor_si128(B0, C0); \
|
||||
B1 = _mm_xor_si128(B1, C1); \
|
||||
\
|
||||
B0 = _mm_roti_epi64(B0, -63); \
|
||||
B1 = _mm_roti_epi64(B1, -63); \
|
||||
} while ((void)0, 0)
|
||||
|
||||
#if defined(__SSSE3__)
|
||||
#define DIAGONALIZE(A0, B0, C0, D0, A1, B1, C1, D1) \
|
||||
do { \
|
||||
__m128i t0 = _mm_alignr_epi8(B1, B0, 8); \
|
||||
__m128i t1 = _mm_alignr_epi8(B0, B1, 8); \
|
||||
B0 = t0; \
|
||||
B1 = t1; \
|
||||
\
|
||||
t0 = C0; \
|
||||
C0 = C1; \
|
||||
C1 = t0; \
|
||||
\
|
||||
t0 = _mm_alignr_epi8(D1, D0, 8); \
|
||||
t1 = _mm_alignr_epi8(D0, D1, 8); \
|
||||
D0 = t1; \
|
||||
D1 = t0; \
|
||||
} while ((void)0, 0)
|
||||
|
||||
#define UNDIAGONALIZE(A0, B0, C0, D0, A1, B1, C1, D1) \
|
||||
do { \
|
||||
__m128i t0 = _mm_alignr_epi8(B0, B1, 8); \
|
||||
__m128i t1 = _mm_alignr_epi8(B1, B0, 8); \
|
||||
B0 = t0; \
|
||||
B1 = t1; \
|
||||
\
|
||||
t0 = C0; \
|
||||
C0 = C1; \
|
||||
C1 = t0; \
|
||||
\
|
||||
t0 = _mm_alignr_epi8(D0, D1, 8); \
|
||||
t1 = _mm_alignr_epi8(D1, D0, 8); \
|
||||
D0 = t1; \
|
||||
D1 = t0; \
|
||||
} while ((void)0, 0)
|
||||
#else /* SSE2 */
|
||||
#define DIAGONALIZE(A0, B0, C0, D0, A1, B1, C1, D1) \
|
||||
do { \
|
||||
__m128i t0 = D0; \
|
||||
__m128i t1 = B0; \
|
||||
D0 = C0; \
|
||||
C0 = C1; \
|
||||
C1 = D0; \
|
||||
D0 = _mm_unpackhi_epi64(D1, _mm_unpacklo_epi64(t0, t0)); \
|
||||
D1 = _mm_unpackhi_epi64(t0, _mm_unpacklo_epi64(D1, D1)); \
|
||||
B0 = _mm_unpackhi_epi64(B0, _mm_unpacklo_epi64(B1, B1)); \
|
||||
B1 = _mm_unpackhi_epi64(B1, _mm_unpacklo_epi64(t1, t1)); \
|
||||
} while ((void)0, 0)
|
||||
|
||||
#define UNDIAGONALIZE(A0, B0, C0, D0, A1, B1, C1, D1) \
|
||||
do { \
|
||||
__m128i t0, t1; \
|
||||
t0 = C0; \
|
||||
C0 = C1; \
|
||||
C1 = t0; \
|
||||
t0 = B0; \
|
||||
t1 = D0; \
|
||||
B0 = _mm_unpackhi_epi64(B1, _mm_unpacklo_epi64(B0, B0)); \
|
||||
B1 = _mm_unpackhi_epi64(t0, _mm_unpacklo_epi64(B1, B1)); \
|
||||
D0 = _mm_unpackhi_epi64(D0, _mm_unpacklo_epi64(D1, D1)); \
|
||||
D1 = _mm_unpackhi_epi64(D1, _mm_unpacklo_epi64(t1, t1)); \
|
||||
} while ((void)0, 0)
|
||||
#endif
|
||||
|
||||
#define BLAKE2_ROUND(A0, A1, B0, B1, C0, C1, D0, D1) \
|
||||
do { \
|
||||
G1(A0, B0, C0, D0, A1, B1, C1, D1); \
|
||||
G2(A0, B0, C0, D0, A1, B1, C1, D1); \
|
||||
\
|
||||
DIAGONALIZE(A0, B0, C0, D0, A1, B1, C1, D1); \
|
||||
\
|
||||
G1(A0, B0, C0, D0, A1, B1, C1, D1); \
|
||||
G2(A0, B0, C0, D0, A1, B1, C1, D1); \
|
||||
\
|
||||
UNDIAGONALIZE(A0, B0, C0, D0, A1, B1, C1, D1); \
|
||||
} while ((void)0, 0)
|
||||
#else /* __AVX2__ */
|
||||
|
||||
#include <immintrin.h>
|
||||
|
||||
#define rotr32(x) _mm256_shuffle_epi32(x, _MM_SHUFFLE(2, 3, 0, 1))
|
||||
#define rotr24(x) _mm256_shuffle_epi8(x, _mm256_setr_epi8(3, 4, 5, 6, 7, 0, 1, 2, 11, 12, 13, 14, 15, 8, 9, 10, 3, 4, 5, 6, 7, 0, 1, 2, 11, 12, 13, 14, 15, 8, 9, 10))
|
||||
#define rotr16(x) _mm256_shuffle_epi8(x, _mm256_setr_epi8(2, 3, 4, 5, 6, 7, 0, 1, 10, 11, 12, 13, 14, 15, 8, 9, 2, 3, 4, 5, 6, 7, 0, 1, 10, 11, 12, 13, 14, 15, 8, 9))
|
||||
#define rotr63(x) _mm256_xor_si256(_mm256_srli_epi64((x), 63), _mm256_add_epi64((x), (x)))
|
||||
|
||||
#define G1_AVX2(A0, A1, B0, B1, C0, C1, D0, D1) \
|
||||
do { \
|
||||
__m256i ml = _mm256_mul_epu32(A0, B0); \
|
||||
ml = _mm256_add_epi64(ml, ml); \
|
||||
A0 = _mm256_add_epi64(A0, _mm256_add_epi64(B0, ml)); \
|
||||
D0 = _mm256_xor_si256(D0, A0); \
|
||||
D0 = rotr32(D0); \
|
||||
\
|
||||
ml = _mm256_mul_epu32(C0, D0); \
|
||||
ml = _mm256_add_epi64(ml, ml); \
|
||||
C0 = _mm256_add_epi64(C0, _mm256_add_epi64(D0, ml)); \
|
||||
\
|
||||
B0 = _mm256_xor_si256(B0, C0); \
|
||||
B0 = rotr24(B0); \
|
||||
\
|
||||
ml = _mm256_mul_epu32(A1, B1); \
|
||||
ml = _mm256_add_epi64(ml, ml); \
|
||||
A1 = _mm256_add_epi64(A1, _mm256_add_epi64(B1, ml)); \
|
||||
D1 = _mm256_xor_si256(D1, A1); \
|
||||
D1 = rotr32(D1); \
|
||||
\
|
||||
ml = _mm256_mul_epu32(C1, D1); \
|
||||
ml = _mm256_add_epi64(ml, ml); \
|
||||
C1 = _mm256_add_epi64(C1, _mm256_add_epi64(D1, ml)); \
|
||||
\
|
||||
B1 = _mm256_xor_si256(B1, C1); \
|
||||
B1 = rotr24(B1); \
|
||||
} while((void)0, 0);
|
||||
|
||||
#define G2_AVX2(A0, A1, B0, B1, C0, C1, D0, D1) \
|
||||
do { \
|
||||
__m256i ml = _mm256_mul_epu32(A0, B0); \
|
||||
ml = _mm256_add_epi64(ml, ml); \
|
||||
A0 = _mm256_add_epi64(A0, _mm256_add_epi64(B0, ml)); \
|
||||
D0 = _mm256_xor_si256(D0, A0); \
|
||||
D0 = rotr16(D0); \
|
||||
\
|
||||
ml = _mm256_mul_epu32(C0, D0); \
|
||||
ml = _mm256_add_epi64(ml, ml); \
|
||||
C0 = _mm256_add_epi64(C0, _mm256_add_epi64(D0, ml)); \
|
||||
B0 = _mm256_xor_si256(B0, C0); \
|
||||
B0 = rotr63(B0); \
|
||||
\
|
||||
ml = _mm256_mul_epu32(A1, B1); \
|
||||
ml = _mm256_add_epi64(ml, ml); \
|
||||
A1 = _mm256_add_epi64(A1, _mm256_add_epi64(B1, ml)); \
|
||||
D1 = _mm256_xor_si256(D1, A1); \
|
||||
D1 = rotr16(D1); \
|
||||
\
|
||||
ml = _mm256_mul_epu32(C1, D1); \
|
||||
ml = _mm256_add_epi64(ml, ml); \
|
||||
C1 = _mm256_add_epi64(C1, _mm256_add_epi64(D1, ml)); \
|
||||
B1 = _mm256_xor_si256(B1, C1); \
|
||||
B1 = rotr63(B1); \
|
||||
} while((void)0, 0);
|
||||
|
||||
#define DIAGONALIZE_1(A0, B0, C0, D0, A1, B1, C1, D1) \
|
||||
do { \
|
||||
B0 = _mm256_permute4x64_epi64(B0, _MM_SHUFFLE(0, 3, 2, 1)); \
|
||||
C0 = _mm256_permute4x64_epi64(C0, _MM_SHUFFLE(1, 0, 3, 2)); \
|
||||
D0 = _mm256_permute4x64_epi64(D0, _MM_SHUFFLE(2, 1, 0, 3)); \
|
||||
\
|
||||
B1 = _mm256_permute4x64_epi64(B1, _MM_SHUFFLE(0, 3, 2, 1)); \
|
||||
C1 = _mm256_permute4x64_epi64(C1, _MM_SHUFFLE(1, 0, 3, 2)); \
|
||||
D1 = _mm256_permute4x64_epi64(D1, _MM_SHUFFLE(2, 1, 0, 3)); \
|
||||
} while((void)0, 0);
|
||||
|
||||
#define DIAGONALIZE_2(A0, A1, B0, B1, C0, C1, D0, D1) \
|
||||
do { \
|
||||
__m256i tmp1 = _mm256_blend_epi32(B0, B1, 0xCC); \
|
||||
__m256i tmp2 = _mm256_blend_epi32(B0, B1, 0x33); \
|
||||
B1 = _mm256_permute4x64_epi64(tmp1, _MM_SHUFFLE(2,3,0,1)); \
|
||||
B0 = _mm256_permute4x64_epi64(tmp2, _MM_SHUFFLE(2,3,0,1)); \
|
||||
\
|
||||
tmp1 = C0; \
|
||||
C0 = C1; \
|
||||
C1 = tmp1; \
|
||||
\
|
||||
tmp1 = _mm256_blend_epi32(D0, D1, 0xCC); \
|
||||
tmp2 = _mm256_blend_epi32(D0, D1, 0x33); \
|
||||
D0 = _mm256_permute4x64_epi64(tmp1, _MM_SHUFFLE(2,3,0,1)); \
|
||||
D1 = _mm256_permute4x64_epi64(tmp2, _MM_SHUFFLE(2,3,0,1)); \
|
||||
} while(0);
|
||||
|
||||
#define UNDIAGONALIZE_1(A0, B0, C0, D0, A1, B1, C1, D1) \
|
||||
do { \
|
||||
B0 = _mm256_permute4x64_epi64(B0, _MM_SHUFFLE(2, 1, 0, 3)); \
|
||||
C0 = _mm256_permute4x64_epi64(C0, _MM_SHUFFLE(1, 0, 3, 2)); \
|
||||
D0 = _mm256_permute4x64_epi64(D0, _MM_SHUFFLE(0, 3, 2, 1)); \
|
||||
\
|
||||
B1 = _mm256_permute4x64_epi64(B1, _MM_SHUFFLE(2, 1, 0, 3)); \
|
||||
C1 = _mm256_permute4x64_epi64(C1, _MM_SHUFFLE(1, 0, 3, 2)); \
|
||||
D1 = _mm256_permute4x64_epi64(D1, _MM_SHUFFLE(0, 3, 2, 1)); \
|
||||
} while((void)0, 0);
|
||||
|
||||
#define UNDIAGONALIZE_2(A0, A1, B0, B1, C0, C1, D0, D1) \
|
||||
do { \
|
||||
__m256i tmp1 = _mm256_blend_epi32(B0, B1, 0xCC); \
|
||||
__m256i tmp2 = _mm256_blend_epi32(B0, B1, 0x33); \
|
||||
B0 = _mm256_permute4x64_epi64(tmp1, _MM_SHUFFLE(2,3,0,1)); \
|
||||
B1 = _mm256_permute4x64_epi64(tmp2, _MM_SHUFFLE(2,3,0,1)); \
|
||||
\
|
||||
tmp1 = C0; \
|
||||
C0 = C1; \
|
||||
C1 = tmp1; \
|
||||
\
|
||||
tmp1 = _mm256_blend_epi32(D0, D1, 0x33); \
|
||||
tmp2 = _mm256_blend_epi32(D0, D1, 0xCC); \
|
||||
D0 = _mm256_permute4x64_epi64(tmp1, _MM_SHUFFLE(2,3,0,1)); \
|
||||
D1 = _mm256_permute4x64_epi64(tmp2, _MM_SHUFFLE(2,3,0,1)); \
|
||||
} while((void)0, 0);
|
||||
|
||||
#define BLAKE2_ROUND_1(A0, A1, B0, B1, C0, C1, D0, D1) \
|
||||
do{ \
|
||||
G1_AVX2(A0, A1, B0, B1, C0, C1, D0, D1) \
|
||||
G2_AVX2(A0, A1, B0, B1, C0, C1, D0, D1) \
|
||||
\
|
||||
DIAGONALIZE_1(A0, B0, C0, D0, A1, B1, C1, D1) \
|
||||
\
|
||||
G1_AVX2(A0, A1, B0, B1, C0, C1, D0, D1) \
|
||||
G2_AVX2(A0, A1, B0, B1, C0, C1, D0, D1) \
|
||||
\
|
||||
UNDIAGONALIZE_1(A0, B0, C0, D0, A1, B1, C1, D1) \
|
||||
} while((void)0, 0);
|
||||
|
||||
#define BLAKE2_ROUND_2(A0, A1, B0, B1, C0, C1, D0, D1) \
|
||||
do{ \
|
||||
G1_AVX2(A0, A1, B0, B1, C0, C1, D0, D1) \
|
||||
G2_AVX2(A0, A1, B0, B1, C0, C1, D0, D1) \
|
||||
\
|
||||
DIAGONALIZE_2(A0, A1, B0, B1, C0, C1, D0, D1) \
|
||||
\
|
||||
G1_AVX2(A0, A1, B0, B1, C0, C1, D0, D1) \
|
||||
G2_AVX2(A0, A1, B0, B1, C0, C1, D0, D1) \
|
||||
\
|
||||
UNDIAGONALIZE_2(A0, A1, B0, B1, C0, C1, D0, D1) \
|
||||
} while((void)0, 0);
|
||||
|
||||
#endif /* __AVX2__ */
|
||||
|
||||
#else /* __AVX512F__ */
|
||||
|
||||
#include <immintrin.h>
|
||||
|
||||
#define ror64(x, n) _mm512_ror_epi64((x), (n))
|
||||
|
||||
static __m512i muladd(__m512i x, __m512i y)
|
||||
{
|
||||
__m512i z = _mm512_mul_epu32(x, y);
|
||||
return _mm512_add_epi64(_mm512_add_epi64(x, y), _mm512_add_epi64(z, z));
|
||||
}
|
||||
|
||||
#define G1(A0, B0, C0, D0, A1, B1, C1, D1) \
|
||||
do { \
|
||||
A0 = muladd(A0, B0); \
|
||||
A1 = muladd(A1, B1); \
|
||||
\
|
||||
D0 = _mm512_xor_si512(D0, A0); \
|
||||
D1 = _mm512_xor_si512(D1, A1); \
|
||||
\
|
||||
D0 = ror64(D0, 32); \
|
||||
D1 = ror64(D1, 32); \
|
||||
\
|
||||
C0 = muladd(C0, D0); \
|
||||
C1 = muladd(C1, D1); \
|
||||
\
|
||||
B0 = _mm512_xor_si512(B0, C0); \
|
||||
B1 = _mm512_xor_si512(B1, C1); \
|
||||
\
|
||||
B0 = ror64(B0, 24); \
|
||||
B1 = ror64(B1, 24); \
|
||||
} while ((void)0, 0)
|
||||
|
||||
#define G2(A0, B0, C0, D0, A1, B1, C1, D1) \
|
||||
do { \
|
||||
A0 = muladd(A0, B0); \
|
||||
A1 = muladd(A1, B1); \
|
||||
\
|
||||
D0 = _mm512_xor_si512(D0, A0); \
|
||||
D1 = _mm512_xor_si512(D1, A1); \
|
||||
\
|
||||
D0 = ror64(D0, 16); \
|
||||
D1 = ror64(D1, 16); \
|
||||
\
|
||||
C0 = muladd(C0, D0); \
|
||||
C1 = muladd(C1, D1); \
|
||||
\
|
||||
B0 = _mm512_xor_si512(B0, C0); \
|
||||
B1 = _mm512_xor_si512(B1, C1); \
|
||||
\
|
||||
B0 = ror64(B0, 63); \
|
||||
B1 = ror64(B1, 63); \
|
||||
} while ((void)0, 0)
|
||||
|
||||
#define DIAGONALIZE(A0, B0, C0, D0, A1, B1, C1, D1) \
|
||||
do { \
|
||||
B0 = _mm512_permutex_epi64(B0, _MM_SHUFFLE(0, 3, 2, 1)); \
|
||||
B1 = _mm512_permutex_epi64(B1, _MM_SHUFFLE(0, 3, 2, 1)); \
|
||||
\
|
||||
C0 = _mm512_permutex_epi64(C0, _MM_SHUFFLE(1, 0, 3, 2)); \
|
||||
C1 = _mm512_permutex_epi64(C1, _MM_SHUFFLE(1, 0, 3, 2)); \
|
||||
\
|
||||
D0 = _mm512_permutex_epi64(D0, _MM_SHUFFLE(2, 1, 0, 3)); \
|
||||
D1 = _mm512_permutex_epi64(D1, _MM_SHUFFLE(2, 1, 0, 3)); \
|
||||
} while ((void)0, 0)
|
||||
|
||||
#define UNDIAGONALIZE(A0, B0, C0, D0, A1, B1, C1, D1) \
|
||||
do { \
|
||||
B0 = _mm512_permutex_epi64(B0, _MM_SHUFFLE(2, 1, 0, 3)); \
|
||||
B1 = _mm512_permutex_epi64(B1, _MM_SHUFFLE(2, 1, 0, 3)); \
|
||||
\
|
||||
C0 = _mm512_permutex_epi64(C0, _MM_SHUFFLE(1, 0, 3, 2)); \
|
||||
C1 = _mm512_permutex_epi64(C1, _MM_SHUFFLE(1, 0, 3, 2)); \
|
||||
\
|
||||
D0 = _mm512_permutex_epi64(D0, _MM_SHUFFLE(0, 3, 2, 1)); \
|
||||
D1 = _mm512_permutex_epi64(D1, _MM_SHUFFLE(0, 3, 2, 1)); \
|
||||
} while ((void)0, 0)
|
||||
|
||||
#define BLAKE2_ROUND(A0, B0, C0, D0, A1, B1, C1, D1) \
|
||||
do { \
|
||||
G1(A0, B0, C0, D0, A1, B1, C1, D1); \
|
||||
G2(A0, B0, C0, D0, A1, B1, C1, D1); \
|
||||
\
|
||||
DIAGONALIZE(A0, B0, C0, D0, A1, B1, C1, D1); \
|
||||
\
|
||||
G1(A0, B0, C0, D0, A1, B1, C1, D1); \
|
||||
G2(A0, B0, C0, D0, A1, B1, C1, D1); \
|
||||
\
|
||||
UNDIAGONALIZE(A0, B0, C0, D0, A1, B1, C1, D1); \
|
||||
} while ((void)0, 0)
|
||||
|
||||
#define SWAP_HALVES(A0, A1) \
|
||||
do { \
|
||||
__m512i t0, t1; \
|
||||
t0 = _mm512_shuffle_i64x2(A0, A1, _MM_SHUFFLE(1, 0, 1, 0)); \
|
||||
t1 = _mm512_shuffle_i64x2(A0, A1, _MM_SHUFFLE(3, 2, 3, 2)); \
|
||||
A0 = t0; \
|
||||
A1 = t1; \
|
||||
} while((void)0, 0)
|
||||
|
||||
#define SWAP_QUARTERS(A0, A1) \
|
||||
do { \
|
||||
SWAP_HALVES(A0, A1); \
|
||||
A0 = _mm512_permutexvar_epi64(_mm512_setr_epi64(0, 1, 4, 5, 2, 3, 6, 7), A0); \
|
||||
A1 = _mm512_permutexvar_epi64(_mm512_setr_epi64(0, 1, 4, 5, 2, 3, 6, 7), A1); \
|
||||
} while((void)0, 0)
|
||||
|
||||
#define UNSWAP_QUARTERS(A0, A1) \
|
||||
do { \
|
||||
A0 = _mm512_permutexvar_epi64(_mm512_setr_epi64(0, 1, 4, 5, 2, 3, 6, 7), A0); \
|
||||
A1 = _mm512_permutexvar_epi64(_mm512_setr_epi64(0, 1, 4, 5, 2, 3, 6, 7), A1); \
|
||||
SWAP_HALVES(A0, A1); \
|
||||
} while((void)0, 0)
|
||||
|
||||
#define BLAKE2_ROUND_1(A0, C0, B0, D0, A1, C1, B1, D1) \
|
||||
do { \
|
||||
SWAP_HALVES(A0, B0); \
|
||||
SWAP_HALVES(C0, D0); \
|
||||
SWAP_HALVES(A1, B1); \
|
||||
SWAP_HALVES(C1, D1); \
|
||||
BLAKE2_ROUND(A0, B0, C0, D0, A1, B1, C1, D1); \
|
||||
SWAP_HALVES(A0, B0); \
|
||||
SWAP_HALVES(C0, D0); \
|
||||
SWAP_HALVES(A1, B1); \
|
||||
SWAP_HALVES(C1, D1); \
|
||||
} while ((void)0, 0)
|
||||
|
||||
#define BLAKE2_ROUND_2(A0, A1, B0, B1, C0, C1, D0, D1) \
|
||||
do { \
|
||||
SWAP_QUARTERS(A0, A1); \
|
||||
SWAP_QUARTERS(B0, B1); \
|
||||
SWAP_QUARTERS(C0, C1); \
|
||||
SWAP_QUARTERS(D0, D1); \
|
||||
BLAKE2_ROUND(A0, B0, C0, D0, A1, B1, C1, D1); \
|
||||
UNSWAP_QUARTERS(A0, A1); \
|
||||
UNSWAP_QUARTERS(B0, B1); \
|
||||
UNSWAP_QUARTERS(C0, C1); \
|
||||
UNSWAP_QUARTERS(D0, D1); \
|
||||
} while ((void)0, 0)
|
||||
|
||||
#endif /* __AVX512F__ */
|
||||
#endif /* BLAKE_ROUND_MKA_OPT_H */
|
||||
56
lib/crypto_backend/argon2/blake2/blamka-round-ref.h
Normal file
56
lib/crypto_backend/argon2/blake2/blamka-round-ref.h
Normal file
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Argon2 reference source code package - reference C implementations
|
||||
*
|
||||
* Copyright 2015
|
||||
* Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves
|
||||
*
|
||||
* You may use this work under the terms of a Creative Commons CC0 1.0
|
||||
* License/Waiver or the Apache Public License 2.0, at your option. The terms of
|
||||
* these licenses can be found at:
|
||||
*
|
||||
* - CC0 1.0 Universal : https://creativecommons.org/publicdomain/zero/1.0
|
||||
* - Apache 2.0 : https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* You should have received a copy of both of these licenses along with this
|
||||
* software. If not, they may be obtained at the above URLs.
|
||||
*/
|
||||
|
||||
#ifndef BLAKE_ROUND_MKA_H
|
||||
#define BLAKE_ROUND_MKA_H
|
||||
|
||||
#include "blake2.h"
|
||||
#include "blake2-impl.h"
|
||||
|
||||
/* designed by the Lyra PHC team */
|
||||
static BLAKE2_INLINE uint64_t fBlaMka(uint64_t x, uint64_t y) {
|
||||
const uint64_t m = UINT64_C(0xFFFFFFFF);
|
||||
const uint64_t xy = (x & m) * (y & m);
|
||||
return x + y + 2 * xy;
|
||||
}
|
||||
|
||||
#define G(a, b, c, d) \
|
||||
do { \
|
||||
a = fBlaMka(a, b); \
|
||||
d = rotr64(d ^ a, 32); \
|
||||
c = fBlaMka(c, d); \
|
||||
b = rotr64(b ^ c, 24); \
|
||||
a = fBlaMka(a, b); \
|
||||
d = rotr64(d ^ a, 16); \
|
||||
c = fBlaMka(c, d); \
|
||||
b = rotr64(b ^ c, 63); \
|
||||
} while ((void)0, 0)
|
||||
|
||||
#define BLAKE2_ROUND_NOMSG(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, \
|
||||
v12, v13, v14, v15) \
|
||||
do { \
|
||||
G(v0, v4, v8, v12); \
|
||||
G(v1, v5, v9, v13); \
|
||||
G(v2, v6, v10, v14); \
|
||||
G(v3, v7, v11, v15); \
|
||||
G(v0, v5, v10, v15); \
|
||||
G(v1, v6, v11, v12); \
|
||||
G(v2, v7, v8, v13); \
|
||||
G(v3, v4, v9, v14); \
|
||||
} while ((void)0, 0)
|
||||
|
||||
#endif
|
||||
641
lib/crypto_backend/argon2/core.c
Normal file
641
lib/crypto_backend/argon2/core.c
Normal file
@@ -0,0 +1,641 @@
|
||||
/*
|
||||
* Argon2 reference source code package - reference C implementations
|
||||
*
|
||||
* Copyright 2015
|
||||
* Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves
|
||||
*
|
||||
* You may use this work under the terms of a Creative Commons CC0 1.0
|
||||
* License/Waiver or the Apache Public License 2.0, at your option. The terms of
|
||||
* these licenses can be found at:
|
||||
*
|
||||
* - CC0 1.0 Universal : https://creativecommons.org/publicdomain/zero/1.0
|
||||
* - Apache 2.0 : https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* You should have received a copy of both of these licenses along with this
|
||||
* software. If not, they may be obtained at the above URLs.
|
||||
*/
|
||||
|
||||
/*For memory wiping*/
|
||||
#ifdef _MSC_VER
|
||||
#include <windows.h>
|
||||
#include <winbase.h> /* For SecureZeroMemory */
|
||||
#endif
|
||||
#if defined __STDC_LIB_EXT1__
|
||||
#define __STDC_WANT_LIB_EXT1__ 1
|
||||
#endif
|
||||
#define VC_GE_2005(version) (version >= 1400)
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "core.h"
|
||||
#include "thread.h"
|
||||
#include "blake2/blake2.h"
|
||||
#include "blake2/blake2-impl.h"
|
||||
|
||||
#ifdef GENKAT
|
||||
#include "genkat.h"
|
||||
#endif
|
||||
|
||||
#if defined(__clang__)
|
||||
#if __has_attribute(optnone)
|
||||
#define NOT_OPTIMIZED __attribute__((optnone))
|
||||
#endif
|
||||
#elif defined(__GNUC__)
|
||||
#define GCC_VERSION \
|
||||
(__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
|
||||
#if GCC_VERSION >= 40400
|
||||
#define NOT_OPTIMIZED __attribute__((optimize("O0")))
|
||||
#endif
|
||||
#endif
|
||||
#ifndef NOT_OPTIMIZED
|
||||
#define NOT_OPTIMIZED
|
||||
#endif
|
||||
|
||||
/***************Instance and Position constructors**********/
|
||||
void init_block_value(block *b, uint8_t in) { memset(b->v, in, sizeof(b->v)); }
|
||||
|
||||
void copy_block(block *dst, const block *src) {
|
||||
memcpy(dst->v, src->v, sizeof(uint64_t) * ARGON2_QWORDS_IN_BLOCK);
|
||||
}
|
||||
|
||||
void xor_block(block *dst, const block *src) {
|
||||
int i;
|
||||
for (i = 0; i < ARGON2_QWORDS_IN_BLOCK; ++i) {
|
||||
dst->v[i] ^= src->v[i];
|
||||
}
|
||||
}
|
||||
|
||||
static void load_block(block *dst, const void *input) {
|
||||
unsigned i;
|
||||
for (i = 0; i < ARGON2_QWORDS_IN_BLOCK; ++i) {
|
||||
dst->v[i] = load64((const uint8_t *)input + i * sizeof(dst->v[i]));
|
||||
}
|
||||
}
|
||||
|
||||
static void store_block(void *output, const block *src) {
|
||||
unsigned i;
|
||||
for (i = 0; i < ARGON2_QWORDS_IN_BLOCK; ++i) {
|
||||
store64((uint8_t *)output + i * sizeof(src->v[i]), src->v[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/***************Memory functions*****************/
|
||||
|
||||
int allocate_memory(const argon2_context *context, uint8_t **memory,
|
||||
size_t num, size_t size) {
|
||||
size_t memory_size = num*size;
|
||||
if (memory == NULL) {
|
||||
return ARGON2_MEMORY_ALLOCATION_ERROR;
|
||||
}
|
||||
|
||||
/* 1. Check for multiplication overflow */
|
||||
if (size != 0 && memory_size / size != num) {
|
||||
return ARGON2_MEMORY_ALLOCATION_ERROR;
|
||||
}
|
||||
|
||||
/* 2. Try to allocate with appropriate allocator */
|
||||
if (context->allocate_cbk) {
|
||||
(context->allocate_cbk)(memory, memory_size);
|
||||
} else {
|
||||
*memory = malloc(memory_size);
|
||||
}
|
||||
|
||||
if (*memory == NULL) {
|
||||
return ARGON2_MEMORY_ALLOCATION_ERROR;
|
||||
}
|
||||
|
||||
return ARGON2_OK;
|
||||
}
|
||||
|
||||
void free_memory(const argon2_context *context, uint8_t *memory,
|
||||
size_t num, size_t size) {
|
||||
size_t memory_size = num*size;
|
||||
clear_internal_memory(memory, memory_size);
|
||||
if (context->free_cbk) {
|
||||
(context->free_cbk)(memory, memory_size);
|
||||
} else {
|
||||
free(memory);
|
||||
}
|
||||
}
|
||||
|
||||
void NOT_OPTIMIZED secure_wipe_memory(void *v, size_t n) {
|
||||
#if defined(_MSC_VER) && VC_GE_2005(_MSC_VER)
|
||||
SecureZeroMemory(v, n);
|
||||
#elif defined memset_s
|
||||
memset_s(v, n, 0, n);
|
||||
#elif defined(HAVE_EXPLICIT_BZERO)
|
||||
explicit_bzero(v, n);
|
||||
#else
|
||||
static void *(*const volatile memset_sec)(void *, int, size_t) = &memset;
|
||||
memset_sec(v, 0, n);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Memory clear flag defaults to true. */
|
||||
int FLAG_clear_internal_memory = 1;
|
||||
void clear_internal_memory(void *v, size_t n) {
|
||||
if (FLAG_clear_internal_memory && v) {
|
||||
secure_wipe_memory(v, n);
|
||||
}
|
||||
}
|
||||
|
||||
void finalize(const argon2_context *context, argon2_instance_t *instance) {
|
||||
if (context != NULL && instance != NULL) {
|
||||
block blockhash;
|
||||
uint32_t l;
|
||||
|
||||
copy_block(&blockhash, instance->memory + instance->lane_length - 1);
|
||||
|
||||
/* XOR the last blocks */
|
||||
for (l = 1; l < instance->lanes; ++l) {
|
||||
uint32_t last_block_in_lane =
|
||||
l * instance->lane_length + (instance->lane_length - 1);
|
||||
xor_block(&blockhash, instance->memory + last_block_in_lane);
|
||||
}
|
||||
|
||||
/* Hash the result */
|
||||
{
|
||||
uint8_t blockhash_bytes[ARGON2_BLOCK_SIZE];
|
||||
store_block(blockhash_bytes, &blockhash);
|
||||
blake2b_long(context->out, context->outlen, blockhash_bytes,
|
||||
ARGON2_BLOCK_SIZE);
|
||||
/* clear blockhash and blockhash_bytes */
|
||||
clear_internal_memory(blockhash.v, ARGON2_BLOCK_SIZE);
|
||||
clear_internal_memory(blockhash_bytes, ARGON2_BLOCK_SIZE);
|
||||
}
|
||||
|
||||
#ifdef GENKAT
|
||||
print_tag(context->out, context->outlen);
|
||||
#endif
|
||||
|
||||
free_memory(context, (uint8_t *)instance->memory,
|
||||
instance->memory_blocks, sizeof(block));
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t index_alpha(const argon2_instance_t *instance,
|
||||
const argon2_position_t *position, uint32_t pseudo_rand,
|
||||
int same_lane) {
|
||||
/*
|
||||
* Pass 0:
|
||||
* This lane : all already finished segments plus already constructed
|
||||
* blocks in this segment
|
||||
* Other lanes : all already finished segments
|
||||
* Pass 1+:
|
||||
* This lane : (SYNC_POINTS - 1) last segments plus already constructed
|
||||
* blocks in this segment
|
||||
* Other lanes : (SYNC_POINTS - 1) last segments
|
||||
*/
|
||||
uint32_t reference_area_size;
|
||||
uint64_t relative_position;
|
||||
uint32_t start_position, absolute_position;
|
||||
|
||||
if (0 == position->pass) {
|
||||
/* First pass */
|
||||
if (0 == position->slice) {
|
||||
/* First slice */
|
||||
reference_area_size =
|
||||
position->index - 1; /* all but the previous */
|
||||
} else {
|
||||
if (same_lane) {
|
||||
/* The same lane => add current segment */
|
||||
reference_area_size =
|
||||
position->slice * instance->segment_length +
|
||||
position->index - 1;
|
||||
} else {
|
||||
reference_area_size =
|
||||
position->slice * instance->segment_length +
|
||||
((position->index == 0) ? (-1) : 0);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* Second pass */
|
||||
if (same_lane) {
|
||||
reference_area_size = instance->lane_length -
|
||||
instance->segment_length + position->index -
|
||||
1;
|
||||
} else {
|
||||
reference_area_size = instance->lane_length -
|
||||
instance->segment_length +
|
||||
((position->index == 0) ? (-1) : 0);
|
||||
}
|
||||
}
|
||||
|
||||
/* 1.2.4. Mapping pseudo_rand to 0..<reference_area_size-1> and produce
|
||||
* relative position */
|
||||
relative_position = pseudo_rand;
|
||||
relative_position = relative_position * relative_position >> 32;
|
||||
relative_position = reference_area_size - 1 -
|
||||
(reference_area_size * relative_position >> 32);
|
||||
|
||||
/* 1.2.5 Computing starting position */
|
||||
start_position = 0;
|
||||
|
||||
if (0 != position->pass) {
|
||||
start_position = (position->slice == ARGON2_SYNC_POINTS - 1)
|
||||
? 0
|
||||
: (position->slice + 1) * instance->segment_length;
|
||||
}
|
||||
|
||||
/* 1.2.6. Computing absolute position */
|
||||
absolute_position = (start_position + relative_position) %
|
||||
instance->lane_length; /* absolute position */
|
||||
return absolute_position;
|
||||
}
|
||||
|
||||
/* Single-threaded version for p=1 case */
|
||||
static int fill_memory_blocks_st(argon2_instance_t *instance) {
|
||||
uint32_t r, s, l;
|
||||
|
||||
for (r = 0; r < instance->passes; ++r) {
|
||||
for (s = 0; s < ARGON2_SYNC_POINTS; ++s) {
|
||||
for (l = 0; l < instance->lanes; ++l) {
|
||||
argon2_position_t position = {r, l, (uint8_t)s, 0};
|
||||
fill_segment(instance, position);
|
||||
}
|
||||
}
|
||||
#ifdef GENKAT
|
||||
internal_kat(instance, r); /* Print all memory blocks */
|
||||
#endif
|
||||
}
|
||||
return ARGON2_OK;
|
||||
}
|
||||
|
||||
#if !defined(ARGON2_NO_THREADS)
|
||||
|
||||
#ifdef _WIN32
|
||||
static unsigned __stdcall fill_segment_thr(void *thread_data)
|
||||
#else
|
||||
static void *fill_segment_thr(void *thread_data)
|
||||
#endif
|
||||
{
|
||||
argon2_thread_data *my_data = thread_data;
|
||||
fill_segment(my_data->instance_ptr, my_data->pos);
|
||||
argon2_thread_exit();
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Multi-threaded version for p > 1 case */
|
||||
static int fill_memory_blocks_mt(argon2_instance_t *instance) {
|
||||
uint32_t r, s;
|
||||
argon2_thread_handle_t *thread = NULL;
|
||||
argon2_thread_data *thr_data = NULL;
|
||||
int rc = ARGON2_OK;
|
||||
|
||||
/* 1. Allocating space for threads */
|
||||
thread = calloc(instance->lanes, sizeof(argon2_thread_handle_t));
|
||||
if (thread == NULL) {
|
||||
rc = ARGON2_MEMORY_ALLOCATION_ERROR;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
thr_data = calloc(instance->lanes, sizeof(argon2_thread_data));
|
||||
if (thr_data == NULL) {
|
||||
rc = ARGON2_MEMORY_ALLOCATION_ERROR;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
for (r = 0; r < instance->passes; ++r) {
|
||||
for (s = 0; s < ARGON2_SYNC_POINTS; ++s) {
|
||||
uint32_t l, ll;
|
||||
|
||||
/* 2. Calling threads */
|
||||
for (l = 0; l < instance->lanes; ++l) {
|
||||
argon2_position_t position;
|
||||
|
||||
/* 2.1 Join a thread if limit is exceeded */
|
||||
if (l >= instance->threads) {
|
||||
if (argon2_thread_join(thread[l - instance->threads])) {
|
||||
rc = ARGON2_THREAD_FAIL;
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
/* 2.2 Create thread */
|
||||
position.pass = r;
|
||||
position.lane = l;
|
||||
position.slice = (uint8_t)s;
|
||||
position.index = 0;
|
||||
thr_data[l].instance_ptr =
|
||||
instance; /* preparing the thread input */
|
||||
memcpy(&(thr_data[l].pos), &position,
|
||||
sizeof(argon2_position_t));
|
||||
if (argon2_thread_create(&thread[l], &fill_segment_thr,
|
||||
(void *)&thr_data[l])) {
|
||||
/* Wait for already running threads */
|
||||
for (ll = 0; ll < l; ++ll)
|
||||
argon2_thread_join(thread[ll]);
|
||||
rc = ARGON2_THREAD_FAIL;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* fill_segment(instance, position); */
|
||||
/*Non-thread equivalent of the lines above */
|
||||
}
|
||||
|
||||
/* 3. Joining remaining threads */
|
||||
for (l = instance->lanes - instance->threads; l < instance->lanes;
|
||||
++l) {
|
||||
if (argon2_thread_join(thread[l])) {
|
||||
rc = ARGON2_THREAD_FAIL;
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef GENKAT
|
||||
internal_kat(instance, r); /* Print all memory blocks */
|
||||
#endif
|
||||
}
|
||||
|
||||
fail:
|
||||
if (thread != NULL) {
|
||||
free(thread);
|
||||
}
|
||||
if (thr_data != NULL) {
|
||||
free(thr_data);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
#endif /* ARGON2_NO_THREADS */
|
||||
|
||||
int fill_memory_blocks(argon2_instance_t *instance) {
|
||||
if (instance == NULL || instance->lanes == 0) {
|
||||
return ARGON2_INCORRECT_PARAMETER;
|
||||
}
|
||||
#if defined(ARGON2_NO_THREADS)
|
||||
return fill_memory_blocks_st(instance);
|
||||
#else
|
||||
return instance->threads == 1 ?
|
||||
fill_memory_blocks_st(instance) : fill_memory_blocks_mt(instance);
|
||||
#endif
|
||||
}
|
||||
|
||||
int validate_inputs(const argon2_context *context) {
|
||||
if (NULL == context) {
|
||||
return ARGON2_INCORRECT_PARAMETER;
|
||||
}
|
||||
|
||||
if (NULL == context->out) {
|
||||
return ARGON2_OUTPUT_PTR_NULL;
|
||||
}
|
||||
|
||||
/* Validate output length */
|
||||
if (ARGON2_MIN_OUTLEN > context->outlen) {
|
||||
return ARGON2_OUTPUT_TOO_SHORT;
|
||||
}
|
||||
|
||||
if (ARGON2_MAX_OUTLEN < context->outlen) {
|
||||
return ARGON2_OUTPUT_TOO_LONG;
|
||||
}
|
||||
|
||||
/* Validate password (required param) */
|
||||
if (NULL == context->pwd) {
|
||||
if (0 != context->pwdlen) {
|
||||
return ARGON2_PWD_PTR_MISMATCH;
|
||||
}
|
||||
}
|
||||
#if ARGON2_MIN_PWD_LENGTH > 0 /* cryptsetup: fix gcc warning */
|
||||
if (ARGON2_MIN_PWD_LENGTH > context->pwdlen) {
|
||||
return ARGON2_PWD_TOO_SHORT;
|
||||
}
|
||||
#endif
|
||||
if (ARGON2_MAX_PWD_LENGTH < context->pwdlen) {
|
||||
return ARGON2_PWD_TOO_LONG;
|
||||
}
|
||||
|
||||
/* Validate salt (required param) */
|
||||
if (NULL == context->salt) {
|
||||
if (0 != context->saltlen) {
|
||||
return ARGON2_SALT_PTR_MISMATCH;
|
||||
}
|
||||
}
|
||||
|
||||
if (ARGON2_MIN_SALT_LENGTH > context->saltlen) {
|
||||
return ARGON2_SALT_TOO_SHORT;
|
||||
}
|
||||
|
||||
if (ARGON2_MAX_SALT_LENGTH < context->saltlen) {
|
||||
return ARGON2_SALT_TOO_LONG;
|
||||
}
|
||||
|
||||
/* Validate secret (optional param) */
|
||||
if (NULL == context->secret) {
|
||||
if (0 != context->secretlen) {
|
||||
return ARGON2_SECRET_PTR_MISMATCH;
|
||||
}
|
||||
} else {
|
||||
#if ARGON2_MIN_SECRET > 0 /* cryptsetup: fix gcc warning */
|
||||
if (ARGON2_MIN_SECRET > context->secretlen) {
|
||||
return ARGON2_SECRET_TOO_SHORT;
|
||||
}
|
||||
#endif
|
||||
if (ARGON2_MAX_SECRET < context->secretlen) {
|
||||
return ARGON2_SECRET_TOO_LONG;
|
||||
}
|
||||
}
|
||||
|
||||
/* Validate associated data (optional param) */
|
||||
if (NULL == context->ad) {
|
||||
if (0 != context->adlen) {
|
||||
return ARGON2_AD_PTR_MISMATCH;
|
||||
}
|
||||
} else {
|
||||
#if ARGON2_MIN_AD_LENGTH > 0 /* cryptsetup: fix gcc warning */
|
||||
if (ARGON2_MIN_AD_LENGTH > context->adlen) {
|
||||
return ARGON2_AD_TOO_SHORT;
|
||||
}
|
||||
#endif
|
||||
if (ARGON2_MAX_AD_LENGTH < context->adlen) {
|
||||
return ARGON2_AD_TOO_LONG;
|
||||
}
|
||||
}
|
||||
|
||||
/* Validate memory cost */
|
||||
if (ARGON2_MIN_MEMORY > context->m_cost) {
|
||||
return ARGON2_MEMORY_TOO_LITTLE;
|
||||
}
|
||||
#if 0 /* UINT32_MAX, cryptsetup: fix gcc warning */
|
||||
if (ARGON2_MAX_MEMORY < context->m_cost) {
|
||||
return ARGON2_MEMORY_TOO_MUCH;
|
||||
}
|
||||
#endif
|
||||
if (context->m_cost < 8 * context->lanes) {
|
||||
return ARGON2_MEMORY_TOO_LITTLE;
|
||||
}
|
||||
|
||||
/* Validate time cost */
|
||||
if (ARGON2_MIN_TIME > context->t_cost) {
|
||||
return ARGON2_TIME_TOO_SMALL;
|
||||
}
|
||||
|
||||
if (ARGON2_MAX_TIME < context->t_cost) {
|
||||
return ARGON2_TIME_TOO_LARGE;
|
||||
}
|
||||
|
||||
/* Validate lanes */
|
||||
if (ARGON2_MIN_LANES > context->lanes) {
|
||||
return ARGON2_LANES_TOO_FEW;
|
||||
}
|
||||
|
||||
if (ARGON2_MAX_LANES < context->lanes) {
|
||||
return ARGON2_LANES_TOO_MANY;
|
||||
}
|
||||
|
||||
/* Validate threads */
|
||||
if (ARGON2_MIN_THREADS > context->threads) {
|
||||
return ARGON2_THREADS_TOO_FEW;
|
||||
}
|
||||
|
||||
if (ARGON2_MAX_THREADS < context->threads) {
|
||||
return ARGON2_THREADS_TOO_MANY;
|
||||
}
|
||||
|
||||
if (NULL != context->allocate_cbk && NULL == context->free_cbk) {
|
||||
return ARGON2_FREE_MEMORY_CBK_NULL;
|
||||
}
|
||||
|
||||
if (NULL == context->allocate_cbk && NULL != context->free_cbk) {
|
||||
return ARGON2_ALLOCATE_MEMORY_CBK_NULL;
|
||||
}
|
||||
|
||||
return ARGON2_OK;
|
||||
}
|
||||
|
||||
void fill_first_blocks(uint8_t *blockhash, const argon2_instance_t *instance) {
|
||||
uint32_t l;
|
||||
/* Make the first and second block in each lane as G(H0||0||i) or
|
||||
G(H0||1||i) */
|
||||
uint8_t blockhash_bytes[ARGON2_BLOCK_SIZE];
|
||||
for (l = 0; l < instance->lanes; ++l) {
|
||||
|
||||
store32(blockhash + ARGON2_PREHASH_DIGEST_LENGTH, 0);
|
||||
store32(blockhash + ARGON2_PREHASH_DIGEST_LENGTH + 4, l);
|
||||
blake2b_long(blockhash_bytes, ARGON2_BLOCK_SIZE, blockhash,
|
||||
ARGON2_PREHASH_SEED_LENGTH);
|
||||
load_block(&instance->memory[l * instance->lane_length + 0],
|
||||
blockhash_bytes);
|
||||
|
||||
store32(blockhash + ARGON2_PREHASH_DIGEST_LENGTH, 1);
|
||||
blake2b_long(blockhash_bytes, ARGON2_BLOCK_SIZE, blockhash,
|
||||
ARGON2_PREHASH_SEED_LENGTH);
|
||||
load_block(&instance->memory[l * instance->lane_length + 1],
|
||||
blockhash_bytes);
|
||||
}
|
||||
clear_internal_memory(blockhash_bytes, ARGON2_BLOCK_SIZE);
|
||||
}
|
||||
|
||||
void initial_hash(uint8_t *blockhash, argon2_context *context,
|
||||
argon2_type type) {
|
||||
blake2b_state BlakeHash;
|
||||
uint8_t value[sizeof(uint32_t)];
|
||||
|
||||
if (NULL == context || NULL == blockhash) {
|
||||
return;
|
||||
}
|
||||
|
||||
blake2b_init(&BlakeHash, ARGON2_PREHASH_DIGEST_LENGTH);
|
||||
|
||||
store32(&value, context->lanes);
|
||||
blake2b_update(&BlakeHash, (const uint8_t *)&value, sizeof(value));
|
||||
|
||||
store32(&value, context->outlen);
|
||||
blake2b_update(&BlakeHash, (const uint8_t *)&value, sizeof(value));
|
||||
|
||||
store32(&value, context->m_cost);
|
||||
blake2b_update(&BlakeHash, (const uint8_t *)&value, sizeof(value));
|
||||
|
||||
store32(&value, context->t_cost);
|
||||
blake2b_update(&BlakeHash, (const uint8_t *)&value, sizeof(value));
|
||||
|
||||
store32(&value, context->version);
|
||||
blake2b_update(&BlakeHash, (const uint8_t *)&value, sizeof(value));
|
||||
|
||||
store32(&value, (uint32_t)type);
|
||||
blake2b_update(&BlakeHash, (const uint8_t *)&value, sizeof(value));
|
||||
|
||||
store32(&value, context->pwdlen);
|
||||
blake2b_update(&BlakeHash, (const uint8_t *)&value, sizeof(value));
|
||||
|
||||
if (context->pwd != NULL) {
|
||||
blake2b_update(&BlakeHash, (const uint8_t *)context->pwd,
|
||||
context->pwdlen);
|
||||
|
||||
if (context->flags & ARGON2_FLAG_CLEAR_PASSWORD) {
|
||||
secure_wipe_memory(context->pwd, context->pwdlen);
|
||||
context->pwdlen = 0;
|
||||
}
|
||||
}
|
||||
|
||||
store32(&value, context->saltlen);
|
||||
blake2b_update(&BlakeHash, (const uint8_t *)&value, sizeof(value));
|
||||
|
||||
if (context->salt != NULL) {
|
||||
blake2b_update(&BlakeHash, (const uint8_t *)context->salt,
|
||||
context->saltlen);
|
||||
}
|
||||
|
||||
store32(&value, context->secretlen);
|
||||
blake2b_update(&BlakeHash, (const uint8_t *)&value, sizeof(value));
|
||||
|
||||
if (context->secret != NULL) {
|
||||
blake2b_update(&BlakeHash, (const uint8_t *)context->secret,
|
||||
context->secretlen);
|
||||
|
||||
if (context->flags & ARGON2_FLAG_CLEAR_SECRET) {
|
||||
secure_wipe_memory(context->secret, context->secretlen);
|
||||
context->secretlen = 0;
|
||||
}
|
||||
}
|
||||
|
||||
store32(&value, context->adlen);
|
||||
blake2b_update(&BlakeHash, (const uint8_t *)&value, sizeof(value));
|
||||
|
||||
if (context->ad != NULL) {
|
||||
blake2b_update(&BlakeHash, (const uint8_t *)context->ad,
|
||||
context->adlen);
|
||||
}
|
||||
|
||||
blake2b_final(&BlakeHash, blockhash, ARGON2_PREHASH_DIGEST_LENGTH);
|
||||
}
|
||||
|
||||
int initialize(argon2_instance_t *instance, argon2_context *context) {
|
||||
uint8_t blockhash[ARGON2_PREHASH_SEED_LENGTH];
|
||||
int result = ARGON2_OK;
|
||||
|
||||
if (instance == NULL || context == NULL)
|
||||
return ARGON2_INCORRECT_PARAMETER;
|
||||
instance->context_ptr = context;
|
||||
|
||||
/* 1. Memory allocation */
|
||||
result = allocate_memory(context, (uint8_t **)&(instance->memory),
|
||||
instance->memory_blocks, sizeof(block));
|
||||
if (result != ARGON2_OK) {
|
||||
return result;
|
||||
}
|
||||
|
||||
/* 2. Initial hashing */
|
||||
/* H_0 + 8 extra bytes to produce the first blocks */
|
||||
/* uint8_t blockhash[ARGON2_PREHASH_SEED_LENGTH]; */
|
||||
/* Hashing all inputs */
|
||||
initial_hash(blockhash, context, instance->type);
|
||||
/* Zeroing 8 extra bytes */
|
||||
clear_internal_memory(blockhash + ARGON2_PREHASH_DIGEST_LENGTH,
|
||||
ARGON2_PREHASH_SEED_LENGTH -
|
||||
ARGON2_PREHASH_DIGEST_LENGTH);
|
||||
|
||||
#ifdef GENKAT
|
||||
initial_kat(blockhash, context, instance->type);
|
||||
#endif
|
||||
|
||||
/* 3. Creating first blocks, we always have at least two blocks in a slice
|
||||
*/
|
||||
fill_first_blocks(blockhash, instance);
|
||||
/* Clearing the hash */
|
||||
clear_internal_memory(blockhash, ARGON2_PREHASH_SEED_LENGTH);
|
||||
|
||||
return ARGON2_OK;
|
||||
}
|
||||
228
lib/crypto_backend/argon2/core.h
Normal file
228
lib/crypto_backend/argon2/core.h
Normal file
@@ -0,0 +1,228 @@
|
||||
/*
|
||||
* Argon2 reference source code package - reference C implementations
|
||||
*
|
||||
* Copyright 2015
|
||||
* Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves
|
||||
*
|
||||
* You may use this work under the terms of a Creative Commons CC0 1.0
|
||||
* License/Waiver or the Apache Public License 2.0, at your option. The terms of
|
||||
* these licenses can be found at:
|
||||
*
|
||||
* - CC0 1.0 Universal : https://creativecommons.org/publicdomain/zero/1.0
|
||||
* - Apache 2.0 : https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* You should have received a copy of both of these licenses along with this
|
||||
* software. If not, they may be obtained at the above URLs.
|
||||
*/
|
||||
|
||||
#ifndef ARGON2_CORE_H
|
||||
#define ARGON2_CORE_H
|
||||
|
||||
#include "argon2.h"
|
||||
|
||||
#define CONST_CAST(x) (x)(uintptr_t)
|
||||
|
||||
/**********************Argon2 internal constants*******************************/
|
||||
|
||||
enum argon2_core_constants {
|
||||
/* Memory block size in bytes */
|
||||
ARGON2_BLOCK_SIZE = 1024,
|
||||
ARGON2_QWORDS_IN_BLOCK = ARGON2_BLOCK_SIZE / 8,
|
||||
ARGON2_OWORDS_IN_BLOCK = ARGON2_BLOCK_SIZE / 16,
|
||||
ARGON2_HWORDS_IN_BLOCK = ARGON2_BLOCK_SIZE / 32,
|
||||
ARGON2_512BIT_WORDS_IN_BLOCK = ARGON2_BLOCK_SIZE / 64,
|
||||
|
||||
/* Number of pseudo-random values generated by one call to Blake in Argon2i
|
||||
to
|
||||
generate reference block positions */
|
||||
ARGON2_ADDRESSES_IN_BLOCK = 128,
|
||||
|
||||
/* Pre-hashing digest length and its extension*/
|
||||
ARGON2_PREHASH_DIGEST_LENGTH = 64,
|
||||
ARGON2_PREHASH_SEED_LENGTH = 72
|
||||
};
|
||||
|
||||
/*************************Argon2 internal data types***********************/
|
||||
|
||||
/*
|
||||
* Structure for the (1KB) memory block implemented as 128 64-bit words.
|
||||
* Memory blocks can be copied, XORed. Internal words can be accessed by [] (no
|
||||
* bounds checking).
|
||||
*/
|
||||
typedef struct block_ { uint64_t v[ARGON2_QWORDS_IN_BLOCK]; } block;
|
||||
|
||||
/*****************Functions that work with the block******************/
|
||||
|
||||
/* Initialize each byte of the block with @in */
|
||||
void init_block_value(block *b, uint8_t in);
|
||||
|
||||
/* Copy block @src to block @dst */
|
||||
void copy_block(block *dst, const block *src);
|
||||
|
||||
/* XOR @src onto @dst bytewise */
|
||||
void xor_block(block *dst, const block *src);
|
||||
|
||||
/*
|
||||
* Argon2 instance: memory pointer, number of passes, amount of memory, type,
|
||||
* and derived values.
|
||||
* Used to evaluate the number and location of blocks to construct in each
|
||||
* thread
|
||||
*/
|
||||
typedef struct Argon2_instance_t {
|
||||
block *memory; /* Memory pointer */
|
||||
uint32_t version;
|
||||
uint32_t passes; /* Number of passes */
|
||||
uint32_t memory_blocks; /* Number of blocks in memory */
|
||||
uint32_t segment_length;
|
||||
uint32_t lane_length;
|
||||
uint32_t lanes;
|
||||
uint32_t threads;
|
||||
argon2_type type;
|
||||
int print_internals; /* whether to print the memory blocks */
|
||||
argon2_context *context_ptr; /* points back to original context */
|
||||
} argon2_instance_t;
|
||||
|
||||
/*
|
||||
* Argon2 position: where we construct the block right now. Used to distribute
|
||||
* work between threads.
|
||||
*/
|
||||
typedef struct Argon2_position_t {
|
||||
uint32_t pass;
|
||||
uint32_t lane;
|
||||
uint8_t slice;
|
||||
uint32_t index;
|
||||
} argon2_position_t;
|
||||
|
||||
/*Struct that holds the inputs for thread handling FillSegment*/
|
||||
typedef struct Argon2_thread_data {
|
||||
argon2_instance_t *instance_ptr;
|
||||
argon2_position_t pos;
|
||||
} argon2_thread_data;
|
||||
|
||||
/*************************Argon2 core functions********************************/
|
||||
|
||||
/* Allocates memory to the given pointer, uses the appropriate allocator as
|
||||
* specified in the context. Total allocated memory is num*size.
|
||||
* @param context argon2_context which specifies the allocator
|
||||
* @param memory pointer to the pointer to the memory
|
||||
* @param size the size in bytes for each element to be allocated
|
||||
* @param num the number of elements to be allocated
|
||||
* @return ARGON2_OK if @memory is a valid pointer and memory is allocated
|
||||
*/
|
||||
int allocate_memory(const argon2_context *context, uint8_t **memory,
|
||||
size_t num, size_t size);
|
||||
|
||||
/*
|
||||
* Frees memory at the given pointer, uses the appropriate deallocator as
|
||||
* specified in the context. Also cleans the memory using clear_internal_memory.
|
||||
* @param context argon2_context which specifies the deallocator
|
||||
* @param memory pointer to buffer to be freed
|
||||
* @param size the size in bytes for each element to be deallocated
|
||||
* @param num the number of elements to be deallocated
|
||||
*/
|
||||
void free_memory(const argon2_context *context, uint8_t *memory,
|
||||
size_t num, size_t size);
|
||||
|
||||
/* Function that securely cleans the memory. This ignores any flags set
|
||||
* regarding clearing memory. Usually one just calls clear_internal_memory.
|
||||
* @param mem Pointer to the memory
|
||||
* @param s Memory size in bytes
|
||||
*/
|
||||
void secure_wipe_memory(void *v, size_t n);
|
||||
|
||||
/* Function that securely clears the memory if FLAG_clear_internal_memory is
|
||||
* set. If the flag isn't set, this function does nothing.
|
||||
* @param mem Pointer to the memory
|
||||
* @param s Memory size in bytes
|
||||
*/
|
||||
void clear_internal_memory(void *v, size_t n);
|
||||
|
||||
/*
|
||||
* Computes absolute position of reference block in the lane following a skewed
|
||||
* distribution and using a pseudo-random value as input
|
||||
* @param instance Pointer to the current instance
|
||||
* @param position Pointer to the current position
|
||||
* @param pseudo_rand 32-bit pseudo-random value used to determine the position
|
||||
* @param same_lane Indicates if the block will be taken from the current lane.
|
||||
* If so we can reference the current segment
|
||||
* @pre All pointers must be valid
|
||||
*/
|
||||
uint32_t index_alpha(const argon2_instance_t *instance,
|
||||
const argon2_position_t *position, uint32_t pseudo_rand,
|
||||
int same_lane);
|
||||
|
||||
/*
|
||||
* Function that validates all inputs against predefined restrictions and return
|
||||
* an error code
|
||||
* @param context Pointer to current Argon2 context
|
||||
* @return ARGON2_OK if everything is all right, otherwise one of error codes
|
||||
* (all defined in <argon2.h>
|
||||
*/
|
||||
int validate_inputs(const argon2_context *context);
|
||||
|
||||
/*
|
||||
* Hashes all the inputs into @a blockhash[PREHASH_DIGEST_LENGTH], clears
|
||||
* password and secret if needed
|
||||
* @param context Pointer to the Argon2 internal structure containing memory
|
||||
* pointer, and parameters for time and space requirements.
|
||||
* @param blockhash Buffer for pre-hashing digest
|
||||
* @param type Argon2 type
|
||||
* @pre @a blockhash must have at least @a PREHASH_DIGEST_LENGTH bytes
|
||||
* allocated
|
||||
*/
|
||||
void initial_hash(uint8_t *blockhash, argon2_context *context,
|
||||
argon2_type type);
|
||||
|
||||
/*
|
||||
* Function creates first 2 blocks per lane
|
||||
* @param instance Pointer to the current instance
|
||||
* @param blockhash Pointer to the pre-hashing digest
|
||||
* @pre blockhash must point to @a PREHASH_SEED_LENGTH allocated values
|
||||
*/
|
||||
void fill_first_blocks(uint8_t *blockhash, const argon2_instance_t *instance);
|
||||
|
||||
/*
|
||||
* Function allocates memory, hashes the inputs with Blake, and creates first
|
||||
* two blocks. Returns the pointer to the main memory with 2 blocks per lane
|
||||
* initialized
|
||||
* @param context Pointer to the Argon2 internal structure containing memory
|
||||
* pointer, and parameters for time and space requirements.
|
||||
* @param instance Current Argon2 instance
|
||||
* @return Zero if successful, -1 if memory failed to allocate. @context->state
|
||||
* will be modified if successful.
|
||||
*/
|
||||
int initialize(argon2_instance_t *instance, argon2_context *context);
|
||||
|
||||
/*
|
||||
* XORing the last block of each lane, hashing it, making the tag. Deallocates
|
||||
* the memory.
|
||||
* @param context Pointer to current Argon2 context (use only the out parameters
|
||||
* from it)
|
||||
* @param instance Pointer to current instance of Argon2
|
||||
* @pre instance->state must point to necessary amount of memory
|
||||
* @pre context->out must point to outlen bytes of memory
|
||||
* @pre if context->free_cbk is not NULL, it should point to a function that
|
||||
* deallocates memory
|
||||
*/
|
||||
void finalize(const argon2_context *context, argon2_instance_t *instance);
|
||||
|
||||
/*
|
||||
* Function that fills the segment using previous segments also from other
|
||||
* threads
|
||||
* @param context current context
|
||||
* @param instance Pointer to the current instance
|
||||
* @param position Current position
|
||||
* @pre all block pointers must be valid
|
||||
*/
|
||||
void fill_segment(const argon2_instance_t *instance,
|
||||
argon2_position_t position);
|
||||
|
||||
/*
|
||||
* Function that fills the entire memory t_cost times based on the first two
|
||||
* blocks in each lane
|
||||
* @param instance Pointer to the current instance
|
||||
* @return ARGON2_OK if successful, @context->state
|
||||
*/
|
||||
int fill_memory_blocks(argon2_instance_t *instance);
|
||||
|
||||
#endif
|
||||
462
lib/crypto_backend/argon2/encoding.c
Normal file
462
lib/crypto_backend/argon2/encoding.c
Normal file
@@ -0,0 +1,462 @@
|
||||
/*
|
||||
* Argon2 reference source code package - reference C implementations
|
||||
*
|
||||
* Copyright 2015
|
||||
* Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves
|
||||
*
|
||||
* You may use this work under the terms of a Creative Commons CC0 1.0
|
||||
* License/Waiver or the Apache Public License 2.0, at your option. The terms of
|
||||
* these licenses can be found at:
|
||||
*
|
||||
* - CC0 1.0 Universal : https://creativecommons.org/publicdomain/zero/1.0
|
||||
* - Apache 2.0 : https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* You should have received a copy of both of these licenses along with this
|
||||
* software. If not, they may be obtained at the above URLs.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <limits.h>
|
||||
#include "encoding.h"
|
||||
#include "core.h"
|
||||
|
||||
/*
|
||||
* Example code for a decoder and encoder of "hash strings", with Argon2
|
||||
* parameters.
|
||||
*
|
||||
* This code comprises three sections:
|
||||
*
|
||||
* -- The first section contains generic Base64 encoding and decoding
|
||||
* functions. It is conceptually applicable to any hash function
|
||||
* implementation that uses Base64 to encode and decode parameters,
|
||||
* salts and outputs. It could be made into a library, provided that
|
||||
* the relevant functions are made public (non-static) and be given
|
||||
* reasonable names to avoid collisions with other functions.
|
||||
*
|
||||
* -- The second section is specific to Argon2. It encodes and decodes
|
||||
* the parameters, salts and outputs. It does not compute the hash
|
||||
* itself.
|
||||
*
|
||||
* The code was originally written by Thomas Pornin <pornin@bolet.org>,
|
||||
* to whom comments and remarks may be sent. It is released under what
|
||||
* should amount to Public Domain or its closest equivalent; the
|
||||
* following mantra is supposed to incarnate that fact with all the
|
||||
* proper legal rituals:
|
||||
*
|
||||
* ---------------------------------------------------------------------
|
||||
* This file is provided under the terms of Creative Commons CC0 1.0
|
||||
* Public Domain Dedication. To the extent possible under law, the
|
||||
* author (Thomas Pornin) has waived all copyright and related or
|
||||
* neighboring rights to this file. This work is published from: Canada.
|
||||
* ---------------------------------------------------------------------
|
||||
*
|
||||
* Copyright (c) 2015 Thomas Pornin
|
||||
*/
|
||||
|
||||
/* ==================================================================== */
|
||||
/*
|
||||
* Common code; could be shared between different hash functions.
|
||||
*
|
||||
* Note: the Base64 functions below assume that uppercase letters (resp.
|
||||
* lowercase letters) have consecutive numerical codes, that fit on 8
|
||||
* bits. All modern systems use ASCII-compatible charsets, where these
|
||||
* properties are true. If you are stuck with a dinosaur of a system
|
||||
* that still defaults to EBCDIC then you already have much bigger
|
||||
* interoperability issues to deal with.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Some macros for constant-time comparisons. These work over values in
|
||||
* the 0..255 range. Returned value is 0x00 on "false", 0xFF on "true".
|
||||
*/
|
||||
#define EQ(x, y) ((((0U - ((unsigned)(x) ^ (unsigned)(y))) >> 8) & 0xFF) ^ 0xFF)
|
||||
#define GT(x, y) ((((unsigned)(y) - (unsigned)(x)) >> 8) & 0xFF)
|
||||
#define GE(x, y) (GT(y, x) ^ 0xFF)
|
||||
#define LT(x, y) GT(y, x)
|
||||
#define LE(x, y) GE(y, x)
|
||||
|
||||
/*
|
||||
* Convert value x (0..63) to corresponding Base64 character.
|
||||
*/
|
||||
static int b64_byte_to_char(unsigned x) {
|
||||
return (LT(x, 26) & (x + 'A')) |
|
||||
(GE(x, 26) & LT(x, 52) & (x + ('a' - 26))) |
|
||||
(GE(x, 52) & LT(x, 62) & (x + ('0' - 52))) | (EQ(x, 62) & '+') |
|
||||
(EQ(x, 63) & '/');
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert character c to the corresponding 6-bit value. If character c
|
||||
* is not a Base64 character, then 0xFF (255) is returned.
|
||||
*/
|
||||
static unsigned b64_char_to_byte(int c) {
|
||||
unsigned x;
|
||||
|
||||
x = (GE(c, 'A') & LE(c, 'Z') & (c - 'A')) |
|
||||
(GE(c, 'a') & LE(c, 'z') & (c - ('a' - 26))) |
|
||||
(GE(c, '0') & LE(c, '9') & (c - ('0' - 52))) | (EQ(c, '+') & 62) |
|
||||
(EQ(c, '/') & 63);
|
||||
return x | (EQ(x, 0) & (EQ(c, 'A') ^ 0xFF));
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert some bytes to Base64. 'dst_len' is the length (in characters)
|
||||
* of the output buffer 'dst'; if that buffer is not large enough to
|
||||
* receive the result (including the terminating 0), then (size_t)-1
|
||||
* is returned. Otherwise, the zero-terminated Base64 string is written
|
||||
* in the buffer, and the output length (counted WITHOUT the terminating
|
||||
* zero) is returned.
|
||||
*/
|
||||
static size_t to_base64(char *dst, size_t dst_len, const void *src,
|
||||
size_t src_len) {
|
||||
size_t olen;
|
||||
const unsigned char *buf;
|
||||
unsigned acc, acc_len;
|
||||
|
||||
olen = (src_len / 3) << 2;
|
||||
switch (src_len % 3) {
|
||||
case 2:
|
||||
olen++;
|
||||
/* fall through */
|
||||
case 1:
|
||||
olen += 2;
|
||||
break;
|
||||
}
|
||||
if (dst_len <= olen) {
|
||||
return (size_t)-1;
|
||||
}
|
||||
acc = 0;
|
||||
acc_len = 0;
|
||||
buf = (const unsigned char *)src;
|
||||
while (src_len-- > 0) {
|
||||
acc = (acc << 8) + (*buf++);
|
||||
acc_len += 8;
|
||||
while (acc_len >= 6) {
|
||||
acc_len -= 6;
|
||||
*dst++ = (char)b64_byte_to_char((acc >> acc_len) & 0x3F);
|
||||
}
|
||||
}
|
||||
if (acc_len > 0) {
|
||||
*dst++ = (char)b64_byte_to_char((acc << (6 - acc_len)) & 0x3F);
|
||||
}
|
||||
*dst++ = 0;
|
||||
return olen;
|
||||
}
|
||||
|
||||
/*
|
||||
* Decode Base64 chars into bytes. The '*dst_len' value must initially
|
||||
* contain the length of the output buffer '*dst'; when the decoding
|
||||
* ends, the actual number of decoded bytes is written back in
|
||||
* '*dst_len'.
|
||||
*
|
||||
* Decoding stops when a non-Base64 character is encountered, or when
|
||||
* the output buffer capacity is exceeded. If an error occurred (output
|
||||
* buffer is too small, invalid last characters leading to unprocessed
|
||||
* buffered bits), then NULL is returned; otherwise, the returned value
|
||||
* points to the first non-Base64 character in the source stream, which
|
||||
* may be the terminating zero.
|
||||
*/
|
||||
static const char *from_base64(void *dst, size_t *dst_len, const char *src) {
|
||||
size_t len;
|
||||
unsigned char *buf;
|
||||
unsigned acc, acc_len;
|
||||
|
||||
buf = (unsigned char *)dst;
|
||||
len = 0;
|
||||
acc = 0;
|
||||
acc_len = 0;
|
||||
for (;;) {
|
||||
unsigned d;
|
||||
|
||||
d = b64_char_to_byte(*src);
|
||||
if (d == 0xFF) {
|
||||
break;
|
||||
}
|
||||
src++;
|
||||
acc = (acc << 6) + d;
|
||||
acc_len += 6;
|
||||
if (acc_len >= 8) {
|
||||
acc_len -= 8;
|
||||
if ((len++) >= *dst_len) {
|
||||
return NULL;
|
||||
}
|
||||
*buf++ = (acc >> acc_len) & 0xFF;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If the input length is equal to 1 modulo 4 (which is
|
||||
* invalid), then there will remain 6 unprocessed bits;
|
||||
* otherwise, only 0, 2 or 4 bits are buffered. The buffered
|
||||
* bits must also all be zero.
|
||||
*/
|
||||
if (acc_len > 4 || (acc & (((unsigned)1 << acc_len) - 1)) != 0) {
|
||||
return NULL;
|
||||
}
|
||||
*dst_len = len;
|
||||
return src;
|
||||
}
|
||||
|
||||
/*
|
||||
* Decode decimal integer from 'str'; the value is written in '*v'.
|
||||
* Returned value is a pointer to the next non-decimal character in the
|
||||
* string. If there is no digit at all, or the value encoding is not
|
||||
* minimal (extra leading zeros), or the value does not fit in an
|
||||
* 'unsigned long', then NULL is returned.
|
||||
*/
|
||||
static const char *decode_decimal(const char *str, unsigned long *v) {
|
||||
const char *orig;
|
||||
unsigned long acc;
|
||||
|
||||
acc = 0;
|
||||
for (orig = str;; str++) {
|
||||
int c;
|
||||
|
||||
c = *str;
|
||||
if (c < '0' || c > '9') {
|
||||
break;
|
||||
}
|
||||
c -= '0';
|
||||
if (acc > (ULONG_MAX / 10)) {
|
||||
return NULL;
|
||||
}
|
||||
acc *= 10;
|
||||
if ((unsigned long)c > (ULONG_MAX - acc)) {
|
||||
return NULL;
|
||||
}
|
||||
acc += (unsigned long)c;
|
||||
}
|
||||
if (str == orig || (*orig == '0' && str != (orig + 1))) {
|
||||
return NULL;
|
||||
}
|
||||
*v = acc;
|
||||
return str;
|
||||
}
|
||||
|
||||
/* ==================================================================== */
|
||||
/*
|
||||
* Code specific to Argon2.
|
||||
*
|
||||
* The code below applies the following format:
|
||||
*
|
||||
* $argon2<T>[$v=<num>]$m=<num>,t=<num>,p=<num>$<bin>$<bin>
|
||||
*
|
||||
* where <T> is either 'd', 'id', or 'i', <num> is a decimal integer (positive,
|
||||
* fits in an 'unsigned long'), and <bin> is Base64-encoded data (no '=' padding
|
||||
* characters, no newline or whitespace).
|
||||
*
|
||||
* The last two binary chunks (encoded in Base64) are, in that order,
|
||||
* the salt and the output. Both are required. The binary salt length and the
|
||||
* output length must be in the allowed ranges defined in argon2.h.
|
||||
*
|
||||
* The ctx struct must contain buffers large enough to hold the salt and pwd
|
||||
* when it is fed into decode_string.
|
||||
*/
|
||||
|
||||
int decode_string(argon2_context *ctx, const char *str, argon2_type type) {
|
||||
|
||||
/* check for prefix */
|
||||
#define CC(prefix) \
|
||||
do { \
|
||||
size_t cc_len = strlen(prefix); \
|
||||
if (strncmp(str, prefix, cc_len) != 0) { \
|
||||
return ARGON2_DECODING_FAIL; \
|
||||
} \
|
||||
str += cc_len; \
|
||||
} while ((void)0, 0)
|
||||
|
||||
/* optional prefix checking with supplied code */
|
||||
#define CC_opt(prefix, code) \
|
||||
do { \
|
||||
size_t cc_len = strlen(prefix); \
|
||||
if (strncmp(str, prefix, cc_len) == 0) { \
|
||||
str += cc_len; \
|
||||
{ code; } \
|
||||
} \
|
||||
} while ((void)0, 0)
|
||||
|
||||
/* Decoding prefix into decimal */
|
||||
#define DECIMAL(x) \
|
||||
do { \
|
||||
unsigned long dec_x; \
|
||||
str = decode_decimal(str, &dec_x); \
|
||||
if (str == NULL) { \
|
||||
return ARGON2_DECODING_FAIL; \
|
||||
} \
|
||||
(x) = dec_x; \
|
||||
} while ((void)0, 0)
|
||||
|
||||
|
||||
/* Decoding prefix into uint32_t decimal */
|
||||
#define DECIMAL_U32(x) \
|
||||
do { \
|
||||
unsigned long dec_x; \
|
||||
str = decode_decimal(str, &dec_x); \
|
||||
if (str == NULL || dec_x > UINT32_MAX) { \
|
||||
return ARGON2_DECODING_FAIL; \
|
||||
} \
|
||||
(x) = (uint32_t)dec_x; \
|
||||
} while ((void)0, 0)
|
||||
|
||||
|
||||
/* Decoding base64 into a binary buffer */
|
||||
#define BIN(buf, max_len, len) \
|
||||
do { \
|
||||
size_t bin_len = (max_len); \
|
||||
str = from_base64(buf, &bin_len, str); \
|
||||
if (str == NULL || bin_len > UINT32_MAX) { \
|
||||
return ARGON2_DECODING_FAIL; \
|
||||
} \
|
||||
(len) = (uint32_t)bin_len; \
|
||||
} while ((void)0, 0)
|
||||
|
||||
size_t maxsaltlen = ctx->saltlen;
|
||||
size_t maxoutlen = ctx->outlen;
|
||||
int validation_result;
|
||||
const char* type_string;
|
||||
|
||||
/* We should start with the argon2_type we are using */
|
||||
type_string = argon2_type2string(type, 0);
|
||||
if (!type_string) {
|
||||
return ARGON2_INCORRECT_TYPE;
|
||||
}
|
||||
|
||||
CC("$");
|
||||
CC(type_string);
|
||||
|
||||
/* Reading the version number if the default is suppressed */
|
||||
ctx->version = ARGON2_VERSION_10;
|
||||
CC_opt("$v=", DECIMAL_U32(ctx->version));
|
||||
|
||||
CC("$m=");
|
||||
DECIMAL_U32(ctx->m_cost);
|
||||
CC(",t=");
|
||||
DECIMAL_U32(ctx->t_cost);
|
||||
CC(",p=");
|
||||
DECIMAL_U32(ctx->lanes);
|
||||
ctx->threads = ctx->lanes;
|
||||
|
||||
CC("$");
|
||||
BIN(ctx->salt, maxsaltlen, ctx->saltlen);
|
||||
CC("$");
|
||||
BIN(ctx->out, maxoutlen, ctx->outlen);
|
||||
|
||||
/* The rest of the fields get the default values */
|
||||
ctx->secret = NULL;
|
||||
ctx->secretlen = 0;
|
||||
ctx->ad = NULL;
|
||||
ctx->adlen = 0;
|
||||
ctx->allocate_cbk = NULL;
|
||||
ctx->free_cbk = NULL;
|
||||
ctx->flags = ARGON2_DEFAULT_FLAGS;
|
||||
|
||||
/* On return, must have valid context */
|
||||
validation_result = validate_inputs(ctx);
|
||||
if (validation_result != ARGON2_OK) {
|
||||
return validation_result;
|
||||
}
|
||||
|
||||
/* Can't have any additional characters */
|
||||
if (*str == 0) {
|
||||
return ARGON2_OK;
|
||||
} else {
|
||||
return ARGON2_DECODING_FAIL;
|
||||
}
|
||||
#undef CC
|
||||
#undef CC_opt
|
||||
#undef DECIMAL
|
||||
#undef BIN
|
||||
}
|
||||
|
||||
int encode_string(char *dst, size_t dst_len, argon2_context *ctx,
|
||||
argon2_type type) {
|
||||
#define SS(str) \
|
||||
do { \
|
||||
size_t pp_len = strlen(str); \
|
||||
if (pp_len >= dst_len) { \
|
||||
return ARGON2_ENCODING_FAIL; \
|
||||
} \
|
||||
memcpy(dst, str, pp_len + 1); \
|
||||
dst += pp_len; \
|
||||
dst_len -= pp_len; \
|
||||
} while ((void)0, 0)
|
||||
|
||||
#define SX(x) \
|
||||
do { \
|
||||
char tmp[30]; \
|
||||
sprintf(tmp, "%lu", (unsigned long)(x)); \
|
||||
SS(tmp); \
|
||||
} while ((void)0, 0)
|
||||
|
||||
#define SB(buf, len) \
|
||||
do { \
|
||||
size_t sb_len = to_base64(dst, dst_len, buf, len); \
|
||||
if (sb_len == (size_t)-1) { \
|
||||
return ARGON2_ENCODING_FAIL; \
|
||||
} \
|
||||
dst += sb_len; \
|
||||
dst_len -= sb_len; \
|
||||
} while ((void)0, 0)
|
||||
|
||||
const char* type_string = argon2_type2string(type, 0);
|
||||
int validation_result = validate_inputs(ctx);
|
||||
|
||||
if (!type_string) {
|
||||
return ARGON2_ENCODING_FAIL;
|
||||
}
|
||||
|
||||
if (validation_result != ARGON2_OK) {
|
||||
return validation_result;
|
||||
}
|
||||
|
||||
|
||||
SS("$");
|
||||
SS(type_string);
|
||||
|
||||
SS("$v=");
|
||||
SX(ctx->version);
|
||||
|
||||
SS("$m=");
|
||||
SX(ctx->m_cost);
|
||||
SS(",t=");
|
||||
SX(ctx->t_cost);
|
||||
SS(",p=");
|
||||
SX(ctx->lanes);
|
||||
|
||||
SS("$");
|
||||
SB(ctx->salt, ctx->saltlen);
|
||||
|
||||
SS("$");
|
||||
SB(ctx->out, ctx->outlen);
|
||||
return ARGON2_OK;
|
||||
|
||||
#undef SS
|
||||
#undef SX
|
||||
#undef SB
|
||||
}
|
||||
|
||||
size_t b64len(uint32_t len) {
|
||||
size_t olen = ((size_t)len / 3) << 2;
|
||||
|
||||
switch (len % 3) {
|
||||
case 2:
|
||||
olen++;
|
||||
/* fall through */
|
||||
case 1:
|
||||
olen += 2;
|
||||
break;
|
||||
}
|
||||
|
||||
return olen;
|
||||
}
|
||||
|
||||
size_t numlen(uint32_t num) {
|
||||
size_t len = 1;
|
||||
while (num >= 10) {
|
||||
++len;
|
||||
num = num / 10;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
57
lib/crypto_backend/argon2/encoding.h
Normal file
57
lib/crypto_backend/argon2/encoding.h
Normal file
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Argon2 reference source code package - reference C implementations
|
||||
*
|
||||
* Copyright 2015
|
||||
* Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves
|
||||
*
|
||||
* You may use this work under the terms of a Creative Commons CC0 1.0
|
||||
* License/Waiver or the Apache Public License 2.0, at your option. The terms of
|
||||
* these licenses can be found at:
|
||||
*
|
||||
* - CC0 1.0 Universal : https://creativecommons.org/publicdomain/zero/1.0
|
||||
* - Apache 2.0 : https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* You should have received a copy of both of these licenses along with this
|
||||
* software. If not, they may be obtained at the above URLs.
|
||||
*/
|
||||
|
||||
#ifndef ENCODING_H
|
||||
#define ENCODING_H
|
||||
#include "argon2.h"
|
||||
|
||||
#define ARGON2_MAX_DECODED_LANES UINT32_C(255)
|
||||
#define ARGON2_MIN_DECODED_SALT_LEN UINT32_C(8)
|
||||
#define ARGON2_MIN_DECODED_OUT_LEN UINT32_C(12)
|
||||
|
||||
/*
|
||||
* encode an Argon2 hash string into the provided buffer. 'dst_len'
|
||||
* contains the size, in characters, of the 'dst' buffer; if 'dst_len'
|
||||
* is less than the number of required characters (including the
|
||||
* terminating 0), then this function returns ARGON2_ENCODING_ERROR.
|
||||
*
|
||||
* on success, ARGON2_OK is returned.
|
||||
*/
|
||||
int encode_string(char *dst, size_t dst_len, argon2_context *ctx,
|
||||
argon2_type type);
|
||||
|
||||
/*
|
||||
* Decodes an Argon2 hash string into the provided structure 'ctx'.
|
||||
* The only fields that must be set prior to this call are ctx.saltlen and
|
||||
* ctx.outlen (which must be the maximal salt and out length values that are
|
||||
* allowed), ctx.salt and ctx.out (which must be buffers of the specified
|
||||
* length), and ctx.pwd and ctx.pwdlen which must hold a valid password.
|
||||
*
|
||||
* Invalid input string causes an error. On success, the ctx is valid and all
|
||||
* fields have been initialized.
|
||||
*
|
||||
* Returned value is ARGON2_OK on success, other ARGON2_ codes on error.
|
||||
*/
|
||||
int decode_string(argon2_context *ctx, const char *str, argon2_type type);
|
||||
|
||||
/* Returns the length of the encoded byte stream with length len */
|
||||
size_t b64len(uint32_t len);
|
||||
|
||||
/* Returns the length of the encoded number num */
|
||||
size_t numlen(uint32_t num);
|
||||
|
||||
#endif
|
||||
283
lib/crypto_backend/argon2/opt.c
Normal file
283
lib/crypto_backend/argon2/opt.c
Normal file
@@ -0,0 +1,283 @@
|
||||
/*
|
||||
* Argon2 reference source code package - reference C implementations
|
||||
*
|
||||
* Copyright 2015
|
||||
* Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves
|
||||
*
|
||||
* You may use this work under the terms of a Creative Commons CC0 1.0
|
||||
* License/Waiver or the Apache Public License 2.0, at your option. The terms of
|
||||
* these licenses can be found at:
|
||||
*
|
||||
* - CC0 1.0 Universal : https://creativecommons.org/publicdomain/zero/1.0
|
||||
* - Apache 2.0 : https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* You should have received a copy of both of these licenses along with this
|
||||
* software. If not, they may be obtained at the above URLs.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "argon2.h"
|
||||
#include "core.h"
|
||||
|
||||
#include "blake2/blake2.h"
|
||||
#include "blake2/blamka-round-opt.h"
|
||||
|
||||
/*
|
||||
* Function fills a new memory block and optionally XORs the old block over the new one.
|
||||
* Memory must be initialized.
|
||||
* @param state Pointer to the just produced block. Content will be updated(!)
|
||||
* @param ref_block Pointer to the reference block
|
||||
* @param next_block Pointer to the block to be XORed over. May coincide with @ref_block
|
||||
* @param with_xor Whether to XOR into the new block (1) or just overwrite (0)
|
||||
* @pre all block pointers must be valid
|
||||
*/
|
||||
#if defined(__AVX512F__)
|
||||
static void fill_block(__m512i *state, const block *ref_block,
|
||||
block *next_block, int with_xor) {
|
||||
__m512i block_XY[ARGON2_512BIT_WORDS_IN_BLOCK];
|
||||
unsigned int i;
|
||||
|
||||
if (with_xor) {
|
||||
for (i = 0; i < ARGON2_512BIT_WORDS_IN_BLOCK; i++) {
|
||||
state[i] = _mm512_xor_si512(
|
||||
state[i], _mm512_loadu_si512((const __m512i *)ref_block->v + i));
|
||||
block_XY[i] = _mm512_xor_si512(
|
||||
state[i], _mm512_loadu_si512((const __m512i *)next_block->v + i));
|
||||
}
|
||||
} else {
|
||||
for (i = 0; i < ARGON2_512BIT_WORDS_IN_BLOCK; i++) {
|
||||
block_XY[i] = state[i] = _mm512_xor_si512(
|
||||
state[i], _mm512_loadu_si512((const __m512i *)ref_block->v + i));
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < 2; ++i) {
|
||||
BLAKE2_ROUND_1(
|
||||
state[8 * i + 0], state[8 * i + 1], state[8 * i + 2], state[8 * i + 3],
|
||||
state[8 * i + 4], state[8 * i + 5], state[8 * i + 6], state[8 * i + 7]);
|
||||
}
|
||||
|
||||
for (i = 0; i < 2; ++i) {
|
||||
BLAKE2_ROUND_2(
|
||||
state[2 * 0 + i], state[2 * 1 + i], state[2 * 2 + i], state[2 * 3 + i],
|
||||
state[2 * 4 + i], state[2 * 5 + i], state[2 * 6 + i], state[2 * 7 + i]);
|
||||
}
|
||||
|
||||
for (i = 0; i < ARGON2_512BIT_WORDS_IN_BLOCK; i++) {
|
||||
state[i] = _mm512_xor_si512(state[i], block_XY[i]);
|
||||
_mm512_storeu_si512((__m512i *)next_block->v + i, state[i]);
|
||||
}
|
||||
}
|
||||
#elif defined(__AVX2__)
|
||||
static void fill_block(__m256i *state, const block *ref_block,
|
||||
block *next_block, int with_xor) {
|
||||
__m256i block_XY[ARGON2_HWORDS_IN_BLOCK];
|
||||
unsigned int i;
|
||||
|
||||
if (with_xor) {
|
||||
for (i = 0; i < ARGON2_HWORDS_IN_BLOCK; i++) {
|
||||
state[i] = _mm256_xor_si256(
|
||||
state[i], _mm256_loadu_si256((const __m256i *)ref_block->v + i));
|
||||
block_XY[i] = _mm256_xor_si256(
|
||||
state[i], _mm256_loadu_si256((const __m256i *)next_block->v + i));
|
||||
}
|
||||
} else {
|
||||
for (i = 0; i < ARGON2_HWORDS_IN_BLOCK; i++) {
|
||||
block_XY[i] = state[i] = _mm256_xor_si256(
|
||||
state[i], _mm256_loadu_si256((const __m256i *)ref_block->v + i));
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < 4; ++i) {
|
||||
BLAKE2_ROUND_1(state[8 * i + 0], state[8 * i + 4], state[8 * i + 1], state[8 * i + 5],
|
||||
state[8 * i + 2], state[8 * i + 6], state[8 * i + 3], state[8 * i + 7]);
|
||||
}
|
||||
|
||||
for (i = 0; i < 4; ++i) {
|
||||
BLAKE2_ROUND_2(state[ 0 + i], state[ 4 + i], state[ 8 + i], state[12 + i],
|
||||
state[16 + i], state[20 + i], state[24 + i], state[28 + i]);
|
||||
}
|
||||
|
||||
for (i = 0; i < ARGON2_HWORDS_IN_BLOCK; i++) {
|
||||
state[i] = _mm256_xor_si256(state[i], block_XY[i]);
|
||||
_mm256_storeu_si256((__m256i *)next_block->v + i, state[i]);
|
||||
}
|
||||
}
|
||||
#else
|
||||
static void fill_block(__m128i *state, const block *ref_block,
|
||||
block *next_block, int with_xor) {
|
||||
__m128i block_XY[ARGON2_OWORDS_IN_BLOCK];
|
||||
unsigned int i;
|
||||
|
||||
if (with_xor) {
|
||||
for (i = 0; i < ARGON2_OWORDS_IN_BLOCK; i++) {
|
||||
state[i] = _mm_xor_si128(
|
||||
state[i], _mm_loadu_si128((const __m128i *)ref_block->v + i));
|
||||
block_XY[i] = _mm_xor_si128(
|
||||
state[i], _mm_loadu_si128((const __m128i *)next_block->v + i));
|
||||
}
|
||||
} else {
|
||||
for (i = 0; i < ARGON2_OWORDS_IN_BLOCK; i++) {
|
||||
block_XY[i] = state[i] = _mm_xor_si128(
|
||||
state[i], _mm_loadu_si128((const __m128i *)ref_block->v + i));
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < 8; ++i) {
|
||||
BLAKE2_ROUND(state[8 * i + 0], state[8 * i + 1], state[8 * i + 2],
|
||||
state[8 * i + 3], state[8 * i + 4], state[8 * i + 5],
|
||||
state[8 * i + 6], state[8 * i + 7]);
|
||||
}
|
||||
|
||||
for (i = 0; i < 8; ++i) {
|
||||
BLAKE2_ROUND(state[8 * 0 + i], state[8 * 1 + i], state[8 * 2 + i],
|
||||
state[8 * 3 + i], state[8 * 4 + i], state[8 * 5 + i],
|
||||
state[8 * 6 + i], state[8 * 7 + i]);
|
||||
}
|
||||
|
||||
for (i = 0; i < ARGON2_OWORDS_IN_BLOCK; i++) {
|
||||
state[i] = _mm_xor_si128(state[i], block_XY[i]);
|
||||
_mm_storeu_si128((__m128i *)next_block->v + i, state[i]);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static void next_addresses(block *address_block, block *input_block) {
|
||||
/*Temporary zero-initialized blocks*/
|
||||
#if defined(__AVX512F__)
|
||||
__m512i zero_block[ARGON2_512BIT_WORDS_IN_BLOCK];
|
||||
__m512i zero2_block[ARGON2_512BIT_WORDS_IN_BLOCK];
|
||||
#elif defined(__AVX2__)
|
||||
__m256i zero_block[ARGON2_HWORDS_IN_BLOCK];
|
||||
__m256i zero2_block[ARGON2_HWORDS_IN_BLOCK];
|
||||
#else
|
||||
__m128i zero_block[ARGON2_OWORDS_IN_BLOCK];
|
||||
__m128i zero2_block[ARGON2_OWORDS_IN_BLOCK];
|
||||
#endif
|
||||
|
||||
memset(zero_block, 0, sizeof(zero_block));
|
||||
memset(zero2_block, 0, sizeof(zero2_block));
|
||||
|
||||
/*Increasing index counter*/
|
||||
input_block->v[6]++;
|
||||
|
||||
/*First iteration of G*/
|
||||
fill_block(zero_block, input_block, address_block, 0);
|
||||
|
||||
/*Second iteration of G*/
|
||||
fill_block(zero2_block, address_block, address_block, 0);
|
||||
}
|
||||
|
||||
void fill_segment(const argon2_instance_t *instance,
|
||||
argon2_position_t position) {
|
||||
block *ref_block = NULL, *curr_block = NULL;
|
||||
block address_block, input_block;
|
||||
uint64_t pseudo_rand, ref_index, ref_lane;
|
||||
uint32_t prev_offset, curr_offset;
|
||||
uint32_t starting_index, i;
|
||||
#if defined(__AVX512F__)
|
||||
__m512i state[ARGON2_512BIT_WORDS_IN_BLOCK];
|
||||
#elif defined(__AVX2__)
|
||||
__m256i state[ARGON2_HWORDS_IN_BLOCK];
|
||||
#else
|
||||
__m128i state[ARGON2_OWORDS_IN_BLOCK];
|
||||
#endif
|
||||
int data_independent_addressing;
|
||||
|
||||
if (instance == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
data_independent_addressing =
|
||||
(instance->type == Argon2_i) ||
|
||||
(instance->type == Argon2_id && (position.pass == 0) &&
|
||||
(position.slice < ARGON2_SYNC_POINTS / 2));
|
||||
|
||||
if (data_independent_addressing) {
|
||||
init_block_value(&input_block, 0);
|
||||
|
||||
input_block.v[0] = position.pass;
|
||||
input_block.v[1] = position.lane;
|
||||
input_block.v[2] = position.slice;
|
||||
input_block.v[3] = instance->memory_blocks;
|
||||
input_block.v[4] = instance->passes;
|
||||
input_block.v[5] = instance->type;
|
||||
}
|
||||
|
||||
starting_index = 0;
|
||||
|
||||
if ((0 == position.pass) && (0 == position.slice)) {
|
||||
starting_index = 2; /* we have already generated the first two blocks */
|
||||
|
||||
/* Don't forget to generate the first block of addresses: */
|
||||
if (data_independent_addressing) {
|
||||
next_addresses(&address_block, &input_block);
|
||||
}
|
||||
}
|
||||
|
||||
/* Offset of the current block */
|
||||
curr_offset = position.lane * instance->lane_length +
|
||||
position.slice * instance->segment_length + starting_index;
|
||||
|
||||
if (0 == curr_offset % instance->lane_length) {
|
||||
/* Last block in this lane */
|
||||
prev_offset = curr_offset + instance->lane_length - 1;
|
||||
} else {
|
||||
/* Previous block */
|
||||
prev_offset = curr_offset - 1;
|
||||
}
|
||||
|
||||
memcpy(state, ((instance->memory + prev_offset)->v), ARGON2_BLOCK_SIZE);
|
||||
|
||||
for (i = starting_index; i < instance->segment_length;
|
||||
++i, ++curr_offset, ++prev_offset) {
|
||||
/*1.1 Rotating prev_offset if needed */
|
||||
if (curr_offset % instance->lane_length == 1) {
|
||||
prev_offset = curr_offset - 1;
|
||||
}
|
||||
|
||||
/* 1.2 Computing the index of the reference block */
|
||||
/* 1.2.1 Taking pseudo-random value from the previous block */
|
||||
if (data_independent_addressing) {
|
||||
if (i % ARGON2_ADDRESSES_IN_BLOCK == 0) {
|
||||
next_addresses(&address_block, &input_block);
|
||||
}
|
||||
pseudo_rand = address_block.v[i % ARGON2_ADDRESSES_IN_BLOCK];
|
||||
} else {
|
||||
pseudo_rand = instance->memory[prev_offset].v[0];
|
||||
}
|
||||
|
||||
/* 1.2.2 Computing the lane of the reference block */
|
||||
ref_lane = ((pseudo_rand >> 32)) % instance->lanes;
|
||||
|
||||
if ((position.pass == 0) && (position.slice == 0)) {
|
||||
/* Can not reference other lanes yet */
|
||||
ref_lane = position.lane;
|
||||
}
|
||||
|
||||
/* 1.2.3 Computing the number of possible reference block within the
|
||||
* lane.
|
||||
*/
|
||||
position.index = i;
|
||||
ref_index = index_alpha(instance, &position, pseudo_rand & 0xFFFFFFFF,
|
||||
ref_lane == position.lane);
|
||||
|
||||
/* 2 Creating a new block */
|
||||
ref_block =
|
||||
instance->memory + instance->lane_length * ref_lane + ref_index;
|
||||
curr_block = instance->memory + curr_offset;
|
||||
if (ARGON2_VERSION_10 == instance->version) {
|
||||
/* version 1.2.1 and earlier: overwrite, not XOR */
|
||||
fill_block(state, ref_block, curr_block, 0);
|
||||
} else {
|
||||
if(0 == position.pass) {
|
||||
fill_block(state, ref_block, curr_block, 0);
|
||||
} else {
|
||||
fill_block(state, ref_block, curr_block, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
194
lib/crypto_backend/argon2/ref.c
Normal file
194
lib/crypto_backend/argon2/ref.c
Normal file
@@ -0,0 +1,194 @@
|
||||
/*
|
||||
* Argon2 reference source code package - reference C implementations
|
||||
*
|
||||
* Copyright 2015
|
||||
* Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves
|
||||
*
|
||||
* You may use this work under the terms of a Creative Commons CC0 1.0
|
||||
* License/Waiver or the Apache Public License 2.0, at your option. The terms of
|
||||
* these licenses can be found at:
|
||||
*
|
||||
* - CC0 1.0 Universal : https://creativecommons.org/publicdomain/zero/1.0
|
||||
* - Apache 2.0 : https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* You should have received a copy of both of these licenses along with this
|
||||
* software. If not, they may be obtained at the above URLs.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "argon2.h"
|
||||
#include "core.h"
|
||||
|
||||
#include "blake2/blamka-round-ref.h"
|
||||
#include "blake2/blake2-impl.h"
|
||||
#include "blake2/blake2.h"
|
||||
|
||||
|
||||
/*
|
||||
* Function fills a new memory block and optionally XORs the old block over the new one.
|
||||
* @next_block must be initialized.
|
||||
* @param prev_block Pointer to the previous block
|
||||
* @param ref_block Pointer to the reference block
|
||||
* @param next_block Pointer to the block to be constructed
|
||||
* @param with_xor Whether to XOR into the new block (1) or just overwrite (0)
|
||||
* @pre all block pointers must be valid
|
||||
*/
|
||||
static void fill_block(const block *prev_block, const block *ref_block,
|
||||
block *next_block, int with_xor) {
|
||||
block blockR, block_tmp;
|
||||
unsigned i;
|
||||
|
||||
copy_block(&blockR, ref_block);
|
||||
xor_block(&blockR, prev_block);
|
||||
copy_block(&block_tmp, &blockR);
|
||||
/* Now blockR = ref_block + prev_block and block_tmp = ref_block + prev_block */
|
||||
if (with_xor) {
|
||||
/* Saving the next block contents for XOR over: */
|
||||
xor_block(&block_tmp, next_block);
|
||||
/* Now blockR = ref_block + prev_block and
|
||||
block_tmp = ref_block + prev_block + next_block */
|
||||
}
|
||||
|
||||
/* Apply Blake2 on columns of 64-bit words: (0,1,...,15) , then
|
||||
(16,17,..31)... finally (112,113,...127) */
|
||||
for (i = 0; i < 8; ++i) {
|
||||
BLAKE2_ROUND_NOMSG(
|
||||
blockR.v[16 * i], blockR.v[16 * i + 1], blockR.v[16 * i + 2],
|
||||
blockR.v[16 * i + 3], blockR.v[16 * i + 4], blockR.v[16 * i + 5],
|
||||
blockR.v[16 * i + 6], blockR.v[16 * i + 7], blockR.v[16 * i + 8],
|
||||
blockR.v[16 * i + 9], blockR.v[16 * i + 10], blockR.v[16 * i + 11],
|
||||
blockR.v[16 * i + 12], blockR.v[16 * i + 13], blockR.v[16 * i + 14],
|
||||
blockR.v[16 * i + 15]);
|
||||
}
|
||||
|
||||
/* Apply Blake2 on rows of 64-bit words: (0,1,16,17,...112,113), then
|
||||
(2,3,18,19,...,114,115).. finally (14,15,30,31,...,126,127) */
|
||||
for (i = 0; i < 8; i++) {
|
||||
BLAKE2_ROUND_NOMSG(
|
||||
blockR.v[2 * i], blockR.v[2 * i + 1], blockR.v[2 * i + 16],
|
||||
blockR.v[2 * i + 17], blockR.v[2 * i + 32], blockR.v[2 * i + 33],
|
||||
blockR.v[2 * i + 48], blockR.v[2 * i + 49], blockR.v[2 * i + 64],
|
||||
blockR.v[2 * i + 65], blockR.v[2 * i + 80], blockR.v[2 * i + 81],
|
||||
blockR.v[2 * i + 96], blockR.v[2 * i + 97], blockR.v[2 * i + 112],
|
||||
blockR.v[2 * i + 113]);
|
||||
}
|
||||
|
||||
copy_block(next_block, &block_tmp);
|
||||
xor_block(next_block, &blockR);
|
||||
}
|
||||
|
||||
static void next_addresses(block *address_block, block *input_block,
|
||||
const block *zero_block) {
|
||||
input_block->v[6]++;
|
||||
fill_block(zero_block, input_block, address_block, 0);
|
||||
fill_block(zero_block, address_block, address_block, 0);
|
||||
}
|
||||
|
||||
void fill_segment(const argon2_instance_t *instance,
|
||||
argon2_position_t position) {
|
||||
block *ref_block = NULL, *curr_block = NULL;
|
||||
block address_block, input_block, zero_block;
|
||||
uint64_t pseudo_rand, ref_index, ref_lane;
|
||||
uint32_t prev_offset, curr_offset;
|
||||
uint32_t starting_index;
|
||||
uint32_t i;
|
||||
int data_independent_addressing;
|
||||
|
||||
if (instance == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
data_independent_addressing =
|
||||
(instance->type == Argon2_i) ||
|
||||
(instance->type == Argon2_id && (position.pass == 0) &&
|
||||
(position.slice < ARGON2_SYNC_POINTS / 2));
|
||||
|
||||
if (data_independent_addressing) {
|
||||
init_block_value(&zero_block, 0);
|
||||
init_block_value(&input_block, 0);
|
||||
|
||||
input_block.v[0] = position.pass;
|
||||
input_block.v[1] = position.lane;
|
||||
input_block.v[2] = position.slice;
|
||||
input_block.v[3] = instance->memory_blocks;
|
||||
input_block.v[4] = instance->passes;
|
||||
input_block.v[5] = instance->type;
|
||||
}
|
||||
|
||||
starting_index = 0;
|
||||
|
||||
if ((0 == position.pass) && (0 == position.slice)) {
|
||||
starting_index = 2; /* we have already generated the first two blocks */
|
||||
|
||||
/* Don't forget to generate the first block of addresses: */
|
||||
if (data_independent_addressing) {
|
||||
next_addresses(&address_block, &input_block, &zero_block);
|
||||
}
|
||||
}
|
||||
|
||||
/* Offset of the current block */
|
||||
curr_offset = position.lane * instance->lane_length +
|
||||
position.slice * instance->segment_length + starting_index;
|
||||
|
||||
if (0 == curr_offset % instance->lane_length) {
|
||||
/* Last block in this lane */
|
||||
prev_offset = curr_offset + instance->lane_length - 1;
|
||||
} else {
|
||||
/* Previous block */
|
||||
prev_offset = curr_offset - 1;
|
||||
}
|
||||
|
||||
for (i = starting_index; i < instance->segment_length;
|
||||
++i, ++curr_offset, ++prev_offset) {
|
||||
/*1.1 Rotating prev_offset if needed */
|
||||
if (curr_offset % instance->lane_length == 1) {
|
||||
prev_offset = curr_offset - 1;
|
||||
}
|
||||
|
||||
/* 1.2 Computing the index of the reference block */
|
||||
/* 1.2.1 Taking pseudo-random value from the previous block */
|
||||
if (data_independent_addressing) {
|
||||
if (i % ARGON2_ADDRESSES_IN_BLOCK == 0) {
|
||||
next_addresses(&address_block, &input_block, &zero_block);
|
||||
}
|
||||
pseudo_rand = address_block.v[i % ARGON2_ADDRESSES_IN_BLOCK];
|
||||
} else {
|
||||
pseudo_rand = instance->memory[prev_offset].v[0];
|
||||
}
|
||||
|
||||
/* 1.2.2 Computing the lane of the reference block */
|
||||
ref_lane = ((pseudo_rand >> 32)) % instance->lanes;
|
||||
|
||||
if ((position.pass == 0) && (position.slice == 0)) {
|
||||
/* Can not reference other lanes yet */
|
||||
ref_lane = position.lane;
|
||||
}
|
||||
|
||||
/* 1.2.3 Computing the number of possible reference block within the
|
||||
* lane.
|
||||
*/
|
||||
position.index = i;
|
||||
ref_index = index_alpha(instance, &position, pseudo_rand & 0xFFFFFFFF,
|
||||
ref_lane == position.lane);
|
||||
|
||||
/* 2 Creating a new block */
|
||||
ref_block =
|
||||
instance->memory + instance->lane_length * ref_lane + ref_index;
|
||||
curr_block = instance->memory + curr_offset;
|
||||
if (ARGON2_VERSION_10 == instance->version) {
|
||||
/* version 1.2.1 and earlier: overwrite, not XOR */
|
||||
fill_block(instance->memory + prev_offset, ref_block, curr_block, 0);
|
||||
} else {
|
||||
if(0 == position.pass) {
|
||||
fill_block(instance->memory + prev_offset, ref_block,
|
||||
curr_block, 0);
|
||||
} else {
|
||||
fill_block(instance->memory + prev_offset, ref_block,
|
||||
curr_block, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
57
lib/crypto_backend/argon2/thread.c
Normal file
57
lib/crypto_backend/argon2/thread.c
Normal file
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Argon2 reference source code package - reference C implementations
|
||||
*
|
||||
* Copyright 2015
|
||||
* Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves
|
||||
*
|
||||
* You may use this work under the terms of a Creative Commons CC0 1.0
|
||||
* License/Waiver or the Apache Public License 2.0, at your option. The terms of
|
||||
* these licenses can be found at:
|
||||
*
|
||||
* - CC0 1.0 Universal : https://creativecommons.org/publicdomain/zero/1.0
|
||||
* - Apache 2.0 : https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* You should have received a copy of both of these licenses along with this
|
||||
* software. If not, they may be obtained at the above URLs.
|
||||
*/
|
||||
|
||||
#if !defined(ARGON2_NO_THREADS)
|
||||
|
||||
#include "thread.h"
|
||||
#if defined(_WIN32)
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
int argon2_thread_create(argon2_thread_handle_t *handle,
|
||||
argon2_thread_func_t func, void *args) {
|
||||
if (NULL == handle || func == NULL) {
|
||||
return -1;
|
||||
}
|
||||
#if defined(_WIN32)
|
||||
*handle = _beginthreadex(NULL, 0, func, args, 0, NULL);
|
||||
return *handle != 0 ? 0 : -1;
|
||||
#else
|
||||
return pthread_create(handle, NULL, func, args);
|
||||
#endif
|
||||
}
|
||||
|
||||
int argon2_thread_join(argon2_thread_handle_t handle) {
|
||||
#if defined(_WIN32)
|
||||
if (WaitForSingleObject((HANDLE)handle, INFINITE) == WAIT_OBJECT_0) {
|
||||
return CloseHandle((HANDLE)handle) != 0 ? 0 : -1;
|
||||
}
|
||||
return -1;
|
||||
#else
|
||||
return pthread_join(handle, NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
void argon2_thread_exit(void) {
|
||||
#if defined(_WIN32)
|
||||
_endthreadex(0);
|
||||
#else
|
||||
pthread_exit(NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif /* ARGON2_NO_THREADS */
|
||||
67
lib/crypto_backend/argon2/thread.h
Normal file
67
lib/crypto_backend/argon2/thread.h
Normal file
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Argon2 reference source code package - reference C implementations
|
||||
*
|
||||
* Copyright 2015
|
||||
* Daniel Dinu, Dmitry Khovratovich, Jean-Philippe Aumasson, and Samuel Neves
|
||||
*
|
||||
* You may use this work under the terms of a Creative Commons CC0 1.0
|
||||
* License/Waiver or the Apache Public License 2.0, at your option. The terms of
|
||||
* these licenses can be found at:
|
||||
*
|
||||
* - CC0 1.0 Universal : https://creativecommons.org/publicdomain/zero/1.0
|
||||
* - Apache 2.0 : https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* You should have received a copy of both of these licenses along with this
|
||||
* software. If not, they may be obtained at the above URLs.
|
||||
*/
|
||||
|
||||
#ifndef ARGON2_THREAD_H
|
||||
#define ARGON2_THREAD_H
|
||||
|
||||
#if !defined(ARGON2_NO_THREADS)
|
||||
|
||||
/*
|
||||
Here we implement an abstraction layer for the simpĺe requirements
|
||||
of the Argon2 code. We only require 3 primitives---thread creation,
|
||||
joining, and termination---so full emulation of the pthreads API
|
||||
is unwarranted. Currently we wrap pthreads and Win32 threads.
|
||||
|
||||
The API defines 2 types: the function pointer type,
|
||||
argon2_thread_func_t,
|
||||
and the type of the thread handle---argon2_thread_handle_t.
|
||||
*/
|
||||
#if defined(_WIN32)
|
||||
#include <process.h>
|
||||
typedef unsigned(__stdcall *argon2_thread_func_t)(void *);
|
||||
typedef uintptr_t argon2_thread_handle_t;
|
||||
#else
|
||||
#include <pthread.h>
|
||||
typedef void *(*argon2_thread_func_t)(void *);
|
||||
typedef pthread_t argon2_thread_handle_t;
|
||||
#endif
|
||||
|
||||
/* Creates a thread
|
||||
* @param handle pointer to a thread handle, which is the output of this
|
||||
* function. Must not be NULL.
|
||||
* @param func A function pointer for the thread's entry point. Must not be
|
||||
* NULL.
|
||||
* @param args Pointer that is passed as an argument to @func. May be NULL.
|
||||
* @return 0 if @handle and @func are valid pointers and a thread is successfully
|
||||
* created.
|
||||
*/
|
||||
int argon2_thread_create(argon2_thread_handle_t *handle,
|
||||
argon2_thread_func_t func, void *args);
|
||||
|
||||
/* Waits for a thread to terminate
|
||||
* @param handle Handle to a thread created with argon2_thread_create.
|
||||
* @return 0 if @handle is a valid handle, and joining completed successfully.
|
||||
*/
|
||||
int argon2_thread_join(argon2_thread_handle_t handle);
|
||||
|
||||
/* Terminate the current thread. Must be run inside a thread created by
|
||||
* argon2_thread_create.
|
||||
*/
|
||||
void argon2_thread_exit(void);
|
||||
|
||||
#endif /* ARGON2_NO_THREADS */
|
||||
#endif
|
||||
79
lib/crypto_backend/argon2_generic.c
Normal file
79
lib/crypto_backend/argon2_generic.c
Normal file
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* Argon2 PBKDF2 library wrapper
|
||||
*
|
||||
* Copyright (C) 2016-2021 Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2016-2021 Milan Broz
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This file is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this file; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include "crypto_backend_internal.h"
|
||||
#if HAVE_ARGON2_H
|
||||
#include <argon2.h>
|
||||
#else
|
||||
#include "argon2/argon2.h"
|
||||
#endif
|
||||
|
||||
#define CONST_CAST(x) (x)(uintptr_t)
|
||||
|
||||
int argon2(const char *type, const char *password, size_t password_length,
|
||||
const char *salt, size_t salt_length,
|
||||
char *key, size_t key_length,
|
||||
uint32_t iterations, uint32_t memory, uint32_t parallel)
|
||||
{
|
||||
#if !USE_INTERNAL_ARGON2 && !HAVE_ARGON2_H
|
||||
return -EINVAL;
|
||||
#else
|
||||
argon2_type atype;
|
||||
argon2_context context = {
|
||||
.flags = ARGON2_DEFAULT_FLAGS,
|
||||
.version = ARGON2_VERSION_NUMBER,
|
||||
.t_cost = (uint32_t)iterations,
|
||||
.m_cost = (uint32_t)memory,
|
||||
.lanes = (uint32_t)parallel,
|
||||
.threads = (uint32_t)parallel,
|
||||
.out = (uint8_t *)key,
|
||||
.outlen = (uint32_t)key_length,
|
||||
.pwd = CONST_CAST(uint8_t *)password,
|
||||
.pwdlen = (uint32_t)password_length,
|
||||
.salt = CONST_CAST(uint8_t *)salt,
|
||||
.saltlen = (uint32_t)salt_length,
|
||||
};
|
||||
int r;
|
||||
|
||||
if (!strcmp(type, "argon2i"))
|
||||
atype = Argon2_i;
|
||||
else if(!strcmp(type, "argon2id"))
|
||||
atype = Argon2_id;
|
||||
else
|
||||
return -EINVAL;
|
||||
|
||||
switch (argon2_ctx(&context, atype)) {
|
||||
case ARGON2_OK:
|
||||
r = 0;
|
||||
break;
|
||||
case ARGON2_MEMORY_ALLOCATION_ERROR:
|
||||
case ARGON2_FREE_MEMORY_CBK_NULL:
|
||||
case ARGON2_ALLOCATE_MEMORY_CBK_NULL:
|
||||
r = -ENOMEM;
|
||||
break;
|
||||
default:
|
||||
r = -EINVAL;
|
||||
}
|
||||
|
||||
return r;
|
||||
#endif
|
||||
}
|
||||
161
lib/crypto_backend/cipher_check.c
Normal file
161
lib/crypto_backend/cipher_check.c
Normal file
@@ -0,0 +1,161 @@
|
||||
/*
|
||||
* Cipher performance check
|
||||
*
|
||||
* Copyright (C) 2018-2021 Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2018-2021 Milan Broz
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This file is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this file; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <time.h>
|
||||
#include "crypto_backend_internal.h"
|
||||
|
||||
#ifndef CLOCK_MONOTONIC_RAW
|
||||
#define CLOCK_MONOTONIC_RAW CLOCK_MONOTONIC
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This is not simulating storage, so using disk block causes extreme overhead.
|
||||
* Let's use some fixed block size where results are more reliable...
|
||||
*/
|
||||
#define CIPHER_BLOCK_BYTES 65536
|
||||
|
||||
/*
|
||||
* If the measured value is lower, encrypted buffer is probably too small
|
||||
* and calculated values are not reliable.
|
||||
*/
|
||||
#define CIPHER_TIME_MIN_MS 0.001
|
||||
|
||||
/*
|
||||
* The whole test depends on Linux kernel usermode crypto API for now.
|
||||
* (The same implementations are used in dm-crypt though.)
|
||||
*/
|
||||
|
||||
static int time_ms(struct timespec *start, struct timespec *end, double *ms)
|
||||
{
|
||||
double start_ms, end_ms;
|
||||
|
||||
start_ms = start->tv_sec * 1000.0 + start->tv_nsec / (1000.0 * 1000);
|
||||
end_ms = end->tv_sec * 1000.0 + end->tv_nsec / (1000.0 * 1000);
|
||||
|
||||
*ms = end_ms - start_ms;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cipher_perf_one(const char *name, const char *mode, char *buffer, size_t buffer_size,
|
||||
const char *key, size_t key_size, const char *iv, size_t iv_size, int enc)
|
||||
{
|
||||
struct crypt_cipher_kernel cipher;
|
||||
size_t done = 0, block = CIPHER_BLOCK_BYTES;
|
||||
int r;
|
||||
|
||||
if (buffer_size < block)
|
||||
block = buffer_size;
|
||||
|
||||
r = crypt_cipher_init_kernel(&cipher, name, mode, key, key_size);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
while (done < buffer_size) {
|
||||
if ((done + block) > buffer_size)
|
||||
block = buffer_size - done;
|
||||
|
||||
if (enc)
|
||||
r = crypt_cipher_encrypt_kernel(&cipher, &buffer[done], &buffer[done],
|
||||
block, iv, iv_size);
|
||||
else
|
||||
r = crypt_cipher_decrypt_kernel(&cipher, &buffer[done], &buffer[done],
|
||||
block, iv, iv_size);
|
||||
if (r < 0)
|
||||
break;
|
||||
|
||||
done += block;
|
||||
}
|
||||
|
||||
crypt_cipher_destroy_kernel(&cipher);
|
||||
|
||||
return r;
|
||||
}
|
||||
static int cipher_measure(const char *name, const char *mode, char *buffer, size_t buffer_size,
|
||||
const char *key, size_t key_size, const char *iv, size_t iv_size,
|
||||
int encrypt, double *ms)
|
||||
{
|
||||
struct timespec start, end;
|
||||
int r;
|
||||
|
||||
/*
|
||||
* Using getrusage would be better here but the precision
|
||||
* is not adequate, so better stick with CLOCK_MONOTONIC
|
||||
*/
|
||||
if (clock_gettime(CLOCK_MONOTONIC_RAW, &start) < 0)
|
||||
return -EINVAL;
|
||||
|
||||
r = cipher_perf_one(name, mode, buffer, buffer_size, key, key_size, iv, iv_size, encrypt);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (clock_gettime(CLOCK_MONOTONIC_RAW, &end) < 0)
|
||||
return -EINVAL;
|
||||
|
||||
r = time_ms(&start, &end, ms);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (*ms < CIPHER_TIME_MIN_MS)
|
||||
return -ERANGE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static double speed_mbs(unsigned long bytes, double ms)
|
||||
{
|
||||
double speed = bytes, s = ms / 1000.;
|
||||
|
||||
return speed / (1024 * 1024) / s;
|
||||
}
|
||||
|
||||
int crypt_cipher_perf_kernel(const char *name, const char *mode, char *buffer, size_t buffer_size,
|
||||
const char *key, size_t key_size, const char *iv, size_t iv_size,
|
||||
double *encryption_mbs, double *decryption_mbs)
|
||||
{
|
||||
double ms_enc, ms_dec, ms;
|
||||
int r, repeat_enc, repeat_dec;
|
||||
|
||||
ms_enc = 0.0;
|
||||
repeat_enc = 1;
|
||||
while (ms_enc < 1000.0) {
|
||||
r = cipher_measure(name, mode, buffer, buffer_size, key, key_size, iv, iv_size, 1, &ms);
|
||||
if (r < 0)
|
||||
return r;
|
||||
ms_enc += ms;
|
||||
repeat_enc++;
|
||||
}
|
||||
|
||||
ms_dec = 0.0;
|
||||
repeat_dec = 1;
|
||||
while (ms_dec < 1000.0) {
|
||||
r = cipher_measure(name, mode, buffer, buffer_size, key, key_size, iv, iv_size, 0, &ms);
|
||||
if (r < 0)
|
||||
return r;
|
||||
ms_dec += ms;
|
||||
repeat_dec++;
|
||||
}
|
||||
|
||||
*encryption_mbs = speed_mbs(buffer_size * repeat_enc, ms_enc);
|
||||
*decryption_mbs = speed_mbs(buffer_size * repeat_dec, ms_dec);
|
||||
|
||||
return 0;
|
||||
}
|
||||
89
lib/crypto_backend/cipher_generic.c
Normal file
89
lib/crypto_backend/cipher_generic.c
Normal file
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* Linux kernel cipher generic utilities
|
||||
*
|
||||
* Copyright (C) 2018-2021 Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2018-2021 Milan Broz
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This file is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this file; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
#include <errno.h>
|
||||
#include "crypto_backend.h"
|
||||
|
||||
struct cipher_alg {
|
||||
const char *name;
|
||||
const char *mode;
|
||||
int blocksize;
|
||||
bool wrapped_key;
|
||||
};
|
||||
|
||||
static const struct cipher_alg cipher_algs[] = {
|
||||
{ "cipher_null", NULL, 16, false },
|
||||
{ "aes", NULL, 16, false },
|
||||
{ "serpent", NULL, 16, false },
|
||||
{ "twofish", NULL, 16, false },
|
||||
{ "anubis", NULL, 16, false },
|
||||
{ "blowfish", NULL, 8, false },
|
||||
{ "camellia", NULL, 16, false },
|
||||
{ "cast5", NULL, 8, false },
|
||||
{ "cast6", NULL, 16, false },
|
||||
{ "des", NULL, 8, false },
|
||||
{ "des3_ede", NULL, 8, false },
|
||||
{ "khazad", NULL, 8, false },
|
||||
{ "seed", NULL, 16, false },
|
||||
{ "tea", NULL, 8, false },
|
||||
{ "xtea", NULL, 8, false },
|
||||
{ "paes", NULL, 16, true }, /* protected AES, s390 wrapped key scheme */
|
||||
{ "xchacha12,aes", "adiantum", 32, false },
|
||||
{ "xchacha20,aes", "adiantum", 32, false },
|
||||
{ "sm4", NULL, 16, false },
|
||||
{ NULL, NULL, 0, false }
|
||||
};
|
||||
|
||||
static const struct cipher_alg *_get_alg(const char *name, const char *mode)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
while (name && cipher_algs[i].name) {
|
||||
if (!strcasecmp(name, cipher_algs[i].name))
|
||||
if (!mode || !cipher_algs[i].mode ||
|
||||
!strncasecmp(mode, cipher_algs[i].mode, strlen(cipher_algs[i].mode)))
|
||||
return &cipher_algs[i];
|
||||
i++;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int crypt_cipher_ivsize(const char *name, const char *mode)
|
||||
{
|
||||
const struct cipher_alg *ca = _get_alg(name, mode);
|
||||
|
||||
if (!ca)
|
||||
return -EINVAL;
|
||||
|
||||
if (mode && !strcasecmp(mode, "ecb"))
|
||||
return 0;
|
||||
|
||||
return ca->blocksize;
|
||||
}
|
||||
|
||||
int crypt_cipher_wrapped_key(const char *name, const char *mode)
|
||||
{
|
||||
const struct cipher_alg *ca = _get_alg(name, mode);
|
||||
|
||||
return ca ? (int)ca->wrapped_key : 0;
|
||||
}
|
||||
@@ -19,7 +19,7 @@
|
||||
* order from highest-order term to lowest-order term. UARTs transmit
|
||||
* characters in order from LSB to MSB. By storing the CRC this way,
|
||||
* we hand it to the UART in the order low-byte to high-byte; the UART
|
||||
* sends each low-bit to hight-bit; and the result is transmission bit
|
||||
* sends each low-bit to high-bit; and the result is transmission bit
|
||||
* by bit from highest- to lowest-order term without requiring any bit
|
||||
* shuffling on our part. Reception works similarly.
|
||||
*
|
||||
@@ -42,7 +42,6 @@
|
||||
|
||||
#include "crypto_backend.h"
|
||||
|
||||
|
||||
static const uint32_t crc32_tab[] = {
|
||||
0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
|
||||
0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
|
||||
@@ -113,4 +112,3 @@ uint32_t crypt_crc32(uint32_t seed, const unsigned char *buf, size_t len)
|
||||
|
||||
return crc;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
* crypto backend implementation
|
||||
*
|
||||
* Copyright (C) 2010-2012, Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2010-2014, Milan Broz
|
||||
* Copyright (C) 2010-2021 Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2010-2021 Milan Broz
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
@@ -22,15 +22,17 @@
|
||||
#define _CRYPTO_BACKEND_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
|
||||
struct crypt_device;
|
||||
struct crypt_hash;
|
||||
struct crypt_hmac;
|
||||
struct crypt_cipher;
|
||||
struct crypt_storage;
|
||||
|
||||
int crypt_backend_init(struct crypt_device *ctx);
|
||||
int crypt_backend_init(void);
|
||||
void crypt_backend_destroy(void);
|
||||
|
||||
#define CRYPT_BACKEND_KERNEL (1 << 0) /* Crypto uses kernel part, for benchmark */
|
||||
|
||||
@@ -42,71 +44,95 @@ int crypt_hash_size(const char *name);
|
||||
int crypt_hash_init(struct crypt_hash **ctx, const char *name);
|
||||
int crypt_hash_write(struct crypt_hash *ctx, const char *buffer, size_t length);
|
||||
int crypt_hash_final(struct crypt_hash *ctx, char *buffer, size_t length);
|
||||
int crypt_hash_destroy(struct crypt_hash *ctx);
|
||||
void crypt_hash_destroy(struct crypt_hash *ctx);
|
||||
|
||||
/* HMAC */
|
||||
int crypt_hmac_size(const char *name);
|
||||
int crypt_hmac_init(struct crypt_hmac **ctx, const char *name,
|
||||
const void *buffer, size_t length);
|
||||
const void *key, size_t key_length);
|
||||
int crypt_hmac_write(struct crypt_hmac *ctx, const char *buffer, size_t length);
|
||||
int crypt_hmac_final(struct crypt_hmac *ctx, char *buffer, size_t length);
|
||||
int crypt_hmac_destroy(struct crypt_hmac *ctx);
|
||||
void crypt_hmac_destroy(struct crypt_hmac *ctx);
|
||||
|
||||
/* RNG (if fips paramater set, must provide FIPS compliance) */
|
||||
/* RNG (if fips parameter set, must provide FIPS compliance) */
|
||||
enum { CRYPT_RND_NORMAL = 0, CRYPT_RND_KEY = 1, CRYPT_RND_SALT = 2 };
|
||||
int crypt_backend_rng(char *buffer, size_t length, int quality, int fips);
|
||||
|
||||
|
||||
/* PBKDF*/
|
||||
int crypt_pbkdf_check(const char *kdf, const char *hash,
|
||||
const char *password, size_t password_length,
|
||||
const char *salt, size_t salt_length,
|
||||
size_t key_length, uint64_t *iter_secs);
|
||||
struct crypt_pbkdf_limits {
|
||||
uint32_t min_iterations, max_iterations;
|
||||
uint32_t min_memory, max_memory, min_bench_memory;
|
||||
uint32_t min_parallel, max_parallel;
|
||||
};
|
||||
|
||||
int crypt_pbkdf_get_limits(const char *kdf, struct crypt_pbkdf_limits *l);
|
||||
int crypt_pbkdf(const char *kdf, const char *hash,
|
||||
const char *password, size_t password_length,
|
||||
const char *salt, size_t salt_length,
|
||||
char *key, size_t key_length,
|
||||
unsigned int iterations);
|
||||
|
||||
#if USE_INTERNAL_PBKDF2
|
||||
/* internal PBKDF2 implementation */
|
||||
int pkcs5_pbkdf2(const char *hash,
|
||||
const char *P, size_t Plen,
|
||||
const char *S, size_t Slen,
|
||||
unsigned int c,
|
||||
unsigned int dkLen, char *DK,
|
||||
unsigned int hash_block_size);
|
||||
#endif
|
||||
uint32_t iterations, uint32_t memory, uint32_t parallel);
|
||||
int crypt_pbkdf_perf(const char *kdf, const char *hash,
|
||||
const char *password, size_t password_size,
|
||||
const char *salt, size_t salt_size,
|
||||
size_t volume_key_size, uint32_t time_ms,
|
||||
uint32_t max_memory_kb, uint32_t parallel_threads,
|
||||
uint32_t *iterations_out, uint32_t *memory_out,
|
||||
int (*progress)(uint32_t time_ms, void *usrptr), void *usrptr);
|
||||
|
||||
/* CRC32 */
|
||||
uint32_t crypt_crc32(uint32_t seed, const unsigned char *buf, size_t len);
|
||||
|
||||
/* ciphers */
|
||||
int crypt_cipher_blocksize(const char *name);
|
||||
/* Block ciphers */
|
||||
int crypt_cipher_ivsize(const char *name, const char *mode);
|
||||
int crypt_cipher_wrapped_key(const char *name, const char *mode);
|
||||
int crypt_cipher_init(struct crypt_cipher **ctx, const char *name,
|
||||
const char *mode, const void *buffer, size_t length);
|
||||
int crypt_cipher_destroy(struct crypt_cipher *ctx);
|
||||
const char *mode, const void *key, size_t key_length);
|
||||
void crypt_cipher_destroy(struct crypt_cipher *ctx);
|
||||
int crypt_cipher_encrypt(struct crypt_cipher *ctx,
|
||||
const char *in, char *out, size_t length,
|
||||
const char *iv, size_t iv_length);
|
||||
int crypt_cipher_decrypt(struct crypt_cipher *ctx,
|
||||
const char *in, char *out, size_t length,
|
||||
const char *iv, size_t iv_length);
|
||||
bool crypt_cipher_kernel_only(struct crypt_cipher *ctx);
|
||||
|
||||
/* storage encryption wrappers */
|
||||
int crypt_storage_init(struct crypt_storage **ctx, uint64_t sector_start,
|
||||
/* Benchmark of kernel cipher performance */
|
||||
int crypt_cipher_perf_kernel(const char *name, const char *mode, char *buffer, size_t buffer_size,
|
||||
const char *key, size_t key_size, const char *iv, size_t iv_size,
|
||||
double *encryption_mbs, double *decryption_mbs);
|
||||
|
||||
/* Check availability of a cipher (in kernel only) */
|
||||
int crypt_cipher_check_kernel(const char *name, const char *mode,
|
||||
const char *integrity, size_t key_length);
|
||||
|
||||
/* Storage encryption wrappers */
|
||||
int crypt_storage_init(struct crypt_storage **ctx, size_t sector_size,
|
||||
const char *cipher, const char *cipher_mode,
|
||||
char *key, size_t key_length);
|
||||
int crypt_storage_destroy(struct crypt_storage *ctx);
|
||||
int crypt_storage_decrypt(struct crypt_storage *ctx, uint64_t sector,
|
||||
size_t count, char *buffer);
|
||||
int crypt_storage_encrypt(struct crypt_storage *ctx, uint64_t sector,
|
||||
size_t count, char *buffer);
|
||||
const void *key, size_t key_length, bool large_iv);
|
||||
void crypt_storage_destroy(struct crypt_storage *ctx);
|
||||
int crypt_storage_decrypt(struct crypt_storage *ctx, uint64_t iv_offset,
|
||||
uint64_t length, char *buffer);
|
||||
int crypt_storage_encrypt(struct crypt_storage *ctx, uint64_t iv_offset,
|
||||
uint64_t length, char *buffer);
|
||||
|
||||
bool crypt_storage_kernel_only(struct crypt_storage *ctx);
|
||||
|
||||
/* Temporary Bitlk helper */
|
||||
int crypt_bitlk_decrypt_key(const void *key, size_t key_length,
|
||||
const char *in, char *out, size_t length,
|
||||
const char *iv, size_t iv_length,
|
||||
const char *tag, size_t tag_length);
|
||||
|
||||
/* Memzero helper (memset on stack can be optimized out) */
|
||||
static inline void crypt_backend_memzero(void *s, size_t n)
|
||||
{
|
||||
#ifdef HAVE_EXPLICIT_BZERO
|
||||
explicit_bzero(s, n);
|
||||
#else
|
||||
volatile uint8_t *p = (volatile uint8_t *)s;
|
||||
while(n--) *p++ = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif /* _CRYPTO_BACKEND_H */
|
||||
|
||||
61
lib/crypto_backend/crypto_backend_internal.h
Normal file
61
lib/crypto_backend/crypto_backend_internal.h
Normal file
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* crypto backend implementation
|
||||
*
|
||||
* Copyright (C) 2010-2021 Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2010-2021 Milan Broz
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This file is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this file; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
#ifndef _CRYPTO_BACKEND_INTERNAL_H
|
||||
#define _CRYPTO_BACKEND_INTERNAL_H
|
||||
|
||||
#include "crypto_backend.h"
|
||||
|
||||
/* internal PBKDF2 implementation */
|
||||
int pkcs5_pbkdf2(const char *hash,
|
||||
const char *P, size_t Plen,
|
||||
const char *S, size_t Slen,
|
||||
unsigned int c,
|
||||
unsigned int dkLen, char *DK,
|
||||
unsigned int hash_block_size);
|
||||
|
||||
/* Argon2 implementation wrapper */
|
||||
int argon2(const char *type, const char *password, size_t password_length,
|
||||
const char *salt, size_t salt_length,
|
||||
char *key, size_t key_length,
|
||||
uint32_t iterations, uint32_t memory, uint32_t parallel);
|
||||
|
||||
/* Block ciphers: fallback to kernel crypto API */
|
||||
|
||||
struct crypt_cipher_kernel {
|
||||
int tfmfd;
|
||||
int opfd;
|
||||
};
|
||||
|
||||
int crypt_cipher_init_kernel(struct crypt_cipher_kernel *ctx, const char *name,
|
||||
const char *mode, const void *key, size_t key_length);
|
||||
int crypt_cipher_encrypt_kernel(struct crypt_cipher_kernel *ctx,
|
||||
const char *in, char *out, size_t length,
|
||||
const char *iv, size_t iv_length);
|
||||
int crypt_cipher_decrypt_kernel(struct crypt_cipher_kernel *ctx,
|
||||
const char *in, char *out, size_t length,
|
||||
const char *iv, size_t iv_length);
|
||||
void crypt_cipher_destroy_kernel(struct crypt_cipher_kernel *ctx);
|
||||
int crypt_bitlk_decrypt_key_kernel(const void *key, size_t key_length,
|
||||
const char *in, char *out, size_t length,
|
||||
const char *iv, size_t iv_length,
|
||||
const char *tag, size_t tag_length);
|
||||
|
||||
#endif /* _CRYPTO_BACKEND_INTERNAL_H */
|
||||
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
* Linux kernel userspace API crypto backend implementation (skcipher)
|
||||
*
|
||||
* Copyright (C) 2012, Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2012-2014, Milan Broz
|
||||
* Copyright (C) 2012-2021 Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2012-2021 Milan Broz
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
@@ -22,11 +22,12 @@
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdbool.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/stat.h>
|
||||
#include "crypto_backend.h"
|
||||
#include "crypto_backend_internal.h"
|
||||
|
||||
#ifdef ENABLE_AF_ALG
|
||||
|
||||
@@ -39,125 +40,80 @@
|
||||
#define SOL_ALG 279
|
||||
#endif
|
||||
|
||||
struct crypt_cipher {
|
||||
int tfmfd;
|
||||
int opfd;
|
||||
};
|
||||
#ifndef ALG_SET_AEAD_AUTHSIZE
|
||||
#define ALG_SET_AEAD_AUTHSIZE 5
|
||||
#endif
|
||||
|
||||
struct cipher_alg {
|
||||
const char *name;
|
||||
int blocksize;
|
||||
};
|
||||
|
||||
/* FIXME: Getting block size should be dynamic from cipher backend. */
|
||||
static struct cipher_alg cipher_algs[] = {
|
||||
{ "cipher_null", 16 },
|
||||
{ "aes", 16 },
|
||||
{ "serpent", 16 },
|
||||
{ "twofish", 16 },
|
||||
{ "anubis", 16 },
|
||||
{ "blowfish", 8 },
|
||||
{ "camellia", 16 },
|
||||
{ "cast5", 8 },
|
||||
{ "cast6", 16 },
|
||||
{ "des", 8 },
|
||||
{ "des3_ede", 8 },
|
||||
{ "khazad", 8 },
|
||||
{ "seed", 16 },
|
||||
{ "tea", 8 },
|
||||
{ "xtea", 8 },
|
||||
{ NULL, 0 }
|
||||
};
|
||||
|
||||
static struct cipher_alg *_get_alg(const char *name)
|
||||
/*
|
||||
* ciphers
|
||||
*
|
||||
* ENOENT - algorithm not available
|
||||
* ENOTSUP - AF_ALG family not available
|
||||
* (but cannot check specifically for skcipher API)
|
||||
*/
|
||||
static int _crypt_cipher_init(struct crypt_cipher_kernel *ctx,
|
||||
const void *key, size_t key_length,
|
||||
size_t tag_length, struct sockaddr_alg *sa)
|
||||
{
|
||||
int i = 0;
|
||||
if (!ctx)
|
||||
return -EINVAL;
|
||||
|
||||
while (name && cipher_algs[i].name) {
|
||||
if (!strcasecmp(name, cipher_algs[i].name))
|
||||
return &cipher_algs[i];
|
||||
i++;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int crypt_cipher_blocksize(const char *name)
|
||||
{
|
||||
struct cipher_alg *ca = _get_alg(name);
|
||||
|
||||
return ca ? ca->blocksize : -EINVAL;
|
||||
}
|
||||
|
||||
/* Shared with hash kernel backend */
|
||||
int crypt_kernel_socket_init(struct sockaddr_alg *sa, int *tfmfd, int *opfd);
|
||||
|
||||
int crypt_kernel_socket_init(struct sockaddr_alg *sa, int *tfmfd, int *opfd)
|
||||
{
|
||||
*tfmfd = socket(AF_ALG, SOCK_SEQPACKET, 0);
|
||||
if (*tfmfd == -1)
|
||||
ctx->opfd = -1;
|
||||
ctx->tfmfd = socket(AF_ALG, SOCK_SEQPACKET, 0);
|
||||
if (ctx->tfmfd < 0) {
|
||||
crypt_cipher_destroy_kernel(ctx);
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
if (bind(*tfmfd, (struct sockaddr *)sa, sizeof(*sa)) == -1) {
|
||||
close(*tfmfd);
|
||||
*tfmfd = -1;
|
||||
if (bind(ctx->tfmfd, (struct sockaddr *)sa, sizeof(*sa)) < 0) {
|
||||
crypt_cipher_destroy_kernel(ctx);
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
*opfd = accept(*tfmfd, NULL, 0);
|
||||
if (*opfd == -1) {
|
||||
close(*tfmfd);
|
||||
*tfmfd = -1;
|
||||
if (setsockopt(ctx->tfmfd, SOL_ALG, ALG_SET_KEY, key, key_length) < 0) {
|
||||
crypt_cipher_destroy_kernel(ctx);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (tag_length && setsockopt(ctx->tfmfd, SOL_ALG, ALG_SET_AEAD_AUTHSIZE, NULL, tag_length) < 0) {
|
||||
crypt_cipher_destroy_kernel(ctx);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ctx->opfd = accept(ctx->tfmfd, NULL, 0);
|
||||
if (ctx->opfd < 0) {
|
||||
crypt_cipher_destroy_kernel(ctx);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
*ciphers
|
||||
*
|
||||
* ENOENT - algorithm not available
|
||||
* ENOTSUP - AF_ALG family not available
|
||||
* (but cannot check specificaly for skcipher API)
|
||||
*/
|
||||
int crypt_cipher_init(struct crypt_cipher **ctx, const char *name,
|
||||
const char *mode, const void *buffer, size_t length)
|
||||
int crypt_cipher_init_kernel(struct crypt_cipher_kernel *ctx, const char *name,
|
||||
const char *mode, const void *key, size_t key_length)
|
||||
{
|
||||
struct crypt_cipher *h;
|
||||
struct sockaddr_alg sa = {
|
||||
.salg_family = AF_ALG,
|
||||
.salg_type = "skcipher",
|
||||
};
|
||||
int r;
|
||||
|
||||
h = malloc(sizeof(*h));
|
||||
if (!h)
|
||||
return -ENOMEM;
|
||||
if (!strcmp(name, "cipher_null"))
|
||||
key_length = 0;
|
||||
|
||||
snprintf((char *)sa.salg_name, sizeof(sa.salg_name),
|
||||
"%s(%s)", mode, name);
|
||||
|
||||
r = crypt_kernel_socket_init(&sa, &h->tfmfd, &h->opfd);
|
||||
if (r < 0) {
|
||||
free(h);
|
||||
return r;
|
||||
}
|
||||
|
||||
if (length && strcmp(name, "cipher_null") &&
|
||||
setsockopt(h->tfmfd, SOL_ALG, ALG_SET_KEY, buffer, length) == -1) {
|
||||
crypt_cipher_destroy(h);
|
||||
r = snprintf((char *)sa.salg_name, sizeof(sa.salg_name), "%s(%s)", mode, name);
|
||||
if (r < 0 || (size_t)r >= sizeof(sa.salg_name))
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
*ctx = h;
|
||||
return 0;
|
||||
return _crypt_cipher_init(ctx, key, key_length, 0, &sa);
|
||||
}
|
||||
|
||||
/* The in/out should be aligned to page boundary */
|
||||
static int crypt_cipher_crypt(struct crypt_cipher *ctx,
|
||||
const char *in, char *out, size_t length,
|
||||
const char *iv, size_t iv_length,
|
||||
uint32_t direction)
|
||||
static int _crypt_cipher_crypt(struct crypt_cipher_kernel *ctx,
|
||||
const char *in, size_t in_length,
|
||||
char *out, size_t out_length,
|
||||
const char *iv, size_t iv_length,
|
||||
uint32_t direction)
|
||||
{
|
||||
int r = 0;
|
||||
ssize_t len;
|
||||
@@ -166,7 +122,7 @@ static int crypt_cipher_crypt(struct crypt_cipher *ctx,
|
||||
uint32_t *type;
|
||||
struct iovec iov = {
|
||||
.iov_base = (void*)(uintptr_t)in,
|
||||
.iov_len = length,
|
||||
.iov_len = in_length,
|
||||
};
|
||||
int iv_msg_size = iv ? CMSG_SPACE(sizeof(*alg_iv) + iv_length) : 0;
|
||||
char buffer[CMSG_SPACE(sizeof(*type)) + iv_msg_size];
|
||||
@@ -177,7 +133,7 @@ static int crypt_cipher_crypt(struct crypt_cipher *ctx,
|
||||
.msg_iovlen = 1,
|
||||
};
|
||||
|
||||
if (!in || !out || !length)
|
||||
if (!in || !out || !in_length)
|
||||
return -EINVAL;
|
||||
|
||||
if ((!iv && iv_length) || (iv && !iv_length))
|
||||
@@ -199,6 +155,9 @@ static int crypt_cipher_crypt(struct crypt_cipher *ctx,
|
||||
/* Set IV */
|
||||
if (iv) {
|
||||
header = CMSG_NXTHDR(&msg, header);
|
||||
if (!header)
|
||||
return -EINVAL;
|
||||
|
||||
header->cmsg_level = SOL_ALG;
|
||||
header->cmsg_type = ALG_SET_IV;
|
||||
header->cmsg_len = iv_msg_size;
|
||||
@@ -208,74 +167,185 @@ static int crypt_cipher_crypt(struct crypt_cipher *ctx,
|
||||
}
|
||||
|
||||
len = sendmsg(ctx->opfd, &msg, 0);
|
||||
if (len != (ssize_t)length) {
|
||||
if (len != (ssize_t)(in_length))
|
||||
r = -EIO;
|
||||
goto bad;
|
||||
else {
|
||||
len = read(ctx->opfd, out, out_length);
|
||||
if (len != (ssize_t)out_length)
|
||||
r = -EIO;
|
||||
}
|
||||
|
||||
len = read(ctx->opfd, out, length);
|
||||
if (len != (ssize_t)length)
|
||||
r = -EIO;
|
||||
bad:
|
||||
crypt_backend_memzero(buffer, sizeof(buffer));
|
||||
return r;
|
||||
}
|
||||
|
||||
int crypt_cipher_encrypt(struct crypt_cipher *ctx,
|
||||
const char *in, char *out, size_t length,
|
||||
const char *iv, size_t iv_length)
|
||||
int crypt_cipher_encrypt_kernel(struct crypt_cipher_kernel *ctx,
|
||||
const char *in, char *out, size_t length,
|
||||
const char *iv, size_t iv_length)
|
||||
{
|
||||
return crypt_cipher_crypt(ctx, in, out, length,
|
||||
iv, iv_length, ALG_OP_ENCRYPT);
|
||||
return _crypt_cipher_crypt(ctx, in, length, out, length,
|
||||
iv, iv_length, ALG_OP_ENCRYPT);
|
||||
}
|
||||
|
||||
int crypt_cipher_decrypt(struct crypt_cipher *ctx,
|
||||
const char *in, char *out, size_t length,
|
||||
const char *iv, size_t iv_length)
|
||||
int crypt_cipher_decrypt_kernel(struct crypt_cipher_kernel *ctx,
|
||||
const char *in, char *out, size_t length,
|
||||
const char *iv, size_t iv_length)
|
||||
{
|
||||
return crypt_cipher_crypt(ctx, in, out, length,
|
||||
iv, iv_length, ALG_OP_DECRYPT);
|
||||
return _crypt_cipher_crypt(ctx, in, length, out, length,
|
||||
iv, iv_length, ALG_OP_DECRYPT);
|
||||
}
|
||||
|
||||
int crypt_cipher_destroy(struct crypt_cipher *ctx)
|
||||
void crypt_cipher_destroy_kernel(struct crypt_cipher_kernel *ctx)
|
||||
{
|
||||
if (ctx->tfmfd != -1)
|
||||
if (ctx->tfmfd >= 0)
|
||||
close(ctx->tfmfd);
|
||||
if (ctx->opfd != -1)
|
||||
if (ctx->opfd >= 0)
|
||||
close(ctx->opfd);
|
||||
memset(ctx, 0, sizeof(*ctx));
|
||||
free(ctx);
|
||||
return 0;
|
||||
|
||||
ctx->tfmfd = -1;
|
||||
ctx->opfd = -1;
|
||||
}
|
||||
|
||||
int crypt_cipher_check_kernel(const char *name, const char *mode,
|
||||
const char *integrity, size_t key_length)
|
||||
{
|
||||
struct crypt_cipher_kernel c;
|
||||
char mode_name[64], tmp_salg_name[180], *real_mode = NULL, *cipher_iv = NULL, *key;
|
||||
const char *salg_type;
|
||||
bool aead;
|
||||
int r;
|
||||
struct sockaddr_alg sa = {
|
||||
.salg_family = AF_ALG,
|
||||
};
|
||||
|
||||
aead = integrity && strcmp(integrity, "none");
|
||||
|
||||
/* Remove IV if present */
|
||||
if (mode) {
|
||||
strncpy(mode_name, mode, sizeof(mode_name));
|
||||
mode_name[sizeof(mode_name) - 1] = 0;
|
||||
cipher_iv = strchr(mode_name, '-');
|
||||
if (cipher_iv) {
|
||||
*cipher_iv = '\0';
|
||||
real_mode = mode_name;
|
||||
}
|
||||
}
|
||||
|
||||
salg_type = aead ? "aead" : "skcipher";
|
||||
r = snprintf((char *)sa.salg_type, sizeof(sa.salg_type), "%s", salg_type);
|
||||
if (r < 0 || (size_t)r >= sizeof(sa.salg_name))
|
||||
return -EINVAL;
|
||||
|
||||
memset(tmp_salg_name, 0, sizeof(tmp_salg_name));
|
||||
|
||||
/* FIXME: this is duplicating a part of devmapper backend */
|
||||
if (aead && !strcmp(integrity, "poly1305"))
|
||||
r = snprintf(tmp_salg_name, sizeof(tmp_salg_name), "rfc7539(%s,%s)", name, integrity);
|
||||
else if (!real_mode)
|
||||
r = snprintf(tmp_salg_name, sizeof(tmp_salg_name), "%s", name);
|
||||
else if (aead && !strcmp(real_mode, "ccm"))
|
||||
r = snprintf(tmp_salg_name, sizeof(tmp_salg_name), "rfc4309(%s(%s))", real_mode, name);
|
||||
else
|
||||
r = snprintf(tmp_salg_name, sizeof(tmp_salg_name), "%s(%s)", real_mode, name);
|
||||
|
||||
if (r < 0 || (size_t)r >= sizeof(tmp_salg_name))
|
||||
return -EINVAL;
|
||||
|
||||
memcpy(sa.salg_name, tmp_salg_name, sizeof(sa.salg_name));
|
||||
|
||||
key = malloc(key_length);
|
||||
if (!key)
|
||||
return -ENOMEM;
|
||||
|
||||
/* We cannot use RNG yet, any key works here, tweak the first part if it is split key (XTS). */
|
||||
memset(key, 0xab, key_length);
|
||||
*key = 0xef;
|
||||
|
||||
r = _crypt_cipher_init(&c, key, key_length, 0, &sa);
|
||||
crypt_cipher_destroy_kernel(&c);
|
||||
free(key);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int crypt_bitlk_decrypt_key_kernel(const void *key, size_t key_length,
|
||||
const char *in, char *out, size_t length,
|
||||
const char *iv, size_t iv_length,
|
||||
const char *tag, size_t tag_length)
|
||||
{
|
||||
struct crypt_cipher_kernel c;
|
||||
struct sockaddr_alg sa = {
|
||||
.salg_family = AF_ALG,
|
||||
.salg_type = "aead",
|
||||
.salg_name = "ccm(aes)",
|
||||
};
|
||||
int r;
|
||||
char buffer[128], ccm_iv[16];
|
||||
|
||||
if (length + tag_length > sizeof(buffer))
|
||||
return -EINVAL;
|
||||
|
||||
if (iv_length > sizeof(ccm_iv) - 2)
|
||||
return -EINVAL;
|
||||
|
||||
r = _crypt_cipher_init(&c, key, key_length, tag_length, &sa);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
memcpy(buffer, in, length);
|
||||
memcpy(buffer + length, tag, tag_length);
|
||||
|
||||
/* CCM IV - RFC3610 */
|
||||
memset(ccm_iv, 0, sizeof(ccm_iv));
|
||||
ccm_iv[0] = 15 - iv_length - 1;
|
||||
memcpy(ccm_iv + 1, iv, iv_length);
|
||||
memset(ccm_iv + 1 + iv_length, 0, ccm_iv[0] + 1);
|
||||
iv_length = sizeof(ccm_iv);
|
||||
|
||||
r = _crypt_cipher_crypt(&c, buffer, length + tag_length, out, length,
|
||||
ccm_iv, iv_length, ALG_OP_DECRYPT);
|
||||
|
||||
crypt_cipher_destroy_kernel(&c);
|
||||
crypt_backend_memzero(buffer, sizeof(buffer));
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
#else /* ENABLE_AF_ALG */
|
||||
|
||||
int crypt_cipher_blocksize(const char *name)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
int crypt_cipher_init(struct crypt_cipher **ctx, const char *name,
|
||||
const char *mode, const void *buffer, size_t length)
|
||||
int crypt_cipher_init_kernel(struct crypt_cipher_kernel *ctx, const char *name,
|
||||
const char *mode, const void *key, size_t key_length)
|
||||
{
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
int crypt_cipher_destroy(struct crypt_cipher *ctx)
|
||||
void crypt_cipher_destroy_kernel(struct crypt_cipher_kernel *ctx)
|
||||
{
|
||||
return 0;
|
||||
return;
|
||||
}
|
||||
|
||||
int crypt_cipher_encrypt(struct crypt_cipher *ctx,
|
||||
const char *in, char *out, size_t length,
|
||||
const char *iv, size_t iv_length)
|
||||
int crypt_cipher_encrypt_kernel(struct crypt_cipher_kernel *ctx,
|
||||
const char *in, char *out, size_t length,
|
||||
const char *iv, size_t iv_length)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
int crypt_cipher_decrypt(struct crypt_cipher *ctx,
|
||||
const char *in, char *out, size_t length,
|
||||
const char *iv, size_t iv_length)
|
||||
int crypt_cipher_decrypt_kernel(struct crypt_cipher_kernel *ctx,
|
||||
const char *in, char *out, size_t length,
|
||||
const char *iv, size_t iv_length)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
int crypt_cipher_check_kernel(const char *name, const char *mode,
|
||||
const char *integrity, size_t key_length)
|
||||
{
|
||||
/* Cannot check, expect success. */
|
||||
return 0;
|
||||
}
|
||||
int crypt_bitlk_decrypt_key_kernel(const void *key, size_t key_length,
|
||||
const char *in, char *out, size_t length,
|
||||
const char *iv, size_t iv_length,
|
||||
const char *tag, size_t tag_length)
|
||||
{
|
||||
return -ENOTSUP;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
* GCRYPT crypto backend implementation
|
||||
*
|
||||
* Copyright (C) 2010-2012, Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2010-2014, Milan Broz
|
||||
* Copyright (C) 2010-2021 Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2010-2021 Milan Broz
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
@@ -24,7 +24,7 @@
|
||||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
#include <gcrypt.h>
|
||||
#include "crypto_backend.h"
|
||||
#include "crypto_backend_internal.h"
|
||||
|
||||
static int crypto_backend_initialised = 0;
|
||||
static int crypto_backend_secmem = 1;
|
||||
@@ -43,9 +43,22 @@ struct crypt_hmac {
|
||||
int hash_len;
|
||||
};
|
||||
|
||||
struct crypt_cipher {
|
||||
bool use_kernel;
|
||||
union {
|
||||
struct crypt_cipher_kernel kernel;
|
||||
gcry_cipher_hd_t hd;
|
||||
} u;
|
||||
};
|
||||
|
||||
struct hash_alg {
|
||||
const char *name;
|
||||
const char *gcrypt_name;
|
||||
};
|
||||
|
||||
/*
|
||||
* Test for wrong Whirlpool variant,
|
||||
* Ref: http://lists.gnupg.org/pipermail/gcrypt-devel/2014-January/002889.html
|
||||
* Ref: https://lists.gnupg.org/pipermail/gcrypt-devel/2014-January/002889.html
|
||||
*/
|
||||
static void crypt_hash_test_whirlpool_bug(void)
|
||||
{
|
||||
@@ -81,8 +94,10 @@ static void crypt_hash_test_whirlpool_bug(void)
|
||||
crypto_backend_whirlpool_bug = 1;
|
||||
}
|
||||
|
||||
int crypt_backend_init(struct crypt_device *ctx)
|
||||
int crypt_backend_init(void)
|
||||
{
|
||||
int r;
|
||||
|
||||
if (crypto_backend_initialised)
|
||||
return 0;
|
||||
|
||||
@@ -91,7 +106,7 @@ int crypt_backend_init(struct crypt_device *ctx)
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
/* FIXME: If gcrypt compiled to support POSIX 1003.1e capabilities,
|
||||
/* If gcrypt compiled to support POSIX 1003.1e capabilities,
|
||||
* it drops all privileges during secure memory initialisation.
|
||||
* For now, the only workaround is to disable secure memory in gcrypt.
|
||||
* cryptsetup always need at least cap_sys_admin privilege for dm-ioctl
|
||||
@@ -112,15 +127,24 @@ int crypt_backend_init(struct crypt_device *ctx)
|
||||
crypto_backend_initialised = 1;
|
||||
crypt_hash_test_whirlpool_bug();
|
||||
|
||||
snprintf(version, 64, "gcrypt %s%s%s",
|
||||
r = snprintf(version, sizeof(version), "gcrypt %s%s%s",
|
||||
gcry_check_version(NULL),
|
||||
crypto_backend_secmem ? "" : ", secmem disabled",
|
||||
crypto_backend_whirlpool_bug > 0 ? ", flawed whirlpool" : ""
|
||||
);
|
||||
crypto_backend_whirlpool_bug > 0 ? ", flawed whirlpool" : "");
|
||||
if (r < 0 || (size_t)r >= sizeof(version))
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void crypt_backend_destroy(void)
|
||||
{
|
||||
if (crypto_backend_initialised)
|
||||
gcry_control(GCRYCTL_TERM_SECMEM);
|
||||
|
||||
crypto_backend_initialised = 0;
|
||||
}
|
||||
|
||||
const char *crypt_backend_version(void)
|
||||
{
|
||||
return crypto_backend_initialised ? version : "";
|
||||
@@ -134,10 +158,24 @@ uint32_t crypt_backend_flags(void)
|
||||
static const char *crypt_hash_compat_name(const char *name, unsigned int *flags)
|
||||
{
|
||||
const char *hash_name = name;
|
||||
int i;
|
||||
static struct hash_alg hash_algs[] = {
|
||||
{ "blake2b-160", "blake2b_160" },
|
||||
{ "blake2b-256", "blake2b_256" },
|
||||
{ "blake2b-384", "blake2b_384" },
|
||||
{ "blake2b-512", "blake2b_512" },
|
||||
{ "blake2s-128", "blake2s_128" },
|
||||
{ "blake2s-160", "blake2s_160" },
|
||||
{ "blake2s-224", "blake2s_224" },
|
||||
{ "blake2s-256", "blake2s_256" },
|
||||
{ NULL, NULL, }};
|
||||
|
||||
if (!name)
|
||||
return NULL;
|
||||
|
||||
/* "whirlpool_gcryptbug" is out shortcut to flawed whirlpool
|
||||
* in libgcrypt < 1.6.0 */
|
||||
if (name && !strcasecmp(name, "whirlpool_gcryptbug")) {
|
||||
if (!strcasecmp(name, "whirlpool_gcryptbug")) {
|
||||
#if GCRYPT_VERSION_NUMBER >= 0x010601
|
||||
if (flags)
|
||||
*flags |= GCRY_MD_FLAG_BUGEMU1;
|
||||
@@ -145,6 +183,15 @@ static const char *crypt_hash_compat_name(const char *name, unsigned int *flags)
|
||||
hash_name = "whirlpool";
|
||||
}
|
||||
|
||||
i = 0;
|
||||
while (hash_algs[i].name) {
|
||||
if (!strcasecmp(name, hash_algs[i].name)) {
|
||||
hash_name = hash_algs[i].gcrypt_name;
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
return hash_name;
|
||||
}
|
||||
|
||||
@@ -217,12 +264,11 @@ int crypt_hash_final(struct crypt_hash *ctx, char *buffer, size_t length)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int crypt_hash_destroy(struct crypt_hash *ctx)
|
||||
void crypt_hash_destroy(struct crypt_hash *ctx)
|
||||
{
|
||||
gcry_md_close(ctx->hd);
|
||||
memset(ctx, 0, sizeof(*ctx));
|
||||
free(ctx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* HMAC */
|
||||
@@ -232,7 +278,7 @@ int crypt_hmac_size(const char *name)
|
||||
}
|
||||
|
||||
int crypt_hmac_init(struct crypt_hmac **ctx, const char *name,
|
||||
const void *buffer, size_t length)
|
||||
const void *key, size_t key_length)
|
||||
{
|
||||
struct crypt_hmac *h;
|
||||
unsigned int flags = GCRY_MD_FLAG_HMAC;
|
||||
@@ -254,7 +300,7 @@ int crypt_hmac_init(struct crypt_hmac **ctx, const char *name,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (gcry_md_setkey(h->hd, buffer, length)) {
|
||||
if (gcry_md_setkey(h->hd, key, key_length)) {
|
||||
gcry_md_close(h->hd);
|
||||
free(h);
|
||||
return -EINVAL;
|
||||
@@ -293,16 +339,15 @@ int crypt_hmac_final(struct crypt_hmac *ctx, char *buffer, size_t length)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int crypt_hmac_destroy(struct crypt_hmac *ctx)
|
||||
void crypt_hmac_destroy(struct crypt_hmac *ctx)
|
||||
{
|
||||
gcry_md_close(ctx->hd);
|
||||
memset(ctx, 0, sizeof(*ctx));
|
||||
free(ctx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* RNG */
|
||||
int crypt_backend_rng(char *buffer, size_t length, int quality, int fips)
|
||||
int crypt_backend_rng(char *buffer, size_t length, int quality, int fips __attribute__((unused)))
|
||||
{
|
||||
switch(quality) {
|
||||
case CRYPT_RND_NORMAL:
|
||||
@@ -317,38 +362,191 @@ int crypt_backend_rng(char *buffer, size_t length, int quality, int fips)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* PBKDF */
|
||||
int crypt_pbkdf(const char *kdf, const char *hash,
|
||||
const char *password, size_t password_length,
|
||||
const char *salt, size_t salt_length,
|
||||
char *key, size_t key_length,
|
||||
unsigned int iterations)
|
||||
static int pbkdf2(const char *hash,
|
||||
const char *password, size_t password_length,
|
||||
const char *salt, size_t salt_length,
|
||||
char *key, size_t key_length,
|
||||
uint32_t iterations)
|
||||
{
|
||||
const char *hash_name = crypt_hash_compat_name(hash, NULL);
|
||||
|
||||
#if USE_INTERNAL_PBKDF2
|
||||
if (!kdf || strncmp(kdf, "pbkdf2", 6))
|
||||
return -EINVAL;
|
||||
|
||||
return pkcs5_pbkdf2(hash_name, password, password_length, salt, salt_length,
|
||||
iterations, key_length, key, 0);
|
||||
|
||||
#else /* USE_INTERNAL_PBKDF2 */
|
||||
int hash_id = gcry_md_map_name(hash_name);
|
||||
int kdf_id;
|
||||
|
||||
if (!hash_id)
|
||||
return -EINVAL;
|
||||
|
||||
if (kdf && !strncmp(kdf, "pbkdf2", 6))
|
||||
kdf_id = GCRY_KDF_PBKDF2;
|
||||
else
|
||||
return -EINVAL;
|
||||
|
||||
if (gcry_kdf_derive(password, password_length, kdf_id, hash_id,
|
||||
if (gcry_kdf_derive(password, password_length, GCRY_KDF_PBKDF2, hash_id,
|
||||
salt, salt_length, iterations, key_length, key))
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
#endif /* USE_INTERNAL_PBKDF2 */
|
||||
}
|
||||
|
||||
/* PBKDF */
|
||||
int crypt_pbkdf(const char *kdf, const char *hash,
|
||||
const char *password, size_t password_length,
|
||||
const char *salt, size_t salt_length,
|
||||
char *key, size_t key_length,
|
||||
uint32_t iterations, uint32_t memory, uint32_t parallel)
|
||||
{
|
||||
if (!kdf)
|
||||
return -EINVAL;
|
||||
|
||||
if (!strcmp(kdf, "pbkdf2"))
|
||||
return pbkdf2(hash, password, password_length, salt, salt_length,
|
||||
key, key_length, iterations);
|
||||
else if (!strncmp(kdf, "argon2", 6))
|
||||
return argon2(kdf, password, password_length, salt, salt_length,
|
||||
key, key_length, iterations, memory, parallel);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Block ciphers */
|
||||
static int _cipher_init(gcry_cipher_hd_t *hd, const char *name,
|
||||
const char *mode, const void *buffer, size_t length)
|
||||
{
|
||||
int cipher_id, mode_id;
|
||||
|
||||
cipher_id = gcry_cipher_map_name(name);
|
||||
if (cipher_id == GCRY_CIPHER_MODE_NONE)
|
||||
return -ENOENT;
|
||||
|
||||
if (!strcmp(mode, "ecb"))
|
||||
mode_id = GCRY_CIPHER_MODE_ECB;
|
||||
else if (!strcmp(mode, "cbc"))
|
||||
mode_id = GCRY_CIPHER_MODE_CBC;
|
||||
#if HAVE_DECL_GCRY_CIPHER_MODE_XTS
|
||||
else if (!strcmp(mode, "xts"))
|
||||
mode_id = GCRY_CIPHER_MODE_XTS;
|
||||
#endif
|
||||
else
|
||||
return -ENOENT;
|
||||
|
||||
if (gcry_cipher_open(hd, cipher_id, mode_id, 0))
|
||||
return -EINVAL;
|
||||
|
||||
if (gcry_cipher_setkey(*hd, buffer, length)) {
|
||||
gcry_cipher_close(*hd);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int crypt_cipher_init(struct crypt_cipher **ctx, const char *name,
|
||||
const char *mode, const void *key, size_t key_length)
|
||||
{
|
||||
struct crypt_cipher *h;
|
||||
int r;
|
||||
|
||||
h = malloc(sizeof(*h));
|
||||
if (!h)
|
||||
return -ENOMEM;
|
||||
|
||||
if (!_cipher_init(&h->u.hd, name, mode, key, key_length)) {
|
||||
h->use_kernel = false;
|
||||
*ctx = h;
|
||||
return 0;
|
||||
}
|
||||
|
||||
r = crypt_cipher_init_kernel(&h->u.kernel, name, mode, key, key_length);
|
||||
if (r < 0) {
|
||||
free(h);
|
||||
return r;
|
||||
}
|
||||
|
||||
h->use_kernel = true;
|
||||
*ctx = h;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void crypt_cipher_destroy(struct crypt_cipher *ctx)
|
||||
{
|
||||
if (ctx->use_kernel)
|
||||
crypt_cipher_destroy_kernel(&ctx->u.kernel);
|
||||
else
|
||||
gcry_cipher_close(ctx->u.hd);
|
||||
free(ctx);
|
||||
}
|
||||
|
||||
int crypt_cipher_encrypt(struct crypt_cipher *ctx,
|
||||
const char *in, char *out, size_t length,
|
||||
const char *iv, size_t iv_length)
|
||||
{
|
||||
if (ctx->use_kernel)
|
||||
return crypt_cipher_encrypt_kernel(&ctx->u.kernel, in, out, length, iv, iv_length);
|
||||
|
||||
if (iv && gcry_cipher_setiv(ctx->u.hd, iv, iv_length))
|
||||
return -EINVAL;
|
||||
|
||||
if (gcry_cipher_encrypt(ctx->u.hd, out, length, in, length))
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int crypt_cipher_decrypt(struct crypt_cipher *ctx,
|
||||
const char *in, char *out, size_t length,
|
||||
const char *iv, size_t iv_length)
|
||||
{
|
||||
if (ctx->use_kernel)
|
||||
return crypt_cipher_decrypt_kernel(&ctx->u.kernel, in, out, length, iv, iv_length);
|
||||
|
||||
if (iv && gcry_cipher_setiv(ctx->u.hd, iv, iv_length))
|
||||
return -EINVAL;
|
||||
|
||||
if (gcry_cipher_decrypt(ctx->u.hd, out, length, in, length))
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool crypt_cipher_kernel_only(struct crypt_cipher *ctx)
|
||||
{
|
||||
return ctx->use_kernel;
|
||||
}
|
||||
|
||||
int crypt_bitlk_decrypt_key(const void *key, size_t key_length,
|
||||
const char *in, char *out, size_t length,
|
||||
const char *iv, size_t iv_length,
|
||||
const char *tag, size_t tag_length)
|
||||
{
|
||||
#ifdef GCRY_CCM_BLOCK_LEN
|
||||
gcry_cipher_hd_t hd;
|
||||
uint64_t l[3];
|
||||
int r = -EINVAL;
|
||||
|
||||
if (gcry_cipher_open(&hd, GCRY_CIPHER_AES256, GCRY_CIPHER_MODE_CCM, 0))
|
||||
return -EINVAL;
|
||||
|
||||
if (gcry_cipher_setkey(hd, key, key_length))
|
||||
goto out;
|
||||
|
||||
if (gcry_cipher_setiv(hd, iv, iv_length))
|
||||
goto out;
|
||||
|
||||
l[0] = length;
|
||||
l[1] = 0;
|
||||
l[2] = tag_length;
|
||||
if (gcry_cipher_ctl(hd, GCRYCTL_SET_CCM_LENGTHS, l, sizeof(l)))
|
||||
goto out;
|
||||
|
||||
if (gcry_cipher_decrypt(hd, out, length, in, length))
|
||||
goto out;
|
||||
|
||||
if (gcry_cipher_checktag(hd, tag, tag_length))
|
||||
goto out;
|
||||
|
||||
r = 0;
|
||||
out:
|
||||
gcry_cipher_close(hd);
|
||||
return r;
|
||||
#else
|
||||
return -ENOTSUP;
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
* Linux kernel userspace API crypto backend implementation
|
||||
*
|
||||
* Copyright (C) 2010-2012, Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2010-2014, Milan Broz
|
||||
* Copyright (C) 2010-2021 Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2010-2021 Milan Broz
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
@@ -27,9 +27,8 @@
|
||||
#include <sys/socket.h>
|
||||
#include <sys/utsname.h>
|
||||
#include <linux/if_alg.h>
|
||||
#include "crypto_backend.h"
|
||||
#include "crypto_backend_internal.h"
|
||||
|
||||
/* FIXME: remove later */
|
||||
#ifndef AF_ALG
|
||||
#define AF_ALG 38
|
||||
#endif
|
||||
@@ -38,7 +37,7 @@
|
||||
#endif
|
||||
|
||||
static int crypto_backend_initialised = 0;
|
||||
static char version[64];
|
||||
static char version[256];
|
||||
|
||||
struct hash_alg {
|
||||
const char *name;
|
||||
@@ -48,12 +47,29 @@ struct hash_alg {
|
||||
};
|
||||
|
||||
static struct hash_alg hash_algs[] = {
|
||||
{ "sha1", "sha1", 20, 64 },
|
||||
{ "sha256", "sha256", 32, 64 },
|
||||
{ "sha512", "sha512", 64, 128 },
|
||||
{ "ripemd160", "rmd160", 20, 64 },
|
||||
{ "whirlpool", "wp512", 64, 64 },
|
||||
{ NULL, NULL, 0, 0 }
|
||||
{ "sha1", "sha1", 20, 64 },
|
||||
{ "sha224", "sha224", 28, 64 },
|
||||
{ "sha256", "sha256", 32, 64 },
|
||||
{ "sha384", "sha384", 48, 128 },
|
||||
{ "sha512", "sha512", 64, 128 },
|
||||
{ "ripemd160", "rmd160", 20, 64 },
|
||||
{ "whirlpool", "wp512", 64, 64 },
|
||||
{ "sha3-224", "sha3-224", 28, 144 },
|
||||
{ "sha3-256", "sha3-256", 32, 136 },
|
||||
{ "sha3-384", "sha3-384", 48, 104 },
|
||||
{ "sha3-512", "sha3-512", 64, 72 },
|
||||
{ "stribog256","streebog256", 32, 64 },
|
||||
{ "stribog512","streebog512", 64, 64 },
|
||||
{ "sm3", "sm3", 32, 64 },
|
||||
{ "blake2b-160","blake2b-160",20, 128 },
|
||||
{ "blake2b-256","blake2b-256",32, 128 },
|
||||
{ "blake2b-384","blake2b-384",48, 128 },
|
||||
{ "blake2b-512","blake2b-512",64, 128 },
|
||||
{ "blake2s-128","blake2s-128",16, 64 },
|
||||
{ "blake2s-160","blake2s-160",20, 64 },
|
||||
{ "blake2s-224","blake2s-224",28, 64 },
|
||||
{ "blake2s-256","blake2s-256",32, 64 },
|
||||
{ NULL, NULL, 0, 0 }
|
||||
};
|
||||
|
||||
struct crypt_hash {
|
||||
@@ -68,10 +84,40 @@ struct crypt_hmac {
|
||||
int hash_len;
|
||||
};
|
||||
|
||||
/* Defined in crypt_kernel_ciphers.c */
|
||||
extern int crypt_kernel_socket_init(struct sockaddr_alg *sa, int *tfmfd, int *opfd);
|
||||
struct crypt_cipher {
|
||||
struct crypt_cipher_kernel ck;
|
||||
};
|
||||
|
||||
int crypt_backend_init(struct crypt_device *ctx)
|
||||
static int crypt_kernel_socket_init(struct sockaddr_alg *sa, int *tfmfd, int *opfd,
|
||||
const void *key, size_t key_length)
|
||||
{
|
||||
*tfmfd = socket(AF_ALG, SOCK_SEQPACKET, 0);
|
||||
if (*tfmfd < 0)
|
||||
return -ENOTSUP;
|
||||
|
||||
if (bind(*tfmfd, (struct sockaddr *)sa, sizeof(*sa)) < 0) {
|
||||
close(*tfmfd);
|
||||
*tfmfd = -1;
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
if (key && setsockopt(*tfmfd, SOL_ALG, ALG_SET_KEY, key, key_length) < 0) {
|
||||
close(*tfmfd);
|
||||
*tfmfd = -1;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
*opfd = accept(*tfmfd, NULL, 0);
|
||||
if (*opfd < 0) {
|
||||
close(*tfmfd);
|
||||
*tfmfd = -1;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int crypt_backend_init(void)
|
||||
{
|
||||
struct utsname uts;
|
||||
struct sockaddr_alg sa = {
|
||||
@@ -79,7 +125,7 @@ int crypt_backend_init(struct crypt_device *ctx)
|
||||
.salg_type = "hash",
|
||||
.salg_name = "sha256",
|
||||
};
|
||||
int tfmfd = -1, opfd = -1;
|
||||
int r, tfmfd = -1, opfd = -1;
|
||||
|
||||
if (crypto_backend_initialised)
|
||||
return 0;
|
||||
@@ -87,19 +133,26 @@ int crypt_backend_init(struct crypt_device *ctx)
|
||||
if (uname(&uts) == -1 || strcmp(uts.sysname, "Linux"))
|
||||
return -EINVAL;
|
||||
|
||||
if (crypt_kernel_socket_init(&sa, &tfmfd, &opfd) < 0)
|
||||
r = snprintf(version, sizeof(version), "%s %s kernel cryptoAPI",
|
||||
uts.sysname, uts.release);
|
||||
if (r < 0 || (size_t)r >= sizeof(version))
|
||||
return -EINVAL;
|
||||
|
||||
if (crypt_kernel_socket_init(&sa, &tfmfd, &opfd, NULL, 0) < 0)
|
||||
return -EINVAL;
|
||||
|
||||
close(tfmfd);
|
||||
close(opfd);
|
||||
|
||||
snprintf(version, sizeof(version), "%s %s kernel cryptoAPI",
|
||||
uts.sysname, uts.release);
|
||||
|
||||
crypto_backend_initialised = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void crypt_backend_destroy(void)
|
||||
{
|
||||
crypto_backend_initialised = 0;
|
||||
}
|
||||
|
||||
uint32_t crypt_backend_flags(void)
|
||||
{
|
||||
return CRYPT_BACKEND_KERNEL;
|
||||
@@ -150,9 +203,9 @@ int crypt_hash_init(struct crypt_hash **ctx, const char *name)
|
||||
}
|
||||
h->hash_len = ha->length;
|
||||
|
||||
strncpy((char *)sa.salg_name, ha->kernel_name, sizeof(sa.salg_name));
|
||||
strncpy((char *)sa.salg_name, ha->kernel_name, sizeof(sa.salg_name)-1);
|
||||
|
||||
if (crypt_kernel_socket_init(&sa, &h->tfmfd, &h->opfd) < 0) {
|
||||
if (crypt_kernel_socket_init(&sa, &h->tfmfd, &h->opfd, NULL, 0) < 0) {
|
||||
free(h);
|
||||
return -EINVAL;
|
||||
}
|
||||
@@ -186,15 +239,14 @@ int crypt_hash_final(struct crypt_hash *ctx, char *buffer, size_t length)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int crypt_hash_destroy(struct crypt_hash *ctx)
|
||||
void crypt_hash_destroy(struct crypt_hash *ctx)
|
||||
{
|
||||
if (ctx->tfmfd != -1)
|
||||
if (ctx->tfmfd >= 0)
|
||||
close(ctx->tfmfd);
|
||||
if (ctx->opfd != -1)
|
||||
if (ctx->opfd >= 0)
|
||||
close(ctx->opfd);
|
||||
memset(ctx, 0, sizeof(*ctx));
|
||||
free(ctx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* HMAC */
|
||||
@@ -204,7 +256,7 @@ int crypt_hmac_size(const char *name)
|
||||
}
|
||||
|
||||
int crypt_hmac_init(struct crypt_hmac **ctx, const char *name,
|
||||
const void *buffer, size_t length)
|
||||
const void *key, size_t key_length)
|
||||
{
|
||||
struct crypt_hmac *h;
|
||||
struct hash_alg *ha;
|
||||
@@ -212,6 +264,7 @@ int crypt_hmac_init(struct crypt_hmac **ctx, const char *name,
|
||||
.salg_family = AF_ALG,
|
||||
.salg_type = "hash",
|
||||
};
|
||||
int r;
|
||||
|
||||
h = malloc(sizeof(*h));
|
||||
if (!h)
|
||||
@@ -224,16 +277,15 @@ int crypt_hmac_init(struct crypt_hmac **ctx, const char *name,
|
||||
}
|
||||
h->hash_len = ha->length;
|
||||
|
||||
snprintf((char *)sa.salg_name, sizeof(sa.salg_name),
|
||||
r = snprintf((char *)sa.salg_name, sizeof(sa.salg_name),
|
||||
"hmac(%s)", ha->kernel_name);
|
||||
|
||||
if (crypt_kernel_socket_init(&sa, &h->tfmfd, &h->opfd) < 0) {
|
||||
if (r < 0 || (size_t)r >= sizeof(sa.salg_name)) {
|
||||
free(h);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (setsockopt(h->tfmfd, SOL_ALG, ALG_SET_KEY, buffer, length) == -1) {
|
||||
crypt_hmac_destroy(h);
|
||||
if (crypt_kernel_socket_init(&sa, &h->tfmfd, &h->opfd, key, key_length) < 0) {
|
||||
free(h);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@@ -266,19 +318,19 @@ int crypt_hmac_final(struct crypt_hmac *ctx, char *buffer, size_t length)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int crypt_hmac_destroy(struct crypt_hmac *ctx)
|
||||
void crypt_hmac_destroy(struct crypt_hmac *ctx)
|
||||
{
|
||||
if (ctx->tfmfd != -1)
|
||||
if (ctx->tfmfd >= 0)
|
||||
close(ctx->tfmfd);
|
||||
if (ctx->opfd != -1)
|
||||
if (ctx->opfd >= 0)
|
||||
close(ctx->opfd);
|
||||
memset(ctx, 0, sizeof(*ctx));
|
||||
free(ctx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* RNG - N/A */
|
||||
int crypt_backend_rng(char *buffer, size_t length, int quality, int fips)
|
||||
int crypt_backend_rng(char *buffer __attribute__((unused)), size_t length __attribute__((unused)),
|
||||
int quality __attribute__((unused)), int fips __attribute__((unused)))
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
@@ -288,13 +340,79 @@ int crypt_pbkdf(const char *kdf, const char *hash,
|
||||
const char *password, size_t password_length,
|
||||
const char *salt, size_t salt_length,
|
||||
char *key, size_t key_length,
|
||||
unsigned int iterations)
|
||||
uint32_t iterations, uint32_t memory, uint32_t parallel)
|
||||
{
|
||||
struct hash_alg *ha = _get_alg(hash);
|
||||
struct hash_alg *ha;
|
||||
|
||||
if (!ha || !kdf || strncmp(kdf, "pbkdf2", 6))
|
||||
if (!kdf)
|
||||
return -EINVAL;
|
||||
|
||||
return pkcs5_pbkdf2(hash, password, password_length, salt, salt_length,
|
||||
iterations, key_length, key, ha->block_length);
|
||||
if (!strcmp(kdf, "pbkdf2")) {
|
||||
ha = _get_alg(hash);
|
||||
if (!ha)
|
||||
return -EINVAL;
|
||||
|
||||
return pkcs5_pbkdf2(hash, password, password_length, salt, salt_length,
|
||||
iterations, key_length, key, ha->block_length);
|
||||
} else if (!strncmp(kdf, "argon2", 6)) {
|
||||
return argon2(kdf, password, password_length, salt, salt_length,
|
||||
key, key_length, iterations, memory, parallel);
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Block ciphers */
|
||||
int crypt_cipher_init(struct crypt_cipher **ctx, const char *name,
|
||||
const char *mode, const void *key, size_t key_length)
|
||||
{
|
||||
struct crypt_cipher *h;
|
||||
int r;
|
||||
|
||||
h = malloc(sizeof(*h));
|
||||
if (!h)
|
||||
return -ENOMEM;
|
||||
|
||||
r = crypt_cipher_init_kernel(&h->ck, name, mode, key, key_length);
|
||||
if (r < 0) {
|
||||
free(h);
|
||||
return r;
|
||||
}
|
||||
|
||||
*ctx = h;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void crypt_cipher_destroy(struct crypt_cipher *ctx)
|
||||
{
|
||||
crypt_cipher_destroy_kernel(&ctx->ck);
|
||||
free(ctx);
|
||||
}
|
||||
|
||||
int crypt_cipher_encrypt(struct crypt_cipher *ctx,
|
||||
const char *in, char *out, size_t length,
|
||||
const char *iv, size_t iv_length)
|
||||
{
|
||||
return crypt_cipher_encrypt_kernel(&ctx->ck, in, out, length, iv, iv_length);
|
||||
}
|
||||
|
||||
int crypt_cipher_decrypt(struct crypt_cipher *ctx,
|
||||
const char *in, char *out, size_t length,
|
||||
const char *iv, size_t iv_length)
|
||||
{
|
||||
return crypt_cipher_decrypt_kernel(&ctx->ck, in, out, length, iv, iv_length);
|
||||
}
|
||||
|
||||
bool crypt_cipher_kernel_only(struct crypt_cipher *ctx __attribute__((unused)))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
int crypt_bitlk_decrypt_key(const void *key, size_t key_length,
|
||||
const char *in, char *out, size_t length,
|
||||
const char *iv, size_t iv_length,
|
||||
const char *tag, size_t tag_length)
|
||||
{
|
||||
return crypt_bitlk_decrypt_key_kernel(key, key_length, in, out, length,
|
||||
iv, iv_length, tag, tag_length);
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
* Nettle crypto backend implementation
|
||||
*
|
||||
* Copyright (C) 2011-2012 Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2011-2014, Milan Broz
|
||||
* Copyright (C) 2011-2021 Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2011-2021 Milan Broz
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
@@ -23,16 +23,24 @@
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <nettle/sha.h>
|
||||
#include <nettle/sha3.h>
|
||||
#include <nettle/hmac.h>
|
||||
#include <nettle/pbkdf2.h>
|
||||
#include "crypto_backend.h"
|
||||
#include "crypto_backend_internal.h"
|
||||
|
||||
static char *version = "Nettle";
|
||||
#if HAVE_NETTLE_VERSION_H
|
||||
#include <nettle/version.h>
|
||||
#define VSTR(s) STR(s)
|
||||
#define STR(s) #s
|
||||
static const char *version = "Nettle "VSTR(NETTLE_VERSION_MAJOR)"."VSTR(NETTLE_VERSION_MINOR);
|
||||
#else
|
||||
static const char *version = "Nettle";
|
||||
#endif
|
||||
|
||||
typedef void (*init_func) (void *);
|
||||
typedef void (*update_func) (void *, unsigned, const uint8_t *);
|
||||
typedef void (*digest_func) (void *, unsigned, uint8_t *);
|
||||
typedef void (*set_key_func) (void *, unsigned, const uint8_t *);
|
||||
typedef void (*update_func) (void *, size_t, const uint8_t *);
|
||||
typedef void (*digest_func) (void *, size_t, uint8_t *);
|
||||
typedef void (*set_key_func) (void *, size_t, const uint8_t *);
|
||||
|
||||
struct hash_alg {
|
||||
const char *name;
|
||||
@@ -45,6 +53,24 @@ struct hash_alg {
|
||||
set_key_func hmac_set_key;
|
||||
};
|
||||
|
||||
/* Missing HMAC wrappers in Nettle */
|
||||
#define HMAC_FCE(xxx) \
|
||||
struct xhmac_##xxx##_ctx HMAC_CTX(struct xxx##_ctx); \
|
||||
static void xhmac_##xxx##_set_key(struct xhmac_##xxx##_ctx *ctx, \
|
||||
size_t key_length, const uint8_t *key) \
|
||||
{HMAC_SET_KEY(ctx, &nettle_##xxx, key_length, key);} \
|
||||
static void xhmac_##xxx##_update(struct xhmac_##xxx##_ctx *ctx, \
|
||||
size_t length, const uint8_t *data) \
|
||||
{xxx##_update(&ctx->state, length, data);} \
|
||||
static void xhmac_##xxx##_digest(struct xhmac_##xxx##_ctx *ctx, \
|
||||
size_t length, uint8_t *digest) \
|
||||
{HMAC_DIGEST(ctx, &nettle_##xxx, length, digest);}
|
||||
|
||||
HMAC_FCE(sha3_224);
|
||||
HMAC_FCE(sha3_256);
|
||||
HMAC_FCE(sha3_384);
|
||||
HMAC_FCE(sha3_512);
|
||||
|
||||
static struct hash_alg hash_algs[] = {
|
||||
{ "sha1", SHA1_DIGEST_SIZE,
|
||||
(init_func) sha1_init,
|
||||
@@ -94,6 +120,41 @@ static struct hash_alg hash_algs[] = {
|
||||
(digest_func) hmac_ripemd160_digest,
|
||||
(set_key_func) hmac_ripemd160_set_key,
|
||||
},
|
||||
/* Nettle prior to version 3.2 has incompatible SHA3 implementation */
|
||||
#if NETTLE_SHA3_FIPS202
|
||||
{ "sha3-224", SHA3_224_DIGEST_SIZE,
|
||||
(init_func) sha3_224_init,
|
||||
(update_func) sha3_224_update,
|
||||
(digest_func) sha3_224_digest,
|
||||
(update_func) xhmac_sha3_224_update,
|
||||
(digest_func) xhmac_sha3_224_digest,
|
||||
(set_key_func) xhmac_sha3_224_set_key,
|
||||
},
|
||||
{ "sha3-256", SHA3_256_DIGEST_SIZE,
|
||||
(init_func) sha3_256_init,
|
||||
(update_func) sha3_256_update,
|
||||
(digest_func) sha3_256_digest,
|
||||
(update_func) xhmac_sha3_256_update,
|
||||
(digest_func) xhmac_sha3_256_digest,
|
||||
(set_key_func) xhmac_sha3_256_set_key,
|
||||
},
|
||||
{ "sha3-384", SHA3_384_DIGEST_SIZE,
|
||||
(init_func) sha3_384_init,
|
||||
(update_func) sha3_384_update,
|
||||
(digest_func) sha3_384_digest,
|
||||
(update_func) xhmac_sha3_384_update,
|
||||
(digest_func) xhmac_sha3_384_digest,
|
||||
(set_key_func) xhmac_sha3_384_set_key,
|
||||
},
|
||||
{ "sha3-512", SHA3_512_DIGEST_SIZE,
|
||||
(init_func) sha3_512_init,
|
||||
(update_func) sha3_512_update,
|
||||
(digest_func) sha3_512_digest,
|
||||
(update_func) xhmac_sha3_512_update,
|
||||
(digest_func) xhmac_sha3_512_digest,
|
||||
(set_key_func) xhmac_sha3_512_set_key,
|
||||
},
|
||||
#endif
|
||||
{ NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL, }
|
||||
};
|
||||
|
||||
@@ -105,6 +166,11 @@ struct crypt_hash {
|
||||
struct sha256_ctx sha256;
|
||||
struct sha384_ctx sha384;
|
||||
struct sha512_ctx sha512;
|
||||
struct ripemd160_ctx ripemd160;
|
||||
struct sha3_224_ctx sha3_224;
|
||||
struct sha3_256_ctx sha3_256;
|
||||
struct sha3_384_ctx sha3_384;
|
||||
struct sha3_512_ctx sha3_512;
|
||||
} nettle_ctx;
|
||||
};
|
||||
|
||||
@@ -116,11 +182,20 @@ struct crypt_hmac {
|
||||
struct hmac_sha256_ctx sha256;
|
||||
struct hmac_sha384_ctx sha384;
|
||||
struct hmac_sha512_ctx sha512;
|
||||
struct hmac_ripemd160_ctx ripemd160;
|
||||
struct xhmac_sha3_224_ctx sha3_224;
|
||||
struct xhmac_sha3_256_ctx sha3_256;
|
||||
struct xhmac_sha3_384_ctx sha3_384;
|
||||
struct xhmac_sha3_512_ctx sha3_512;
|
||||
} nettle_ctx;
|
||||
size_t key_length;
|
||||
uint8_t *key;
|
||||
};
|
||||
|
||||
struct crypt_cipher {
|
||||
struct crypt_cipher_kernel ck;
|
||||
};
|
||||
|
||||
uint32_t crypt_backend_flags(void)
|
||||
{
|
||||
return 0;
|
||||
@@ -138,11 +213,16 @@ static struct hash_alg *_get_alg(const char *name)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int crypt_backend_init(struct crypt_device *ctx)
|
||||
int crypt_backend_init(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void crypt_backend_destroy(void)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const char *crypt_backend_version(void)
|
||||
{
|
||||
return version;
|
||||
@@ -197,11 +277,10 @@ int crypt_hash_final(struct crypt_hash *ctx, char *buffer, size_t length)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int crypt_hash_destroy(struct crypt_hash *ctx)
|
||||
void crypt_hash_destroy(struct crypt_hash *ctx)
|
||||
{
|
||||
memset(ctx, 0, sizeof(*ctx));
|
||||
free(ctx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* HMAC */
|
||||
@@ -211,7 +290,7 @@ int crypt_hmac_size(const char *name)
|
||||
}
|
||||
|
||||
int crypt_hmac_init(struct crypt_hmac **ctx, const char *name,
|
||||
const void *buffer, size_t length)
|
||||
const void *key, size_t key_length)
|
||||
{
|
||||
struct crypt_hmac *h;
|
||||
|
||||
@@ -222,24 +301,25 @@ int crypt_hmac_init(struct crypt_hmac **ctx, const char *name,
|
||||
|
||||
|
||||
h->hash = _get_alg(name);
|
||||
if (!h->hash)
|
||||
goto bad;
|
||||
if (!h->hash) {
|
||||
free(h);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
h->key = malloc(length);
|
||||
if (!h->key)
|
||||
goto bad;
|
||||
h->key = malloc(key_length);
|
||||
if (!h->key) {
|
||||
free(h);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
memcpy(h->key, buffer, length);
|
||||
h->key_length = length;
|
||||
memcpy(h->key, key, key_length);
|
||||
h->key_length = key_length;
|
||||
|
||||
h->hash->init(&h->nettle_ctx);
|
||||
h->hash->hmac_set_key(&h->nettle_ctx, h->key_length, h->key);
|
||||
|
||||
*ctx = h;
|
||||
return 0;
|
||||
bad:
|
||||
free(h);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static void crypt_hmac_restart(struct crypt_hmac *ctx)
|
||||
@@ -263,17 +343,19 @@ int crypt_hmac_final(struct crypt_hmac *ctx, char *buffer, size_t length)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int crypt_hmac_destroy(struct crypt_hmac *ctx)
|
||||
void crypt_hmac_destroy(struct crypt_hmac *ctx)
|
||||
{
|
||||
memset(ctx->key, 0, ctx->key_length);
|
||||
free(ctx->key);
|
||||
memset(ctx, 0, sizeof(*ctx));
|
||||
free(ctx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* RNG - N/A */
|
||||
int crypt_backend_rng(char *buffer, size_t length, int quality, int fips)
|
||||
int crypt_backend_rng(char *buffer __attribute__((unused)),
|
||||
size_t length __attribute__((unused)),
|
||||
int quality __attribute__((unused)),
|
||||
int fips __attribute__((unused)))
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
@@ -283,23 +365,84 @@ int crypt_pbkdf(const char *kdf, const char *hash,
|
||||
const char *password, size_t password_length,
|
||||
const char *salt, size_t salt_length,
|
||||
char *key, size_t key_length,
|
||||
unsigned int iterations)
|
||||
uint32_t iterations, uint32_t memory, uint32_t parallel)
|
||||
{
|
||||
struct crypt_hmac *h;
|
||||
int r;
|
||||
|
||||
if (!kdf || strncmp(kdf, "pbkdf2", 6))
|
||||
if (!kdf)
|
||||
return -EINVAL;
|
||||
|
||||
r = crypt_hmac_init(&h, hash, password, password_length);
|
||||
if (r < 0)
|
||||
if (!strcmp(kdf, "pbkdf2")) {
|
||||
r = crypt_hmac_init(&h, hash, password, password_length);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
nettle_pbkdf2(&h->nettle_ctx, h->hash->hmac_update,
|
||||
h->hash->hmac_digest, h->hash->length, iterations,
|
||||
salt_length, (const uint8_t *)salt, key_length,
|
||||
(uint8_t *)key);
|
||||
crypt_hmac_destroy(h);
|
||||
return 0;
|
||||
} else if (!strncmp(kdf, "argon2", 6)) {
|
||||
return argon2(kdf, password, password_length, salt, salt_length,
|
||||
key, key_length, iterations, memory, parallel);
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Block ciphers */
|
||||
int crypt_cipher_init(struct crypt_cipher **ctx, const char *name,
|
||||
const char *mode, const void *key, size_t key_length)
|
||||
{
|
||||
struct crypt_cipher *h;
|
||||
int r;
|
||||
|
||||
h = malloc(sizeof(*h));
|
||||
if (!h)
|
||||
return -ENOMEM;
|
||||
|
||||
r = crypt_cipher_init_kernel(&h->ck, name, mode, key, key_length);
|
||||
if (r < 0) {
|
||||
free(h);
|
||||
return r;
|
||||
}
|
||||
|
||||
nettle_pbkdf2(&h->nettle_ctx, h->hash->nettle_hmac_update,
|
||||
h->hash->nettle_hmac_digest, h->hash->length, iterations,
|
||||
salt_length, (const uint8_t *)salt, key_length,
|
||||
(uint8_t *)key);
|
||||
crypt_hmac_destroy(h);
|
||||
|
||||
*ctx = h;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void crypt_cipher_destroy(struct crypt_cipher *ctx)
|
||||
{
|
||||
crypt_cipher_destroy_kernel(&ctx->ck);
|
||||
free(ctx);
|
||||
}
|
||||
|
||||
int crypt_cipher_encrypt(struct crypt_cipher *ctx,
|
||||
const char *in, char *out, size_t length,
|
||||
const char *iv, size_t iv_length)
|
||||
{
|
||||
return crypt_cipher_encrypt_kernel(&ctx->ck, in, out, length, iv, iv_length);
|
||||
}
|
||||
|
||||
int crypt_cipher_decrypt(struct crypt_cipher *ctx,
|
||||
const char *in, char *out, size_t length,
|
||||
const char *iv, size_t iv_length)
|
||||
{
|
||||
return crypt_cipher_decrypt_kernel(&ctx->ck, in, out, length, iv, iv_length);
|
||||
}
|
||||
|
||||
bool crypt_cipher_kernel_only(struct crypt_cipher *ctx __attribute__((unused)))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
int crypt_bitlk_decrypt_key(const void *key, size_t key_length,
|
||||
const char *in, char *out, size_t length,
|
||||
const char *iv, size_t iv_length,
|
||||
const char *tag, size_t tag_length)
|
||||
{
|
||||
return crypt_bitlk_decrypt_key_kernel(key, key_length, in, out, length,
|
||||
iv, iv_length, tag, tag_length);
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
* NSS crypto backend implementation
|
||||
*
|
||||
* Copyright (C) 2010-2012, Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2010-2014, Milan Broz
|
||||
* Copyright (C) 2010-2021 Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2010-2021 Milan Broz
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
@@ -23,7 +23,7 @@
|
||||
#include <errno.h>
|
||||
#include <nss.h>
|
||||
#include <pk11pub.h>
|
||||
#include "crypto_backend.h"
|
||||
#include "crypto_backend_internal.h"
|
||||
|
||||
#define CONST_CAST(x) (x)(uintptr_t)
|
||||
|
||||
@@ -59,6 +59,10 @@ struct crypt_hmac {
|
||||
const struct hash_alg *hash;
|
||||
};
|
||||
|
||||
struct crypt_cipher {
|
||||
struct crypt_cipher_kernel ck;
|
||||
};
|
||||
|
||||
static struct hash_alg *_get_alg(const char *name)
|
||||
{
|
||||
int i = 0;
|
||||
@@ -71,8 +75,10 @@ static struct hash_alg *_get_alg(const char *name)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int crypt_backend_init(struct crypt_device *ctx)
|
||||
int crypt_backend_init(void)
|
||||
{
|
||||
int r;
|
||||
|
||||
if (crypto_backend_initialised)
|
||||
return 0;
|
||||
|
||||
@@ -80,14 +86,22 @@ int crypt_backend_init(struct crypt_device *ctx)
|
||||
return -EINVAL;
|
||||
|
||||
#if HAVE_DECL_NSS_GETVERSION
|
||||
snprintf(version, 64, "NSS %s", NSS_GetVersion());
|
||||
r = snprintf(version, sizeof(version), "NSS %s", NSS_GetVersion());
|
||||
#else
|
||||
snprintf(version, 64, "NSS");
|
||||
r = snprintf(version, sizeof(version), "NSS");
|
||||
#endif
|
||||
if (r < 0 || (size_t)r >= sizeof(version))
|
||||
return -EINVAL;
|
||||
|
||||
crypto_backend_initialised = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void crypt_backend_destroy(void)
|
||||
{
|
||||
crypto_backend_initialised = 0;
|
||||
}
|
||||
|
||||
uint32_t crypt_backend_flags(void)
|
||||
{
|
||||
return 0;
|
||||
@@ -175,12 +189,11 @@ int crypt_hash_final(struct crypt_hash *ctx, char *buffer, size_t length)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int crypt_hash_destroy(struct crypt_hash *ctx)
|
||||
void crypt_hash_destroy(struct crypt_hash *ctx)
|
||||
{
|
||||
PK11_DestroyContext(ctx->md, PR_TRUE);
|
||||
memset(ctx, 0, sizeof(*ctx));
|
||||
free(ctx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* HMAC */
|
||||
@@ -190,15 +203,15 @@ int crypt_hmac_size(const char *name)
|
||||
}
|
||||
|
||||
int crypt_hmac_init(struct crypt_hmac **ctx, const char *name,
|
||||
const void *buffer, size_t length)
|
||||
const void *key, size_t key_length)
|
||||
{
|
||||
struct crypt_hmac *h;
|
||||
SECItem keyItem;
|
||||
SECItem noParams;
|
||||
|
||||
keyItem.type = siBuffer;
|
||||
keyItem.data = CONST_CAST(unsigned char *)buffer;
|
||||
keyItem.len = (int)length;
|
||||
keyItem.data = CONST_CAST(unsigned char *)key;
|
||||
keyItem.len = (int)key_length;
|
||||
|
||||
noParams.type = siBuffer;
|
||||
noParams.data = 0;
|
||||
@@ -212,28 +225,28 @@ int crypt_hmac_init(struct crypt_hmac **ctx, const char *name,
|
||||
|
||||
h->hash = _get_alg(name);
|
||||
if (!h->hash)
|
||||
goto bad;
|
||||
goto err;
|
||||
|
||||
h->slot = PK11_GetInternalKeySlot();
|
||||
if (!h->slot)
|
||||
goto bad;
|
||||
goto err;
|
||||
|
||||
h->key = PK11_ImportSymKey(h->slot, h->hash->ck_type, PK11_OriginUnwrap,
|
||||
CKA_SIGN, &keyItem, NULL);
|
||||
if (!h->key)
|
||||
goto bad;
|
||||
goto err;
|
||||
|
||||
h->md = PK11_CreateContextBySymKey(h->hash->ck_type, CKA_SIGN, h->key,
|
||||
&noParams);
|
||||
if (!h->md)
|
||||
goto bad;
|
||||
goto err;
|
||||
|
||||
if (PK11_DigestBegin(h->md) != SECSuccess)
|
||||
goto bad;
|
||||
goto err;
|
||||
|
||||
*ctx = h;
|
||||
return 0;
|
||||
bad:
|
||||
err:
|
||||
crypt_hmac_destroy(h);
|
||||
return -EINVAL;
|
||||
}
|
||||
@@ -277,7 +290,7 @@ int crypt_hmac_final(struct crypt_hmac *ctx, char *buffer, size_t length)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int crypt_hmac_destroy(struct crypt_hmac *ctx)
|
||||
void crypt_hmac_destroy(struct crypt_hmac *ctx)
|
||||
{
|
||||
if (ctx->key)
|
||||
PK11_FreeSymKey(ctx->key);
|
||||
@@ -287,11 +300,10 @@ int crypt_hmac_destroy(struct crypt_hmac *ctx)
|
||||
PK11_DestroyContext(ctx->md, PR_TRUE);
|
||||
memset(ctx, 0, sizeof(*ctx));
|
||||
free(ctx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* RNG */
|
||||
int crypt_backend_rng(char *buffer, size_t length, int quality, int fips)
|
||||
int crypt_backend_rng(char *buffer, size_t length, int quality __attribute__((unused)), int fips)
|
||||
{
|
||||
if (fips)
|
||||
return -EINVAL;
|
||||
@@ -307,13 +319,79 @@ int crypt_pbkdf(const char *kdf, const char *hash,
|
||||
const char *password, size_t password_length,
|
||||
const char *salt, size_t salt_length,
|
||||
char *key, size_t key_length,
|
||||
unsigned int iterations)
|
||||
uint32_t iterations, uint32_t memory, uint32_t parallel)
|
||||
{
|
||||
struct hash_alg *ha = _get_alg(hash);
|
||||
struct hash_alg *ha;
|
||||
|
||||
if (!ha || !kdf || strncmp(kdf, "pbkdf2", 6))
|
||||
if (!kdf)
|
||||
return -EINVAL;
|
||||
|
||||
return pkcs5_pbkdf2(hash, password, password_length, salt, salt_length,
|
||||
iterations, key_length, key, ha->block_length);
|
||||
if (!strcmp(kdf, "pbkdf2")) {
|
||||
ha = _get_alg(hash);
|
||||
if (!ha)
|
||||
return -EINVAL;
|
||||
|
||||
return pkcs5_pbkdf2(hash, password, password_length, salt, salt_length,
|
||||
iterations, key_length, key, ha->block_length);
|
||||
} else if (!strncmp(kdf, "argon2", 6)) {
|
||||
return argon2(kdf, password, password_length, salt, salt_length,
|
||||
key, key_length, iterations, memory, parallel);
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Block ciphers */
|
||||
int crypt_cipher_init(struct crypt_cipher **ctx, const char *name,
|
||||
const char *mode, const void *key, size_t key_length)
|
||||
{
|
||||
struct crypt_cipher *h;
|
||||
int r;
|
||||
|
||||
h = malloc(sizeof(*h));
|
||||
if (!h)
|
||||
return -ENOMEM;
|
||||
|
||||
r = crypt_cipher_init_kernel(&h->ck, name, mode, key, key_length);
|
||||
if (r < 0) {
|
||||
free(h);
|
||||
return r;
|
||||
}
|
||||
|
||||
*ctx = h;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void crypt_cipher_destroy(struct crypt_cipher *ctx)
|
||||
{
|
||||
crypt_cipher_destroy_kernel(&ctx->ck);
|
||||
free(ctx);
|
||||
}
|
||||
|
||||
int crypt_cipher_encrypt(struct crypt_cipher *ctx,
|
||||
const char *in, char *out, size_t length,
|
||||
const char *iv, size_t iv_length)
|
||||
{
|
||||
return crypt_cipher_encrypt_kernel(&ctx->ck, in, out, length, iv, iv_length);
|
||||
}
|
||||
|
||||
int crypt_cipher_decrypt(struct crypt_cipher *ctx,
|
||||
const char *in, char *out, size_t length,
|
||||
const char *iv, size_t iv_length)
|
||||
{
|
||||
return crypt_cipher_decrypt_kernel(&ctx->ck, in, out, length, iv, iv_length);
|
||||
}
|
||||
|
||||
bool crypt_cipher_kernel_only(struct crypt_cipher *ctx __attribute__((unused)))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
int crypt_bitlk_decrypt_key(const void *key, size_t key_length,
|
||||
const char *in, char *out, size_t length,
|
||||
const char *iv, size_t iv_length,
|
||||
const char *tag, size_t tag_length)
|
||||
{
|
||||
return crypt_bitlk_decrypt_key_kernel(key, key_length, in, out, length,
|
||||
iv, iv_length, tag, tag_length);
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
* OPENSSL crypto backend implementation
|
||||
*
|
||||
* Copyright (C) 2010-2012, Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2010-2014, Milan Broz
|
||||
* Copyright (C) 2010-2021 Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2010-2021 Milan Broz
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
@@ -28,38 +28,159 @@
|
||||
* for all of the code used other than OpenSSL.
|
||||
*/
|
||||
|
||||
/*
|
||||
* HMAC will be later rewritten to a new API from OpenSSL 3
|
||||
*/
|
||||
#define OPENSSL_SUPPRESS_DEPRECATED
|
||||
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/hmac.h>
|
||||
#include <openssl/rand.h>
|
||||
#include "crypto_backend.h"
|
||||
#include "crypto_backend_internal.h"
|
||||
#if OPENSSL_VERSION_MAJOR >= 3
|
||||
#include <openssl/provider.h>
|
||||
static OSSL_PROVIDER *ossl_legacy = NULL;
|
||||
static OSSL_PROVIDER *ossl_default = NULL;
|
||||
#endif
|
||||
|
||||
#define CONST_CAST(x) (x)(uintptr_t)
|
||||
|
||||
static int crypto_backend_initialised = 0;
|
||||
|
||||
struct crypt_hash {
|
||||
EVP_MD_CTX md;
|
||||
EVP_MD_CTX *md;
|
||||
const EVP_MD *hash_id;
|
||||
int hash_len;
|
||||
};
|
||||
|
||||
struct crypt_hmac {
|
||||
HMAC_CTX md;
|
||||
HMAC_CTX *md;
|
||||
const EVP_MD *hash_id;
|
||||
int hash_len;
|
||||
};
|
||||
|
||||
int crypt_backend_init(struct crypt_device *ctx)
|
||||
struct crypt_cipher {
|
||||
bool use_kernel;
|
||||
union {
|
||||
struct crypt_cipher_kernel kernel;
|
||||
struct {
|
||||
EVP_CIPHER_CTX *hd_enc;
|
||||
EVP_CIPHER_CTX *hd_dec;
|
||||
size_t iv_length;
|
||||
} lib;
|
||||
} u;
|
||||
};
|
||||
|
||||
struct hash_alg {
|
||||
const char *name;
|
||||
const char *openssl_name;
|
||||
};
|
||||
|
||||
/*
|
||||
* Compatible wrappers for OpenSSL < 1.1.0 and LibreSSL < 2.7.0
|
||||
*/
|
||||
#if OPENSSL_VERSION_NUMBER < 0x10100000L || \
|
||||
(defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x2070000fL)
|
||||
|
||||
static void openssl_backend_init(void)
|
||||
{
|
||||
OpenSSL_add_all_algorithms();
|
||||
}
|
||||
|
||||
static void openssl_backend_exit(void)
|
||||
{
|
||||
}
|
||||
|
||||
static const char *openssl_backend_version(void)
|
||||
{
|
||||
return SSLeay_version(SSLEAY_VERSION);
|
||||
}
|
||||
|
||||
static EVP_MD_CTX *EVP_MD_CTX_new(void)
|
||||
{
|
||||
EVP_MD_CTX *md = malloc(sizeof(*md));
|
||||
|
||||
if (md)
|
||||
EVP_MD_CTX_init(md);
|
||||
|
||||
return md;
|
||||
}
|
||||
|
||||
static void EVP_MD_CTX_free(EVP_MD_CTX *md)
|
||||
{
|
||||
EVP_MD_CTX_cleanup(md);
|
||||
free(md);
|
||||
}
|
||||
|
||||
static HMAC_CTX *HMAC_CTX_new(void)
|
||||
{
|
||||
HMAC_CTX *md = malloc(sizeof(*md));
|
||||
|
||||
if (md)
|
||||
HMAC_CTX_init(md);
|
||||
|
||||
return md;
|
||||
}
|
||||
|
||||
static void HMAC_CTX_free(HMAC_CTX *md)
|
||||
{
|
||||
HMAC_CTX_cleanup(md);
|
||||
free(md);
|
||||
}
|
||||
#else
|
||||
static void openssl_backend_init(void)
|
||||
{
|
||||
/*
|
||||
* OpenSSL >= 3.0.0 provides some algorithms in legacy provider
|
||||
*/
|
||||
#if OPENSSL_VERSION_MAJOR >= 3
|
||||
OPENSSL_init_crypto(OPENSSL_INIT_NO_ATEXIT, NULL);
|
||||
ossl_legacy = OSSL_PROVIDER_try_load(NULL, "legacy", 0);
|
||||
ossl_default = OSSL_PROVIDER_try_load(NULL, "default", 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void openssl_backend_exit(void)
|
||||
{
|
||||
#if OPENSSL_VERSION_MAJOR >= 3
|
||||
/*
|
||||
* If Destructor was already called, we must not call it again
|
||||
*/
|
||||
if (OPENSSL_init_crypto(0, NULL) != 0) {
|
||||
OSSL_PROVIDER_unload(ossl_legacy);
|
||||
OSSL_PROVIDER_unload(ossl_default);
|
||||
OPENSSL_cleanup();
|
||||
}
|
||||
ossl_legacy = NULL;
|
||||
ossl_default = NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
static const char *openssl_backend_version(void)
|
||||
{
|
||||
return OpenSSL_version(OPENSSL_VERSION);
|
||||
}
|
||||
#endif
|
||||
|
||||
int crypt_backend_init(void)
|
||||
{
|
||||
if (crypto_backend_initialised)
|
||||
return 0;
|
||||
|
||||
OpenSSL_add_all_algorithms();
|
||||
openssl_backend_init();
|
||||
|
||||
crypto_backend_initialised = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void crypt_backend_destroy(void)
|
||||
{
|
||||
crypto_backend_initialised = 0;
|
||||
openssl_backend_exit();
|
||||
}
|
||||
|
||||
uint32_t crypt_backend_flags(void)
|
||||
{
|
||||
return 0;
|
||||
@@ -67,14 +188,39 @@ uint32_t crypt_backend_flags(void)
|
||||
|
||||
const char *crypt_backend_version(void)
|
||||
{
|
||||
return SSLeay_version(SSLEAY_VERSION);
|
||||
return openssl_backend_version();
|
||||
}
|
||||
|
||||
static const char *crypt_hash_compat_name(const char *name)
|
||||
{
|
||||
const char *hash_name = name;
|
||||
int i;
|
||||
static struct hash_alg hash_algs[] = {
|
||||
{ "blake2b-512", "blake2b512" },
|
||||
{ "blake2s-256", "blake2s256" },
|
||||
{ NULL, NULL, }};
|
||||
|
||||
if (!name)
|
||||
return NULL;
|
||||
|
||||
i = 0;
|
||||
while (hash_algs[i].name) {
|
||||
if (!strcasecmp(name, hash_algs[i].name)) {
|
||||
hash_name = hash_algs[i].openssl_name;
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
return hash_name;
|
||||
}
|
||||
|
||||
/* HASH */
|
||||
int crypt_hash_size(const char *name)
|
||||
{
|
||||
const EVP_MD *hash_id = EVP_get_digestbyname(name);
|
||||
const EVP_MD *hash_id;
|
||||
|
||||
hash_id = EVP_get_digestbyname(crypt_hash_compat_name(name));
|
||||
if (!hash_id)
|
||||
return -EINVAL;
|
||||
|
||||
@@ -89,13 +235,21 @@ int crypt_hash_init(struct crypt_hash **ctx, const char *name)
|
||||
if (!h)
|
||||
return -ENOMEM;
|
||||
|
||||
h->hash_id = EVP_get_digestbyname(name);
|
||||
h->md = EVP_MD_CTX_new();
|
||||
if (!h->md) {
|
||||
free(h);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
h->hash_id = EVP_get_digestbyname(crypt_hash_compat_name(name));
|
||||
if (!h->hash_id) {
|
||||
EVP_MD_CTX_free(h->md);
|
||||
free(h);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (EVP_DigestInit(&h->md, h->hash_id) != 1) {
|
||||
if (EVP_DigestInit_ex(h->md, h->hash_id, NULL) != 1) {
|
||||
EVP_MD_CTX_free(h->md);
|
||||
free(h);
|
||||
return -EINVAL;
|
||||
}
|
||||
@@ -107,7 +261,7 @@ int crypt_hash_init(struct crypt_hash **ctx, const char *name)
|
||||
|
||||
static int crypt_hash_restart(struct crypt_hash *ctx)
|
||||
{
|
||||
if (EVP_DigestInit(&ctx->md, ctx->hash_id) != 1)
|
||||
if (EVP_DigestInit_ex(ctx->md, ctx->hash_id, NULL) != 1)
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
@@ -115,7 +269,7 @@ static int crypt_hash_restart(struct crypt_hash *ctx)
|
||||
|
||||
int crypt_hash_write(struct crypt_hash *ctx, const char *buffer, size_t length)
|
||||
{
|
||||
if (EVP_DigestUpdate(&ctx->md, buffer, length) != 1)
|
||||
if (EVP_DigestUpdate(ctx->md, buffer, length) != 1)
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
@@ -129,7 +283,7 @@ int crypt_hash_final(struct crypt_hash *ctx, char *buffer, size_t length)
|
||||
if (length > (size_t)ctx->hash_len)
|
||||
return -EINVAL;
|
||||
|
||||
if (EVP_DigestFinal_ex(&ctx->md, tmp, &tmp_len) != 1)
|
||||
if (EVP_DigestFinal_ex(ctx->md, tmp, &tmp_len) != 1)
|
||||
return -EINVAL;
|
||||
|
||||
memcpy(buffer, tmp, length);
|
||||
@@ -144,12 +298,11 @@ int crypt_hash_final(struct crypt_hash *ctx, char *buffer, size_t length)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int crypt_hash_destroy(struct crypt_hash *ctx)
|
||||
void crypt_hash_destroy(struct crypt_hash *ctx)
|
||||
{
|
||||
EVP_MD_CTX_cleanup(&ctx->md);
|
||||
EVP_MD_CTX_free(ctx->md);
|
||||
memset(ctx, 0, sizeof(*ctx));
|
||||
free(ctx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* HMAC */
|
||||
@@ -159,7 +312,7 @@ int crypt_hmac_size(const char *name)
|
||||
}
|
||||
|
||||
int crypt_hmac_init(struct crypt_hmac **ctx, const char *name,
|
||||
const void *buffer, size_t length)
|
||||
const void *key, size_t key_length)
|
||||
{
|
||||
struct crypt_hmac *h;
|
||||
|
||||
@@ -167,14 +320,20 @@ int crypt_hmac_init(struct crypt_hmac **ctx, const char *name,
|
||||
if (!h)
|
||||
return -ENOMEM;
|
||||
|
||||
h->hash_id = EVP_get_digestbyname(name);
|
||||
h->md = HMAC_CTX_new();
|
||||
if (!h->md) {
|
||||
free(h);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
h->hash_id = EVP_get_digestbyname(crypt_hash_compat_name(name));
|
||||
if (!h->hash_id) {
|
||||
HMAC_CTX_free(h->md);
|
||||
free(h);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
HMAC_CTX_init(&h->md);
|
||||
HMAC_Init_ex(&h->md, buffer, length, h->hash_id, NULL);
|
||||
HMAC_Init_ex(h->md, key, key_length, h->hash_id, NULL);
|
||||
|
||||
h->hash_len = EVP_MD_size(h->hash_id);
|
||||
*ctx = h;
|
||||
@@ -183,12 +342,12 @@ int crypt_hmac_init(struct crypt_hmac **ctx, const char *name,
|
||||
|
||||
static void crypt_hmac_restart(struct crypt_hmac *ctx)
|
||||
{
|
||||
HMAC_Init_ex(&ctx->md, NULL, 0, ctx->hash_id, NULL);
|
||||
HMAC_Init_ex(ctx->md, NULL, 0, ctx->hash_id, NULL);
|
||||
}
|
||||
|
||||
int crypt_hmac_write(struct crypt_hmac *ctx, const char *buffer, size_t length)
|
||||
{
|
||||
HMAC_Update(&ctx->md, (const unsigned char *)buffer, length);
|
||||
HMAC_Update(ctx->md, (const unsigned char *)buffer, length);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -200,7 +359,7 @@ int crypt_hmac_final(struct crypt_hmac *ctx, char *buffer, size_t length)
|
||||
if (length > (size_t)ctx->hash_len)
|
||||
return -EINVAL;
|
||||
|
||||
HMAC_Final(&ctx->md, tmp, &tmp_len);
|
||||
HMAC_Final(ctx->md, tmp, &tmp_len);
|
||||
|
||||
memcpy(buffer, tmp, length);
|
||||
crypt_backend_memzero(tmp, sizeof(tmp));
|
||||
@@ -213,20 +372,17 @@ int crypt_hmac_final(struct crypt_hmac *ctx, char *buffer, size_t length)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int crypt_hmac_destroy(struct crypt_hmac *ctx)
|
||||
void crypt_hmac_destroy(struct crypt_hmac *ctx)
|
||||
{
|
||||
HMAC_CTX_cleanup(&ctx->md);
|
||||
HMAC_CTX_free(ctx->md);
|
||||
memset(ctx, 0, sizeof(*ctx));
|
||||
free(ctx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* RNG */
|
||||
int crypt_backend_rng(char *buffer, size_t length, int quality, int fips)
|
||||
int crypt_backend_rng(char *buffer, size_t length,
|
||||
int quality __attribute__((unused)), int fips __attribute__((unused)))
|
||||
{
|
||||
if (fips)
|
||||
return -EINVAL;
|
||||
|
||||
if (RAND_bytes((unsigned char *)buffer, length) != 1)
|
||||
return -EINVAL;
|
||||
|
||||
@@ -238,21 +394,223 @@ int crypt_pbkdf(const char *kdf, const char *hash,
|
||||
const char *password, size_t password_length,
|
||||
const char *salt, size_t salt_length,
|
||||
char *key, size_t key_length,
|
||||
unsigned int iterations)
|
||||
uint32_t iterations, uint32_t memory, uint32_t parallel)
|
||||
|
||||
{
|
||||
const EVP_MD *hash_id;
|
||||
|
||||
if (!kdf || strncmp(kdf, "pbkdf2", 6))
|
||||
if (!kdf)
|
||||
return -EINVAL;
|
||||
|
||||
hash_id = EVP_get_digestbyname(hash);
|
||||
if (!hash_id)
|
||||
if (!strcmp(kdf, "pbkdf2")) {
|
||||
hash_id = EVP_get_digestbyname(crypt_hash_compat_name(hash));
|
||||
if (!hash_id)
|
||||
return -EINVAL;
|
||||
|
||||
if (!PKCS5_PBKDF2_HMAC(password, (int)password_length,
|
||||
(const unsigned char *)salt, (int)salt_length,
|
||||
(int)iterations, hash_id, (int)key_length, (unsigned char *)key))
|
||||
return -EINVAL;
|
||||
return 0;
|
||||
} else if (!strncmp(kdf, "argon2", 6)) {
|
||||
return argon2(kdf, password, password_length, salt, salt_length,
|
||||
key, key_length, iterations, memory, parallel);
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Block ciphers */
|
||||
static void _cipher_destroy(EVP_CIPHER_CTX **hd_enc, EVP_CIPHER_CTX **hd_dec)
|
||||
{
|
||||
EVP_CIPHER_CTX_free(*hd_enc);
|
||||
*hd_enc = NULL;
|
||||
|
||||
EVP_CIPHER_CTX_free(*hd_dec);
|
||||
*hd_dec = NULL;
|
||||
}
|
||||
|
||||
static int _cipher_init(EVP_CIPHER_CTX **hd_enc, EVP_CIPHER_CTX **hd_dec, const char *name,
|
||||
const char *mode, const void *key, size_t key_length, size_t *iv_length)
|
||||
{
|
||||
char cipher_name[256];
|
||||
const EVP_CIPHER *type;
|
||||
int r, key_bits;
|
||||
|
||||
key_bits = key_length * 8;
|
||||
if (!strcmp(mode, "xts"))
|
||||
key_bits /= 2;
|
||||
|
||||
r = snprintf(cipher_name, sizeof(cipher_name), "%s-%d-%s", name, key_bits, mode);
|
||||
if (r < 0 || (size_t)r >= sizeof(cipher_name))
|
||||
return -EINVAL;
|
||||
|
||||
if (!PKCS5_PBKDF2_HMAC(password, (int)password_length,
|
||||
(unsigned char *)salt, (int)salt_length,
|
||||
(int)iterations, hash_id, (int)key_length, (unsigned char *)key))
|
||||
type = EVP_get_cipherbyname(cipher_name);
|
||||
if (!type)
|
||||
return -ENOENT;
|
||||
|
||||
if (EVP_CIPHER_key_length(type) != (int)key_length)
|
||||
return -EINVAL;
|
||||
|
||||
*hd_enc = EVP_CIPHER_CTX_new();
|
||||
*hd_dec = EVP_CIPHER_CTX_new();
|
||||
*iv_length = EVP_CIPHER_iv_length(type);
|
||||
|
||||
if (!*hd_enc || !*hd_dec)
|
||||
return -EINVAL;
|
||||
|
||||
if (EVP_EncryptInit_ex(*hd_enc, type, NULL, key, NULL) != 1 ||
|
||||
EVP_DecryptInit_ex(*hd_dec, type, NULL, key, NULL) != 1) {
|
||||
_cipher_destroy(hd_enc, hd_dec);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (EVP_CIPHER_CTX_set_padding(*hd_enc, 0) != 1 ||
|
||||
EVP_CIPHER_CTX_set_padding(*hd_dec, 0) != 1) {
|
||||
_cipher_destroy(hd_enc, hd_dec);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int crypt_cipher_init(struct crypt_cipher **ctx, const char *name,
|
||||
const char *mode, const void *key, size_t key_length)
|
||||
{
|
||||
struct crypt_cipher *h;
|
||||
int r;
|
||||
|
||||
h = malloc(sizeof(*h));
|
||||
if (!h)
|
||||
return -ENOMEM;
|
||||
|
||||
if (!_cipher_init(&h->u.lib.hd_enc, &h->u.lib.hd_dec, name, mode, key,
|
||||
key_length, &h->u.lib.iv_length)) {
|
||||
h->use_kernel = false;
|
||||
*ctx = h;
|
||||
return 0;
|
||||
}
|
||||
|
||||
r = crypt_cipher_init_kernel(&h->u.kernel, name, mode, key, key_length);
|
||||
if (r < 0) {
|
||||
free(h);
|
||||
return r;
|
||||
}
|
||||
|
||||
h->use_kernel = true;
|
||||
*ctx = h;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void crypt_cipher_destroy(struct crypt_cipher *ctx)
|
||||
{
|
||||
if (ctx->use_kernel)
|
||||
crypt_cipher_destroy_kernel(&ctx->u.kernel);
|
||||
else
|
||||
_cipher_destroy(&ctx->u.lib.hd_enc, &ctx->u.lib.hd_dec);
|
||||
free(ctx);
|
||||
}
|
||||
|
||||
static int _cipher_encrypt(struct crypt_cipher *ctx, const unsigned char *in, unsigned char *out,
|
||||
int length, const unsigned char *iv, size_t iv_length)
|
||||
{
|
||||
int len;
|
||||
|
||||
if (ctx->u.lib.iv_length != iv_length)
|
||||
return -EINVAL;
|
||||
|
||||
if (EVP_EncryptInit_ex(ctx->u.lib.hd_enc, NULL, NULL, NULL, iv) != 1)
|
||||
return -EINVAL;
|
||||
|
||||
if (EVP_EncryptUpdate(ctx->u.lib.hd_enc, out, &len, in, length) != 1)
|
||||
return -EINVAL;
|
||||
|
||||
if (EVP_EncryptFinal(ctx->u.lib.hd_enc, out + len, &len) != 1)
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _cipher_decrypt(struct crypt_cipher *ctx, const unsigned char *in, unsigned char *out,
|
||||
int length, const unsigned char *iv, size_t iv_length)
|
||||
{
|
||||
int len;
|
||||
|
||||
if (ctx->u.lib.iv_length != iv_length)
|
||||
return -EINVAL;
|
||||
|
||||
if (EVP_DecryptInit_ex(ctx->u.lib.hd_dec, NULL, NULL, NULL, iv) != 1)
|
||||
return -EINVAL;
|
||||
|
||||
if (EVP_DecryptUpdate(ctx->u.lib.hd_dec, out, &len, in, length) != 1)
|
||||
return -EINVAL;
|
||||
|
||||
if (EVP_DecryptFinal(ctx->u.lib.hd_dec, out + len, &len) != 1)
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int crypt_cipher_encrypt(struct crypt_cipher *ctx,
|
||||
const char *in, char *out, size_t length,
|
||||
const char *iv, size_t iv_length)
|
||||
{
|
||||
if (ctx->use_kernel)
|
||||
return crypt_cipher_encrypt_kernel(&ctx->u.kernel, in, out, length, iv, iv_length);
|
||||
|
||||
return _cipher_encrypt(ctx, (const unsigned char*)in,
|
||||
(unsigned char *)out, length, (const unsigned char*)iv, iv_length);
|
||||
}
|
||||
|
||||
int crypt_cipher_decrypt(struct crypt_cipher *ctx,
|
||||
const char *in, char *out, size_t length,
|
||||
const char *iv, size_t iv_length)
|
||||
{
|
||||
if (ctx->use_kernel)
|
||||
return crypt_cipher_decrypt_kernel(&ctx->u.kernel, in, out, length, iv, iv_length);
|
||||
|
||||
return _cipher_decrypt(ctx, (const unsigned char*)in,
|
||||
(unsigned char *)out, length, (const unsigned char*)iv, iv_length);
|
||||
}
|
||||
|
||||
bool crypt_cipher_kernel_only(struct crypt_cipher *ctx)
|
||||
{
|
||||
return ctx->use_kernel;
|
||||
}
|
||||
|
||||
int crypt_bitlk_decrypt_key(const void *key, size_t key_length __attribute__((unused)),
|
||||
const char *in, char *out, size_t length,
|
||||
const char *iv, size_t iv_length,
|
||||
const char *tag, size_t tag_length)
|
||||
{
|
||||
#ifdef EVP_CTRL_CCM_SET_IVLEN
|
||||
EVP_CIPHER_CTX *ctx;
|
||||
int len = 0, r = -EINVAL;
|
||||
|
||||
ctx = EVP_CIPHER_CTX_new();
|
||||
if (!ctx)
|
||||
return -EINVAL;
|
||||
|
||||
if (EVP_DecryptInit_ex(ctx, EVP_aes_256_ccm(), NULL, NULL, NULL) != 1)
|
||||
goto out;
|
||||
|
||||
//EVP_CIPHER_CTX_key_length(ctx)
|
||||
//EVP_CIPHER_CTX_iv_length(ctx)
|
||||
|
||||
if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_SET_IVLEN, iv_length, NULL) != 1)
|
||||
goto out;
|
||||
if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_SET_TAG, tag_length, CONST_CAST(void*)tag) != 1)
|
||||
goto out;
|
||||
|
||||
if (EVP_DecryptInit_ex(ctx, NULL, NULL, key, (const unsigned char*)iv) != 1)
|
||||
goto out;
|
||||
|
||||
if (EVP_DecryptUpdate(ctx, (unsigned char*)out, &len, (const unsigned char*)in, length) == 1)
|
||||
r = 0;
|
||||
out:
|
||||
EVP_CIPHER_CTX_free(ctx);
|
||||
return r;
|
||||
#else
|
||||
return -ENOTSUP;
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* Generic wrapper for storage encryption modes and Initial Vectors
|
||||
* (reimplementation of some functions from Linux dm-crypt kernel)
|
||||
*
|
||||
* Copyright (C) 2014, Milan Broz
|
||||
* Copyright (C) 2014-2021 Milan Broz
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
@@ -21,27 +21,28 @@
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <strings.h>
|
||||
#include "bitops.h"
|
||||
#include "crypto_backend.h"
|
||||
|
||||
#define SECTOR_SHIFT 9
|
||||
#define SECTOR_SIZE (1 << SECTOR_SHIFT)
|
||||
|
||||
/*
|
||||
* Internal IV helper
|
||||
* IV documentation: https://gitlab.com/cryptsetup/cryptsetup/wikis/DMCrypt
|
||||
*/
|
||||
struct crypt_sector_iv {
|
||||
enum { IV_NONE, IV_NULL, IV_PLAIN, IV_PLAIN64, IV_ESSIV, IV_BENBI } type;
|
||||
enum { IV_NONE, IV_NULL, IV_PLAIN, IV_PLAIN64, IV_ESSIV, IV_BENBI, IV_PLAIN64BE, IV_EBOIV } type;
|
||||
int iv_size;
|
||||
char *iv;
|
||||
struct crypt_cipher *essiv_cipher;
|
||||
int benbi_shift;
|
||||
struct crypt_cipher *cipher;
|
||||
int shift;
|
||||
};
|
||||
|
||||
/* Block encryption storage context */
|
||||
struct crypt_storage {
|
||||
uint64_t sector_start;
|
||||
size_t sector_size;
|
||||
unsigned iv_shift;
|
||||
struct crypt_cipher *cipher;
|
||||
struct crypt_sector_iv cipher_iv;
|
||||
};
|
||||
@@ -56,24 +57,32 @@ static int int_log2(unsigned int x)
|
||||
|
||||
static int crypt_sector_iv_init(struct crypt_sector_iv *ctx,
|
||||
const char *cipher_name, const char *mode_name,
|
||||
const char *iv_name, char *key, size_t key_length)
|
||||
const char *iv_name, const void *key, size_t key_length,
|
||||
size_t sector_size)
|
||||
{
|
||||
int r;
|
||||
|
||||
memset(ctx, 0, sizeof(*ctx));
|
||||
|
||||
ctx->iv_size = crypt_cipher_blocksize(cipher_name);
|
||||
if (ctx->iv_size < 0)
|
||||
ctx->iv_size = crypt_cipher_ivsize(cipher_name, mode_name);
|
||||
if (ctx->iv_size < 0 || (strcmp(mode_name, "ecb") && ctx->iv_size < 8))
|
||||
return -ENOENT;
|
||||
|
||||
if (!iv_name ||
|
||||
!strcmp(cipher_name, "cipher_null") ||
|
||||
if (!strcmp(cipher_name, "cipher_null") ||
|
||||
!strcmp(mode_name, "ecb")) {
|
||||
if (iv_name)
|
||||
return -EINVAL;
|
||||
ctx->type = IV_NONE;
|
||||
ctx->iv_size = 0;
|
||||
return 0;
|
||||
} else if (!iv_name) {
|
||||
return -EINVAL;
|
||||
} else if (!strcasecmp(iv_name, "null")) {
|
||||
ctx->type = IV_NULL;
|
||||
} else if (!strcasecmp(iv_name, "plain64")) {
|
||||
ctx->type = IV_PLAIN64;
|
||||
} else if (!strcasecmp(iv_name, "plain64be")) {
|
||||
ctx->type = IV_PLAIN64BE;
|
||||
} else if (!strcasecmp(iv_name, "plain")) {
|
||||
ctx->type = IV_PLAIN;
|
||||
} else if (!strncasecmp(iv_name, "essiv:", 6)) {
|
||||
@@ -81,7 +90,6 @@ static int crypt_sector_iv_init(struct crypt_sector_iv *ctx,
|
||||
char *hash_name = strchr(iv_name, ':');
|
||||
int hash_size;
|
||||
char tmp[256];
|
||||
int r;
|
||||
|
||||
if (!hash_name)
|
||||
return -EINVAL;
|
||||
@@ -109,7 +117,7 @@ static int crypt_sector_iv_init(struct crypt_sector_iv *ctx,
|
||||
return r;
|
||||
}
|
||||
|
||||
r = crypt_cipher_init(&ctx->essiv_cipher, cipher_name, "ecb",
|
||||
r = crypt_cipher_init(&ctx->cipher, cipher_name, "ecb",
|
||||
tmp, hash_size);
|
||||
crypt_backend_memzero(tmp, sizeof(tmp));
|
||||
if (r)
|
||||
@@ -122,7 +130,15 @@ static int crypt_sector_iv_init(struct crypt_sector_iv *ctx,
|
||||
return -EINVAL;
|
||||
|
||||
ctx->type = IV_BENBI;
|
||||
ctx->benbi_shift = SECTOR_SHIFT - log;
|
||||
ctx->shift = SECTOR_SHIFT - log;
|
||||
} else if (!strncasecmp(iv_name, "eboiv", 5)) {
|
||||
r = crypt_cipher_init(&ctx->cipher, cipher_name, "ecb",
|
||||
key, key_length);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
ctx->type = IV_EBOIV;
|
||||
ctx->shift = int_log2(sector_size);
|
||||
} else
|
||||
return -ENOENT;
|
||||
|
||||
@@ -151,17 +167,27 @@ static int crypt_sector_iv_generate(struct crypt_sector_iv *ctx, uint64_t sector
|
||||
memset(ctx->iv, 0, ctx->iv_size);
|
||||
*(uint64_t *)ctx->iv = cpu_to_le64(sector);
|
||||
break;
|
||||
case IV_PLAIN64BE:
|
||||
memset(ctx->iv, 0, ctx->iv_size);
|
||||
*(uint64_t *)&ctx->iv[ctx->iv_size - sizeof(uint64_t)] = cpu_to_be64(sector);
|
||||
break;
|
||||
case IV_ESSIV:
|
||||
memset(ctx->iv, 0, ctx->iv_size);
|
||||
*(uint64_t *)ctx->iv = cpu_to_le64(sector);
|
||||
return crypt_cipher_encrypt(ctx->essiv_cipher,
|
||||
return crypt_cipher_encrypt(ctx->cipher,
|
||||
ctx->iv, ctx->iv, ctx->iv_size, NULL, 0);
|
||||
break;
|
||||
case IV_BENBI:
|
||||
memset(ctx->iv, 0, ctx->iv_size);
|
||||
val = cpu_to_be64((sector << ctx->benbi_shift) + 1);
|
||||
val = cpu_to_be64((sector << ctx->shift) + 1);
|
||||
memcpy(ctx->iv + ctx->iv_size - sizeof(val), &val, sizeof(val));
|
||||
break;
|
||||
case IV_EBOIV:
|
||||
memset(ctx->iv, 0, ctx->iv_size);
|
||||
*(uint64_t *)ctx->iv = cpu_to_le64(sector << ctx->shift);
|
||||
return crypt_cipher_encrypt(ctx->cipher,
|
||||
ctx->iv, ctx->iv, ctx->iv_size, NULL, 0);
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
@@ -169,10 +195,10 @@ static int crypt_sector_iv_generate(struct crypt_sector_iv *ctx, uint64_t sector
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int crypt_sector_iv_destroy(struct crypt_sector_iv *ctx)
|
||||
static void crypt_sector_iv_destroy(struct crypt_sector_iv *ctx)
|
||||
{
|
||||
if (ctx->type == IV_ESSIV)
|
||||
crypt_cipher_destroy(ctx->essiv_cipher);
|
||||
if (ctx->type == IV_ESSIV || ctx->type == IV_EBOIV)
|
||||
crypt_cipher_destroy(ctx->cipher);
|
||||
|
||||
if (ctx->iv) {
|
||||
memset(ctx->iv, 0, ctx->iv_size);
|
||||
@@ -180,22 +206,27 @@ static int crypt_sector_iv_destroy(struct crypt_sector_iv *ctx)
|
||||
}
|
||||
|
||||
memset(ctx, 0, sizeof(*ctx));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Block encryption storage wrappers */
|
||||
|
||||
int crypt_storage_init(struct crypt_storage **ctx,
|
||||
uint64_t sector_start,
|
||||
size_t sector_size,
|
||||
const char *cipher,
|
||||
const char *cipher_mode,
|
||||
char *key, size_t key_length)
|
||||
const void *key, size_t key_length,
|
||||
bool large_iv)
|
||||
{
|
||||
struct crypt_storage *s;
|
||||
char mode_name[64];
|
||||
char *cipher_iv = NULL;
|
||||
int r = -EIO;
|
||||
|
||||
if (sector_size < (1 << SECTOR_SHIFT) ||
|
||||
sector_size > (1 << (SECTOR_SHIFT + 3)) ||
|
||||
sector_size & (sector_size - 1))
|
||||
return -EINVAL;
|
||||
|
||||
s = malloc(sizeof(*s));
|
||||
if (!s)
|
||||
return -ENOMEM;
|
||||
@@ -216,33 +247,40 @@ int crypt_storage_init(struct crypt_storage **ctx,
|
||||
return r;
|
||||
}
|
||||
|
||||
r = crypt_sector_iv_init(&s->cipher_iv, cipher, mode_name, cipher_iv, key, key_length);
|
||||
r = crypt_sector_iv_init(&s->cipher_iv, cipher, mode_name, cipher_iv, key, key_length, sector_size);
|
||||
if (r) {
|
||||
crypt_storage_destroy(s);
|
||||
return r;
|
||||
}
|
||||
|
||||
s->sector_start = sector_start;
|
||||
s->sector_size = sector_size;
|
||||
s->iv_shift = large_iv ? int_log2(sector_size) - SECTOR_SHIFT : 0;
|
||||
|
||||
*ctx = s;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int crypt_storage_decrypt(struct crypt_storage *ctx,
|
||||
uint64_t sector, size_t count,
|
||||
char *buffer)
|
||||
uint64_t iv_offset,
|
||||
uint64_t length, char *buffer)
|
||||
{
|
||||
unsigned int i;
|
||||
uint64_t i;
|
||||
int r = 0;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
r = crypt_sector_iv_generate(&ctx->cipher_iv, sector + i);
|
||||
if (length & (ctx->sector_size - 1))
|
||||
return -EINVAL;
|
||||
|
||||
if (iv_offset & ((ctx->sector_size >> SECTOR_SHIFT) - 1))
|
||||
return -EINVAL;
|
||||
|
||||
for (i = 0; i < length; i += ctx->sector_size) {
|
||||
r = crypt_sector_iv_generate(&ctx->cipher_iv, (iv_offset + (i >> SECTOR_SHIFT)) >> ctx->iv_shift);
|
||||
if (r)
|
||||
break;
|
||||
r = crypt_cipher_decrypt(ctx->cipher,
|
||||
&buffer[i * SECTOR_SIZE],
|
||||
&buffer[i * SECTOR_SIZE],
|
||||
SECTOR_SIZE,
|
||||
&buffer[i],
|
||||
&buffer[i],
|
||||
ctx->sector_size,
|
||||
ctx->cipher_iv.iv,
|
||||
ctx->cipher_iv.iv_size);
|
||||
if (r)
|
||||
@@ -253,20 +291,26 @@ int crypt_storage_decrypt(struct crypt_storage *ctx,
|
||||
}
|
||||
|
||||
int crypt_storage_encrypt(struct crypt_storage *ctx,
|
||||
uint64_t sector, size_t count,
|
||||
char *buffer)
|
||||
uint64_t iv_offset,
|
||||
uint64_t length, char *buffer)
|
||||
{
|
||||
unsigned int i;
|
||||
uint64_t i;
|
||||
int r = 0;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
r = crypt_sector_iv_generate(&ctx->cipher_iv, sector + i);
|
||||
if (length & (ctx->sector_size - 1))
|
||||
return -EINVAL;
|
||||
|
||||
if (iv_offset & ((ctx->sector_size >> SECTOR_SHIFT) - 1))
|
||||
return -EINVAL;
|
||||
|
||||
for (i = 0; i < length; i += ctx->sector_size) {
|
||||
r = crypt_sector_iv_generate(&ctx->cipher_iv, (iv_offset + (i >> SECTOR_SHIFT)) >> ctx->iv_shift);
|
||||
if (r)
|
||||
break;
|
||||
r = crypt_cipher_encrypt(ctx->cipher,
|
||||
&buffer[i * SECTOR_SIZE],
|
||||
&buffer[i * SECTOR_SIZE],
|
||||
SECTOR_SIZE,
|
||||
&buffer[i],
|
||||
&buffer[i],
|
||||
ctx->sector_size,
|
||||
ctx->cipher_iv.iv,
|
||||
ctx->cipher_iv.iv_size);
|
||||
if (r)
|
||||
@@ -276,10 +320,10 @@ int crypt_storage_encrypt(struct crypt_storage *ctx,
|
||||
return r;
|
||||
}
|
||||
|
||||
int crypt_storage_destroy(struct crypt_storage *ctx)
|
||||
void crypt_storage_destroy(struct crypt_storage *ctx)
|
||||
{
|
||||
if (!ctx)
|
||||
return 0;
|
||||
return;
|
||||
|
||||
crypt_sector_iv_destroy(&ctx->cipher_iv);
|
||||
|
||||
@@ -288,6 +332,9 @@ int crypt_storage_destroy(struct crypt_storage *ctx)
|
||||
|
||||
memset(ctx, 0, sizeof(*ctx));
|
||||
free(ctx);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool crypt_storage_kernel_only(struct crypt_storage *ctx)
|
||||
{
|
||||
return crypt_cipher_kernel_only(ctx->cipher);
|
||||
}
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
* Copyright (C) 2004 Free Software Foundation
|
||||
*
|
||||
* cryptsetup related changes
|
||||
* Copyright (C) 2012, Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2012-2014, Milan Broz
|
||||
* Copyright (C) 2012-2021 Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2012-2021 Milan Broz
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
@@ -25,7 +25,7 @@
|
||||
|
||||
#include <errno.h>
|
||||
#include <alloca.h>
|
||||
#include "crypto_backend.h"
|
||||
#include "crypto_backend_internal.h"
|
||||
|
||||
static int hash_buf(const char *src, size_t src_len,
|
||||
char *dst, size_t dst_len,
|
||||
@@ -230,197 +230,3 @@ out:
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
#if 0
|
||||
#include <stdio.h>
|
||||
|
||||
struct test_vector {
|
||||
const char *hash;
|
||||
unsigned int hash_block_length;
|
||||
unsigned int iterations;
|
||||
const char *password;
|
||||
unsigned int password_length;
|
||||
const char *salt;
|
||||
unsigned int salt_length;
|
||||
const char *output;
|
||||
unsigned int output_length;
|
||||
};
|
||||
|
||||
struct test_vector test_vectors[] = {
|
||||
/* RFC 3962 */
|
||||
{
|
||||
"sha1", 64, 1,
|
||||
"password", 8,
|
||||
"ATHENA.MIT.EDUraeburn", 21,
|
||||
"\xcd\xed\xb5\x28\x1b\xb2\xf8\x01"
|
||||
"\x56\x5a\x11\x22\xb2\x56\x35\x15"
|
||||
"\x0a\xd1\xf7\xa0\x4b\xb9\xf3\xa3"
|
||||
"\x33\xec\xc0\xe2\xe1\xf7\x08\x37", 32
|
||||
}, {
|
||||
"sha1", 64, 2,
|
||||
"password", 8,
|
||||
"ATHENA.MIT.EDUraeburn", 21,
|
||||
"\x01\xdb\xee\x7f\x4a\x9e\x24\x3e"
|
||||
"\x98\x8b\x62\xc7\x3c\xda\x93\x5d"
|
||||
"\xa0\x53\x78\xb9\x32\x44\xec\x8f"
|
||||
"\x48\xa9\x9e\x61\xad\x79\x9d\x86", 32
|
||||
}, {
|
||||
"sha1", 64, 1200,
|
||||
"password", 8,
|
||||
"ATHENA.MIT.EDUraeburn", 21,
|
||||
"\x5c\x08\xeb\x61\xfd\xf7\x1e\x4e"
|
||||
"\x4e\xc3\xcf\x6b\xa1\xf5\x51\x2b"
|
||||
"\xa7\xe5\x2d\xdb\xc5\xe5\x14\x2f"
|
||||
"\x70\x8a\x31\xe2\xe6\x2b\x1e\x13", 32
|
||||
}, {
|
||||
"sha1", 64, 5,
|
||||
"password", 8,
|
||||
"\0224VxxV4\022", 8, // "\x1234567878563412
|
||||
"\xd1\xda\xa7\x86\x15\xf2\x87\xe6"
|
||||
"\xa1\xc8\xb1\x20\xd7\x06\x2a\x49"
|
||||
"\x3f\x98\xd2\x03\xe6\xbe\x49\xa6"
|
||||
"\xad\xf4\xfa\x57\x4b\x6e\x64\xee", 32
|
||||
}, {
|
||||
"sha1", 64, 1200,
|
||||
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
|
||||
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", 64,
|
||||
"pass phrase equals block size", 29,
|
||||
"\x13\x9c\x30\xc0\x96\x6b\xc3\x2b"
|
||||
"\xa5\x5f\xdb\xf2\x12\x53\x0a\xc9"
|
||||
"\xc5\xec\x59\xf1\xa4\x52\xf5\xcc"
|
||||
"\x9a\xd9\x40\xfe\xa0\x59\x8e\xd1", 32
|
||||
}, {
|
||||
"sha1", 64, 1200,
|
||||
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
|
||||
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", 65,
|
||||
"pass phrase exceeds block size", 30,
|
||||
"\x9c\xca\xd6\xd4\x68\x77\x0c\xd5"
|
||||
"\x1b\x10\xe6\xa6\x87\x21\xbe\x61"
|
||||
"\x1a\x8b\x4d\x28\x26\x01\xdb\x3b"
|
||||
"\x36\xbe\x92\x46\x91\x5e\xc8\x2a", 32
|
||||
}, {
|
||||
"sha1", 64, 50,
|
||||
"\360\235\204\236", 4, // g-clef ("\xf09d849e)
|
||||
"EXAMPLE.COMpianist", 18,
|
||||
"\x6b\x9c\xf2\x6d\x45\x45\x5a\x43"
|
||||
"\xa5\xb8\xbb\x27\x6a\x40\x3b\x39"
|
||||
"\xe7\xfe\x37\xa0\xc4\x1e\x02\xc2"
|
||||
"\x81\xff\x30\x69\xe1\xe9\x4f\x52", 32
|
||||
}, {
|
||||
/* RFC-6070 */
|
||||
"sha1", 64, 1,
|
||||
"password", 8,
|
||||
"salt", 4,
|
||||
"\x0c\x60\xc8\x0f\x96\x1f\x0e\x71\xf3\xa9"
|
||||
"\xb5\x24\xaf\x60\x12\x06\x2f\xe0\x37\xa6", 20
|
||||
}, {
|
||||
"sha1", 64, 2,
|
||||
"password", 8,
|
||||
"salt", 4,
|
||||
"\xea\x6c\x01\x4d\xc7\x2d\x6f\x8c\xcd\x1e"
|
||||
"\xd9\x2a\xce\x1d\x41\xf0\xd8\xde\x89\x57", 20
|
||||
}, {
|
||||
"sha1", 64, 4096,
|
||||
"password", 8,
|
||||
"salt", 4,
|
||||
"\x4b\x00\x79\x01\xb7\x65\x48\x9a\xbe\xad"
|
||||
"\x49\xd9\x26\xf7\x21\xd0\x65\xa4\x29\xc1", 20
|
||||
}, {
|
||||
"sha1", 64, 16777216,
|
||||
"password", 8,
|
||||
"salt", 4,
|
||||
"\xee\xfe\x3d\x61\xcd\x4d\xa4\xe4\xe9\x94"
|
||||
"\x5b\x3d\x6b\xa2\x15\x8c\x26\x34\xe9\x84", 20
|
||||
}, {
|
||||
"sha1", 64, 4096,
|
||||
"passwordPASSWORDpassword", 24,
|
||||
"saltSALTsaltSALTsaltSALTsaltSALTsalt", 36,
|
||||
"\x3d\x2e\xec\x4f\xe4\x1c\x84\x9b\x80\xc8"
|
||||
"\xd8\x36\x62\xc0\xe4\x4a\x8b\x29\x1a\x96"
|
||||
"\x4c\xf2\xf0\x70\x38", 25
|
||||
}, {
|
||||
"sha1", 64, 4096,
|
||||
"pass\0word", 9,
|
||||
"sa\0lt", 5,
|
||||
"\x56\xfa\x6a\xa7\x55\x48\x09\x9d\xcc\x37"
|
||||
"\xd7\xf0\x34\x25\xe0\xc3", 16
|
||||
}, {
|
||||
/* empty password test */
|
||||
"sha1", 64, 2,
|
||||
"", 0,
|
||||
"salt", 4,
|
||||
"\x13\x3a\x4c\xe8\x37\xb4\xd2\x52\x1e\xe2"
|
||||
"\xbf\x03\xe1\x1c\x71\xca\x79\x4e\x07\x97", 20
|
||||
}, {
|
||||
/* Password exceeds block size test */
|
||||
"sha256", 64, 1200,
|
||||
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
|
||||
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", 65,
|
||||
"pass phrase exceeds block size", 30,
|
||||
"\x22\x34\x4b\xc4\xb6\xe3\x26\x75"
|
||||
"\xa8\x09\x0f\x3e\xa8\x0b\xe0\x1d"
|
||||
"\x5f\x95\x12\x6a\x2c\xdd\xc3\xfa"
|
||||
"\xcc\x4a\x5e\x6d\xca\x04\xec\x58", 32
|
||||
}, {
|
||||
"sha512", 128, 1200,
|
||||
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
|
||||
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
|
||||
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
|
||||
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", 129,
|
||||
"pass phrase exceeds block size", 30,
|
||||
"\x0f\xb2\xed\x2c\x0e\x6e\xfb\x7d"
|
||||
"\x7d\x8e\xdd\x58\x01\xb4\x59\x72"
|
||||
"\x99\x92\x16\x30\x5e\xa4\x36\x8d"
|
||||
"\x76\x14\x80\xf3\xe3\x7a\x22\xb9", 32
|
||||
}, {
|
||||
"whirlpool", 64, 1200,
|
||||
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
|
||||
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", 65,
|
||||
"pass phrase exceeds block size", 30,
|
||||
"\x9c\x1c\x74\xf5\x88\x26\xe7\x6a"
|
||||
"\x53\x58\xf4\x0c\x39\xe7\x80\x89"
|
||||
"\x07\xc0\x31\x19\x9a\x50\xa2\x48"
|
||||
"\xf1\xd9\xfe\x78\x64\xe5\x84\x50", 32
|
||||
}
|
||||
};
|
||||
|
||||
static void printhex(const char *s, const char *buf, size_t len)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
printf("%s: ", s);
|
||||
for (i = 0; i < len; i++)
|
||||
printf("\\x%02x", (unsigned char)buf[i]);
|
||||
printf("\n");
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
static int pkcs5_pbkdf2_test_vectors(void)
|
||||
{
|
||||
char result[64];
|
||||
unsigned int i, j;
|
||||
struct test_vector *vec;
|
||||
|
||||
for (i = 0; i < (sizeof(test_vectors) / sizeof(*test_vectors)); i++) {
|
||||
vec = &test_vectors[i];
|
||||
for (j = 1; j <= vec->output_length; j++) {
|
||||
if (pkcs5_pbkdf2(vec->hash,
|
||||
vec->password, vec->password_length,
|
||||
vec->salt, vec->salt_length,
|
||||
vec->iterations,
|
||||
j, result, vec->hash_block_length)) {
|
||||
printf("pbkdf2 failed, vector %d\n", i);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (memcmp(result, vec->output, j) != 0) {
|
||||
printf("vector %u\n", i);
|
||||
printhex(" got", result, j);
|
||||
printhex("want", vec->output, j);
|
||||
return -EINVAL;
|
||||
}
|
||||
memset(result, 0, sizeof(result));
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
/*
|
||||
* PBKDF performance check
|
||||
* Copyright (C) 2012, Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2012-2014, Milan Broz
|
||||
* Copyright (C) 2012-2021 Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2012-2021 Milan Broz
|
||||
* Copyright (C) 2016-2020 Ondrej Mosnacek
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
@@ -20,10 +21,52 @@
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <time.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/resource.h>
|
||||
#include "crypto_backend.h"
|
||||
|
||||
#ifndef CLOCK_MONOTONIC_RAW
|
||||
#define CLOCK_MONOTONIC_RAW CLOCK_MONOTONIC
|
||||
#endif
|
||||
|
||||
#define BENCH_MIN_MS 250
|
||||
#define BENCH_MIN_MS_FAST 10
|
||||
#define BENCH_PERCENT_ATLEAST 95
|
||||
#define BENCH_PERCENT_ATMOST 110
|
||||
#define BENCH_SAMPLES_FAST 3
|
||||
#define BENCH_SAMPLES_SLOW 1
|
||||
|
||||
/* These PBKDF2 limits must be never violated */
|
||||
int crypt_pbkdf_get_limits(const char *kdf, struct crypt_pbkdf_limits *limits)
|
||||
{
|
||||
if (!kdf || !limits)
|
||||
return -EINVAL;
|
||||
|
||||
if (!strcmp(kdf, "pbkdf2")) {
|
||||
limits->min_iterations = 1000; /* recommendation in NIST SP 800-132 */
|
||||
limits->max_iterations = UINT32_MAX;
|
||||
limits->min_memory = 0; /* N/A */
|
||||
limits->min_bench_memory=0; /* N/A */
|
||||
limits->max_memory = 0; /* N/A */
|
||||
limits->min_parallel = 0; /* N/A */
|
||||
limits->max_parallel = 0; /* N/A */
|
||||
return 0;
|
||||
} else if (!strcmp(kdf, "argon2i") || !strcmp(kdf, "argon2id")) {
|
||||
limits->min_iterations = 4;
|
||||
limits->max_iterations = UINT32_MAX;
|
||||
limits->min_memory = 32; /* hard limit */
|
||||
limits->min_bench_memory=64*1024; /* 64 MiB minimum for benchmark */
|
||||
limits->max_memory = 4*1024*1024; /* 4GiB */
|
||||
limits->min_parallel = 1;
|
||||
limits->max_parallel = 4;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static long time_ms(struct rusage *start, struct rusage *end)
|
||||
{
|
||||
int count_kernel_time = 0;
|
||||
@@ -33,7 +76,7 @@ static long time_ms(struct rusage *start, struct rusage *end)
|
||||
count_kernel_time = 1;
|
||||
|
||||
/*
|
||||
* FIXME: if there is no self usage info, count system time.
|
||||
* If there is no self usage info, count system time.
|
||||
* This seem like getrusage() bug in some hypervisors...
|
||||
*/
|
||||
if (!end->ru_utime.tv_sec && !start->ru_utime.tv_sec &&
|
||||
@@ -51,17 +94,245 @@ static long time_ms(struct rusage *start, struct rusage *end)
|
||||
return ms;
|
||||
}
|
||||
|
||||
static long timespec_ms(struct timespec *start, struct timespec *end)
|
||||
{
|
||||
return (end->tv_sec - start->tv_sec) * 1000 +
|
||||
(end->tv_nsec - start->tv_nsec) / (1000 * 1000);
|
||||
}
|
||||
|
||||
static int measure_argon2(const char *kdf, const char *password, size_t password_length,
|
||||
const char *salt, size_t salt_length,
|
||||
char *key, size_t key_length,
|
||||
uint32_t t_cost, uint32_t m_cost, uint32_t parallel,
|
||||
size_t samples, long ms_atleast, long *out_ms)
|
||||
{
|
||||
long ms, ms_min = LONG_MAX;
|
||||
int r;
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < samples; i++) {
|
||||
struct timespec tstart, tend;
|
||||
|
||||
/*
|
||||
* NOTE: We must use clock_gettime here, because Argon2 can run over
|
||||
* multiple threads, and thus we care about real time, not CPU time!
|
||||
*/
|
||||
if (clock_gettime(CLOCK_MONOTONIC_RAW, &tstart) < 0)
|
||||
return -EINVAL;
|
||||
|
||||
r = crypt_pbkdf(kdf, NULL, password, password_length, salt,
|
||||
salt_length, key, key_length, t_cost, m_cost, parallel);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (clock_gettime(CLOCK_MONOTONIC_RAW, &tend) < 0)
|
||||
return -EINVAL;
|
||||
|
||||
ms = timespec_ms(&tstart, &tend);
|
||||
if (ms < 0)
|
||||
return -EINVAL;
|
||||
|
||||
if (ms < ms_atleast) {
|
||||
/* early exit */
|
||||
ms_min = ms;
|
||||
break;
|
||||
}
|
||||
if (ms < ms_min) {
|
||||
ms_min = ms;
|
||||
}
|
||||
}
|
||||
*out_ms = ms_min;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define CONTINUE 0
|
||||
#define FINAL 1
|
||||
static int next_argon2_params(uint32_t *t_cost, uint32_t *m_cost,
|
||||
uint32_t min_t_cost, uint32_t min_m_cost,
|
||||
uint32_t max_m_cost, long ms, uint32_t target_ms)
|
||||
{
|
||||
uint32_t old_t_cost, old_m_cost, new_t_cost, new_m_cost;
|
||||
uint64_t num, denom;
|
||||
|
||||
old_t_cost = *t_cost;
|
||||
old_m_cost = *m_cost;
|
||||
|
||||
if ((uint32_t)ms > target_ms) {
|
||||
/* decreasing, first try to lower t_cost, then m_cost */
|
||||
num = (uint64_t)*t_cost * (uint64_t)target_ms;
|
||||
denom = (uint64_t)ms;
|
||||
new_t_cost = (uint32_t)(num / denom);
|
||||
if (new_t_cost < min_t_cost) {
|
||||
num = (uint64_t)*t_cost * (uint64_t)*m_cost *
|
||||
(uint64_t)target_ms;
|
||||
denom = (uint64_t)min_t_cost * (uint64_t)ms;
|
||||
*t_cost = min_t_cost;
|
||||
*m_cost = (uint32_t)(num / denom);
|
||||
if (*m_cost < min_m_cost) {
|
||||
*m_cost = min_m_cost;
|
||||
return FINAL;
|
||||
}
|
||||
} else {
|
||||
*t_cost = new_t_cost;
|
||||
}
|
||||
} else {
|
||||
/* increasing, first try to increase m_cost, then t_cost */
|
||||
num = (uint64_t)*m_cost * (uint64_t)target_ms;
|
||||
denom = (uint64_t)ms;
|
||||
new_m_cost = (uint32_t)(num / denom);
|
||||
if (new_m_cost > max_m_cost) {
|
||||
num = (uint64_t)*t_cost * (uint64_t)*m_cost *
|
||||
(uint64_t)target_ms;
|
||||
denom = (uint64_t)max_m_cost * (uint64_t)ms;
|
||||
*t_cost = (uint32_t)(num / denom);
|
||||
*m_cost = max_m_cost;
|
||||
if (*t_cost <= min_t_cost) {
|
||||
*t_cost = min_t_cost;
|
||||
return FINAL;
|
||||
}
|
||||
} else if (new_m_cost < min_m_cost) {
|
||||
*m_cost = min_m_cost;
|
||||
return FINAL;
|
||||
} else {
|
||||
*m_cost = new_m_cost;
|
||||
}
|
||||
}
|
||||
|
||||
/* do not continue if it is the same as in the previous run */
|
||||
if (old_t_cost == *t_cost && old_m_cost == *m_cost)
|
||||
return FINAL;
|
||||
|
||||
return CONTINUE;
|
||||
}
|
||||
|
||||
static int crypt_argon2_check(const char *kdf, const char *password,
|
||||
size_t password_length, const char *salt,
|
||||
size_t salt_length, size_t key_length,
|
||||
uint32_t min_t_cost, uint32_t min_m_cost, uint32_t max_m_cost,
|
||||
uint32_t parallel, uint32_t target_ms,
|
||||
uint32_t *out_t_cost, uint32_t *out_m_cost,
|
||||
int (*progress)(uint32_t time_ms, void *usrptr),
|
||||
void *usrptr)
|
||||
{
|
||||
int r = 0;
|
||||
char *key = NULL;
|
||||
uint32_t t_cost, m_cost;
|
||||
long ms;
|
||||
long ms_atleast = (long)target_ms * BENCH_PERCENT_ATLEAST / 100;
|
||||
long ms_atmost = (long)target_ms * BENCH_PERCENT_ATMOST / 100;
|
||||
|
||||
if (key_length <= 0 || target_ms <= 0)
|
||||
return -EINVAL;
|
||||
|
||||
if (min_m_cost < (parallel * 8))
|
||||
min_m_cost = parallel * 8;
|
||||
|
||||
if (max_m_cost < min_m_cost)
|
||||
return -EINVAL;
|
||||
|
||||
key = malloc(key_length);
|
||||
if (!key)
|
||||
return -ENOMEM;
|
||||
|
||||
t_cost = min_t_cost;
|
||||
m_cost = min_m_cost;
|
||||
|
||||
/* 1. Find some small parameters, s. t. ms >= BENCH_MIN_MS: */
|
||||
while (1) {
|
||||
r = measure_argon2(kdf, password, password_length, salt, salt_length,
|
||||
key, key_length, t_cost, m_cost, parallel,
|
||||
BENCH_SAMPLES_FAST, BENCH_MIN_MS, &ms);
|
||||
if (!r) {
|
||||
/* Update parameters to actual measurement */
|
||||
*out_t_cost = t_cost;
|
||||
*out_m_cost = m_cost;
|
||||
if (progress && progress((uint32_t)ms, usrptr))
|
||||
r = -EINTR;
|
||||
}
|
||||
|
||||
if (r < 0)
|
||||
goto out;
|
||||
|
||||
if (ms >= BENCH_MIN_MS)
|
||||
break;
|
||||
|
||||
if (m_cost == max_m_cost) {
|
||||
if (ms < BENCH_MIN_MS_FAST)
|
||||
t_cost *= 16;
|
||||
else {
|
||||
uint32_t new = (t_cost * BENCH_MIN_MS) / (uint32_t)ms;
|
||||
if (new == t_cost)
|
||||
break;
|
||||
|
||||
t_cost = new;
|
||||
}
|
||||
} else {
|
||||
if (ms < BENCH_MIN_MS_FAST)
|
||||
m_cost *= 16;
|
||||
else {
|
||||
uint32_t new = (m_cost * BENCH_MIN_MS) / (uint32_t)ms;
|
||||
if (new == m_cost)
|
||||
break;
|
||||
|
||||
m_cost = new;
|
||||
}
|
||||
if (m_cost > max_m_cost) {
|
||||
m_cost = max_m_cost;
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
* 2. Use the params obtained in (1.) to estimate the target params.
|
||||
* 3. Then repeatedly measure the candidate params and if they fall out of
|
||||
* the acceptance range (+-5 %), try to improve the estimate:
|
||||
*/
|
||||
do {
|
||||
if (next_argon2_params(&t_cost, &m_cost, min_t_cost, min_m_cost,
|
||||
max_m_cost, ms, target_ms)) {
|
||||
/* Update parameters to final computation */
|
||||
*out_t_cost = t_cost;
|
||||
*out_m_cost = m_cost;
|
||||
break;
|
||||
}
|
||||
|
||||
r = measure_argon2(kdf, password, password_length, salt, salt_length,
|
||||
key, key_length, t_cost, m_cost, parallel,
|
||||
BENCH_SAMPLES_SLOW, ms_atleast, &ms);
|
||||
|
||||
if (!r) {
|
||||
/* Update parameters to actual measurement */
|
||||
*out_t_cost = t_cost;
|
||||
*out_m_cost = m_cost;
|
||||
if (progress && progress((uint32_t)ms, usrptr))
|
||||
r = -EINTR;
|
||||
}
|
||||
|
||||
if (r < 0)
|
||||
break;
|
||||
|
||||
} while (ms < ms_atleast || ms > ms_atmost);
|
||||
out:
|
||||
if (key) {
|
||||
crypt_backend_memzero(key, key_length);
|
||||
free(key);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
/* This code benchmarks PBKDF and returns iterations/second using specified hash */
|
||||
int crypt_pbkdf_check(const char *kdf, const char *hash,
|
||||
static int crypt_pbkdf_check(const char *kdf, const char *hash,
|
||||
const char *password, size_t password_length,
|
||||
const char *salt, size_t salt_length,
|
||||
size_t key_length, uint64_t *iter_secs)
|
||||
size_t key_length, uint32_t *iter_secs, uint32_t target_ms,
|
||||
int (*progress)(uint32_t time_ms, void *usrptr), void *usrptr)
|
||||
|
||||
{
|
||||
struct rusage rstart, rend;
|
||||
int r = 0, step = 0;
|
||||
long ms = 0;
|
||||
char *key = NULL;
|
||||
unsigned int iterations;
|
||||
uint32_t iterations;
|
||||
double PBKDF2_temp;
|
||||
|
||||
if (!kdf || !hash || key_length <= 0)
|
||||
return -EINVAL;
|
||||
@@ -70,15 +341,17 @@ int crypt_pbkdf_check(const char *kdf, const char *hash,
|
||||
if (!key)
|
||||
return -ENOMEM;
|
||||
|
||||
*iter_secs = 0;
|
||||
iterations = 1 << 15;
|
||||
while (ms < 500) {
|
||||
while (1) {
|
||||
if (getrusage(RUSAGE_SELF, &rstart) < 0) {
|
||||
r = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
r = crypt_pbkdf(kdf, hash, password, password_length, salt,
|
||||
salt_length, key, key_length, iterations);
|
||||
salt_length, key, key_length, iterations, 0, 0);
|
||||
|
||||
if (r < 0)
|
||||
goto out;
|
||||
|
||||
@@ -88,6 +361,20 @@ int crypt_pbkdf_check(const char *kdf, const char *hash,
|
||||
}
|
||||
|
||||
ms = time_ms(&rstart, &rend);
|
||||
if (ms) {
|
||||
PBKDF2_temp = (double)iterations * target_ms / ms;
|
||||
if (PBKDF2_temp > UINT32_MAX) {
|
||||
r = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
*iter_secs = (uint32_t)PBKDF2_temp;
|
||||
}
|
||||
|
||||
if (progress && progress((uint32_t)ms, usrptr)) {
|
||||
r = -EINTR;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (ms > 500)
|
||||
break;
|
||||
|
||||
@@ -105,9 +392,6 @@ int crypt_pbkdf_check(const char *kdf, const char *hash,
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
if (iter_secs)
|
||||
*iter_secs = (iterations * 1000) / ms;
|
||||
out:
|
||||
if (key) {
|
||||
crypt_backend_memzero(key, key_length);
|
||||
@@ -115,3 +399,45 @@ out:
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
int crypt_pbkdf_perf(const char *kdf, const char *hash,
|
||||
const char *password, size_t password_size,
|
||||
const char *salt, size_t salt_size,
|
||||
size_t volume_key_size, uint32_t time_ms,
|
||||
uint32_t max_memory_kb, uint32_t parallel_threads,
|
||||
uint32_t *iterations_out, uint32_t *memory_out,
|
||||
int (*progress)(uint32_t time_ms, void *usrptr), void *usrptr)
|
||||
{
|
||||
struct crypt_pbkdf_limits pbkdf_limits;
|
||||
int r = -EINVAL;
|
||||
uint32_t min_memory;
|
||||
|
||||
if (!kdf || !iterations_out || !memory_out)
|
||||
return -EINVAL;
|
||||
|
||||
r = crypt_pbkdf_get_limits(kdf, &pbkdf_limits);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
min_memory = pbkdf_limits.min_bench_memory;
|
||||
if (min_memory > max_memory_kb)
|
||||
min_memory = max_memory_kb;
|
||||
|
||||
*memory_out = 0;
|
||||
*iterations_out = 0;
|
||||
|
||||
if (!strcmp(kdf, "pbkdf2"))
|
||||
r = crypt_pbkdf_check(kdf, hash, password, password_size,
|
||||
salt, salt_size, volume_key_size,
|
||||
iterations_out, time_ms, progress, usrptr);
|
||||
|
||||
else if (!strncmp(kdf, "argon2", 6))
|
||||
r = crypt_argon2_check(kdf, password, password_size,
|
||||
salt, salt_size, volume_key_size,
|
||||
pbkdf_limits.min_iterations,
|
||||
min_memory,
|
||||
max_memory_kb,
|
||||
parallel_threads, time_ms, iterations_out,
|
||||
memory_out, progress, usrptr);
|
||||
return r;
|
||||
}
|
||||
|
||||
378
lib/integrity/integrity.c
Normal file
378
lib/integrity/integrity.c
Normal file
@@ -0,0 +1,378 @@
|
||||
/*
|
||||
* Integrity volume handling
|
||||
*
|
||||
* Copyright (C) 2016-2021 Milan Broz
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This file is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this file; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <uuid/uuid.h>
|
||||
|
||||
#include "integrity.h"
|
||||
#include "internal.h"
|
||||
|
||||
static int INTEGRITY_read_superblock(struct crypt_device *cd,
|
||||
struct device *device,
|
||||
uint64_t offset, struct superblock *sb)
|
||||
{
|
||||
int devfd, r;
|
||||
|
||||
devfd = device_open(cd, device, O_RDONLY);
|
||||
if(devfd < 0)
|
||||
return -EINVAL;
|
||||
|
||||
if (read_lseek_blockwise(devfd, device_block_size(cd, device),
|
||||
device_alignment(device), sb, sizeof(*sb), offset) != sizeof(*sb) ||
|
||||
memcmp(sb->magic, SB_MAGIC, sizeof(sb->magic)) ||
|
||||
sb->version < SB_VERSION_1 || sb->version > SB_VERSION_5) {
|
||||
log_std(cd, "No integrity superblock detected on %s.\n",
|
||||
device_path(device));
|
||||
r = -EINVAL;
|
||||
} else {
|
||||
sb->integrity_tag_size = le16toh(sb->integrity_tag_size);
|
||||
sb->journal_sections = le32toh(sb->journal_sections);
|
||||
sb->provided_data_sectors = le64toh(sb->provided_data_sectors);
|
||||
sb->recalc_sector = le64toh(sb->recalc_sector);
|
||||
sb->flags = le32toh(sb->flags);
|
||||
r = 0;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int INTEGRITY_read_sb(struct crypt_device *cd,
|
||||
struct crypt_params_integrity *params,
|
||||
uint32_t *flags)
|
||||
{
|
||||
struct superblock sb;
|
||||
int r;
|
||||
|
||||
r = INTEGRITY_read_superblock(cd, crypt_metadata_device(cd), 0, &sb);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
params->sector_size = SECTOR_SIZE << sb.log2_sectors_per_block;
|
||||
params->tag_size = sb.integrity_tag_size;
|
||||
|
||||
if (flags)
|
||||
*flags = sb.flags;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int INTEGRITY_dump(struct crypt_device *cd, struct device *device, uint64_t offset)
|
||||
{
|
||||
struct superblock sb;
|
||||
int r;
|
||||
|
||||
r = INTEGRITY_read_superblock(cd, device, offset, &sb);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
log_std(cd, "Info for integrity device %s.\n", device_path(device));
|
||||
log_std(cd, "superblock_version %d\n", (unsigned)sb.version);
|
||||
log_std(cd, "log2_interleave_sectors %d\n", sb.log2_interleave_sectors);
|
||||
log_std(cd, "integrity_tag_size %u\n", sb.integrity_tag_size);
|
||||
log_std(cd, "journal_sections %u\n", sb.journal_sections);
|
||||
log_std(cd, "provided_data_sectors %" PRIu64 "\n", sb.provided_data_sectors);
|
||||
log_std(cd, "sector_size %u\n", SECTOR_SIZE << sb.log2_sectors_per_block);
|
||||
if (sb.version >= SB_VERSION_2 && (sb.flags & SB_FLAG_RECALCULATING))
|
||||
log_std(cd, "recalc_sector %" PRIu64 "\n", sb.recalc_sector);
|
||||
log_std(cd, "log2_blocks_per_bitmap %u\n", sb.log2_blocks_per_bitmap_bit);
|
||||
log_std(cd, "flags %s%s%s%s%s\n",
|
||||
sb.flags & SB_FLAG_HAVE_JOURNAL_MAC ? "have_journal_mac " : "",
|
||||
sb.flags & SB_FLAG_RECALCULATING ? "recalculating " : "",
|
||||
sb.flags & SB_FLAG_DIRTY_BITMAP ? "dirty_bitmap " : "",
|
||||
sb.flags & SB_FLAG_FIXED_PADDING ? "fix_padding " : "",
|
||||
sb.flags & SB_FLAG_FIXED_HMAC ? "fix_hmac " : "");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int INTEGRITY_data_sectors(struct crypt_device *cd,
|
||||
struct device *device, uint64_t offset,
|
||||
uint64_t *data_sectors)
|
||||
{
|
||||
struct superblock sb;
|
||||
int r;
|
||||
|
||||
r = INTEGRITY_read_superblock(cd, device, offset, &sb);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
*data_sectors = sb.provided_data_sectors;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int INTEGRITY_key_size(struct crypt_device *cd __attribute__((unused)), const char *integrity)
|
||||
{
|
||||
if (!integrity)
|
||||
return 0;
|
||||
|
||||
//FIXME: use crypto backend hash size
|
||||
if (!strcmp(integrity, "aead"))
|
||||
return 0;
|
||||
else if (!strcmp(integrity, "hmac(sha1)"))
|
||||
return 20;
|
||||
else if (!strcmp(integrity, "hmac(sha256)"))
|
||||
return 32;
|
||||
else if (!strcmp(integrity, "hmac(sha512)"))
|
||||
return 64;
|
||||
else if (!strcmp(integrity, "poly1305"))
|
||||
return 0;
|
||||
else if (!strcmp(integrity, "none"))
|
||||
return 0;
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Return hash or hmac(hash) size, if known */
|
||||
int INTEGRITY_hash_tag_size(const char *integrity)
|
||||
{
|
||||
char hash[MAX_CIPHER_LEN];
|
||||
int r;
|
||||
|
||||
if (!integrity)
|
||||
return 0;
|
||||
|
||||
if (!strcmp(integrity, "crc32") || !strcmp(integrity, "crc32c"))
|
||||
return 4;
|
||||
|
||||
r = sscanf(integrity, "hmac(%" MAX_CIPHER_LEN_STR "[^)]s", hash);
|
||||
if (r == 1)
|
||||
r = crypt_hash_size(hash);
|
||||
else
|
||||
r = crypt_hash_size(integrity);
|
||||
|
||||
return r < 0 ? 0 : r;
|
||||
}
|
||||
|
||||
int INTEGRITY_tag_size(struct crypt_device *cd __attribute__((unused)),
|
||||
const char *integrity,
|
||||
const char *cipher,
|
||||
const char *cipher_mode)
|
||||
{
|
||||
int iv_tag_size = 0, auth_tag_size = 0;
|
||||
|
||||
if (!cipher_mode)
|
||||
iv_tag_size = 0;
|
||||
else if (!strcmp(cipher_mode, "xts-random"))
|
||||
iv_tag_size = 16;
|
||||
else if (!strcmp(cipher_mode, "gcm-random"))
|
||||
iv_tag_size = 12;
|
||||
else if (!strcmp(cipher_mode, "ccm-random"))
|
||||
iv_tag_size = 8;
|
||||
else if (!strcmp(cipher_mode, "ctr-random"))
|
||||
iv_tag_size = 16;
|
||||
else if (!strcmp(cipher, "aegis256") && !strcmp(cipher_mode, "random"))
|
||||
iv_tag_size = 32;
|
||||
else if (!strcmp(cipher_mode, "random"))
|
||||
iv_tag_size = 16;
|
||||
|
||||
//FIXME: use crypto backend hash size
|
||||
if (!integrity || !strcmp(integrity, "none"))
|
||||
auth_tag_size = 0;
|
||||
else if (!strcmp(integrity, "aead"))
|
||||
auth_tag_size = 16; /* gcm- mode only */
|
||||
else if (!strcmp(integrity, "cmac(aes)"))
|
||||
auth_tag_size = 16;
|
||||
else if (!strcmp(integrity, "hmac(sha1)"))
|
||||
auth_tag_size = 20;
|
||||
else if (!strcmp(integrity, "hmac(sha256)"))
|
||||
auth_tag_size = 32;
|
||||
else if (!strcmp(integrity, "hmac(sha512)"))
|
||||
auth_tag_size = 64;
|
||||
else if (!strcmp(integrity, "poly1305")) {
|
||||
if (iv_tag_size)
|
||||
iv_tag_size = 12;
|
||||
auth_tag_size = 16;
|
||||
}
|
||||
|
||||
return iv_tag_size + auth_tag_size;
|
||||
}
|
||||
|
||||
int INTEGRITY_create_dmd_device(struct crypt_device *cd,
|
||||
const struct crypt_params_integrity *params,
|
||||
struct volume_key *vk,
|
||||
struct volume_key *journal_crypt_key,
|
||||
struct volume_key *journal_mac_key,
|
||||
struct crypt_dm_active_device *dmd,
|
||||
uint32_t flags, uint32_t sb_flags)
|
||||
{
|
||||
int r;
|
||||
|
||||
if (!dmd)
|
||||
return -EINVAL;
|
||||
|
||||
*dmd = (struct crypt_dm_active_device) {
|
||||
.flags = flags,
|
||||
};
|
||||
|
||||
/* Workaround for kernel dm-integrity table bug */
|
||||
if (sb_flags & SB_FLAG_RECALCULATING)
|
||||
dmd->flags |= CRYPT_ACTIVATE_RECALCULATE;
|
||||
|
||||
r = INTEGRITY_data_sectors(cd, crypt_metadata_device(cd),
|
||||
crypt_get_data_offset(cd) * SECTOR_SIZE, &dmd->size);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return dm_integrity_target_set(cd, &dmd->segment, 0, dmd->size,
|
||||
crypt_metadata_device(cd), crypt_data_device(cd),
|
||||
crypt_get_integrity_tag_size(cd), crypt_get_data_offset(cd),
|
||||
crypt_get_sector_size(cd), vk, journal_crypt_key,
|
||||
journal_mac_key, params);
|
||||
}
|
||||
|
||||
int INTEGRITY_activate_dmd_device(struct crypt_device *cd,
|
||||
const char *name,
|
||||
const char *type,
|
||||
struct crypt_dm_active_device *dmd,
|
||||
uint32_t sb_flags)
|
||||
{
|
||||
int r;
|
||||
uint32_t dmi_flags;
|
||||
struct dm_target *tgt = &dmd->segment;
|
||||
|
||||
if (!single_segment(dmd) || tgt->type != DM_INTEGRITY)
|
||||
return -EINVAL;
|
||||
|
||||
log_dbg(cd, "Trying to activate INTEGRITY device on top of %s, using name %s, tag size %d, provided sectors %" PRIu64".",
|
||||
device_path(tgt->data_device), name, tgt->u.integrity.tag_size, dmd->size);
|
||||
|
||||
r = device_block_adjust(cd, tgt->data_device, DEV_EXCL,
|
||||
tgt->u.integrity.offset, NULL, &dmd->flags);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
if (tgt->u.integrity.meta_device) {
|
||||
r = device_block_adjust(cd, tgt->u.integrity.meta_device, DEV_EXCL, 0, NULL, NULL);
|
||||
if (r)
|
||||
return r;
|
||||
}
|
||||
|
||||
r = dm_create_device(cd, name, type, dmd);
|
||||
if (r < 0 && (dm_flags(cd, DM_INTEGRITY, &dmi_flags) || !(dmi_flags & DM_INTEGRITY_SUPPORTED))) {
|
||||
log_err(cd, _("Kernel does not support dm-integrity mapping."));
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
if (r < 0 && (sb_flags & SB_FLAG_FIXED_PADDING) && !dm_flags(cd, DM_INTEGRITY, &dmi_flags) &&
|
||||
!(dmi_flags & DM_INTEGRITY_FIX_PADDING_SUPPORTED)) {
|
||||
log_err(cd, _("Kernel does not support dm-integrity fixed metadata alignment."));
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
if (r < 0 && (dmd->flags & CRYPT_ACTIVATE_RECALCULATE) &&
|
||||
!(crypt_get_compatibility(cd) & CRYPT_COMPAT_LEGACY_INTEGRITY_RECALC) &&
|
||||
((sb_flags & SB_FLAG_FIXED_HMAC) ?
|
||||
(tgt->u.integrity.vk && !tgt->u.integrity.journal_integrity_key) :
|
||||
(tgt->u.integrity.vk || tgt->u.integrity.journal_integrity_key))) {
|
||||
log_err(cd, _("Kernel refuses to activate insecure recalculate option (see legacy activation options to override)."));
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int INTEGRITY_activate(struct crypt_device *cd,
|
||||
const char *name,
|
||||
const struct crypt_params_integrity *params,
|
||||
struct volume_key *vk,
|
||||
struct volume_key *journal_crypt_key,
|
||||
struct volume_key *journal_mac_key,
|
||||
uint32_t flags, uint32_t sb_flags)
|
||||
{
|
||||
struct crypt_dm_active_device dmd = {};
|
||||
int r = INTEGRITY_create_dmd_device(cd, params, vk, journal_crypt_key,
|
||||
journal_mac_key, &dmd, flags, sb_flags);
|
||||
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = INTEGRITY_activate_dmd_device(cd, name, CRYPT_INTEGRITY, &dmd, sb_flags);
|
||||
dm_targets_free(cd, &dmd);
|
||||
return r;
|
||||
}
|
||||
|
||||
int INTEGRITY_format(struct crypt_device *cd,
|
||||
const struct crypt_params_integrity *params,
|
||||
struct volume_key *journal_crypt_key,
|
||||
struct volume_key *journal_mac_key)
|
||||
{
|
||||
uint32_t dmi_flags;
|
||||
char tmp_name[64], tmp_uuid[40];
|
||||
struct crypt_dm_active_device dmdi = {
|
||||
.size = 8,
|
||||
.flags = CRYPT_ACTIVATE_PRIVATE, /* We always create journal but it can be unused later */
|
||||
};
|
||||
struct dm_target *tgt = &dmdi.segment;
|
||||
int r;
|
||||
uuid_t tmp_uuid_bin;
|
||||
struct volume_key *vk = NULL;
|
||||
|
||||
uuid_generate(tmp_uuid_bin);
|
||||
uuid_unparse(tmp_uuid_bin, tmp_uuid);
|
||||
|
||||
r = snprintf(tmp_name, sizeof(tmp_name), "temporary-cryptsetup-%s", tmp_uuid);
|
||||
if (r < 0 || (size_t)r >= sizeof(tmp_name))
|
||||
return -EINVAL;
|
||||
|
||||
/* There is no data area, we can actually use fake zeroed key */
|
||||
if (params && params->integrity_key_size)
|
||||
vk = crypt_alloc_volume_key(params->integrity_key_size, NULL);
|
||||
|
||||
r = dm_integrity_target_set(cd, tgt, 0, dmdi.size, crypt_metadata_device(cd),
|
||||
crypt_data_device(cd), crypt_get_integrity_tag_size(cd),
|
||||
crypt_get_data_offset(cd), crypt_get_sector_size(cd), vk,
|
||||
journal_crypt_key, journal_mac_key, params);
|
||||
if (r < 0) {
|
||||
crypt_free_volume_key(vk);
|
||||
return r;
|
||||
}
|
||||
|
||||
log_dbg(cd, "Trying to format INTEGRITY device on top of %s, tmp name %s, tag size %d.",
|
||||
device_path(tgt->data_device), tmp_name, tgt->u.integrity.tag_size);
|
||||
|
||||
r = device_block_adjust(cd, tgt->data_device, DEV_EXCL, tgt->u.integrity.offset, NULL, NULL);
|
||||
if (r < 0 && (dm_flags(cd, DM_INTEGRITY, &dmi_flags) || !(dmi_flags & DM_INTEGRITY_SUPPORTED))) {
|
||||
log_err(cd, _("Kernel does not support dm-integrity mapping."));
|
||||
r = -ENOTSUP;
|
||||
}
|
||||
if (r) {
|
||||
dm_targets_free(cd, &dmdi);
|
||||
return r;
|
||||
}
|
||||
|
||||
if (tgt->u.integrity.meta_device) {
|
||||
r = device_block_adjust(cd, tgt->u.integrity.meta_device, DEV_EXCL, 0, NULL, NULL);
|
||||
if (r) {
|
||||
dm_targets_free(cd, &dmdi);
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
r = dm_create_device(cd, tmp_name, CRYPT_INTEGRITY, &dmdi);
|
||||
crypt_free_volume_key(vk);
|
||||
dm_targets_free(cd, &dmdi);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
return dm_remove_device(cd, tmp_name, CRYPT_DEACTIVATE_FORCE);
|
||||
}
|
||||
102
lib/integrity/integrity.h
Normal file
102
lib/integrity/integrity.h
Normal file
@@ -0,0 +1,102 @@
|
||||
/*
|
||||
* Integrity header definition
|
||||
*
|
||||
* Copyright (C) 2016-2021 Milan Broz
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This file is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this file; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef _CRYPTSETUP_INTEGRITY_H
|
||||
#define _CRYPTSETUP_INTEGRITY_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
struct crypt_device;
|
||||
struct device;
|
||||
struct crypt_params_integrity;
|
||||
struct volume_key;
|
||||
struct crypt_dm_active_device;
|
||||
|
||||
/* dm-integrity helper */
|
||||
#define SB_MAGIC "integrt"
|
||||
#define SB_VERSION_1 1
|
||||
#define SB_VERSION_2 2
|
||||
#define SB_VERSION_3 3
|
||||
#define SB_VERSION_4 4
|
||||
#define SB_VERSION_5 5
|
||||
|
||||
#define SB_FLAG_HAVE_JOURNAL_MAC (1 << 0)
|
||||
#define SB_FLAG_RECALCULATING (1 << 1) /* V2 only */
|
||||
#define SB_FLAG_DIRTY_BITMAP (1 << 2) /* V3 only */
|
||||
#define SB_FLAG_FIXED_PADDING (1 << 3) /* V4 only */
|
||||
#define SB_FLAG_FIXED_HMAC (1 << 4) /* V5 only */
|
||||
|
||||
struct superblock {
|
||||
uint8_t magic[8];
|
||||
uint8_t version;
|
||||
int8_t log2_interleave_sectors;
|
||||
uint16_t integrity_tag_size;
|
||||
uint32_t journal_sections;
|
||||
uint64_t provided_data_sectors;
|
||||
uint32_t flags;
|
||||
uint8_t log2_sectors_per_block;
|
||||
uint8_t log2_blocks_per_bitmap_bit; /* V3 only */
|
||||
uint8_t pad[2];
|
||||
uint64_t recalc_sector; /* V2 only */
|
||||
} __attribute__ ((packed));
|
||||
|
||||
int INTEGRITY_read_sb(struct crypt_device *cd,
|
||||
struct crypt_params_integrity *params,
|
||||
uint32_t *flags);
|
||||
|
||||
int INTEGRITY_dump(struct crypt_device *cd, struct device *device, uint64_t offset);
|
||||
|
||||
int INTEGRITY_data_sectors(struct crypt_device *cd,
|
||||
struct device *device, uint64_t offset,
|
||||
uint64_t *data_sectors);
|
||||
int INTEGRITY_key_size(struct crypt_device *cd, const char *integrity);
|
||||
int INTEGRITY_tag_size(struct crypt_device *cd,
|
||||
const char *integrity,
|
||||
const char *cipher,
|
||||
const char *cipher_mode);
|
||||
int INTEGRITY_hash_tag_size(const char *integrity);
|
||||
|
||||
int INTEGRITY_format(struct crypt_device *cd,
|
||||
const struct crypt_params_integrity *params,
|
||||
struct volume_key *journal_crypt_key,
|
||||
struct volume_key *journal_mac_key);
|
||||
|
||||
int INTEGRITY_activate(struct crypt_device *cd,
|
||||
const char *name,
|
||||
const struct crypt_params_integrity *params,
|
||||
struct volume_key *vk,
|
||||
struct volume_key *journal_crypt_key,
|
||||
struct volume_key *journal_mac_key,
|
||||
uint32_t flags, uint32_t sb_flags);
|
||||
|
||||
int INTEGRITY_create_dmd_device(struct crypt_device *cd,
|
||||
const struct crypt_params_integrity *params,
|
||||
struct volume_key *vk,
|
||||
struct volume_key *journal_crypt_key,
|
||||
struct volume_key *journal_mac_key,
|
||||
struct crypt_dm_active_device *dmd,
|
||||
uint32_t flags, uint32_t sb_flags);
|
||||
|
||||
int INTEGRITY_activate_dmd_device(struct crypt_device *cd,
|
||||
const char *name,
|
||||
const char *type,
|
||||
struct crypt_dm_active_device *dmd,
|
||||
uint32_t sb_flags);
|
||||
#endif
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user