xref: /rk3399_rockchip-uboot/cmd/crypto.c (revision 65ac8e46b20981899f99004644294a40485a7ee3)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (c) 2019 Fuzhou Rockchip Electronics Co., Ltd
4  */
5 
6 #include <common.h>
7 #include <command.h>
8 #include <crypto.h>
9 #include <dm.h>
10 #include <u-boot/md5.h>
11 #include <u-boot/sha1.h>
12 #include <u-boot/sha256.h>
13 #include <u-boot/sha512.h>
14 #include <rockchip/crypto_fix_test_data.h>
15 
16 #define PERF_TOTAL_SIZE			(128 * 1024 * 1024)
17 #define PERF_BUFF_SIZE			(4 * 1024 * 1024)
18 
19 #define CALC_RATE_MPBS(bytes, ms)	(((bytes) / 1024) / (ms))
20 
21 struct hash_test_data {
22 	const char	*algo_name;
23 	const char	*mode_name;
24 	u32		algo;
25 	const u8	*data;
26 	u32		data_len;
27 	const u8	*hash;
28 	u32		hash_len;
29 	const u8	*key;
30 	u32		key_len;
31 };
32 
33 struct cipher_test_data {
34 	const char	*algo_name;
35 	const char	*mode_name;
36 	u32		algo;
37 	u32		mode;
38 	const u8	*key;
39 	const u8	*twk_key;
40 	u32		key_len;
41 	const u8	*iv;
42 	u32		iv_len;
43 	const u8	*plain;
44 	u32		plain_len;
45 	const u8	*cipher;
46 	u32		cipher_len;
47 };
48 
49 struct rsa_test_data {
50 	const char	*algo_name;
51 	const char	*mode_name;
52 	u32		algo;
53 	const u8	*n;
54 	u32		n_len;
55 	const u8	*e;
56 	u32		e_len;
57 	const u8	*d;
58 	u32		d_len;
59 	const u8	*c;
60 	u32		c_len;
61 	const u8	*sign_in;
62 	u32		sign_in_len;
63 	const u8	*sign_out;
64 	u32		sign_out_len;
65 };
66 
67 #define IS_MAC_MODE(mode)	((mode) == RK_MODE_CBC_MAC || \
68 				 (mode) == RK_MODE_CMAC)
69 
70 #define HASH_TEST(algo_type, data_in, hash_val) {\
71 	.algo_name = "HASH", \
72 	.mode_name = #algo_type, \
73 	.algo      = CRYPTO_##algo_type, \
74 	.data      = (data_in),\
75 	.data_len  = sizeof(data_in), \
76 	.hash      = (hash_val), \
77 	.hash_len  = sizeof(hash_val) \
78 }
79 
80 #define HMAC_TEST(algo_type, data_in, hash_val, hmac_key) {\
81 	.algo_name = "HMAC", \
82 	.mode_name = #algo_type, \
83 	.algo      = CRYPTO_HMAC_##algo_type, \
84 	.data      = (data_in),\
85 	.data_len  = sizeof(data_in), \
86 	.hash      = (hash_val), \
87 	.hash_len  = sizeof(hash_val), \
88 	.key       = (hmac_key), \
89 	.key_len   = sizeof(hmac_key)\
90 }
91 
92 #define CIPHER_XTS_TEST(algo_type, mode_type, key1, key2, iv_val, in, out) { \
93 	.algo_name  = #algo_type, \
94 	.mode_name  = #mode_type, \
95 	.algo       = CRYPTO_##algo_type,\
96 	.mode       = RK_MODE_##mode_type, \
97 	.key        = (key1), \
98 	.twk_key    = (key2), \
99 	.key_len    = sizeof(key1), \
100 	.iv         = (iv_val), \
101 	.iv_len     = sizeof(iv_val), \
102 	.plain      = (in), \
103 	.plain_len  = sizeof(in), \
104 	.cipher     = (out), \
105 	.cipher_len = sizeof(out) \
106 }
107 
108 #define CIPHER_TEST(algo, mode, key, iv, plain, cipher) \
109 		CIPHER_XTS_TEST(algo, mode, key, NULL, iv, plain, cipher)
110 
111 #define RSA_TEST(nbits, bn, be, bc, bd, in, out) { \
112 	.algo_name    = "RSA", \
113 	.mode_name    = #nbits, \
114 	.algo         = CRYPTO_RSA##nbits, \
115 	.n            = (bn), \
116 	.n_len        = sizeof(bn), \
117 	.e            = (be), \
118 	.e_len        = sizeof(be), \
119 	.d            = (bd), \
120 	.d_len        = sizeof(bd), \
121 	.c            = (bc), \
122 	.c_len        = sizeof(bc), \
123 	.sign_in      = (in), \
124 	.sign_in_len  = sizeof(in), \
125 	.sign_out     = (out), \
126 	.sign_out_len = sizeof(out) \
127 }
128 
129 #define EMPTY_TEST() {}
130 
131 const struct hash_test_data hash_data_set[] = {
132 	HASH_TEST(MD5,    foo_data, hash_md5),
133 	HASH_TEST(SHA1,   foo_data, hash_sha1),
134 	HASH_TEST(SHA256, foo_data, hash_sha256),
135 	HASH_TEST(SHA512, foo_data, hash_sha512),
136 	HASH_TEST(SM3,    foo_data, hash_sm3),
137 
138 #if CONFIG_IS_ENABLED(ROCKCHIP_HMAC)
139 	EMPTY_TEST(),
140 	HMAC_TEST(MD5,    foo_data, hmac_md5,    hmac_key),
141 	HMAC_TEST(SHA1,   foo_data, hmac_sha1,   hmac_key),
142 	HMAC_TEST(SHA256, foo_data, hmac_sha256, hmac_key),
143 	HMAC_TEST(SHA512, foo_data, hmac_sha512, hmac_key),
144 	HMAC_TEST(SM3,    foo_data, hmac_sm3,    hmac_key),
145 #endif
146 };
147 
148 const struct cipher_test_data cipher_data_set[] = {
149 #if CONFIG_IS_ENABLED(ROCKCHIP_CIPHER)
150 	CIPHER_TEST(DES, ECB, des_key, des_iv, foo_data, des_ecb_cipher),
151 	CIPHER_TEST(DES, CBC, des_key, des_iv, foo_data, des_cbc_cipher),
152 	CIPHER_TEST(DES, CFB, des_key, des_iv, foo_data, des_cfb_cipher),
153 	CIPHER_TEST(DES, OFB, des_key, des_iv, foo_data, des_ofb_cipher),
154 
155 	EMPTY_TEST(),
156 	CIPHER_TEST(DES, ECB, tdes_key, tdes_iv, foo_data, tdes_ecb_cipher),
157 	CIPHER_TEST(DES, CBC, tdes_key, tdes_iv, foo_data, tdes_cbc_cipher),
158 	CIPHER_TEST(DES, CFB, tdes_key, tdes_iv, foo_data, tdes_cfb_cipher),
159 	CIPHER_TEST(DES, OFB, tdes_key, tdes_iv, foo_data, tdes_ofb_cipher),
160 
161 	EMPTY_TEST(),
162 	CIPHER_TEST(AES, ECB, aes_key, aes_iv, foo_data, aes_ecb_cipher),
163 	CIPHER_TEST(AES, CBC, aes_key, aes_iv, foo_data, aes_cbc_cipher),
164 	CIPHER_TEST(AES, CFB, aes_key, aes_iv, foo_data, aes_cfb_cipher),
165 	CIPHER_TEST(AES, OFB, aes_key, aes_iv, foo_data, aes_ofb_cipher),
166 	CIPHER_TEST(AES, CTS, aes_key, aes_iv, foo_data, aes_cts_cipher),
167 	CIPHER_TEST(AES, CTR, aes_key, aes_iv, foo_data, aes_ctr_cipher),
168 	CIPHER_XTS_TEST(AES, XTS, aes_key, aes_twk_key,
169 			aes_iv, foo_data, aes_xts_cipher),
170 	CIPHER_TEST(AES, CBC_MAC, aes_key, aes_iv, foo_data, aes_cbc_mac),
171 	CIPHER_TEST(AES, CMAC, aes_key, aes_iv, foo_data, aes_cmac),
172 
173 	EMPTY_TEST(),
174 	CIPHER_TEST(SM4, ECB, sm4_key, sm4_iv, foo_data, sm4_ecb_cipher),
175 	CIPHER_TEST(SM4, CBC, sm4_key, sm4_iv, foo_data, sm4_cbc_cipher),
176 	CIPHER_TEST(SM4, CFB, sm4_key, sm4_iv, foo_data, sm4_cfb_cipher),
177 	CIPHER_TEST(SM4, OFB, sm4_key, sm4_iv, foo_data, sm4_ofb_cipher),
178 	CIPHER_TEST(SM4, CTS, sm4_key, sm4_iv, foo_data, sm4_cts_cipher),
179 	CIPHER_TEST(SM4, CTR, sm4_key, sm4_iv, foo_data, sm4_ctr_cipher),
180 	CIPHER_XTS_TEST(SM4, XTS, sm4_key, sm4_twk_key,
181 			sm4_iv, foo_data, sm4_xts_cipher),
182 	CIPHER_TEST(SM4, CBC_MAC, sm4_key, sm4_iv, foo_data, sm4_cbc_mac),
183 	CIPHER_TEST(SM4, CMAC, sm4_key, sm4_iv, foo_data, sm4_cmac),
184 #else
185 	EMPTY_TEST(),
186 #endif
187 };
188 
189 const struct rsa_test_data rsa_data_set[] = {
190 #if CONFIG_IS_ENABLED(ROCKCHIP_RSA)
191 
192 #ifdef CONFIG_ROCKCHIP_CRYPTO_V1
193 	RSA_TEST(2048, rsa2048_n, rsa2048_e, rsa2048_c, rsa2048_d,
194 		 rsa2048_sign_in, rsa2048_sign_out),
195 #else
196 	RSA_TEST(4096, rsa4096_n, rsa4096_e, NULL, rsa4096_d,
197 		 rsa4096_sign_in, rsa4096_sign_out),
198 #endif
199 
200 #else
201 	EMPTY_TEST(),
202 #endif
203 };
204 
205 static void dump_hex(const char *name, const u8 *array, u32 len)
206 {
207 	int i;
208 
209 	printf("[%s]: %uByte", name, len);
210 	for (i = 0; i < len; i++) {
211 		if (i % 32 == 0)
212 			printf("\n");
213 		printf("%02x ", array[i]);
214 	}
215 	printf("\n");
216 }
217 
218 static inline void print_result_MBps(const char *algo_name,
219 				     const char *mode_name,
220 				     const char *crypt, ulong MBps,
221 				     const u8 *expect, const u8 *actual,
222 				     u32 len)
223 {
224 	if (memcmp(expect, actual, len) == 0) {
225 		printf("[%s] %-8s%-8s PASS    (%luMBps)\n",
226 		       algo_name, mode_name, crypt, MBps);
227 	} else {
228 		printf("[%s] %-8s%-8s FAIL\n",
229 		       algo_name, mode_name, crypt);
230 		dump_hex("expect", expect, len);
231 		dump_hex("actual", actual, len);
232 	}
233 }
234 
235 static inline void print_result_ms(const char *algo_name, const char *mode_name,
236 				   const char *crypt, ulong time_cost,
237 				   const u8 *expect, const u8 *actual, u32 len)
238 {
239 	if (memcmp(expect, actual, len) == 0) {
240 		printf("[%s] %-8s%-8s PASS    (%lums)\n",
241 		       algo_name, mode_name, crypt, time_cost);
242 	} else {
243 		printf("[%s] %-8s%-8s FAIL\n",
244 		       algo_name, mode_name, crypt);
245 		dump_hex("expect", expect, len);
246 		dump_hex("actual", actual, len);
247 	}
248 }
249 
250 int test_hash_perf(struct udevice *dev, u32 algo,
251 		   const u8 *key, u32 key_len, ulong *MBps)
252 {
253 	u32 total_size = PERF_TOTAL_SIZE;
254 	u32 data_size = PERF_BUFF_SIZE;
255 	sha_context ctx;
256 	u8 *data = NULL;
257 	u8 hash_out[64];
258 	int ret, i;
259 
260 	*MBps = 0;
261 
262 	ctx.algo = algo;
263 	ctx.length = total_size;
264 
265 	data = (u8 *)memalign(CONFIG_SYS_CACHELINE_SIZE, data_size);
266 	if (!data) {
267 		printf("%s, %d: memalign %u error!\n",
268 		       __func__, __LINE__, data_size);
269 		return -EINVAL;
270 	}
271 
272 	memset(data, 0xab, data_size);
273 
274 	ulong start = get_timer(0);
275 
276 	if (key)
277 		ret = crypto_hmac_init(dev, &ctx, (u8 *)key, key_len);
278 	else
279 		ret = crypto_sha_init(dev, &ctx);
280 
281 	if (ret) {
282 		printf("crypto_sha_init error ret = %d!\n", ret);
283 		goto exit;
284 	}
285 
286 	for (i = 0; i < total_size / data_size; i++) {
287 		ret = crypto_sha_update(dev, (u32 *)data, data_size);
288 		if (ret) {
289 			printf("crypto_sha_update error!\n");
290 			goto exit;
291 		}
292 	}
293 
294 	ret = crypto_sha_final(dev, &ctx, hash_out);
295 	if (ret) {
296 		printf("crypto_sha_final error ret = %d!\n", ret);
297 		goto exit;
298 	}
299 
300 	ulong time_cost = get_timer(start);
301 
302 	*MBps = CALC_RATE_MPBS(total_size, time_cost);
303 
304 exit:
305 	free(data);
306 
307 	return ret;
308 }
309 
310 int test_cipher_perf(struct udevice *dev, cipher_context *ctx,
311 		     ulong *MBps, bool enc)
312 {
313 	u32 total_size = PERF_TOTAL_SIZE;
314 	u32 data_size = PERF_BUFF_SIZE;
315 	u8 *plain = NULL, *cipher = NULL;
316 	int ret = 0, i;
317 
318 	*MBps = 0;
319 
320 	plain = (u8 *)memalign(CONFIG_SYS_CACHELINE_SIZE, data_size);
321 	if (!plain) {
322 		printf("%s, %d: memalign %u error!\n",
323 		       __func__, __LINE__, data_size);
324 		return -EINVAL;
325 	}
326 
327 	cipher = (u8 *)memalign(CONFIG_SYS_CACHELINE_SIZE, data_size);
328 	if (!cipher) {
329 		printf("%s, %d: memalign %u error!\n",
330 		       __func__, __LINE__, data_size);
331 		free(plain);
332 		return -EINVAL;
333 	}
334 
335 	memset(plain, 0xab, data_size);
336 
337 	ulong start = get_timer(0);
338 
339 	for (i = 0; i < total_size / data_size; i++) {
340 		if (IS_MAC_MODE(ctx->mode))
341 			ret = crypto_mac(dev, ctx, plain, data_size, cipher);
342 		else
343 			ret = crypto_cipher(dev, ctx, plain, cipher,
344 					    data_size, enc);
345 		if (ret) {
346 			printf("%s, %d:crypto_aes error! ret = %d\n",
347 			       __func__, __LINE__, ret);
348 			goto exit;
349 		}
350 	}
351 
352 	ulong time_cost = get_timer(start);
353 
354 	*MBps = CALC_RATE_MPBS(total_size, time_cost);
355 exit:
356 	free(plain);
357 	free(cipher);
358 
359 	return ret;
360 }
361 
362 int test_hash_result(void)
363 {
364 	const struct hash_test_data *test_data = NULL;
365 	sha_context csha_ctx;
366 	struct udevice *dev;
367 	unsigned int i;
368 	u8 out[64];
369 	int ret;
370 
371 	printf("\n=================== hash & hmac test ===================\n");
372 
373 	for (i = 0; i < ARRAY_SIZE(hash_data_set); i++) {
374 		test_data = &hash_data_set[i];
375 		if (test_data->algo == 0) {
376 			printf("\n");
377 			continue;
378 		}
379 
380 		dev = crypto_get_device(test_data->algo);
381 		if (!dev) {
382 			printf("[%s] %-16s unsupported!!!\n",
383 			       test_data->algo_name,
384 			       test_data->mode_name);
385 			continue;
386 		}
387 
388 		csha_ctx.algo   = test_data->algo;
389 		csha_ctx.length = test_data->data_len;
390 
391 		memset(out, 0x00, sizeof(out));
392 		if (test_data->key) {
393 			ret = crypto_hmac_init(dev, &csha_ctx,
394 					       (u8 *)test_data->key,
395 					       test_data->key_len);
396 			ret |= crypto_hmac_update(dev, (void *)test_data->data,
397 						  test_data->data_len);
398 			ret |= crypto_hmac_final(dev, &csha_ctx, out);
399 			if (ret) {
400 				printf("hmac calc error ret = %d\n", ret);
401 				goto error;
402 			}
403 		} else {
404 			ret = crypto_sha_init(dev, &csha_ctx);
405 			ret |= crypto_sha_update(dev, (void *)test_data->data,
406 						 test_data->data_len);
407 			ret |= crypto_sha_final(dev, &csha_ctx, out);
408 			if (ret) {
409 				printf("hash calc error ret = %d\n", ret);
410 				goto error;
411 			}
412 		}
413 
414 		ulong MBps = 0;
415 
416 		test_hash_perf(dev, test_data->algo,
417 			       test_data->key, test_data->key_len, &MBps);
418 		print_result_MBps(test_data->algo_name, test_data->mode_name,
419 				  "", MBps, test_data->hash, out,
420 				  test_data->hash_len);
421 		printf("+++++++++++++++++++++++++++++++++++++++++++++++++++\n");
422 	}
423 
424 	return 0;
425 error:
426 	printf("%s %s test error!\n",
427 	       test_data->algo_name, test_data->mode_name);
428 	return ret;
429 }
430 
431 int test_cipher_result(void)
432 {
433 	const struct cipher_test_data *test_data = NULL;
434 	struct udevice *dev;
435 	cipher_context ctx;
436 	u8 out[256];
437 	int ret;
438 	u32 i;
439 
440 	printf("\n===================== cipher test ======================\n");
441 
442 	for (i = 0; i < ARRAY_SIZE(cipher_data_set); i++) {
443 		test_data = &cipher_data_set[i];
444 		if (test_data->algo == 0) {
445 			printf("\n");
446 			continue;
447 		}
448 
449 		dev = crypto_get_device(test_data->algo);
450 		if (!dev) {
451 			printf("[%s] %-16s unsupported!!!\n",
452 			       test_data->algo_name, test_data->mode_name);
453 			continue;
454 		}
455 
456 		memset(&ctx, 0x00, sizeof(ctx));
457 
458 		ctx.algo    = test_data->algo;
459 		ctx.mode    = test_data->mode;
460 		ctx.key     = test_data->key;
461 		ctx.twk_key = test_data->twk_key;
462 		ctx.key_len = test_data->key_len;
463 		ctx.iv      = test_data->iv;
464 		ctx.iv_len  = test_data->iv_len;
465 
466 		ulong MBps = 0;
467 
468 		test_cipher_perf(dev, &ctx, &MBps, true);
469 
470 		/* AES/SM4 mac */
471 		if (IS_MAC_MODE(ctx.mode))
472 			ret = crypto_mac(dev, &ctx, test_data->plain,
473 					 test_data->plain_len, out);
474 		else
475 			ret = crypto_cipher(dev, &ctx, test_data->plain,
476 					    out, test_data->plain_len, true);
477 		if (ret)
478 			goto error;
479 
480 		print_result_MBps(test_data->algo_name, test_data->mode_name,
481 				  "encrypt", MBps, test_data->cipher, out,
482 				  test_data->cipher_len);
483 
484 		if (!IS_MAC_MODE(ctx.mode)) {
485 			test_cipher_perf(dev, &ctx, &MBps, false);
486 			ret = crypto_cipher(dev, &ctx, test_data->cipher,
487 					    out, test_data->cipher_len, false);
488 			if (ret)
489 				goto error;
490 
491 			print_result_MBps(test_data->algo_name,
492 					  test_data->mode_name,
493 					  "decrypt", MBps,
494 					  test_data->plain, out,
495 					  test_data->plain_len);
496 		}
497 		printf("+++++++++++++++++++++++++++++++++++++++++++++++++++\n");
498 	}
499 	return 0;
500 error:
501 	printf("%s %s test error, ret = %d!\n",
502 	       test_data->algo_name, test_data->mode_name, ret);
503 	return ret;
504 }
505 
506 int test_rsa_result(void)
507 {
508 	const struct rsa_test_data *test_data = NULL;
509 	u8 *hard_out = NULL, *e_tmp;
510 	u32 data_size = 4096 / 8;
511 	ulong start, time_cost;
512 	struct udevice *dev;
513 	rsa_key rsa_key;
514 	int ret, i;
515 
516 	hard_out = (u8 *)memalign(CONFIG_SYS_CACHELINE_SIZE, data_size);
517 	if (!hard_out) {
518 		printf("%s, %d: memalign %u error!\n",
519 		       __func__, __LINE__, data_size);
520 		return -EINVAL;
521 	}
522 
523 	e_tmp = (u8 *)memalign(CONFIG_SYS_CACHELINE_SIZE, data_size);
524 	if (!e_tmp) {
525 		printf("%s, %d: memalign %u error!\n",
526 		       __func__, __LINE__, data_size);
527 		return -EINVAL;
528 	}
529 
530 	printf("\n====================== rsa test ========================\n");
531 	for (i = 0; i < ARRAY_SIZE(rsa_data_set); i++) {
532 		test_data = &rsa_data_set[i];
533 		if (test_data->algo == 0) {
534 			printf("\n");
535 			continue;
536 		}
537 
538 		dev = crypto_get_device(test_data->algo);
539 		if (!dev) {
540 			printf("[%s] %-16s unsupported!!!\n",
541 			       test_data->algo_name, test_data->mode_name);
542 			continue;
543 		}
544 
545 		/* sign test */
546 		memset(&rsa_key, 0x00, sizeof(rsa_key));
547 		rsa_key.algo = test_data->algo;
548 		rsa_key.n = (u32 *)test_data->n;
549 		rsa_key.e = (u32 *)test_data->d;
550 #ifdef CONFIG_ROCKCHIP_CRYPTO_V1
551 		rsa_key.c = (u32 *)test_data->c;
552 #endif
553 
554 		start = get_timer(0);
555 		ret = crypto_rsa_verify(dev, &rsa_key,
556 					(u8 *)test_data->sign_in, hard_out);
557 		if (ret) {
558 			printf("sign test error, ret = %d\n", ret);
559 			goto error;
560 		}
561 		time_cost = get_timer(start);
562 		print_result_ms(test_data->algo_name, test_data->mode_name,
563 				"sign", time_cost, test_data->sign_out,
564 				hard_out, test_data->n_len);
565 
566 		/* verify test */
567 		memset(&rsa_key, 0x00, sizeof(rsa_key));
568 		memset(e_tmp, 0x00, data_size);
569 		memcpy(e_tmp, test_data->e, test_data->e_len);
570 		rsa_key.algo = test_data->algo;
571 		rsa_key.n = (u32 *)test_data->n;
572 		rsa_key.e = (u32 *)e_tmp;
573 #ifdef CONFIG_ROCKCHIP_CRYPTO_V1
574 		rsa_key.c = (u32 *)test_data->c;
575 #endif
576 
577 		start = get_timer(0);
578 		ret = crypto_rsa_verify(dev, &rsa_key,
579 					(u8 *)test_data->sign_out, hard_out);
580 		if (ret) {
581 			printf("verify test error, ret = %d\n", ret);
582 			goto error;
583 		}
584 		time_cost = get_timer(start);
585 
586 		print_result_ms(test_data->algo_name, test_data->mode_name,
587 				"verify", time_cost, test_data->sign_in,
588 				hard_out, test_data->n_len);
589 
590 		printf("+++++++++++++++++++++++++++++++++++++++++++++++++++\n");
591 	}
592 
593 	free(hard_out);
594 	free(e_tmp);
595 
596 	return 0;
597 error:
598 	free(hard_out);
599 	free(e_tmp);
600 	printf("%s %s test error!\n",
601 	       test_data->algo_name, test_data->mode_name);
602 	return ret;
603 }
604 
605 static int test_all_result(void)
606 {
607 	int ret = 0;
608 
609 	ret = test_hash_result();
610 	if (ret)
611 		goto exit;
612 
613 	ret = test_cipher_result();
614 	if (ret)
615 		goto exit;
616 
617 	ret = test_rsa_result();
618 	if (ret)
619 		goto exit;
620 
621 exit:
622 	return 0;
623 }
624 
625 static int do_crypto(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
626 {
627 	return test_all_result();
628 }
629 
630 U_BOOT_CMD(
631 	crypto, 1, 1, do_crypto,
632 	"crypto test",
633 	""
634 );
635