1%% -*- mode: erlang; tab-width: 4; indent-tabs-mode: 1; st-rulers: [70] -*-
2%% vim: ts=4 sw=4 ft=erlang noet
3%%%-------------------------------------------------------------------
4%%% @author Andrew Bennett <andrew@pixid.com>
5%%% @copyright 2014-2015, Andrew Bennett
6%%% @doc
7%%%
8%%% @end
9%%% Created :  11 Aug 2015 by Andrew Bennett <andrew@pixid.com>
10%%%-------------------------------------------------------------------
11-module(cavp_SUITE).
12
13-include_lib("common_test/include/ct.hrl").
14
15-include_lib("public_key/include/public_key.hrl").
16-include_lib("stdlib/include/zip.hrl").
17
18%% ct.
19-export([all/0]).
20-export([groups/0]).
21-export([init_per_suite/1]).
22-export([end_per_suite/1]).
23-export([init_per_group/2]).
24-export([end_per_group/2]).
25
26%% Tests.
27-export([concatenation_kdf/1]).
28-export([curve25519/1]).
29-export([curve448/1]).
30-export([ed25519/1]).
31-export([ed25519ph/1]).
32-export([ed448/1]).
33-export([ed448ph/1]).
34-export([emc_rsa_oaep_encrypt_and_decrypt/1]).
35-export([emc_rsa_pss_sign_and_verify/1]).
36-export([fips_aes_encrypt_and_decrypt/1]).
37-export([fips_aes_gcm_encrypt_and_decrypt/1]).
38-export([fips_aeskw_unwrap/1]).
39-export([fips_aeskw_wrap/1]).
40-export([fips_rsa_pss_sign/1]).
41-export([fips_rsa_pss_verify/1]).
42-export([fips_sha3/1]).
43-export([pbkdf1/1]).
44-export([pbkdf2/1]).
45-export([pkcs7_pad_and_unpad/1]).
46-export([x25519/1]).
47-export([x448/1]).
48
49%% Macros.
50-define(tv_ok(T, M, F, A, E),
51	case erlang:apply(M, F, A) of
52		E ->
53			ok;
54		T ->
55			ct:fail({{M, F, A}, {expected, E}, {got, T}})
56	end).
57
58all() ->
59	[
60		{group, '186-3rsatestvectors'},
61		{group, 'aesmmt'},
62		{group, 'curve25519'},
63		{group, 'curve448'},
64		{group, 'gcmtestvectors'},
65		{group, 'KAT_AES'},
66		{group, 'keccaktestvectors'},
67		{group, 'kwtestvectors'},
68		{group, 'nist-800-56A'},
69		{group, 'pkcs-1v2-1-vec'},
70		{group, 'pkcs-5'},
71		{group, 'pkcs-7'}
72	].
73
74groups() ->
75	[
76		{'186-3rsatestvectors', [parallel], [
77			fips_rsa_pss_sign,
78			fips_rsa_pss_verify
79		]},
80		{'aesmmt', [], [
81			fips_aes_encrypt_and_decrypt
82		]},
83		{'curve25519', [parallel], [
84			curve25519,
85			ed25519,
86			ed25519ph,
87			x25519
88		]},
89		{'curve448', [parallel], [
90			curve448,
91			ed448,
92			ed448ph,
93			x448
94		]},
95		{'gcmtestvectors', [], [
96			fips_aes_gcm_encrypt_and_decrypt
97		]},
98		{'KAT_AES', [], [
99			fips_aes_encrypt_and_decrypt
100		]},
101		{'keccaktestvectors', [], [
102			fips_sha3
103		]},
104		{'kwtestvectors', [parallel], [
105			fips_aeskw_unwrap,
106			fips_aeskw_wrap
107		]},
108		{'nist-800-56A', [], [
109			concatenation_kdf
110		]},
111		{'pkcs-1v2-1-vec', [parallel], [
112			emc_rsa_oaep_encrypt_and_decrypt,
113			emc_rsa_pss_sign_and_verify
114		]},
115		{'pkcs-5', [parallel], [
116			pbkdf1,
117			pbkdf2
118		]},
119		{'pkcs-7', [], [
120			pkcs7_pad_and_unpad
121		]}
122	].
123
124init_per_suite(Config) ->
125	application:set_env(jose, crypto_fallback, true),
126	application:set_env(jose, unsecured_signing, true),
127	_ = application:ensure_all_started(jose),
128	data_setup(Config).
129
130end_per_suite(_Config) ->
131	_ = application:stop(jose),
132	ok.
133
134init_per_group(G='186-3rsatestvectors', Config) ->
135	SigGenFile = data_file("186-3rsatestvectors/SigGenPSS_186-3.txt", Config),
136	SigVerFile = data_file("186-3rsatestvectors/SigVerPSS_186-3.rsp", Config),
137	[{sig_gen_file, SigGenFile}, {sig_ver_file, SigVerFile} | jose_ct:start(G, Config)];
138init_per_group(G='aesmmt', Config) ->
139	Folder = data_file("aesmmt", Config),
140	{ok, Entries} = file:list_dir(Folder),
141	Files = [filename:join([Folder, Entry]) || Entry <- Entries],
142	[{aes_files, Files} | jose_ct:start(G, Config)];
143init_per_group(G='curve25519', Config) ->
144	[
145		{curve25519, [
146			{
147				31029842492115040904895560451863089656472772604678260265531221036453811406496,  % Input scalar
148				34426434033919594451155107781188821651316167215306631574996226621102155684838,  % Input u-coordinate
149				hexstr2lint("c3da55379de9c6908e94ea4df28d084f32eccf03491c71f754b4075577a28552") % Output u-coordinate
150			},
151			{
152				35156891815674817266734212754503633747128614016119564763269015315466259359304,  % Input scalar
153				8883857351183929894090759386610649319417338800022198945255395922347792736741,   % Input u-coordinate
154				hexstr2lint("95cbde9476e8907d7aade45cb4b873f88b595a68799fa152e6f8f7647aac7957") % Output u-coordinate
155			}
156		]},
157		{ed25519, [
158			{ % TEST 1
159				hexstr2bin(
160					"9d61b19deffd5a60ba844af492ec2cc4"
161					"4449c5697b326919703bac031cae7f60"), % SECRET KEY
162				hexstr2bin(
163					"d75a980182b10ab7d54bfed3c964073a"
164					"0ee172f3daa62325af021a68f707511a"), % PUBLIC KEY
165				<<>>, % MESSAGE
166				hexstr2bin(
167					"e5564300c360ac729086e2cc806e828a"
168					"84877f1eb8e5d974d873e06522490155"
169					"5fb8821590a33bacc61e39701cf9b46b"
170					"d25bf5f0595bbe24655141438e7a100b") % SIGNATURE
171			},
172			{ % TEST 2
173				hexstr2bin(
174					"4ccd089b28ff96da9db6c346ec114e0f"
175					"5b8a319f35aba624da8cf6ed4fb8a6fb"), % SECRET KEY
176				hexstr2bin(
177					"3d4017c3e843895a92b70aa74d1b7ebc"
178					"9c982ccf2ec4968cc0cd55f12af4660c"), % PUBLIC KEY
179				hexstr2bin("72"), % MESSAGE
180				hexstr2bin(
181					"92a009a9f0d4cab8720e820b5f642540"
182					"a2b27b5416503f8fb3762223ebdb69da"
183					"085ac1e43e15996e458f3613d0f11d8c"
184					"387b2eaeb4302aeeb00d291612bb0c00") % SIGNATURE
185			},
186			{ % TEST 3
187				hexstr2bin(
188					"c5aa8df43f9f837bedb7442f31dcb7b1"
189					"66d38535076f094b85ce3a2e0b4458f7"), % SECRET KEY
190				hexstr2bin(
191					"fc51cd8e6218a1a38da47ed00230f058"
192					"0816ed13ba3303ac5deb911548908025"), % PUBLIC KEY
193				hexstr2bin("af82"), % MESSAGE
194				hexstr2bin(
195					"6291d657deec24024827e69c3abe01a3"
196					"0ce548a284743a445e3680d7db5ac3ac"
197					"18ff9b538d16f290ae67f760984dc659"
198					"4a7c15e9716ed28dc027beceea1ec40a") % SIGNATURE
199			},
200			{ % TEST 1024
201				hexstr2bin(
202					"f5e5767cf153319517630f226876b86c"
203					"8160cc583bc013744c6bf255f5cc0ee5"), % SECRET KEY
204				hexstr2bin(
205					"278117fc144c72340f67d0f2316e8386"
206					"ceffbf2b2428c9c51fef7c597f1d426e"), % PUBLIC KEY
207				hexstr2bin(
208					"08b8b2b733424243760fe426a4b54908"
209					"632110a66c2f6591eabd3345e3e4eb98"
210					"fa6e264bf09efe12ee50f8f54e9f77b1"
211					"e355f6c50544e23fb1433ddf73be84d8"
212					"79de7c0046dc4996d9e773f4bc9efe57"
213					"38829adb26c81b37c93a1b270b20329d"
214					"658675fc6ea534e0810a4432826bf58c"
215					"941efb65d57a338bbd2e26640f89ffbc"
216					"1a858efcb8550ee3a5e1998bd177e93a"
217					"7363c344fe6b199ee5d02e82d522c4fe"
218					"ba15452f80288a821a579116ec6dad2b"
219					"3b310da903401aa62100ab5d1a36553e"
220					"06203b33890cc9b832f79ef80560ccb9"
221					"a39ce767967ed628c6ad573cb116dbef"
222					"efd75499da96bd68a8a97b928a8bbc10"
223					"3b6621fcde2beca1231d206be6cd9ec7"
224					"aff6f6c94fcd7204ed3455c68c83f4a4"
225					"1da4af2b74ef5c53f1d8ac70bdcb7ed1"
226					"85ce81bd84359d44254d95629e9855a9"
227					"4a7c1958d1f8ada5d0532ed8a5aa3fb2"
228					"d17ba70eb6248e594e1a2297acbbb39d"
229					"502f1a8c6eb6f1ce22b3de1a1f40cc24"
230					"554119a831a9aad6079cad88425de6bd"
231					"e1a9187ebb6092cf67bf2b13fd65f270"
232					"88d78b7e883c8759d2c4f5c65adb7553"
233					"878ad575f9fad878e80a0c9ba63bcbcc"
234					"2732e69485bbc9c90bfbd62481d9089b"
235					"eccf80cfe2df16a2cf65bd92dd597b07"
236					"07e0917af48bbb75fed413d238f5555a"
237					"7a569d80c3414a8d0859dc65a46128ba"
238					"b27af87a71314f318c782b23ebfe808b"
239					"82b0ce26401d2e22f04d83d1255dc51a"
240					"ddd3b75a2b1ae0784504df543af8969b"
241					"e3ea7082ff7fc9888c144da2af58429e"
242					"c96031dbcad3dad9af0dcbaaaf268cb8"
243					"fcffead94f3c7ca495e056a9b47acdb7"
244					"51fb73e666c6c655ade8297297d07ad1"
245					"ba5e43f1bca32301651339e22904cc8c"
246					"42f58c30c04aafdb038dda0847dd988d"
247					"cda6f3bfd15c4b4c4525004aa06eeff8"
248					"ca61783aacec57fb3d1f92b0fe2fd1a8"
249					"5f6724517b65e614ad6808d6f6ee34df"
250					"f7310fdc82aebfd904b01e1dc54b2927"
251					"094b2db68d6f903b68401adebf5a7e08"
252					"d78ff4ef5d63653a65040cf9bfd4aca7"
253					"984a74d37145986780fc0b16ac451649"
254					"de6188a7dbdf191f64b5fc5e2ab47b57"
255					"f7f7276cd419c17a3ca8e1b939ae49e4"
256					"88acba6b965610b5480109c8b17b80e1"
257					"b7b750dfc7598d5d5011fd2dcc5600a3"
258					"2ef5b52a1ecc820e308aa342721aac09"
259					"43bf6686b64b2579376504ccc493d97e"
260					"6aed3fb0f9cd71a43dd497f01f17c0e2"
261					"cb3797aa2a2f256656168e6c496afc5f"
262					"b93246f6b1116398a346f1a641f3b041"
263					"e989f7914f90cc2c7fff357876e506b5"
264					"0d334ba77c225bc307ba537152f3f161"
265					"0e4eafe595f6d9d90d11faa933a15ef1"
266					"369546868a7f3a45a96768d40fd9d034"
267					"12c091c6315cf4fde7cb68606937380d"
268					"b2eaaa707b4c4185c32eddcdd306705e"
269					"4dc1ffc872eeee475a64dfac86aba41c"
270					"0618983f8741c5ef68d3a101e8a3b8ca"
271					"c60c905c15fc910840b94c00a0b9d0"), % MESSAGE
272				hexstr2bin(
273					"0aab4c900501b3e24d7cdf4663326a3a"
274					"87df5e4843b2cbdb67cbf6e460fec350"
275					"aa5371b1508f9f4528ecea23c436d94b"
276					"5e8fcd4f681e30a6ac00a9704a188a03") % SIGNATURE
277			},
278			{ % TEST SHA(abc)
279				hexstr2bin(
280					"833fe62409237b9d62ec77587520911e"
281					"9a759cec1d19755b7da901b96dca3d42"), % SECRET KEY
282				hexstr2bin(
283					"ec172b93ad5e563bf4932c70e1245034"
284					"c35467ef2efd4d64ebf819683467e2bf"), % PUBLIC KEY
285				hexstr2bin(
286					"ddaf35a193617abacc417349ae204131"
287					"12e6fa4e89a97ea20a9eeee64b55d39a"
288					"2192992a274fc1a836ba3c23a3feebbd"
289					"454d4423643ce80e2a9ac94fa54ca49f"), % MESSAGE
290				hexstr2bin(
291					"dc2a4459e7369633a52b1bf277839a00"
292					"201009a3efbf3ecb69bea2186c26b589"
293					"09351fc9ac90b3ecfdfbc7c66431e030"
294					"3dca179c138ac17ad9bef1177331a704") % SIGNATURE
295			}
296		]},
297		{ed25519ph, [
298			{ % TEST abc
299				hexstr2bin(
300					"833fe62409237b9d62ec77587520911e"
301					"9a759cec1d19755b7da901b96dca3d42"), % SECRET KEY
302				hexstr2bin(
303					"ec172b93ad5e563bf4932c70e1245034"
304					"c35467ef2efd4d64ebf819683467e2bf"), % PUBLIC KEY
305				hexstr2bin("616263"), % MESSAGE
306				hexstr2bin(
307					"dc2a4459e7369633a52b1bf277839a00"
308					"201009a3efbf3ecb69bea2186c26b589"
309					"09351fc9ac90b3ecfdfbc7c66431e030"
310					"3dca179c138ac17ad9bef1177331a704") % SIGNATURE
311			}
312		]},
313		{x25519, [
314			{
315				hexstr2bin("77076d0a7318a57d3c16c17251b26645df4c2f87ebc0992ab177fba51db92c2a"), % Alice's private key, f
316				hexstr2bin("8520f0098930a754748b7ddcb43ef75a0dbf3a0d26381af4eba4a98eaa9b4e6a"), % Alice's public key, X25519(f, 9)
317				hexstr2bin("5dab087e624a8a4b79e17f8b83800ee66f3bb1292618b6fd1c2f8b27ff88e0eb"), % Bob's private key, g
318				hexstr2bin("de9edb7d7b7dc1b4d35b61c2ece435373f8343c85b78674dadfc7e146f882b4f"), % Bob's public key, X25519(g, 9)
319				hexstr2bin("4a5d9d5ba4ce2de1728e3bf480350f25e07e21c947d19e3376f09b3c1e161742")  % Their shared secret, K
320			}
321		]} | jose_ct:start(G, Config)
322	];
323init_per_group(G='curve448', Config) ->
324	[
325		{curve448, [
326			{
327				599189175373896402783756016145213256157230856085026129926891459468622403380588640249457727683869421921443004045221642549886377526240828, % Input scalar
328				382239910814107330116229961234899377031416365240571325148346555922438025162094455820962429142971339584360034337310079791515452463053830, % Input u-coordinate
329				hexstr2lint("ce3e4ff95a60dc6697da1db1d85e6afbdf79b50a2412d7546d5f239fe14fbaadeb445fc66a01b0779d98223961111e21766282f73dd96b6f")          % Output u-coordinate
330			},
331			{
332				633254335906970592779259481534862372382525155252028961056404001332122152890562527156973881968934311400345568203929409663925541994577184, % Input scalar
333				622761797758325444462922068431234180649590390024811299761625153767228042600197997696167956134770744996690267634159427999832340166786063, % Input u-coordinate
334				hexstr2lint("884a02576239ff7a2f2f63b2db6a9ff37047ac13568e1e30fe63c4a7ad1b3ee3a5700df34321d62077e63633c575c1c954514e99da7c179d")          % Output u-coordinate
335			}
336		]},
337		{ed448, [
338			{ % Blank
339				hexstr2bin(
340					"6c82a562cb808d10d632be89c8513ebf"
341					"6c929f34ddfa8c9f63c9960ef6e348a3"
342					"528c8a3fcc2f044e39a3fc5b94492f8f"
343					"032e7549a20098f95b"), % SECRET KEY
344				hexstr2bin(
345					"5fd7449b59b461fd2ce787ec616ad46a"
346					"1da1342485a70e1f8a0ea75d80e96778"
347					"edf124769b46c7061bd6783df1e50f6c"
348					"d1fa1abeafe8256180"), % PUBLIC KEY
349				<<>>, % MESSAGE
350				hexstr2bin(
351					"533a37f6bbe457251f023c0d88f976ae"
352					"2dfb504a843e34d2074fd823d41a591f"
353					"2b233f034f628281f2fd7a22ddd47d78"
354					"28c59bd0a21bfd3980ff0d2028d4b18a"
355					"9df63e006c5d1c2d345b925d8dc00b41"
356					"04852db99ac5c7cdda8530a113a0f4db"
357					"b61149f05a7363268c71d95808ff2e65"
358					"2600") % SIGNATURE
359			},
360			{ % 1 octet
361				hexstr2bin(
362					"c4eab05d357007c632f3dbb48489924d"
363					"552b08fe0c353a0d4a1f00acda2c463a"
364					"fbea67c5e8d2877c5e3bc397a659949e"
365					"f8021e954e0a12274e"), % SECRET KEY
366				hexstr2bin(
367					"43ba28f430cdff456ae531545f7ecd0a"
368					"c834a55d9358c0372bfa0c6c6798c086"
369					"6aea01eb00742802b8438ea4cb82169c"
370					"235160627b4c3a9480"), % PUBLIC KEY
371				hexstr2bin("03"), % MESSAGE
372				hexstr2bin(
373					"26b8f91727bd62897af15e41eb43c377"
374					"efb9c610d48f2335cb0bd0087810f435"
375					"2541b143c4b981b7e18f62de8ccdf633"
376					"fc1bf037ab7cd779805e0dbcc0aae1cb"
377					"cee1afb2e027df36bc04dcecbf154336"
378					"c19f0af7e0a6472905e799f1953d2a0f"
379					"f3348ab21aa4adafd1d234441cf807c0"
380					"3a00") % SIGNATURE
381			},
382			{ % 1 octet (with context)
383				hexstr2bin(
384					"c4eab05d357007c632f3dbb48489924d"
385					"552b08fe0c353a0d4a1f00acda2c463a"
386					"fbea67c5e8d2877c5e3bc397a659949e"
387					"f8021e954e0a12274e"), % SECRET KEY
388				hexstr2bin(
389					"43ba28f430cdff456ae531545f7ecd0a"
390					"c834a55d9358c0372bfa0c6c6798c086"
391					"6aea01eb00742802b8438ea4cb82169c"
392					"235160627b4c3a9480"), % PUBLIC KEY
393				hexstr2bin("03"), % MESSAGE
394				hexstr2bin("666f6f"), % CONTEXT
395				hexstr2bin(
396					"d4f8f6131770dd46f40867d6fd5d5055"
397					"de43541f8c5e35abbcd001b32a89f7d2"
398					"151f7647f11d8ca2ae279fb842d60721"
399					"7fce6e042f6815ea000c85741de5c8da"
400					"1144a6a1aba7f96de42505d7a7298524"
401					"fda538fccbbb754f578c1cad10d54d0d"
402					"5428407e85dcbc98a49155c13764e66c"
403					"3c00") % SIGNATURE
404			},
405			{ % 11 octets
406				hexstr2bin(
407					"cd23d24f714274e744343237b93290f5"
408					"11f6425f98e64459ff203e8985083ffd"
409					"f60500553abc0e05cd02184bdb89c4cc"
410					"d67e187951267eb328"), % SECRET KEY
411				hexstr2bin(
412					"dcea9e78f35a1bf3499a831b10b86c90"
413					"aac01cd84b67a0109b55a36e9328b1e3"
414					"65fce161d71ce7131a543ea4cb5f7e9f"
415					"1d8b00696447001400"), % PUBLIC KEY
416				hexstr2bin("0c3e544074ec63b0265e0c"), % MESSAGE
417				hexstr2bin(
418					"1f0a8888ce25e8d458a21130879b840a"
419					"9089d999aaba039eaf3e3afa090a09d3"
420					"89dba82c4ff2ae8ac5cdfb7c55e94d5d"
421					"961a29fe0109941e00b8dbdeea6d3b05"
422					"1068df7254c0cdc129cbe62db2dc957d"
423					"bb47b51fd3f213fb8698f064774250a5"
424					"028961c9bf8ffd973fe5d5c206492b14"
425					"0e00") % SIGNATURE
426			},
427			{ % 12 octets
428				hexstr2bin(
429					"258cdd4ada32ed9c9ff54e63756ae582"
430					"fb8fab2ac721f2c8e676a72768513d93"
431					"9f63dddb55609133f29adf86ec9929dc"
432					"cb52c1c5fd2ff7e21b"), % SECRET KEY
433				hexstr2bin(
434					"3ba16da0c6f2cc1f30187740756f5e79"
435					"8d6bc5fc015d7c63cc9510ee3fd44adc"
436					"24d8e968b6e46e6f94d19b945361726b"
437					"d75e149ef09817f580"), % PUBLIC KEY
438				hexstr2bin("64a65f3cdedcdd66811e2915"), % MESSAGE
439				hexstr2bin(
440					"7eeeab7c4e50fb799b418ee5e3197ff6"
441					"bf15d43a14c34389b59dd1a7b1b85b4a"
442					"e90438aca634bea45e3a2695f1270f07"
443					"fdcdf7c62b8efeaf00b45c2c96ba457e"
444					"b1a8bf075a3db28e5c24f6b923ed4ad7"
445					"47c3c9e03c7079efb87cb110d3a99861"
446					"e72003cbae6d6b8b827e4e6c143064ff"
447					"3c00") % SIGNATURE
448			},
449			{ % 13 octets
450				hexstr2bin(
451					"7ef4e84544236752fbb56b8f31a23a10"
452					"e42814f5f55ca037cdcc11c64c9a3b29"
453					"49c1bb60700314611732a6c2fea98eeb"
454					"c0266a11a93970100e"), % SECRET KEY
455				hexstr2bin(
456					"b3da079b0aa493a5772029f0467baebe"
457					"e5a8112d9d3a22532361da294f7bb381"
458					"5c5dc59e176b4d9f381ca0938e13c6c0"
459					"7b174be65dfa578e80"), % PUBLIC KEY
460				hexstr2bin("64a65f3cdedcdd66811e2915e7"), % MESSAGE
461				hexstr2bin(
462					"6a12066f55331b6c22acd5d5bfc5d712"
463					"28fbda80ae8dec26bdd306743c5027cb"
464					"4890810c162c027468675ecf645a8317"
465					"6c0d7323a2ccde2d80efe5a1268e8aca"
466					"1d6fbc194d3f77c44986eb4ab4177919"
467					"ad8bec33eb47bbb5fc6e28196fd1caf5"
468					"6b4e7e0ba5519234d047155ac727a105"
469					"3100") % SIGNATURE
470			},
471			{ % 64 octets
472				hexstr2bin(
473					"d65df341ad13e008567688baedda8e9d"
474					"cdc17dc024974ea5b4227b6530e339bf"
475					"f21f99e68ca6968f3cca6dfe0fb9f4fa"
476					"b4fa135d5542ea3f01"), % SECRET KEY
477				hexstr2bin(
478					"df9705f58edbab802c7f8363cfe5560a"
479					"b1c6132c20a9f1dd163483a26f8ac53a"
480					"39d6808bf4a1dfbd261b099bb03b3fb5"
481					"0906cb28bd8a081f00"), % PUBLIC KEY
482				hexstr2bin(
483					"bd0f6a3747cd561bdddf4640a332461a"
484					"4a30a12a434cd0bf40d766d9c6d458e5"
485					"512204a30c17d1f50b5079631f64eb31"
486					"12182da3005835461113718d1a5ef944"), % MESSAGE
487				hexstr2bin(
488					"554bc2480860b49eab8532d2a533b7d5"
489					"78ef473eeb58c98bb2d0e1ce488a98b1"
490					"8dfde9b9b90775e67f47d4a1c3482058"
491					"efc9f40d2ca033a0801b63d45b3b722e"
492					"f552bad3b4ccb667da350192b61c508c"
493					"f7b6b5adadc2c8d9a446ef003fb05cba"
494					"5f30e88e36ec2703b349ca229c267083"
495					"3900") % SIGNATURE
496			},
497			{ % 64 octets
498				hexstr2bin(
499					"d65df341ad13e008567688baedda8e9d"
500					"cdc17dc024974ea5b4227b6530e339bf"
501					"f21f99e68ca6968f3cca6dfe0fb9f4fa"
502					"b4fa135d5542ea3f01"), % SECRET KEY
503				hexstr2bin(
504					"df9705f58edbab802c7f8363cfe5560a"
505					"b1c6132c20a9f1dd163483a26f8ac53a"
506					"39d6808bf4a1dfbd261b099bb03b3fb5"
507					"0906cb28bd8a081f00"), % PUBLIC KEY
508				hexstr2bin(
509					"bd0f6a3747cd561bdddf4640a332461a"
510					"4a30a12a434cd0bf40d766d9c6d458e5"
511					"512204a30c17d1f50b5079631f64eb31"
512					"12182da3005835461113718d1a5ef944"), % MESSAGE
513				hexstr2bin(
514					"554bc2480860b49eab8532d2a533b7d5"
515					"78ef473eeb58c98bb2d0e1ce488a98b1"
516					"8dfde9b9b90775e67f47d4a1c3482058"
517					"efc9f40d2ca033a0801b63d45b3b722e"
518					"f552bad3b4ccb667da350192b61c508c"
519					"f7b6b5adadc2c8d9a446ef003fb05cba"
520					"5f30e88e36ec2703b349ca229c267083"
521					"3900") % SIGNATURE
522			},
523			{ % 256 octets
524				hexstr2bin(
525					"2ec5fe3c17045abdb136a5e6a913e32a"
526					"b75ae68b53d2fc149b77e504132d3756"
527					"9b7e766ba74a19bd6162343a21c8590a"
528					"a9cebca9014c636df5"), % SECRET KEY
529				hexstr2bin(
530					"79756f014dcfe2079f5dd9e718be4171"
531					"e2ef2486a08f25186f6bff43a9936b9b"
532					"fe12402b08ae65798a3d81e22e9ec80e"
533					"7690862ef3d4ed3a00"), % PUBLIC KEY
534				hexstr2bin(
535					"15777532b0bdd0d1389f636c5f6b9ba7"
536					"34c90af572877e2d272dd078aa1e567c"
537					"fa80e12928bb542330e8409f31745041"
538					"07ecd5efac61ae7504dabe2a602ede89"
539					"e5cca6257a7c77e27a702b3ae39fc769"
540					"fc54f2395ae6a1178cab4738e543072f"
541					"c1c177fe71e92e25bf03e4ecb72f47b6"
542					"4d0465aaea4c7fad372536c8ba516a60"
543					"39c3c2a39f0e4d832be432dfa9a706a6"
544					"e5c7e19f397964ca4258002f7c0541b5"
545					"90316dbc5622b6b2a6fe7a4abffd9610"
546					"5eca76ea7b98816af0748c10df048ce0"
547					"12d901015a51f189f3888145c03650aa"
548					"23ce894c3bd889e030d565071c59f409"
549					"a9981b51878fd6fc110624dcbcde0bf7"
550					"a69ccce38fabdf86f3bef6044819de11"), % MESSAGE
551				hexstr2bin(
552					"c650ddbb0601c19ca11439e1640dd931"
553					"f43c518ea5bea70d3dcde5f4191fe53f"
554					"00cf966546b72bcc7d58be2b9badef28"
555					"743954e3a44a23f880e8d4f1cfce2d7a"
556					"61452d26da05896f0a50da66a239a8a1"
557					"88b6d825b3305ad77b73fbac0836ecc6"
558					"0987fd08527c1a8e80d5823e65cafe2a"
559					"3d00") % SIGNATURE
560			},
561			{ % 1023 octets
562				hexstr2bin(
563					"872d093780f5d3730df7c212664b37b8"
564					"a0f24f56810daa8382cd4fa3f77634ec"
565					"44dc54f1c2ed9bea86fafb7632d8be19"
566					"9ea165f5ad55dd9ce8"), % SECRET KEY
567				hexstr2bin(
568					"a81b2e8a70a5ac94ffdbcc9badfc3feb"
569					"0801f258578bb114ad44ece1ec0e799d"
570					"a08effb81c5d685c0c56f64eecaef8cd"
571					"f11cc38737838cf400"), % PUBLIC KEY
572				hexstr2bin(
573					"6ddf802e1aae4986935f7f981ba3f035"
574					"1d6273c0a0c22c9c0e8339168e675412"
575					"a3debfaf435ed651558007db4384b650"
576					"fcc07e3b586a27a4f7a00ac8a6fec2cd"
577					"86ae4bf1570c41e6a40c931db27b2faa"
578					"15a8cedd52cff7362c4e6e23daec0fbc"
579					"3a79b6806e316efcc7b68119bf46bc76"
580					"a26067a53f296dafdbdc11c77f7777e9"
581					"72660cf4b6a9b369a6665f02e0cc9b6e"
582					"dfad136b4fabe723d2813db3136cfde9"
583					"b6d044322fee2947952e031b73ab5c60"
584					"3349b307bdc27bc6cb8b8bbd7bd32321"
585					"9b8033a581b59eadebb09b3c4f3d2277"
586					"d4f0343624acc817804728b25ab79717"
587					"2b4c5c21a22f9c7839d64300232eb66e"
588					"53f31c723fa37fe387c7d3e50bdf9813"
589					"a30e5bb12cf4cd930c40cfb4e1fc6225"
590					"92a49588794494d56d24ea4b40c89fc0"
591					"596cc9ebb961c8cb10adde976a5d602b"
592					"1c3f85b9b9a001ed3c6a4d3b1437f520"
593					"96cd1956d042a597d561a596ecd3d173"
594					"5a8d570ea0ec27225a2c4aaff26306d1"
595					"526c1af3ca6d9cf5a2c98f47e1c46db9"
596					"a33234cfd4d81f2c98538a09ebe76998"
597					"d0d8fd25997c7d255c6d66ece6fa56f1"
598					"1144950f027795e653008f4bd7ca2dee"
599					"85d8e90f3dc315130ce2a00375a318c7"
600					"c3d97be2c8ce5b6db41a6254ff264fa6"
601					"155baee3b0773c0f497c573f19bb4f42"
602					"40281f0b1f4f7be857a4e59d416c06b4"
603					"c50fa09e1810ddc6b1467baeac5a3668"
604					"d11b6ecaa901440016f389f80acc4db9"
605					"77025e7f5924388c7e340a732e554440"
606					"e76570f8dd71b7d640b3450d1fd5f041"
607					"0a18f9a3494f707c717b79b4bf75c984"
608					"00b096b21653b5d217cf3565c9597456"
609					"f70703497a078763829bc01bb1cbc8fa"
610					"04eadc9a6e3f6699587a9e75c94e5bab"
611					"0036e0b2e711392cff0047d0d6b05bd2"
612					"a588bc109718954259f1d86678a579a3"
613					"120f19cfb2963f177aeb70f2d4844826"
614					"262e51b80271272068ef5b3856fa8535"
615					"aa2a88b2d41f2a0e2fda7624c2850272"
616					"ac4a2f561f8f2f7a318bfd5caf969614"
617					"9e4ac824ad3460538fdc25421beec2cc"
618					"6818162d06bbed0c40a387192349db67"
619					"a118bada6cd5ab0140ee273204f628aa"
620					"d1c135f770279a651e24d8c14d75a605"
621					"9d76b96a6fd857def5e0b354b27ab937"
622					"a5815d16b5fae407ff18222c6d1ed263"
623					"be68c95f32d908bd895cd76207ae7264"
624					"87567f9a67dad79abec316f683b17f2d"
625					"02bf07e0ac8b5bc6162cf94697b3c27c"
626					"d1fea49b27f23ba2901871962506520c"
627					"392da8b6ad0d99f7013fbc06c2c17a56"
628					"9500c8a7696481c1cd33e9b14e40b82e"
629					"79a5f5db82571ba97bae3ad3e0479515"
630					"bb0e2b0f3bfcd1fd33034efc6245eddd"
631					"7ee2086ddae2600d8ca73e214e8c2b0b"
632					"db2b047c6a464a562ed77b73d2d841c4"
633					"b34973551257713b753632efba348169"
634					"abc90a68f42611a40126d7cb21b58695"
635					"568186f7e569d2ff0f9e745d0487dd2e"
636					"b997cafc5abf9dd102e62ff66cba87"), % MESSAGE
637				hexstr2bin(
638					"e301345a41a39a4d72fff8df69c98075"
639					"a0cc082b802fc9b2b6bc503f926b65bd"
640					"df7f4c8f1cb49f6396afc8a70abe6d8a"
641					"ef0db478d4c6b2970076c6a0484fe76d"
642					"76b3a97625d79f1ce240e7c576750d29"
643					"5528286f719b413de9ada3e8eb78ed57"
644					"3603ce30d8bb761785dc30dbc320869e"
645					"1a00") % SIGNATURE
646			}
647		]},
648		{ed448ph, [
649			{ % TEST abc
650				hexstr2bin(
651					"833fe62409237b9d62ec77587520911e"
652					"9a759cec1d19755b7da901b96dca3d42"
653					"ef7822e0d5104127dc05d6dbefde69e3"
654					"ab2cec7c867c6e2c49"), % SECRET KEY
655				hexstr2bin(
656					"259b71c19f83ef77a7abd26524cbdb31"
657					"61b590a48f7d17de3ee0ba9c52beb743"
658					"c09428a131d6b1b57303d90d8132c276"
659					"d5ed3d5d01c0f53880"), % PUBLIC KEY
660				hexstr2bin("616263"), % MESSAGE
661				hexstr2bin(
662					"963cf799d20fdf51c460310c1cf65d0e"
663					"83c4ef5aa73332ba5b4c1e7635ff9e9b"
664					"6a12b16436fa3681b92575e7eba40ee2"
665					"79c487ad724b6d1080e1860e63dbdd58"
666					"9f5125505b4de024264625e61b097956"
667					"8703f9d9e2bbf5523a1886ee6da1ecb2"
668					"0552bb506eb35a042658ec534bfc1c2c"
669					"1a00") % SIGNATURE
670			},
671			{ % TEST abc (with context)
672				hexstr2bin(
673					"833fe62409237b9d62ec77587520911e"
674					"9a759cec1d19755b7da901b96dca3d42"
675					"ef7822e0d5104127dc05d6dbefde69e3"
676					"ab2cec7c867c6e2c49"), % SECRET KEY
677				hexstr2bin(
678					"259b71c19f83ef77a7abd26524cbdb31"
679					"61b590a48f7d17de3ee0ba9c52beb743"
680					"c09428a131d6b1b57303d90d8132c276"
681					"d5ed3d5d01c0f53880"), % PUBLIC KEY
682				hexstr2bin("616263"), % MESSAGE
683				hexstr2bin("666f6f"), % CONTEXT
684				hexstr2bin(
685					"86a6bf52f9e8f84f451b2f392a8d1c3a"
686					"414425fac0068f74aeead53b0e6b53d4"
687					"555cea1726da4a65202880d407267087"
688					"9e8e6fa4d9694c060054f2065dc206a6"
689					"e615d0d8c99b95209b696c8125c5fbb9"
690					"bc82a0f7ed3d99c4c11c47798ef0f7eb"
691					"97b3b72ab4ac86eaf8b43449e8ac30ff"
692					"3f00") % SIGNATURE
693			}
694		]},
695		{x448, [
696			{
697				hexstr2bin("9a8f4925d1519f5775cf46b04b5800d4ee9ee8bae8bc5565d498c28dd9c9baf574a9419744897391006382a6f127ab1d9ac2d8c0a598726b"), % Alice's private key, f
698				hexstr2bin("9b08f7cc31b7e3e67d22d5aea121074a273bd2b83de09c63faa73d2c22c5d9bbc836647241d953d40c5b12da88120d53177f80e532c41fa0"), % Alice's public key, X448(f, 9)
699				hexstr2bin("1c306a7ac2a0e2e0990b294470cba339e6453772b075811d8fad0d1d6927c120bb5ee8972b0d3e21374c9c921b09d1b0366f10b65173992d"), % Bob's private key, g
700				hexstr2bin("3eb7a829b0cd20f5bcfc0b599b6feccf6da4627107bdb0d4f345b43027d8b972fc3e34fb4232a13ca706dcb57aec3dae07bdc1c67bf33609"), % Bob's public key, X448(g, 9)
701				hexstr2bin("07fff4181ac6cc95ec1c16a94a0f74d12da232ce40a77552281d282bb60c0b56fd2464c335543936521c24403085d59a449a5037514a879d")  % Their shared secret, K
702			}
703		]} | jose_ct:start(G, Config)
704	];
705init_per_group(G='gcmtestvectors', Config) ->
706	Folder = data_file("gcmtestvectors", Config),
707	{ok, Entries} = file:list_dir(Folder),
708	Files = [filename:join([Folder, Entry]) || Entry <- Entries],
709	[{aes_gcm_files, Files}, {one_in, 10} | jose_ct:start(G, Config)];
710init_per_group(G='KAT_AES', Config) ->
711	Folder = data_file("KAT_AES", Config),
712	{ok, Entries} = file:list_dir(Folder),
713	Files = [filename:join([Folder, Entry]) || Entry <- Entries],
714	[{aes_files, Files} | jose_ct:start(G, Config)];
715init_per_group(G='keccaktestvectors', Config) ->
716	Folder = data_file("keccaktestvectors", Config),
717	{ok, Entries} = file:list_dir(Folder),
718	Files = [filename:join([Folder, Entry]) || Entry <- Entries],
719	[{sha3_files, Files} | jose_ct:start(G, Config)];
720init_per_group(G='kwtestvectors', Config) ->
721	Folder = data_file("kwtestvectors", Config),
722	{ok, Entries} = file:list_dir(Folder),
723	Files = [filename:join([Folder, Entry]) || Entry <- Entries],
724	[{aeskw_files, Files}, {one_in, 5} | jose_ct:start(G, Config)];
725init_per_group(G='nist-800-56A', Config) ->
726	Vectors = [
727		%% See [https://tools.ietf.org/html/rfc7518#appendix-C]
728		{sha256,
729			<<158,86,217,29,129,113,53,211,114,131,66,131,191,132,38,156,251,49,110,163,218,128,106,72,246,218,167,121,140,254,144,196>>,
730			{<<"A128GCM">>,
731				<<"Alice">>,
732				<<"Bob">>,
733				<< 0, 0, 0, 128 >>,
734				<<>>},
735			128,
736			<<86,170,141,234,248,35,109,32,92,34,40,205,113,167,16,26>>},
737		%% See [https://bitbucket.org/b_c/jose4j/src/cb968fdb10bdef6ecedf279b030f9b3af59f5e8e/src/test/java/org/jose4j/jwe/kdf/ConcatKeyDerivationFunctionTest.java]
738		{sha256,
739			jose_jwa_base64url:decode(<<"Sq8rGLm4rEtzScmnSsY5r1n-AqBl_iBU8FxN80Uc0S0">>),
740			{<<"A256CBC-HS512">>,
741				<<>>,
742				<<>>,
743				<< 0, 0, 2, 0 >>,
744				<<>>},
745			512,
746			jose_jwa_base64url:decode(<<"pgs50IOZ6BxfqvTSie4t9OjWxGr4whiHo1v9Dti93CRiJE2PP60FojLatVVrcjg3BxpuFjnlQxL97GOwAfcwLA">>)},
747		{sha256,
748			jose_jwa_base64url:decode(<<"LfkHot2nGTVlmfxbgxQfMg">>),
749			{<<"A128CBC-HS256">>,
750				<<>>,
751				<<>>,
752				<< 0, 0, 1, 0 >>,
753				<<>>},
754			256,
755			jose_jwa_base64url:decode(<<"vphyobtvExGXF7TaOvAkx6CCjHQNYamP2ET8xkhTu-0">>)},
756		{sha256,
757			jose_jwa_base64url:decode(<<"KSDnQpf2iurUsAbcuI4YH-FKfk2gecN6cWHTYlBzrd8">>),
758			{<<"meh">>,
759				<<"Alice">>,
760				<<"Bob">>,
761				<< 0, 0, 4, 0 >>,
762				<<>>},
763			1024,
764			jose_jwa_base64url:decode(<<"yRbmmZJpxv3H1aq3FgzESa453frljIaeMz6pt5rQZ4Q5Hs-4RYoFRXFh_qBsbTjlsj8JxIYTWj-cp5LKtgi1fBRsf_5yTEcLDv4pKH2fNxjbEOKuVVDWA1_Qv2IkEC0_QSi3lSSELcJaNX-hDG8occ7oQv-w8lg6lLJjg58kOes">>)},
765		{sha256,
766			jose_jwa_base64url:decode(<<"zp9Hot2noTVlmfxbkXqfn1">>),
767			{<<"A192CBC-HS384">>,
768				<<>>,
769				<<>>,
770				<< 0, 0, 1, 128 >>,
771				<<>>},
772			384,
773			jose_jwa_base64url:decode(<<"SNOvl6h5iSYWJ_EhlnvK8o6om9iyR8HkKMQtQYGkYKkVY0HFMleoUm-H6-kLz8sW">>)}
774	],
775	[{vectors, Vectors} | jose_ct:start(G, Config)];
776init_per_group(G='pkcs-1v2-1-vec', Config) ->
777	OAEPVectFile = data_file("pkcs-1v2-1-vec/oaep-vect.txt", Config),
778	PSSVectFile = data_file("pkcs-1v2-1-vec/pss-vect.txt", Config),
779	[{oaep_vect_file, OAEPVectFile}, {pss_vect_file, PSSVectFile} | jose_ct:start(G, Config)];
780init_per_group(G='pkcs-5', Config) ->
781	PBKDF1Vectors = [
782		%% See [https://github.com/erlang/otp/blob/OTP-18.0/lib/public_key/test/pbe_SUITE.erl]
783		{sha,
784			<<"password">>,
785			<<16#78,16#57,16#8E,16#5A,16#5D,16#63,16#CB,16#06>>,
786			1000,
787			16,
788			<<
789				16#DC, 16#19, 16#84, 16#7E,
790				16#05, 16#C6, 16#4D, 16#2F,
791				16#AF, 16#10, 16#EB, 16#FB,
792				16#4A, 16#3D, 16#2A, 16#20
793			>>}
794	],
795	PBKDF2Vectors = [
796		%% See [https://tools.ietf.org/html/rfc6070]
797		{sha,
798			<<"password">>,
799			<<"salt">>,
800			1,
801			20,
802			hex:hex_to_bin(<<"0c60c80f961f0e71f3a9b524af6012062fe037a6">>)},
803		{sha,
804			<<"password">>,
805			<<"salt">>,
806			2,
807			20,
808			hex:hex_to_bin(<<"ea6c014dc72d6f8ccd1ed92ace1d41f0d8de8957">>)},
809		{sha,
810			<<"password">>,
811			<<"salt">>,
812			4096,
813			20,
814			hex:hex_to_bin(<<"4b007901b765489abead49d926f721d065a429c1">>)},
815		{sha,
816			<<"password">>,
817			<<"salt">>,
818			16777216,
819			20,
820			hex:hex_to_bin(<<"eefe3d61cd4da4e4e9945b3d6ba2158c2634e984">>)},
821		{sha,
822			<<"passwordPASSWORDpassword">>,
823			<<"saltSALTsaltSALTsaltSALTsaltSALTsalt">>,
824			4096,
825			25,
826			hex:hex_to_bin(<<"3d2eec4fe41c849b80c8d83662c0e44a8b291a964cf2f07038">>)},
827		{sha,
828			<<"pass\0word">>,
829			<<"sa\0lt">>,
830			4096,
831			16,
832			hex:hex_to_bin(<<"56fa6aa75548099dcc37d7f03425e0c3">>)},
833		%% See [http://stackoverflow.com/a/5136918/818187]
834		{sha256,
835			<<"password">>,
836			<<"salt">>,
837			1,
838			32,
839			hex:hex_to_bin(<<"120fb6cffcf8b32c43e7225256c4f837a86548c92ccc35480805987cb70be17b">>)},
840		{sha256,
841			<<"password">>,
842			<<"salt">>,
843			2,
844			32,
845			hex:hex_to_bin(<<"ae4d0c95af6b46d32d0adff928f06dd02a303f8ef3c251dfd6e2d85a95474c43">>)},
846		{sha256,
847			<<"password">>,
848			<<"salt">>,
849			4096,
850			32,
851			hex:hex_to_bin(<<"c5e478d59288c841aa530db6845c4c8d962893a001ce4e11a4963873aa98134a">>)},
852		{sha256,
853			<<"password">>,
854			<<"salt">>,
855			16777216,
856			32,
857			hex:hex_to_bin(<<"cf81c66fe8cfc04d1f31ecb65dab4089f7f179e89b3b0bcb17ad10e3ac6eba46">>)},
858		{sha256,
859			<<"passwordPASSWORDpassword">>,
860			<<"saltSALTsaltSALTsaltSALTsaltSALTsalt">>,
861			4096,
862			40,
863			hex:hex_to_bin(<<"348c89dbcbd32b2f32d814b8116e84cf2b17347ebc1800181c4e2a1fb8dd53e1c635518c7dac47e9">>)},
864		{sha256,
865			<<"pass\0word">>,
866			<<"sa\0lt">>,
867			4096,
868			16,
869			hex:hex_to_bin(<<"89b69d0516f829893c696226650a8687">>)}
870	],
871	[{pbkdf1_vectors, PBKDF1Vectors}, {pbkdf2_vectors, PBKDF2Vectors} | jose_ct:start(G, Config)];
872init_per_group(G='pkcs-7', Config) ->
873	Vectors = [begin
874		{hex:hex_to_bin(K), hex:hex_to_bin(V)}
875	end || {K, V} <- [
876		{<<                                  >>, <<"10101010101010101010101010101010">>},
877		{<<"00"                              >>, <<"000f0f0f0f0f0f0f0f0f0f0f0f0f0f0f">>},
878		{<<"0000"                            >>, <<"00000e0e0e0e0e0e0e0e0e0e0e0e0e0e">>},
879		{<<"000000"                          >>, <<"0000000d0d0d0d0d0d0d0d0d0d0d0d0d">>},
880		{<<"00000000"                        >>, <<"000000000c0c0c0c0c0c0c0c0c0c0c0c">>},
881		{<<"0000000000"                      >>, <<"00000000000b0b0b0b0b0b0b0b0b0b0b">>},
882		{<<"000000000000"                    >>, <<"0000000000000a0a0a0a0a0a0a0a0a0a">>},
883		{<<"00000000000000"                  >>, <<"00000000000000090909090909090909">>},
884		{<<"0000000000000000"                >>, <<"00000000000000000808080808080808">>},
885		{<<"000000000000000000"              >>, <<"00000000000000000007070707070707">>},
886		{<<"00000000000000000000"            >>, <<"00000000000000000000060606060606">>},
887		{<<"0000000000000000000000"          >>, <<"00000000000000000000000505050505">>},
888		{<<"000000000000000000000000"        >>, <<"00000000000000000000000004040404">>},
889		{<<"00000000000000000000000000"      >>, <<"00000000000000000000000000030303">>},
890		{<<"0000000000000000000000000000"    >>, <<"00000000000000000000000000000202">>},
891		{<<"000000000000000000000000000000"  >>, <<"00000000000000000000000000000001">>},
892		{<<"00000000000000000000000000000000">>, <<"0000000000000000000000000000000010101010101010101010101010101010">>}
893	]],
894	[{vectors, Vectors} | jose_ct:start(G, Config)].
895
896end_per_group(_Group, Config) ->
897	jose_ct:stop(Config),
898	ok.
899
900%%====================================================================
901%% Tests
902%%====================================================================
903
904concatenation_kdf(Config) ->
905	Vectors = ?config(vectors, Config),
906	concatenation_kdf(Vectors, Config).
907
908curve25519(Config) ->
909	Vectors = ?config(curve25519, Config),
910	lists:foreach(fun curve25519_vector/1, Vectors).
911
912curve448(Config) ->
913	Vectors = ?config(curve448, Config),
914	lists:foreach(fun curve448_vector/1, Vectors).
915
916ed25519(Config) ->
917	Vectors = ?config(ed25519, Config),
918	lists:foreach(fun ed25519_vector/1, Vectors).
919
920ed25519ph(Config) ->
921	Vectors = ?config(ed25519ph, Config),
922	lists:foreach(fun ed25519ph_vector/1, Vectors).
923
924ed448(Config) ->
925	Vectors = ?config(ed448, Config),
926	lists:foreach(fun ed448_vector/1, Vectors).
927
928ed448ph(Config) ->
929	Vectors = ?config(ed448ph, Config),
930	lists:foreach(fun ed448ph_vector/1, Vectors).
931
932emc_rsa_oaep_encrypt_and_decrypt(Config) ->
933	Vectors = emc_testvector:from_file(?config(oaep_vect_file, Config)),
934	emc_rsa_oaep_encrypt_and_decrypt(Vectors, Config).
935
936emc_rsa_pss_sign_and_verify(Config) ->
937	Vectors = emc_testvector:from_file(?config(pss_vect_file, Config)),
938	emc_rsa_pss_sign_and_verify(Vectors, Config).
939
940fips_aes_encrypt_and_decrypt(Config) ->
941	Files = ?config(aes_files, Config),
942	lists:foldl(fun fips_aes_encrypt_and_decrypt/2, Config, Files).
943
944fips_aes_gcm_encrypt_and_decrypt(Config) ->
945	Files = ?config(aes_gcm_files, Config),
946	lists:foldl(fun fips_aes_gcm_encrypt_and_decrypt/2, Config, Files).
947
948fips_aeskw_unwrap(Config) ->
949	Filter = fun(File) ->
950		case filename:basename(File) of
951			"KW_AD_" ++ _ ->
952				true;
953			_ ->
954				false
955		end
956	end,
957	Files = [File || File <- ?config(aeskw_files, Config), Filter(File)],
958	lists:foldl(fun fips_aeskw_unwrap/2, Config, Files).
959
960fips_aeskw_wrap(Config) ->
961	Filter = fun(File) ->
962		case filename:basename(File) of
963			"KW_AE_" ++ _ ->
964				true;
965			_ ->
966				false
967		end
968	end,
969	Files = [File || File <- ?config(aeskw_files, Config), Filter(File)],
970	lists:foldl(fun fips_aeskw_wrap/2, Config, Files).
971
972fips_rsa_pss_sign(Config) ->
973	Vectors = fips_testvector:from_file(?config(sig_gen_file, Config)),
974	fips_rsa_pss_sign(Vectors, Config).
975
976fips_rsa_pss_verify(Config) ->
977	Vectors = fips_testvector:from_file(?config(sig_ver_file, Config)),
978	fips_rsa_pss_verify(Vectors, Config).
979
980fips_sha3(Config) ->
981	Files = [File || File <- ?config(sha3_files, Config)],
982	lists:foldl(fun fips_sha3/2, Config, Files).
983
984pbkdf1(Config) ->
985	Vectors = ?config(pbkdf1_vectors, Config),
986	pbkdf1(Vectors, Config).
987
988pbkdf2(Config) ->
989	Vectors = ?config(pbkdf2_vectors, Config),
990	pbkdf2(Vectors, Config).
991
992pkcs7_pad_and_unpad(Config) ->
993	Vectors = ?config(vectors, Config),
994	pkcs7_pad_and_unpad(Vectors, Config).
995
996x25519(Config) ->
997	Vectors = ?config(x25519, Config),
998	lists:foreach(fun x25519_vector/1, Vectors).
999
1000x448(Config) ->
1001	Vectors = ?config(x448, Config),
1002	lists:foreach(fun x448_vector/1, Vectors).
1003
1004%%%-------------------------------------------------------------------
1005%%% Internal functions
1006%%%-------------------------------------------------------------------
1007
1008%% @private
1009archive_file(File, Config) ->
1010	filename:join([?config(data_dir, Config), "archive", File]).
1011
1012%% @private
1013concatenation_kdf([{Hash, Z, OtherInfo, KeyDataLen, DerivedKey} | Vectors], Config) ->
1014	case jose_jwa_concat_kdf:kdf(Hash, Z, OtherInfo, KeyDataLen) of
1015		DerivedKey ->
1016			concatenation_kdf(Vectors, Config);
1017		Other ->
1018			ct:fail({{jose_jwa_concat_kdf, kdf, [Hash, Z, OtherInfo, KeyDataLen]}, {expected, DerivedKey}, {got, Other}})
1019	end;
1020concatenation_kdf([], _Config) ->
1021	ok.
1022
1023%% @private
1024curve25519_vector({InputK, InputU, OutputU}) ->
1025	?tv_ok(T0, jose_jwa_x25519, curve25519, [InputK, InputU], OutputU).
1026
1027%% @private
1028curve448_vector({InputK, InputU, OutputU}) ->
1029	?tv_ok(T0, jose_jwa_x448, curve448, [InputK, InputU], OutputU).
1030
1031%% @private
1032data_file(File, Config) ->
1033	filename:join([?config(data_dir, Config), File]).
1034
1035%% @private
1036data_setup(Config) ->
1037	ArchiveDir = data_file("archive", Config),
1038	case filelib:is_dir(ArchiveDir) of
1039		true ->
1040			ok;
1041		false ->
1042			ok = file:make_dir(ArchiveDir)
1043	end,
1044	lists:foldl(fun(F, C) ->
1045		io:format(user, "\e[0;36m[FETCH] ~s\e[0m", [F]),
1046		{ok, Progress} = jose_ct:progress_start(),
1047		NewC = data_setup(F, C),
1048		ok = jose_ct:progress_stop(Progress),
1049		NewC
1050	end, Config, [
1051		"186-3rsatestvectors.zip",
1052		"aesmmt.zip",
1053		"gcmtestvectors.zip",
1054		"KAT_AES.zip",
1055		"keccaktestvectors",
1056		"kwtestvectors.zip",
1057		"pkcs-1v2-1-vec.zip"
1058	]).
1059
1060%% @private
1061data_setup(F = "186-3rsatestvectors.zip", Config) ->
1062	Zip = archive_file(F, Config),
1063	Dir = data_file("186-3rsatestvectors", Config),
1064	URL = "https://github.com/potatosalad/test-vector-archive/raw/1.0.0/archive/186-3rsatestvectors.zip",
1065	ok = data_setup(Zip, Dir, URL),
1066	Filter = fun
1067		(#zip_file{name = "SigGenPSS_186-3.txt"}) ->
1068			true;
1069		(#zip_file{name = "SigVerPSS_186-3.rsp"}) ->
1070			true;
1071		(_) ->
1072			false
1073	end,
1074	ok = data_setup(Zip, Dir, "SigGenPSS_186-3.txt", Filter),
1075	Config;
1076data_setup(F = "aesmmt.zip", Config) ->
1077	Zip = archive_file(F, Config),
1078	Dir = data_file("aesmmt", Config),
1079	URL = "https://github.com/potatosalad/test-vector-archive/raw/1.0.0/archive/aesmmt.zip",
1080	ok = data_setup(Zip, Dir, URL),
1081	Filter = fun
1082		(#zip_file{name = "CBC" ++ _}) ->
1083			true;
1084		(#zip_file{name = "ECB" ++ _}) ->
1085			true;
1086		(_) ->
1087			false
1088	end,
1089	ok = data_setup(Zip, Dir, "CBCMMT128.rsp", Filter),
1090	Config;
1091data_setup(F = "gcmtestvectors.zip", Config) ->
1092	Zip = archive_file(F, Config),
1093	Dir = data_file("gcmtestvectors", Config),
1094	URL = "https://github.com/potatosalad/test-vector-archive/raw/1.0.0/archive/gcmtestvectors.zip",
1095	ok = data_setup(Zip, Dir, URL),
1096	case filelib:is_file(filename:join([Dir, "gcmDecrypt128.rsp"])) of
1097		true ->
1098			ok;
1099		false ->
1100			{ok, FileList} = zip:unzip(Zip, [
1101				{cwd, Dir}
1102			]),
1103			_ = [begin
1104				file:change_mode(File, 8#00644)
1105			end || File <- FileList],
1106			ok
1107	end,
1108	Config;
1109data_setup(F = "KAT_AES.zip", Config) ->
1110	Zip = archive_file(F, Config),
1111	Dir = data_file("KAT_AES", Config),
1112	URL = "https://github.com/potatosalad/test-vector-archive/raw/1.0.0/archive/KAT_AES.zip",
1113	ok = data_setup(Zip, Dir, URL),
1114	Filter = fun
1115		(#zip_file{name = "CBC" ++ _}) ->
1116			true;
1117		(#zip_file{name = "ECB" ++ _}) ->
1118			true;
1119		(_) ->
1120			false
1121	end,
1122	ok = data_setup(Zip, Dir, "CBCGFSbox128.rsp", Filter),
1123	Config;
1124data_setup(F = "keccaktestvectors", Config) ->
1125	BaseURL = "https://raw.githubusercontent.com/gvanas/KeccakCodePackage/1893f17c8029d0e6423f1fa4de4d15f76b188a27/TestVectors/",
1126	Files = [
1127		"ShortMsgKAT_SHA3-224.txt",
1128		"ShortMsgKAT_SHA3-256.txt",
1129		"ShortMsgKAT_SHA3-384.txt",
1130		"ShortMsgKAT_SHA3-512.txt",
1131		"ShortMsgKAT_SHAKE128.txt",
1132		"ShortMsgKAT_SHAKE256.txt"
1133	],
1134	URLs = [BaseURL ++ File || File <- Files],
1135	Directory = data_file(F, Config),
1136	DataFiles = [data_file(filename:join(F, File), Config) || File <- Files],
1137	ok = data_setup_multiple(DataFiles, Directory, URLs),
1138	Config;
1139data_setup(F = "kwtestvectors.zip", Config) ->
1140	Zip = archive_file(F, Config),
1141	Dir = data_file("kwtestvectors", Config),
1142	URL = "https://github.com/potatosalad/test-vector-archive/raw/1.0.0/archive/kwtestvectors.zip",
1143	ok = data_setup(Zip, Dir, URL),
1144	Filter = fun
1145		(#zip_file{name = "KW_" ++ Name}) ->
1146			case lists:reverse(Name) of
1147				"txt.vni_" ++ _ ->
1148					false;
1149				_ ->
1150					true
1151			end;
1152		(_) ->
1153			false
1154	end,
1155	ok = data_setup(Zip, Dir, "KW_AD_128.txt", Filter),
1156	Config;
1157data_setup(F = "pkcs-1v2-1-vec.zip", Config) ->
1158	Zip = archive_file(F, Config),
1159	Dir = data_file("pkcs-1v2-1-vec", Config),
1160	URL = "https://github.com/potatosalad/test-vector-archive/raw/1.0.0/archive/pkcs-1v2-1-vec.zip",
1161	ok = data_setup(Zip, Dir, URL),
1162	Filter = fun
1163		(#zip_file{name = "oaep-vect.txt"}) ->
1164			true;
1165		(#zip_file{name = "pss-vect.txt"}) ->
1166			true;
1167		(_) ->
1168			false
1169	end,
1170	ok = data_setup(Zip, Dir, "oaep-vect.txt", Filter),
1171	Config.
1172
1173%% @private
1174data_setup(Zip, Directory, URL) ->
1175	case filelib:is_file(Zip) of
1176		true ->
1177			ok;
1178		false ->
1179			ok = fetch:fetch(URL, Zip)
1180	end,
1181	case filelib:is_dir(Directory) of
1182		true ->
1183			ok;
1184		false ->
1185			ok = file:make_dir(Directory)
1186	end,
1187	ok.
1188
1189%% @private
1190data_setup(Zip, Dir, Check, Filter) ->
1191	case filelib:is_file(filename:join([Dir, Check])) of
1192		true ->
1193			ok;
1194		false ->
1195			Options = case is_function(Filter, 1) of
1196				false ->
1197					[{cwd, Dir}];
1198				true ->
1199					[{cwd, Dir}, {file_filter, Filter}]
1200			end,
1201			{ok, FileList} = zip:unzip(Zip, Options),
1202			_ = [begin
1203				file:change_mode(File, 8#00644)
1204			end || File <- FileList],
1205			ok
1206	end.
1207
1208%% @private
1209data_setup_multiple([DataFile | DataFiles], Directory, [URL | URLs]) ->
1210	case filelib:is_dir(Directory) of
1211		true ->
1212			ok;
1213		false ->
1214			ok = file:make_dir(Directory)
1215	end,
1216	case filelib:is_file(DataFile) of
1217		true ->
1218			ok;
1219		false ->
1220			ok = fetch:fetch(URL, DataFile)
1221	end,
1222	data_setup_multiple(DataFiles, Directory, URLs);
1223data_setup_multiple([], _Directory, []) ->
1224	ok.
1225
1226%% @private
1227ed25519_vector({Secret, PK, Message, Signature}) ->
1228	SK = << Secret/binary, PK/binary >>,
1229	?tv_ok(T0, jose_jwa_curve25519, eddsa_secret_to_public, [Secret], PK),
1230	?tv_ok(T1, jose_jwa_curve25519, ed25519_sign, [Message, SK], Signature),
1231	?tv_ok(T2, jose_jwa_curve25519, ed25519_verify, [Signature, Message, PK], true).
1232
1233%% @private
1234ed25519ph_vector({Secret, PK, Message, Signature}) ->
1235	SK = << Secret/binary, PK/binary >>,
1236	?tv_ok(T0, jose_jwa_curve25519, eddsa_secret_to_public, [Secret], PK),
1237	?tv_ok(T1, jose_jwa_curve25519, ed25519ph_sign, [Message, SK], Signature),
1238	?tv_ok(T2, jose_jwa_curve25519, ed25519ph_verify, [Signature, Message, PK], true).
1239
1240%% @private
1241ed448_vector({Secret, PK, Message, Signature}) ->
1242	SK = << Secret/binary, PK/binary >>,
1243	?tv_ok(T0, jose_jwa_curve448, eddsa_secret_to_public, [Secret], PK),
1244	?tv_ok(T1, jose_jwa_curve448, ed448_sign, [Message, SK], Signature),
1245	?tv_ok(T2, jose_jwa_curve448, ed448_verify, [Signature, Message, PK], true);
1246ed448_vector({Secret, PK, Message, Context, Signature}) ->
1247	SK = << Secret/binary, PK/binary >>,
1248	?tv_ok(T0, jose_jwa_curve448, eddsa_secret_to_public, [Secret], PK),
1249	?tv_ok(T1, jose_jwa_curve448, ed448_sign, [Message, SK, Context], Signature),
1250	?tv_ok(T2, jose_jwa_curve448, ed448_verify, [Signature, Message, PK, Context], true).
1251
1252%% @private
1253ed448ph_vector({Secret, PK, Message, Signature}) ->
1254	SK = << Secret/binary, PK/binary >>,
1255	?tv_ok(T0, jose_jwa_curve448, eddsa_secret_to_public, [Secret], PK),
1256	?tv_ok(T1, jose_jwa_curve448, ed448ph_sign, [Message, SK], Signature),
1257	?tv_ok(T2, jose_jwa_curve448, ed448ph_verify, [Signature, Message, PK], true);
1258ed448ph_vector({Secret, PK, Message, Context, Signature}) ->
1259	SK = << Secret/binary, PK/binary >>,
1260	?tv_ok(T0, jose_jwa_curve448, eddsa_secret_to_public, [Secret], PK),
1261	?tv_ok(T1, jose_jwa_curve448, ed448ph_sign, [Message, SK, Context], Signature),
1262	?tv_ok(T2, jose_jwa_curve448, ed448ph_verify, [Signature, Message, PK, Context], true).
1263
1264%% @private
1265emc_rsa_oaep_encrypt_and_decrypt([
1266			divider,
1267			{example, Example},
1268			{component, <<"Components of the RSA Key Pair">>},
1269			{vector, {<<"RSA modulus n">>, N}},
1270			{vector, {<<"RSA public exponent e">>, E}},
1271			{vector, {<<"RSA private exponent d">>, D}},
1272			{vector, {<<"Prime p">>, P}},
1273			{vector, {<<"Prime q">>, Q}},
1274			{vector, {<<"p's CRT exponent dP">>, DP}},
1275			{vector, {<<"q's CRT exponent dQ">>, DQ}},
1276			{vector, {<<"CRT coefficient qInv">>, QI}}
1277			| Vectors
1278		], Config) ->
1279	RSAPrivateKey = #'RSAPrivateKey'{
1280		version = 'two-prime',
1281		otherPrimeInfos = 'asn1_NOVALUE',
1282		privateExponent = crypto:bytes_to_integer(D),
1283		exponent1 = crypto:bytes_to_integer(DP),
1284		exponent2 = crypto:bytes_to_integer(DQ),
1285		publicExponent = crypto:bytes_to_integer(E),
1286		modulus = crypto:bytes_to_integer(N),
1287		prime1 = crypto:bytes_to_integer(P),
1288		prime2 = crypto:bytes_to_integer(Q),
1289		coefficient = crypto:bytes_to_integer(QI)
1290	},
1291	RSAPublicKey = #'RSAPublicKey'{
1292		publicExponent = crypto:bytes_to_integer(E),
1293		modulus = crypto:bytes_to_integer(N)
1294	},
1295	io:format("~s", [Example]),
1296	emc_rsa_oaep_encrypt_and_decrypt(Vectors, {RSAPrivateKey, RSAPublicKey}, Config);
1297emc_rsa_oaep_encrypt_and_decrypt([divider], _Config) ->
1298	ok;
1299emc_rsa_oaep_encrypt_and_decrypt([], _Config) ->
1300	ok.
1301
1302%% @private
1303emc_rsa_oaep_encrypt_and_decrypt([
1304			{component, Component},
1305			{vector, {<<"Message to be encrypted">>, Message}},
1306			{vector, {<<"Seed">>, Seed}},
1307			{vector, {<<"Encryption">>, Encryption}}
1308			| Vectors
1309		], {RSAPrivateKey, RSAPublicKey}, Config) ->
1310	io:format("\t~s", [Component]),
1311	HashFun = sha,
1312	Label = <<>>,
1313	case jose_jwa_pkcs1:rsaes_oaep_encrypt(HashFun, Message, Label, Seed, RSAPublicKey) of
1314		{ok, Encryption} ->
1315			ok;
1316		EncryptError ->
1317			ct:fail({{jose_jwa_pkcs1, rsaes_oaep_encrypt, [HashFun, Message, Label, Seed, RSAPublicKey]}, {expected, {ok, Encryption}}, {got, EncryptError}})
1318	end,
1319	case jose_jwa_pkcs1:rsaes_oaep_decrypt(HashFun, Encryption, Label, RSAPrivateKey) of
1320		Message ->
1321			emc_rsa_oaep_encrypt_and_decrypt(Vectors, {RSAPrivateKey, RSAPublicKey}, Config);
1322		DecryptError ->
1323			ct:fail({{jose_jwa_pkcs1, rsaes_oaep_decrypt, [HashFun, Encryption, Label, RSAPrivateKey]}, {expected, Message}, {got, DecryptError}})
1324	end;
1325emc_rsa_oaep_encrypt_and_decrypt(Vectors = [divider | _], _RSAKeyPair, Config) ->
1326	emc_rsa_oaep_encrypt_and_decrypt(Vectors, Config).
1327
1328%% @private
1329emc_rsa_pss_sign_and_verify([
1330			divider,
1331			{example, Example},
1332			{component, <<"Components of the RSA Key Pair">>},
1333			{vector, {<<"RSA modulus n">>, N}},
1334			{vector, {<<"RSA public exponent e">>, E}},
1335			{vector, {<<"RSA private exponent d">>, D}},
1336			{vector, {<<"Prime p">>, P}},
1337			{vector, {<<"Prime q">>, Q}},
1338			{vector, {<<"p's CRT exponent dP">>, DP}},
1339			{vector, {<<"q's CRT exponent dQ">>, DQ}},
1340			{vector, {<<"CRT coefficient qInv">>, QI}}
1341			| Vectors
1342		], Config) ->
1343	RSAPrivateKey = #'RSAPrivateKey'{
1344		version = 'two-prime',
1345		otherPrimeInfos = 'asn1_NOVALUE',
1346		privateExponent = crypto:bytes_to_integer(D),
1347		exponent1 = crypto:bytes_to_integer(DP),
1348		exponent2 = crypto:bytes_to_integer(DQ),
1349		publicExponent = crypto:bytes_to_integer(E),
1350		modulus = crypto:bytes_to_integer(N),
1351		prime1 = crypto:bytes_to_integer(P),
1352		prime2 = crypto:bytes_to_integer(Q),
1353		coefficient = crypto:bytes_to_integer(QI)
1354	},
1355	RSAPublicKey = #'RSAPublicKey'{
1356		publicExponent = crypto:bytes_to_integer(E),
1357		modulus = crypto:bytes_to_integer(N)
1358	},
1359	io:format("~s", [Example]),
1360	emc_rsa_pss_sign_and_verify(Vectors, {RSAPrivateKey, RSAPublicKey}, Config);
1361emc_rsa_pss_sign_and_verify([divider], _Config) ->
1362	ok;
1363emc_rsa_pss_sign_and_verify([], _Config) ->
1364	ok.
1365
1366%% @private
1367emc_rsa_pss_sign_and_verify([
1368			{component, Component},
1369			{vector, {<<"Message to be signed">>, Message}},
1370			{vector, {<<"Salt">>, Salt}},
1371			{vector, {<<"Signature">>, Signature}}
1372			| Vectors
1373		], {RSAPrivateKey, RSAPublicKey}, Config) ->
1374	io:format("\t~s", [Component]),
1375	HashFun = sha,
1376	case jose_jwa_pkcs1:rsassa_pss_sign(HashFun, Message, Salt, RSAPrivateKey) of
1377		{ok, Signature} ->
1378			ok;
1379		Other ->
1380			ct:fail({{jose_jwa_pkcs1, rsassa_pss_sign, [HashFun, Message, Salt, RSAPrivateKey]}, {expected, {ok, Signature}}, {got, Other}})
1381	end,
1382	SaltLen = byte_size(Salt),
1383	case jose_jwa_pkcs1:rsassa_pss_verify(HashFun, Message, Signature, SaltLen, RSAPublicKey) of
1384		true ->
1385			emc_rsa_pss_sign_and_verify(Vectors, {RSAPrivateKey, RSAPublicKey}, Config);
1386		false ->
1387			ct:fail({{jose_jwa_pkcs1, rsassa_pss_verify, [HashFun, Message, Signature, SaltLen, RSAPublicKey]}, {expected, true}, {got, false}})
1388	end;
1389emc_rsa_pss_sign_and_verify(Vectors = [divider | _], _RSAKeyPair, Config) ->
1390	emc_rsa_pss_sign_and_verify(Vectors, Config).
1391
1392%% @private
1393fips_aes_encrypt_and_decrypt(File, Config) ->
1394	VectorsName = iolist_to_binary(filename:basename(File)),
1395	Algorithm = case VectorsName of
1396		<< "CBC", _/binary >> ->
1397			aes_cbc;
1398		<< "ECB", _/binary >> ->
1399			aes_ecb
1400	end,
1401	{Pos, 3} = binary:match(VectorsName, [<<"128">>, <<"192">>, <<"256">>]),
1402	Bits = binary_to_integer(binary:part(VectorsName, Pos, 3)),
1403	Cipher = {Algorithm, Bits},
1404	Vectors = fips_testvector:from_file(File),
1405	io:format("~s", [VectorsName]),
1406	fips_aes_encrypt_and_decrypt(Vectors, Cipher, Config).
1407
1408%% @private
1409fips_aes_encrypt_and_decrypt([
1410			{vector, {<<"COUNT">>, Count}, _},
1411			{vector, {<<"KEY">>, Key}, _},
1412			{vector, {<<"PLAINTEXT">>, PlainText}, _},
1413			{vector, {<<"CIPHERTEXT">>, CipherText}, _}
1414			| Vectors
1415		], Cipher, Config) ->
1416	io:format("\tENCRYPT = ~w", [Count]),
1417	case jose_jwa_aes:block_encrypt(Cipher, Key, PlainText) of
1418		CipherText ->
1419			fips_aes_encrypt_and_decrypt(Vectors, Cipher, Config);
1420		EncryptError ->
1421			ct:fail({{jose_jwa_aes, block_encrypt, [Cipher, Key, PlainText]}, {expected, CipherText}, {got, EncryptError}})
1422	end;
1423fips_aes_encrypt_and_decrypt([
1424			{vector, {<<"COUNT">>, Count}, _},
1425			{vector, {<<"KEY">>, Key}, _},
1426			{vector, {<<"CIPHERTEXT">>, CipherText}, _},
1427			{vector, {<<"PLAINTEXT">>, PlainText}, _}
1428			| Vectors
1429		], Cipher, Config) ->
1430	io:format("\tDECRYPT = ~w", [Count]),
1431	case jose_jwa_aes:block_decrypt(Cipher, Key, CipherText) of
1432		PlainText ->
1433			fips_aes_encrypt_and_decrypt(Vectors, Cipher, Config);
1434		DecryptError ->
1435			ct:fail({{jose_jwa_aes, block_decrypt, [Cipher, Key, CipherText]}, {expected, PlainText}, {got, DecryptError}})
1436	end;
1437fips_aes_encrypt_and_decrypt([
1438			{vector, {<<"COUNT">>, Count}, _},
1439			{vector, {<<"KEY">>, Key}, _},
1440			{vector, {<<"IV">>, IV}, _},
1441			{vector, {<<"PLAINTEXT">>, PlainText}, _},
1442			{vector, {<<"CIPHERTEXT">>, CipherText}, _}
1443			| Vectors
1444		], Cipher, Config) ->
1445	io:format("\tENCRYPT = ~w", [Count]),
1446	case jose_jwa_aes:block_encrypt(Cipher, Key, IV, PlainText) of
1447		CipherText ->
1448			fips_aes_encrypt_and_decrypt(Vectors, Cipher, Config);
1449		EncryptError ->
1450			ct:fail({{jose_jwa_aes, block_encrypt, [Cipher, Key, IV, PlainText]}, {expected, CipherText}, {got, EncryptError}})
1451	end;
1452fips_aes_encrypt_and_decrypt([
1453			{vector, {<<"COUNT">>, Count}, _},
1454			{vector, {<<"KEY">>, Key}, _},
1455			{vector, {<<"IV">>, IV}, _},
1456			{vector, {<<"CIPHERTEXT">>, CipherText}, _},
1457			{vector, {<<"PLAINTEXT">>, PlainText}, _}
1458			| Vectors
1459		], Cipher, Config) ->
1460	io:format("\tDECRYPT = ~w", [Count]),
1461	case jose_jwa_aes:block_decrypt(Cipher, Key, IV, CipherText) of
1462		PlainText ->
1463			fips_aes_encrypt_and_decrypt(Vectors, Cipher, Config);
1464		DecryptError ->
1465			ct:fail({{jose_jwa_aes, block_decrypt, [Cipher, Key, IV, CipherText]}, {expected, PlainText}, {got, DecryptError}})
1466	end;
1467fips_aes_encrypt_and_decrypt([
1468			{flag, Flag}
1469			| Vectors
1470		], Cipher, Config)
1471			when Flag =:= <<"DECRYPT">>
1472			orelse Flag =:= <<"ENCRYPT">> ->
1473	fips_aes_encrypt_and_decrypt(Vectors, Cipher, Config);
1474fips_aes_encrypt_and_decrypt([], _Cipher, Config) ->
1475	Config.
1476
1477%% @private
1478fips_aes_gcm_encrypt_and_decrypt(File, Config) ->
1479	VectorsName = iolist_to_binary(filename:basename(File)),
1480	{Algorithm, Mode} = case VectorsName of
1481		<< "gcmDecrypt", _/binary >> ->
1482			{aes_gcm, decrypt};
1483		<< "gcmEncrypt", _/binary >> ->
1484			{aes_gcm, encrypt}
1485	end,
1486	{Pos, 3} = binary:match(VectorsName, [<<"128">>, <<"192">>, <<"256">>]),
1487	Bits = binary_to_integer(binary:part(VectorsName, Pos, 3)),
1488	Cipher = {Algorithm, Bits},
1489	Vectors = fips_testvector:from_file(File),
1490	io:format("~s", [VectorsName]),
1491	fips_aes_gcm_encrypt_and_decrypt(Vectors, {Cipher, Mode, undefined}, Config).
1492
1493%% @private
1494fips_aes_gcm_encrypt_and_decrypt([
1495			{vector, {<<"Count">>, Count}, _},
1496			{vector, {<<"Key">>, Key}, _},
1497			{vector, {<<"IV">>, IV}, _},
1498			{vector, {<<"CT">>, CT}, _},
1499			{vector, {<<"AAD">>, AAD}, _},
1500			{vector, {<<"Tag">>, Tag}, _},
1501			{token, <<"FAIL">>}
1502			| Vectors
1503		], {Cipher, decrypt, {Keylen, IVlen, PTlen, AADlen, Taglen, Counts}}, Config)
1504			when bit_size(Key) =:= Keylen
1505			andalso bit_size(IV) =:= IVlen
1506			andalso bit_size(CT) =:= PTlen
1507			andalso bit_size(AAD) =:= AADlen
1508			andalso bit_size(Tag) =:= Taglen ->
1509	case rand:uniform(?config(one_in, Config)) of
1510		1 ->
1511			case jose_jwa_aes:block_decrypt(Cipher, Key, IV, {AAD, CT, Tag}) of
1512				error ->
1513					fips_aes_gcm_encrypt_and_decrypt(Vectors, {Cipher, decrypt, {Keylen, IVlen, PTlen, AADlen, Taglen, << Counts/binary, (integer_to_binary(Count))/binary, "..." >>}}, Config);
1514				OtherDecrypt ->
1515					io:format("\t\tCounts = ~s", [<< Counts/binary, (integer_to_binary(Count))/binary, "..." >>]),
1516					ct:fail({{jose_jwa_aes, block_decrypt, [Cipher, Key, IV, {AAD, CT, Tag}]}, {expected, error}, {got, OtherDecrypt}})
1517			end;
1518		_ ->
1519			fips_aes_gcm_encrypt_and_decrypt(Vectors, {Cipher, decrypt, {Keylen, IVlen, PTlen, AADlen, Taglen, << Counts/binary, (integer_to_binary(Count))/binary, "..." >>}}, Config)
1520	end;
1521fips_aes_gcm_encrypt_and_decrypt([
1522			{vector, {<<"Count">>, Count}, _},
1523			{vector, {<<"Key">>, Key}, _},
1524			{vector, {<<"IV">>, IV}, _},
1525			{vector, {<<"CT">>, CT}, _},
1526			{vector, {<<"AAD">>, AAD}, _},
1527			{vector, {<<"Tag">>, Tag}, _},
1528			{vector, {<<"PT">>, PT}, _}
1529			| Vectors
1530		], {Cipher, decrypt, {Keylen, IVlen, PTlen, AADlen, Taglen, Counts}}, Config)
1531			when bit_size(Key) =:= Keylen
1532			andalso bit_size(IV) =:= IVlen
1533			andalso bit_size(CT) =:= PTlen
1534			andalso bit_size(AAD) =:= AADlen
1535			andalso bit_size(Tag) =:= Taglen
1536			andalso bit_size(PT) =:= PTlen ->
1537	case rand:uniform(?config(one_in, Config)) of
1538		1 ->
1539			case jose_jwa_aes:block_decrypt(Cipher, Key, IV, {AAD, CT, Tag}) of
1540				PT ->
1541					fips_aes_gcm_encrypt_and_decrypt(Vectors, {Cipher, decrypt, {Keylen, IVlen, PTlen, AADlen, Taglen, << Counts/binary, (integer_to_binary(Count))/binary, "..." >>}}, Config);
1542				OtherDecrypt ->
1543					io:format("\t\tCounts = ~s", [<< Counts/binary, (integer_to_binary(Count))/binary, "..." >>]),
1544					io:format("{Cipher, Key, IV, CT, AAD, Tag, PT} = ~w~n", [{Cipher, Key, IV, CT, AAD, Tag, PT}]),
1545					ct:fail({{jose_jwa_aes, block_decrypt, [Cipher, Key, IV, {AAD, CT, Tag}]}, {expected, PT}, {got, OtherDecrypt}})
1546			end;
1547		_ ->
1548			fips_aes_gcm_encrypt_and_decrypt(Vectors, {Cipher, decrypt, {Keylen, IVlen, PTlen, AADlen, Taglen, << Counts/binary, (integer_to_binary(Count))/binary, "..." >>}}, Config)
1549	end;
1550fips_aes_gcm_encrypt_and_decrypt([
1551			{vector, {<<"Count">>, Count}, _},
1552			{vector, {<<"Key">>, Key}, _},
1553			{vector, {<<"IV">>, IV}, _},
1554			{vector, {<<"PT">>, PT}, _},
1555			{vector, {<<"AAD">>, AAD}, _},
1556			{vector, {<<"CT">>, CT}, _},
1557			{vector, {<<"Tag">>, Tag}, _}
1558			| Vectors
1559		], {Cipher, encrypt, {Keylen, IVlen, PTlen, AADlen, Taglen, Counts}}, Config)
1560			when bit_size(Key) =:= Keylen
1561			andalso bit_size(IV) =:= IVlen
1562			andalso bit_size(PT) =:= PTlen
1563			andalso bit_size(AAD) =:= AADlen
1564			andalso bit_size(CT) =:= PTlen
1565			andalso bit_size(Tag) =:= Taglen ->
1566	case rand:uniform(?config(one_in, Config)) of
1567		1 ->
1568			case jose_jwa_aes:block_encrypt(Cipher, Key, IV, {AAD, PT}) of
1569				{CT, << Tag:Taglen/bitstring, _/bitstring >>} ->
1570					fips_aes_gcm_encrypt_and_decrypt(Vectors, {Cipher, encrypt, {Keylen, IVlen, PTlen, AADlen, Taglen, << Counts/binary, (integer_to_binary(Count))/binary, "..." >>}}, Config);
1571				OtherEncrypt ->
1572					io:format("\t\tCounts = ~s", [<< Counts/binary, (integer_to_binary(Count))/binary, "..." >>]),
1573					ct:fail({{jose_jwa_aes, block_encrypt, [Cipher, Key, IV, {AAD, PT}]}, {expected, {CT, Tag}}, {got, OtherEncrypt}})
1574			end;
1575		_ ->
1576			fips_aes_gcm_encrypt_and_decrypt(Vectors, {Cipher, encrypt, {Keylen, IVlen, PTlen, AADlen, Taglen, << Counts/binary, (integer_to_binary(Count))/binary, "..." >>}}, Config)
1577	end;
1578fips_aes_gcm_encrypt_and_decrypt([
1579			{option, {<<"Keylen">>, Keylen}},
1580			{option, {<<"IVlen">>, IVlen}},
1581			{option, {<<"PTlen">>, PTlen}},
1582			{option, {<<"AADlen">>, AADlen}},
1583			{option, {<<"Taglen">>, Taglen}}
1584			| Vectors
1585		], {Cipher, Mode, undefined}, Config) ->
1586	Options = {
1587		binary_to_integer(Keylen),
1588		binary_to_integer(IVlen),
1589		binary_to_integer(PTlen),
1590		binary_to_integer(AADlen),
1591		binary_to_integer(Taglen),
1592		<<>>
1593	},
1594	fips_aes_gcm_encrypt_and_decrypt(Vectors, {Cipher, Mode, Options}, Config);
1595fips_aes_gcm_encrypt_and_decrypt(Vectors, {Cipher, Mode, {_Keylen, _IVlen, _PTlen, _AADlen, _Taglen, _Counts}}, Config) ->
1596	fips_aes_gcm_encrypt_and_decrypt(Vectors, {Cipher, Mode, undefined}, Config);
1597fips_aes_gcm_encrypt_and_decrypt([], _Cipher, Config) ->
1598	Config.
1599
1600%% @private
1601fips_aeskw_unwrap(File, Config) ->
1602	<< "KW_AD_", BitsBin:3/binary, _/binary >> = iolist_to_binary(filename:basename(File)),
1603	Bits = binary_to_integer(BitsBin),
1604	Vectors = fips_testvector:from_file(File),
1605	io:format("~s", [filename:basename(File)]),
1606	fips_aeskw_unwrap(Vectors, {Bits, undefined}, Config).
1607
1608%% @private
1609fips_aeskw_unwrap([
1610			{vector, {<<"COUNT">>, Count}, _},
1611			{vector, {<<"K">>, K}, _},
1612			{vector, {<<"C">>, C}, _},
1613			{vector, {<<"P">>, P}, _}
1614			| Vectors
1615		], {Bits, Len}, Config)
1616			when is_integer(Len)
1617			andalso bit_size(K) =:= Bits
1618			andalso bit_size(P) =:= Len ->
1619	case rand:uniform(?config(one_in, Config)) of
1620		1 ->
1621			case jose_jwa_aes_kw:unwrap(C, K) of
1622				P ->
1623					fips_aeskw_unwrap(Vectors, {Bits, Len}, Config);
1624				Other ->
1625					io:format("\t\tCOUNT = ~w", [Count]),
1626					ct:fail({{jose_jwa_aes_kw, unwrap, [C, K]}, {expected, P}, {got, Other}})
1627			end;
1628		_ ->
1629			fips_aeskw_unwrap(Vectors, {Bits, Len}, Config)
1630	end;
1631fips_aeskw_unwrap([
1632			{vector, {<<"COUNT">>, Count}, _},
1633			{vector, {<<"K">>, K}, _},
1634			{vector, {<<"C">>, C}, _},
1635			{token, <<"FAIL">>}
1636			| Vectors
1637		], {Bits, Len}, Config)
1638			when is_integer(Len)
1639			andalso bit_size(K) =:= Bits ->
1640	case rand:uniform(?config(one_in, Config)) of
1641		1 ->
1642			try jose_jwa_aes_kw:unwrap(C, K) of
1643				Other ->
1644					io:format("\t\tCOUNT = ~w", [Count]),
1645					ct:fail({{jose_jwa_aes_kw, unwrap, [C, K]}, {expected, badarg}, {got, Other}})
1646			catch
1647				_:_ ->
1648					fips_aeskw_unwrap(Vectors, {Bits, Len}, Config)
1649			end;
1650		_ ->
1651			fips_aeskw_unwrap(Vectors, {Bits, Len}, Config)
1652	end;
1653fips_aeskw_unwrap([{option, {<<"PLAINTEXTLENGTH">>, LenBin}} | Vectors], {Bits, _}, Config) ->
1654	Len = binary_to_integer(LenBin),
1655	io:format("\tPLAINTEXTLENGTH = ~w", [Len]),
1656	fips_aeskw_unwrap(Vectors, {Bits, Len}, Config);
1657fips_aeskw_unwrap([], _, Config) ->
1658	Config.
1659
1660%% @private
1661fips_aeskw_wrap(File, Config) ->
1662	<< "KW_AE_", BitsBin:3/binary, _/binary >> = iolist_to_binary(filename:basename(File)),
1663	Bits = binary_to_integer(BitsBin),
1664	Vectors = fips_testvector:from_file(File),
1665	io:format("~s", [filename:basename(File)]),
1666	fips_aeskw_wrap(Vectors, {Bits, undefined}, Config).
1667
1668%% @private
1669fips_aeskw_wrap([
1670			{vector, {<<"COUNT">>, Count}, _},
1671			{vector, {<<"K">>, K}, _},
1672			{vector, {<<"P">>, P}, _},
1673			{vector, {<<"C">>, C}, _}
1674			| Vectors
1675		], {Bits, Len}, Config)
1676			when is_integer(Len)
1677			andalso bit_size(K) =:= Bits
1678			andalso bit_size(P) =:= Len ->
1679	case rand:uniform(?config(one_in, Config)) of
1680		1 ->
1681			case jose_jwa_aes_kw:wrap(P, K) of
1682				C ->
1683					fips_aeskw_wrap(Vectors, {Bits, Len}, Config);
1684				Other ->
1685					io:format("\t\tCOUNT = ~w", [Count]),
1686					ct:fail({{jose_jwa_aes_kw, wrap, [P, K]}, {expected, C}, {got, Other}})
1687			end;
1688		_ ->
1689			fips_aeskw_wrap(Vectors, {Bits, Len}, Config)
1690	end;
1691fips_aeskw_wrap([{option, {<<"PLAINTEXTLENGTH">>, LenBin}} | Vectors], {Bits, _}, Config) ->
1692	Len = binary_to_integer(LenBin),
1693	io:format("\tPLAINTEXTLENGTH = ~w", [Len]),
1694	fips_aeskw_wrap(Vectors, {Bits, Len}, Config);
1695fips_aeskw_wrap([], _, Config) ->
1696	Config.
1697
1698%% @private
1699fips_rsa_pss_sign([
1700			{option, {<<"mod">>, ModVal}},
1701			{vector, {<<"n">>, N}, _},
1702			{vector, {<<"e">>, E}, _},
1703			{vector, {<<"d">>, D}, _}
1704			| Vectors
1705		], Config) ->
1706	ModulusSize = binary_to_integer(ModVal),
1707	RSAPrivateKey = #'RSAPrivateKey'{
1708		modulus = crypto:bytes_to_integer(N),
1709		privateExponent = crypto:bytes_to_integer(D),
1710		publicExponent = crypto:bytes_to_integer(E)
1711	},
1712	fips_rsa_pss_sign(Vectors, ModulusSize, RSAPrivateKey, Config);
1713fips_rsa_pss_sign([], _Config) ->
1714	ok.
1715
1716%% @private
1717fips_rsa_pss_sign([
1718			{vector, {<<"SHAAlg">>, SHAAlg}, _},
1719			{vector, {<<"Msg">>, Msg}, _},
1720			{vector, {<<"S">>, S}, _},
1721			{vector, {<<"SaltVal">>, SaltVal}, _}
1722			| Vectors
1723		], ModulusSize, RSAPrivateKey, Config) ->
1724	HashFun = shaalg_to_hash_fun(SHAAlg),
1725	case jose_jwa_pkcs1:rsassa_pss_sign(HashFun, Msg, SaltVal, RSAPrivateKey) of
1726		{ok, S} ->
1727			ok;
1728		Other ->
1729			ct:fail({{jose_jwa_pkcs1, rsassa_pss_sign, [HashFun, Msg, SaltVal, RSAPrivateKey]}, {expected, {ok, S}}, {got, Other}})
1730	end,
1731	RSAPublicKey = rsa_private_to_public(RSAPrivateKey),
1732	SaltLen = byte_size(SaltVal),
1733	case jose_jwa_pkcs1:rsassa_pss_verify(HashFun, Msg, S, SaltLen, RSAPublicKey) of
1734		true ->
1735			fips_rsa_pss_sign(Vectors, ModulusSize, RSAPrivateKey, Config);
1736		false ->
1737			ct:fail({{jose_jwa_pkcs1, rsassa_pss_verify, [HashFun, Msg, S, SaltLen, RSAPublicKey]}, {expected, true}, {got, false}})
1738	end;
1739fips_rsa_pss_sign(Vectors, _ModulusSize, _RSAPrivateKey, Config) ->
1740	fips_rsa_pss_sign(Vectors, Config).
1741
1742%% @private
1743fips_rsa_pss_verify([
1744			{option, {<<"mod">>, ModVal}},
1745			{vector, {<<"n">>, N}, _},
1746			{vector, {<<"p">>, P}, _},
1747			{vector, {<<"q">>, Q}, _}
1748			| Vectors
1749		], Config) ->
1750	ModulusSize = binary_to_integer(ModVal),
1751	RSAPrivateKey = #'RSAPrivateKey'{
1752		modulus = crypto:bytes_to_integer(N),
1753		prime1 = crypto:bytes_to_integer(P),
1754		prime2 = crypto:bytes_to_integer(Q)
1755	},
1756	fips_rsa_pss_verify(Vectors, ModulusSize, RSAPrivateKey, Config);
1757fips_rsa_pss_verify([], _Config) ->
1758	ok.
1759
1760%% @private
1761fips_rsa_pss_verify([
1762			{vector, {<<"n">>, N}, _},
1763			{vector, {<<"p">>, P}, _},
1764			{vector, {<<"q">>, Q}, _}
1765			| Vectors
1766		], ModulusSize, Config) ->
1767	RSAPrivateKey = #'RSAPrivateKey'{
1768		modulus = crypto:bytes_to_integer(N),
1769		prime1 = crypto:bytes_to_integer(P),
1770		prime2 = crypto:bytes_to_integer(Q)
1771	},
1772	fips_rsa_pss_verify(Vectors, ModulusSize, RSAPrivateKey, Config);
1773fips_rsa_pss_verify(Vectors, _ModulusSize, Config) ->
1774	fips_rsa_pss_verify(Vectors, Config).
1775
1776%% @private
1777fips_rsa_pss_verify([
1778			{vector, {<<"SHAAlg">>, SHAAlg}, _},
1779			{vector, {<<"e">>, E}, _},
1780			{vector, {<<"d">>, D}, _},
1781			{vector, {<<"Msg">>, Msg}, _},
1782			{vector, {<<"S">>, S}, _},
1783			{vector, {<<"SaltVal">>, SaltVal}, _},
1784			{vector, {<<"EM", _/binary>>, _}, _},
1785			{vector, {<<"Result">>, << R, _/binary >>}, _}
1786			| Vectors
1787		], ModulusSize, RSAPrivateKey0, Config) ->
1788	Expected = case R of
1789		$F ->
1790			false;
1791		$P ->
1792			true
1793	end,
1794	HashFun = shaalg_to_hash_fun(SHAAlg),
1795	RSAPrivateKey = RSAPrivateKey0#'RSAPrivateKey'{
1796		privateExponent = crypto:bytes_to_integer(D),
1797		publicExponent = crypto:bytes_to_integer(E)
1798	},
1799	RSAPublicKey = rsa_private_to_public(RSAPrivateKey),
1800	SaltLen = case SaltVal of
1801		<< 0 >> ->
1802			0;
1803		_ ->
1804			byte_size(SaltVal)
1805	end,
1806	case jose_jwa_pkcs1:rsassa_pss_verify(HashFun, Msg, S, SaltLen, RSAPublicKey) of
1807		Expected ->
1808			fips_rsa_pss_verify(Vectors, ModulusSize, RSAPrivateKey0, Config);
1809		Other ->
1810			ct:fail({{jose_jwa_pkcs1, rsassa_pss_verify, [HashFun, Msg, S, SaltLen, RSAPublicKey]}, {expected, Expected}, {got, Other}})
1811	end;
1812fips_rsa_pss_verify([
1813			{vector, {<<"SHAAlg">>, SHAAlg}, _},
1814			{vector, {<<"e">>, E}, _},
1815			{vector, {<<"d">>, D}, _},
1816			{vector, {<<"Msg">>, Msg}, _},
1817			{vector, {<<"S">>, S}, _},
1818			{vector, {<<"SaltVal">>, SaltVal}, _},
1819			{vector, {<<"Result">>, << R, _/binary >>}, _}
1820			| Vectors
1821		], ModulusSize, RSAPrivateKey0, Config) ->
1822	Expected = case R of
1823		$F ->
1824			false;
1825		$P ->
1826			true
1827	end,
1828	HashFun = shaalg_to_hash_fun(SHAAlg),
1829	RSAPrivateKey = RSAPrivateKey0#'RSAPrivateKey'{
1830		privateExponent = crypto:bytes_to_integer(D),
1831		publicExponent = crypto:bytes_to_integer(E)
1832	},
1833	RSAPublicKey = rsa_private_to_public(RSAPrivateKey),
1834	SaltLen = case SaltVal of
1835		<< 0 >> ->
1836			0;
1837		_ ->
1838			byte_size(SaltVal)
1839	end,
1840	case jose_jwa_pkcs1:rsassa_pss_verify(HashFun, Msg, S, SaltLen, RSAPublicKey) of
1841		Expected ->
1842			fips_rsa_pss_verify(Vectors, ModulusSize, RSAPrivateKey0, Config);
1843		Other ->
1844			ct:fail({{jose_jwa_pkcs1, rsassa_pss_verify, [HashFun, Msg, S, SaltLen, RSAPublicKey]}, {expected, Expected}, {got, Other}})
1845	end;
1846fips_rsa_pss_verify(Vectors, ModulusSize, _RSAPrivateKey, Config) ->
1847	fips_rsa_pss_verify(Vectors, ModulusSize, Config).
1848
1849%% @private
1850fips_sha3(File, Config) ->
1851	Options = case iolist_to_binary(filename:basename(File)) of
1852		<< "ShortMsgKAT_SHA3-", BitsBin:3/binary, _/binary >> ->
1853			Bits = binary_to_integer(BitsBin),
1854			Bytes = (Bits + 7) div 8,
1855			Function = list_to_atom("sha3_" ++ integer_to_list(Bits)),
1856			Arity = 1,
1857			{Function, Arity, Bytes};
1858		<< "ShortMsgKAT_SHAKE", BitsBin:3/binary, _/binary >> ->
1859			Bits = binary_to_integer(BitsBin),
1860			Bytes = 512,
1861			Function = list_to_atom("shake" ++ integer_to_list(Bits)),
1862			Arity = 2,
1863			{Function, Arity, Bytes}
1864	end,
1865	Vectors = fips_testvector:from_file(File),
1866	io:format("~s", [filename:basename(File)]),
1867	fips_sha3(Vectors, Options, Config).
1868
1869%% @private
1870fips_sha3([
1871			{vector, {<<"Len">>, Len}, _},
1872			{vector, {<<"Msg">>, Msg}, _},
1873			{vector, {<<"MD">>, MD}, _}
1874			| Vectors
1875		], {Function, Arity=1, OutputByteLen}, Config) when Len rem 8 =:= 0 ->
1876	InputBytes = binary:part(Msg, 0, Len div 8),
1877	case jose_jwa_sha3:Function(InputBytes) of
1878		MD ->
1879			fips_sha3(Vectors, {Function, Arity, OutputByteLen}, Config);
1880		Other ->
1881			ct:fail({{jose_jwa_sha3, Function, [InputBytes]}, {expected, MD}, {got, Other}})
1882	end;
1883fips_sha3([
1884			{vector, {<<"Len">>, Len}, _},
1885			{vector, {<<"Msg">>, Msg}, _},
1886			{vector, {<<"Squeezed">>, Squeezed}, _}
1887			| Vectors
1888		], {Function, Arity=2, OutputByteLen}, Config) when Len rem 8 =:= 0 ->
1889	InputBytes = binary:part(Msg, 0, Len div 8),
1890	case jose_jwa_sha3:Function(InputBytes, OutputByteLen) of
1891		Squeezed ->
1892			fips_sha3(Vectors, {Function, Arity, OutputByteLen}, Config);
1893		Other ->
1894			ct:fail({{jose_jwa_sha3, Function, [InputBytes, OutputByteLen]}, {expected, Squeezed}, {got, Other}})
1895	end;
1896fips_sha3([
1897			{vector, {<<"Len">>, _Len}, _},
1898			{vector, {<<"Msg">>, _Msg}, _},
1899			{vector, {<<"MD">>, _MD}, _}
1900			| Vectors
1901		], Options, Config) ->
1902	fips_sha3(Vectors, Options, Config);
1903fips_sha3([
1904			{vector, {<<"Len">>, _Len}, _},
1905			{vector, {<<"Msg">>, _Msg}, _},
1906			{vector, {<<"Squeezed">>, _Squeezed}, _}
1907			| Vectors
1908		], Options, Config) ->
1909	fips_sha3(Vectors, Options, Config);
1910fips_sha3([], _Opts, _Config) ->
1911	ok.
1912
1913%% @private
1914hexstr2bin(S) ->
1915	list_to_binary(hexstr2list(S)).
1916
1917%% @private
1918hexstr2lint(S) ->
1919	Bin = hexstr2bin(S),
1920	Size = byte_size(Bin),
1921	<< Int:Size/unsigned-little-integer-unit:8 >> = Bin,
1922	Int.
1923
1924%% @private
1925hexstr2list([X,Y|T]) ->
1926	[mkint(X)*16 + mkint(Y) | hexstr2list(T)];
1927hexstr2list([]) ->
1928	[].
1929
1930%% @private
1931mkint(C) when $0 =< C, C =< $9 ->
1932	C - $0;
1933mkint(C) when $A =< C, C =< $F ->
1934	C - $A + 10;
1935mkint(C) when $a =< C, C =< $f ->
1936	C - $a + 10.
1937
1938%% @private
1939pbkdf1([{Hash, Password, Salt, Iterations, DerivedKeyLen, DerivedKey} | Vectors], Config) ->
1940	case jose_jwa_pkcs5:pbkdf1(Hash, Password, Salt, Iterations, DerivedKeyLen) of
1941		{ok, DerivedKey} ->
1942			pbkdf1(Vectors, Config);
1943		Other ->
1944			ct:fail({{jose_jwa_pkcs5, pbkdf1, [Hash, Password, Salt, Iterations, DerivedKeyLen]}, {expected, {ok, DerivedKey}}, {got, Other}})
1945	end;
1946pbkdf1([], _Config) ->
1947	ok.
1948
1949%% @private
1950pbkdf2([{Mac, Password, Salt, Iterations, DerivedKeyLen, DerivedKey} | Vectors], Config) ->
1951	case jose_jwa_pkcs5:pbkdf2(Mac, Password, Salt, Iterations, DerivedKeyLen) of
1952		{ok, DerivedKey} ->
1953			pbkdf2(Vectors, Config);
1954		Other ->
1955			ct:fail({{jose_jwa_pkcs5, pbkdf2, [Mac, Password, Salt, Iterations, DerivedKeyLen]}, {expected, {ok, DerivedKey}}, {got, Other}})
1956	end;
1957pbkdf2([], _Config) ->
1958	ok.
1959
1960%% @private
1961pkcs7_pad_and_unpad([{Unpadded, Padded} | Vectors], Config) ->
1962	case jose_jwa_pkcs7:pad(Unpadded) of
1963		Padded ->
1964			ok;
1965		PadOther ->
1966			ct:fail({{jose_jwa_pkcs7, pad, [Unpadded]}, {expected, Padded}, {got, PadOther}})
1967	end,
1968	case jose_jwa_pkcs7:unpad(Padded) of
1969		Unpadded ->
1970			pkcs7_pad_and_unpad(Vectors, Config);
1971		UnpadOther ->
1972			ct:fail({{jose_jwa_pkcs7, unpad, [Padded]}, {expected, Unpadded}, {got, UnpadOther}})
1973	end;
1974pkcs7_pad_and_unpad([], _Config) ->
1975	ok.
1976
1977%% @private
1978rsa_private_to_public(#'RSAPrivateKey'{ modulus = Modulus, publicExponent = PublicExponent }) ->
1979	#'RSAPublicKey'{ modulus = Modulus, publicExponent = PublicExponent }.
1980
1981%% @private
1982shaalg_to_hash_fun(<<"SHA1">>)   -> sha;
1983shaalg_to_hash_fun(<<"SHA224">>) -> sha224;
1984shaalg_to_hash_fun(<<"SHA256">>) -> sha256;
1985shaalg_to_hash_fun(<<"SHA384">>) -> sha384;
1986shaalg_to_hash_fun(<<"SHA512">>) -> sha512.
1987
1988%% @private
1989x25519_vector({AliceSK, AlicePK, BobSK, BobPK, Shared}) ->
1990	?tv_ok(T0, jose_jwa_curve25519, x25519_secret_to_public, [AliceSK], AlicePK),
1991	?tv_ok(T1, jose_jwa_curve25519, x25519_secret_to_public, [BobSK], BobPK),
1992	?tv_ok(T2, jose_jwa_curve25519, x25519_shared_secret, [AliceSK, BobPK], Shared),
1993	?tv_ok(T3, jose_jwa_curve25519, x25519_shared_secret, [BobSK, AlicePK], Shared).
1994
1995%% @private
1996x448_vector({AliceSK, AlicePK, BobSK, BobPK, Shared}) ->
1997	?tv_ok(T0, jose_jwa_curve448, x448_secret_to_public, [AliceSK], AlicePK),
1998	?tv_ok(T1, jose_jwa_curve448, x448_secret_to_public, [BobSK], BobPK),
1999	?tv_ok(T2, jose_jwa_curve448, x448_shared_secret, [AliceSK, BobPK], Shared),
2000	?tv_ok(T3, jose_jwa_curve448, x448_shared_secret, [BobSK, AlicePK], Shared).
2001