1/*
2 * Copyright (c) 2006 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 *
13 * 2. Redistributions in binary form must reproduce the above copyright
14 *    notice, this list of conditions and the following disclaimer in the
15 *    documentation and/or other materials provided with the distribution.
16 *
17 * 3. Neither the name of the Institute nor the names of its contributors
18 *    may be used to endorse or promote products derived from this software
19 *    without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34#include "cs-config.h"
35
36#include <stdio.h>
37
38#include "rk-roken.h"
39#include "rk-getarg.h"
40
41#include "cs-engine.h"
42#include "cs-evp.h"
43
44struct {
45    const char *cpriv;
46    const char *cpub;
47    const char *spriv;
48    const char *spub;
49} dhtests[] = {
50    {
51	"5C0946275D07223AEAF04301D964498F3285946057B4C50D13B4FE12C88DFD8D499DD3CC00C1BC17C0D343F2FE053C9F53389110551715B1EDF261A0314485C4835D01F7B8894027D534A2D81D63619D2F58C9864AC9816086B3FF75C01B3FAFF355425AB7369A6ABDC8B633F0A0DC4D29B50F364E7594B297183D14E5CDC05D",
52	"2D66DC5998B7AEE3332DC1061C6E6F6CF0FCCD74534187E2CDC9ACBCADF0FC9D5900451F44832A762F01E9CEEF1CBD7D69D020AC524D09FAD087DFADEAC36C845157B83937B51C8DB7F500C3C54FB2A05E074E40BA982186E7FEB2534EDDB387D5480AAA355B398CCAD0886F3952C3718490B7884FA67BD8B6943CDDA20134C6",
53	"42644BA7CF74689E18BA72BF80FCA674D1A2ADF81795EB3828E67C30E42ABD07A8E90E27F046189FAC122D915276870B72427388EAAB5D06994FC38885BBACCEA1CFC45951B730D73C1A8F83208CD1351746601648C11D70BC95B817C86E4A5C40D633654615041C7934BB3CAF4E02754D542033DB024E94C7E561A29ED0C6EC",
54	"C233633AB116E2DB20B4E08DA42DE8766293E6D9042F7A2C2A2F34F18FE66010B074CCF3C9B03EF27B14F0746B738AF22776224161D767D96AEC230A1DFA6DECFFCE9FED23B96F50CCB0093E59817AD0CEAEB7993AB5764679948BFB1293C9560B07AA3DFA229E341EB17C9FAE0B1D483082461D2DDBCEEE6FE7C0A34D96F66D"
55    },
56    {
57	"76295C1280B890970F0F7EB01BBD9C5DF9BB8F590EB384A39EBF85CD141451407F955FD1D39012AA1F8BA53FD6A5A37CB2835CEDB27D1EBF1FE8AC9F2FFD628BD9BF7B8DD77CB80C8DC0A75F4567C7700442B26972833EB9738A8728A1FC274C59CED5E3ADA224B46711112AAA1CB831D2D6125E183ADA4F805A05024C9C6DDB",
58	"1E0AB5EBAAC7985FE67A574447FAE58AE4CB95416278D4C239A789D4532FA8E6F82BA10BE411D8A0A06B9E1DECE704466B3523496A8A4165B97FBCFB9CE9C4FF2DEEE786BA046E8C270FA8A9055D2F6E42EDDB32C73CF7875551A56EB69C0F14A3745745845B81C347401B27D074C60C5177BA9C14BBB1C8C219B78E15126EF8",
59	"68D84A8F92082F113542CFD990DEEFAD9C7EFA545268F8B3EBDF4CCBAF2865CF03EF60044EB4AF4154E6804CC2BDD673B801507446CEFC692DA577B6DC6E0272B7B081A1BEFDC2A4FAC83DB8845E3DA0D1B64DB33AA2164FEDB08A01E815336BD58F4E6DE6A265468E61C8C988B8AEC0D52DB714448DDC007E7C3382C07357DB",
60	"393815D507A2EF80DE2D0F2A55AAB1C25B870ACA3FC97438B4336CBF979BF9A4F8DA1B61C667129F9123045E07E24976040EC5E2368DD4EF70690102D74E900B260D3826256FD473733A7569BF514652AB78C48C334FDCA26C44ABF322643AF15BFF693A37BB2C19CA9FE5F1537FCFE2B24CF74D4E57060D35ABF115B4B6CD21"
61    },
62    {
63	"7307D6C3CB874327A95F7A6A91C336CEAA086736525DF3F8EC49497CF444C68D264EB70CD6904FE56E240EEF34E6C5177911C478A7F250A0F54183BCBE64B42BAB5D019E73E2F17C095C211E4815E6BA5FDD72786AF987ABBC9109ECEEF439AF9E2141D5222CE7DC0152D8E9A6CCCE301D21A7D1D6ACB9B91B5E28379C91890D",
64	"83FBD7BFFDF415BBB7E21D399CB2F36A61AFDBAFC542E428E444C66AA03617C0C55C639FE2428905B57035892AE1BD2C4060E807D9E003B0C204FFC8FDD69CC8ADE7A8E18DCBFFF64E3EF9DA2C117390374241466E48A020A1B2F575AE42C233F8BD357B8331CC203E0345DFC19C73E6F1F70B6C2786E681D73BF48B15FE9992",
65	"61BCF748BB05A48861578B8CB1855200B2E62A40E126BD7323E5B714645A54A2C8761EE39EE39BA6D2FE19B688168EDEA6DC5056400B5315ED299E7926176B887012E58634D78F05D7BCF0E1B81B1B41F5F8EF0B0711D3A64F9A317DD183AE039A4D3BE02A515892362F8C7BB6EB6434BB25418A438ED33D50C475122CBBE862",
66	"7DB8D69D1605D9812B7F2F3E92BCEEB3426FEEE3265A174D71B2B6E16B332B43DF0B3C2FA152E48DE2FAC110D8CECE122C3398558E7987B27CACE12722C0032AC7E7766A9BCC881BA35B9DB9E751BD4E51F7683DE092F6C1D4DD937CDCE9C16E6F7D77CC6AAD806E4082E8E22E28592C4D78256354393FE831E811E03ED0A81A"
67    },
68    {
69	"60C18B62F786DE6A4A8B13EB6DA2380B4C6731F861C715D9496DCF4A9F01CD33DDB52F1AB4D1F820FAF7AD4EFEB66586F7F08135714B13D77FE652B9EEAB2C543596A9ED307C1629CF535DD14AB22F081AE4ADF7A3E0BC7B33E0EC7A7306F9A737F55807974B5E1B7B6394BD0373917128B43A17757B34BAE1B600763E957F75",
70	"0DEDA337C38EA005D5B8567EAB681CE91892C2C62C9D42BF748FBFE681E11F25D98280E42E1539A10EEE9177EF2F40216987936AF19D9B5EBE22EEAC27242D77CE3A5061F2E5CFACF15CD0F80E736AE8642252FE91E129DE3C78CFB85A0B1BB87B059CBB24483444F8A07244F4E89370BA78D58BD409DFBB3D41921B8879B9C7",
71	"462C0707CF3366C2242A808CFDB79B77E8B3AF9D796583EB9CCD7BF4E8792AB0A818E49FFE53CA241F56988F825B366BF1E78481F8086A123259B9D83AC643E85845BF6B2C5412FFDDFAA8C9ED203CA4B3C1BFD777286099976472FA15B3CCC8418CF162F03C0C3E85D7EFC5CF5ACB9B2C039CCF3A1A9C6BB6B9C09C18D86CBD",
72	"56DB382EDB8C2D95934D20261CE1A37090B0802D451E647DB1DA3B73CDB5A878EAD598A8817302449370F9D45E34F5C45F73D02BF4EB2B3712A8665F446F5D2B774039E5444AB74807859FA58DF9EBA4B12BA4545ACED827E4ED64CC71F937D64A1033BC43403F2490C1B715A74822B8D50A72A102213F0CF7A1B98B771B34C4"
73    },
74    {
75	"61B7321207F4A73646E43E99221F902D2F38095E84CE7346A1510FE71BA7B9B34DCB6609E4DDDA8C82426E82D1C23F1E761130ECE4638D77554A7618E1608625049328FCC1F8845CA9A88E847106B01BD31EF6500E3C7EE81A048924BEAA3EDF367E5F4575341206C7A76427571898294B07BD918D4C2642854CC89D439042E5",
76	"29AA38E63E4DD7C651E25DEC7A5A53E48114F52813793D36A9DBDD4F7C06FC38406E330764E0B2AFD811C39D857EA5F904105360E06856DC0780C7D61C53165833F0AEA15CB54732DE113F44C8FCFB86F4A876DD42D7A55356D91C0173F2B012680FB54C13EF54B65DF4AEDE2E13419B1316435187CEF07D44DB3DF57C4703FD",
77	"5ED5AFB04CBFEE43EF3D9B60A57080831563648A2380D98F1EA4A96CF153903A40A2E564DED87E7254DF3270568AB952BF6F400681DD6AD919C9B06AC0F45F0646BCF37B217191AA0B7B7BED226B61F48B46DEA2E5A09E41F316583823A38A60FFD79085F43F60D98871ECA1A0F667701425094E88885A81DE9DA6C293E95060",
78	"4DE4F24EAA3E2790FBCB1B13C2ED0EFD846EC33154DBEBBEFD895E1399B3617D55EC2CE8D71CF380B55D93636FEF741328D6B1E224D46F8A8B60A41D08DD86E88DE806AA781791364E6D88BF68571BF5D8C35CB04BA302227B7E4CB6A67AB7510ACBCDBF2F8A95EB5DEE693CCA5CC425A0F1CA2D18C369A767906A2477E32704"
79    }
80};
81
82static void
83dh_test(DH *server, DH *client)
84{
85    void *skey, *ckey;
86    int ssize, csize;
87
88    skey = emalloc(DH_size(server));
89    ckey = emalloc(DH_size(client));
90
91    ssize = DH_compute_key(skey, client->pub_key, server);
92    if (ssize == -1)
93	errx(1, "DH_compute_key failed for server");
94    csize = DH_compute_key(ckey, server->pub_key, client);
95    if (csize == -1)
96	errx(1, "DH_compute_key failed for client");
97
98    if (ssize != csize)
99	errx(1, "DH_compute_key size mismatch");
100
101    if (memcmp(skey, ckey, csize) != 0)
102	errx(1, "DH_compute_key key mismatch");
103
104    free(skey);
105    free(ckey);
106}
107
108
109static int version_flag;
110static int help_flag;
111static char *id_flag;
112static char *rsa_flag;
113static int dh_flag = 1;
114static int test_random_flag;
115
116static struct getargs args[] = {
117    { "id",		0,	arg_string,	&id_flag,
118      "selects the engine id", 	"engine-id" },
119    { "rsa",		0,	arg_string,	&rsa_flag,
120      "tests RSA modes", 	"private-rsa-der-file" },
121    { "dh",		0,	arg_negative_flag,	&dh_flag,
122      "test dh", NULL },
123    { "test-random",	0,	arg_flag,	&test_random_flag,
124      "test if there is a random device", NULL },
125    { "version",	0,	arg_flag,	&version_flag,
126      "print version", NULL },
127    { "help",		0,	arg_flag,	&help_flag,
128      NULL, 	NULL }
129};
130
131static void
132usage (int ret)
133{
134    arg_printusage (args,
135		    sizeof(args)/sizeof(*args),
136		    NULL,
137		    "filename.so");
138    exit (ret);
139}
140
141int
142main(int argc, char **argv)
143{
144    ENGINE *engine = NULL;
145    int idx = 0;
146    int have_rsa, have_dh;
147
148    setprogname(argv[0]);
149
150    if(getarg(args, sizeof(args) / sizeof(args[0]), argc, argv, &idx))
151	usage(1);
152
153    if (help_flag)
154	usage(0);
155
156    if(version_flag){
157	print_version(NULL);
158	exit(0);
159    }
160
161    argc -= idx;
162    argv += idx;
163
164    OpenSSL_add_all_algorithms();
165
166    if (argc == 0) {
167	OpenSSL_add_all_algorithms();
168	ENGINE_load_builtin_engines();
169	engine = ENGINE_by_id("builtin");
170    } else {
171	engine = ENGINE_by_dso(argv[0], id_flag);
172    }
173    if (engine == NULL)
174	errx(1, "ENGINE_by_dso failed");
175
176    printf("name: %s\n", ENGINE_get_name(engine));
177    printf("id: %s\n", ENGINE_get_id(engine));
178    have_rsa = ENGINE_get_RSA(engine) != NULL;
179    have_dh = ENGINE_get_DH(engine) != NULL;
180    printf("RSA: %s", have_rsa ? "yes," : "no");
181    if (have_rsa)
182	printf(" %s", ENGINE_get_RSA(engine)->name);
183    printf("\n");
184    printf("DH: %s", have_dh ? "yes," : "no");
185    if (have_dh)
186	printf(" %s", ENGINE_get_DH(engine)->name);
187    printf("\n");
188
189    if (RAND_status() != 1)
190	errx(77, "no functional random device, can't execute tests");
191    if (test_random_flag)
192	exit(0);
193
194    if (rsa_flag && have_rsa) {
195	unsigned char buf[1024 * 4];
196	const unsigned char *p;
197	size_t size;
198	int keylen;
199	RSA *rsa;
200	FILE *f;
201
202	f = fopen(rsa_flag, "rb");
203	if (f == NULL)
204	    err(1, "could not open file %s", rsa_flag);
205
206	size = fread(buf, 1, sizeof(buf), f);
207	if (size == 0)
208	    err(1, "failed to read file %s", rsa_flag);
209	if (size == sizeof(buf))
210	    err(1, "key too long in file %s!", rsa_flag);
211	fclose(f);
212
213	p = buf;
214	rsa = d2i_RSAPrivateKey(NULL, &p, size);
215	if (rsa == NULL)
216	    err(1, "failed to parse key in file %s", rsa_flag);
217
218	RSA_set_method(rsa, ENGINE_get_RSA(engine));
219
220	/*
221	 * try rsa signing
222	 */
223
224	memcpy(buf, "hejsan", 7);
225	keylen = RSA_private_encrypt(7, buf, buf, rsa, RSA_PKCS1_PADDING);
226	if (keylen <= 0)
227	    errx(1, "failed to private encrypt");
228
229	keylen = RSA_public_decrypt(keylen, buf, buf, rsa, RSA_PKCS1_PADDING);
230	if (keylen <= 0)
231	    errx(1, "failed to public decrypt");
232
233	if (keylen != 7)
234	    errx(1, "output buffer not same length: %d", (int)keylen);
235
236	if (memcmp(buf, "hejsan", 7) != 0)
237	    errx(1, "string not the same after decryption");
238
239	/*
240	 * try rsa encryption
241	 */
242
243	memcpy(buf, "hejsan", 7);
244	keylen = RSA_public_encrypt(7, buf, buf, rsa, RSA_PKCS1_PADDING);
245	if (keylen <= 0)
246	    errx(1, "failed to public encrypt");
247
248	keylen = RSA_private_decrypt(keylen, buf, buf, rsa, RSA_PKCS1_PADDING);
249	if (keylen <= 0)
250	    errx(1, "failed to private decrypt");
251
252	if (keylen != 7)
253	    errx(1, "output buffer not same length: %d", (int)keylen);
254
255	if (memcmp(buf, "hejsan", 7) != 0)
256	    errx(1, "string not the same after decryption");
257
258	RSA_free(rsa);
259
260	printf("rsa test passed\n");
261
262    }
263
264    if (dh_flag) {
265	DH *server, *client;
266	int i;
267
268	/* RFC2412-MODP-group2 */
269	const char *p =
270	    "FFFFFFFF" "FFFFFFFF" "C90FDAA2" "2168C234" "C4C6628B" "80DC1CD1"
271	    "29024E08" "8A67CC74" "020BBEA6" "3B139B22" "514A0879" "8E3404DD"
272	    "EF9519B3" "CD3A431B" "302B0A6D" "F25F1437" "4FE1356D" "6D51C245"
273	    "E485B576" "625E7EC6" "F44C42E9" "A637ED6B" "0BFF5CB6" "F406B7ED"
274	    "EE386BFB" "5A899FA5" "AE9F2411" "7C4B1FE6" "49286651" "ECE65381"
275	    "FFFFFFFF" "FFFFFFFF";
276	const char *g = "02";
277
278	/*
279	 * Try generated keys
280	 */
281
282	for (i = 0; i < 10; i++) {
283	    server = DH_new_method(engine);
284	    client = DH_new_method(engine);
285
286	    BN_hex2bn(&server->p, p);
287	    BN_hex2bn(&client->p, p);
288	    BN_hex2bn(&server->g, g);
289	    BN_hex2bn(&client->g, g);
290
291	    if (!DH_generate_key(server))
292		errx(1, "DH_generate_key failed for server");
293	    if (!DH_generate_key(client))
294		errx(1, "DH_generate_key failed for client");
295
296	    dh_test(server, client);
297
298	    DH_free(server);
299	    DH_free(client);
300	}
301	/*
302	 * Try known result
303	 */
304
305	for (i = 0; i < sizeof(dhtests)/sizeof(dhtests[0]); i++) {
306
307	    server = DH_new_method(engine);
308	    client = DH_new_method(engine);
309
310	    BN_hex2bn(&server->p, p);
311	    BN_hex2bn(&client->p, p);
312	    BN_hex2bn(&server->g, g);
313	    BN_hex2bn(&client->g, g);
314
315	    BN_hex2bn(&client->priv_key, dhtests[i].cpriv);
316	    BN_hex2bn(&client->pub_key, dhtests[i].cpub);
317	    BN_hex2bn(&server->priv_key, dhtests[i].spriv);
318	    BN_hex2bn(&server->pub_key, dhtests[i].spub);
319
320	    dh_test(server, client);
321
322	    DH_free(server);
323	    DH_free(client);
324	}
325
326	printf("DH test passed\n");
327    }
328
329    ENGINE_finish(engine);
330
331    return 0;
332}
333