enc.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634
  1. /* apps/enc.c */
  2. /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
  3. * All rights reserved.
  4. *
  5. * This package is an SSL implementation written
  6. * by Eric Young (eay@cryptsoft.com).
  7. * The implementation was written so as to conform with Netscapes SSL.
  8. *
  9. * This library is free for commercial and non-commercial use as long as
  10. * the following conditions are aheared to. The following conditions
  11. * apply to all code found in this distribution, be it the RC4, RSA,
  12. * lhash, DES, etc., code; not just the SSL code. The SSL documentation
  13. * included with this distribution is covered by the same copyright terms
  14. * except that the holder is Tim Hudson (tjh@cryptsoft.com).
  15. *
  16. * Copyright remains Eric Young's, and as such any Copyright notices in
  17. * the code are not to be removed.
  18. * If this package is used in a product, Eric Young should be given attribution
  19. * as the author of the parts of the library used.
  20. * This can be in the form of a textual message at program startup or
  21. * in documentation (online or textual) provided with the package.
  22. *
  23. * Redistribution and use in source and binary forms, with or without
  24. * modification, are permitted provided that the following conditions
  25. * are met:
  26. * 1. Redistributions of source code must retain the copyright
  27. * notice, this list of conditions and the following disclaimer.
  28. * 2. Redistributions in binary form must reproduce the above copyright
  29. * notice, this list of conditions and the following disclaimer in the
  30. * documentation and/or other materials provided with the distribution.
  31. * 3. All advertising materials mentioning features or use of this software
  32. * must display the following acknowledgement:
  33. * "This product includes cryptographic software written by
  34. * Eric Young (eay@cryptsoft.com)"
  35. * The word 'cryptographic' can be left out if the rouines from the library
  36. * being used are not cryptographic related :-).
  37. * 4. If you include any Windows specific code (or a derivative thereof) from
  38. * the apps directory (application code) you must include an acknowledgement:
  39. * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
  40. *
  41. * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
  42. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  43. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  44. * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  45. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  46. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  47. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  48. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  49. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  50. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  51. * SUCH DAMAGE.
  52. *
  53. * The licence and distribution terms for any publically available version or
  54. * derivative of this code cannot be changed. i.e. this code cannot simply be
  55. * copied and put under another distribution licence
  56. * [including the GNU Public Licence.]
  57. */
  58. #include <stdio.h>
  59. #include <stdlib.h>
  60. #include <string.h>
  61. #include "apps.h"
  62. #include <openssl/bio.h>
  63. #include <openssl/err.h>
  64. #include <openssl/evp.h>
  65. #include <openssl/objects.h>
  66. #include <openssl/x509.h>
  67. #include <openssl/rand.h>
  68. #ifndef OPENSSL_NO_MD5
  69. #include <openssl/md5.h>
  70. #endif
  71. #include <openssl/pem.h>
  72. #include <openssl/engine.h>
  73. #include <ctype.h>
  74. int set_hex(char *in,unsigned char *out,int size);
  75. #undef SIZE
  76. #undef BSIZE
  77. #undef PROG
  78. #define SIZE (512)
  79. #define BSIZE (8*1024)
  80. #define PROG enc_main
  81. void show_ciphers(const OBJ_NAME *name,void *bio_)
  82. {
  83. BIO *bio=bio_;
  84. static int n;
  85. if(!islower((unsigned char)*name->name))
  86. return;
  87. BIO_printf(bio,"-%-25s",name->name);
  88. if(++n == 3)
  89. {
  90. BIO_printf(bio,"\n");
  91. n=0;
  92. }
  93. else
  94. BIO_printf(bio," ");
  95. }
  96. int MAIN(int, char **);
  97. int MAIN(int argc, char **argv)
  98. {
  99. ENGINE *e = NULL;
  100. static const char magic[]="Salted__";
  101. char mbuf[8]; /* should be 1 smaller than magic */
  102. char *strbuf=NULL;
  103. unsigned char *buff=NULL,*bufsize=NULL;
  104. int bsize=BSIZE,verbose=0;
  105. int ret=1,inl;
  106. int nopad = 0;
  107. unsigned char key[EVP_MAX_KEY_LENGTH],iv[EVP_MAX_IV_LENGTH];
  108. unsigned char salt[PKCS5_SALT_LEN];
  109. char *str=NULL, *passarg = NULL, *pass = NULL;
  110. char *hkey=NULL,*hiv=NULL,*hsalt = NULL;
  111. int enc=1,printkey=0,i,base64=0;
  112. int debug=0,olb64=0,nosalt=0;
  113. const EVP_CIPHER *cipher=NULL,*c;
  114. char *inf=NULL,*outf=NULL;
  115. BIO *in=NULL,*out=NULL,*b64=NULL,*benc=NULL,*rbio=NULL,*wbio=NULL;
  116. #define PROG_NAME_SIZE 16
  117. char pname[PROG_NAME_SIZE];
  118. char *engine = NULL;
  119. apps_startup();
  120. if (bio_err == NULL)
  121. if ((bio_err=BIO_new(BIO_s_file())) != NULL)
  122. BIO_set_fp(bio_err,stderr,BIO_NOCLOSE|BIO_FP_TEXT);
  123. /* first check the program name */
  124. program_name(argv[0],pname,PROG_NAME_SIZE);
  125. if (strcmp(pname,"base64") == 0)
  126. base64=1;
  127. cipher=EVP_get_cipherbyname(pname);
  128. if (!base64 && (cipher == NULL) && (strcmp(pname,"enc") != 0))
  129. {
  130. BIO_printf(bio_err,"%s is an unknown cipher\n",pname);
  131. goto bad;
  132. }
  133. argc--;
  134. argv++;
  135. while (argc >= 1)
  136. {
  137. if (strcmp(*argv,"-e") == 0)
  138. enc=1;
  139. else if (strcmp(*argv,"-in") == 0)
  140. {
  141. if (--argc < 1) goto bad;
  142. inf= *(++argv);
  143. }
  144. else if (strcmp(*argv,"-out") == 0)
  145. {
  146. if (--argc < 1) goto bad;
  147. outf= *(++argv);
  148. }
  149. else if (strcmp(*argv,"-pass") == 0)
  150. {
  151. if (--argc < 1) goto bad;
  152. passarg= *(++argv);
  153. }
  154. else if (strcmp(*argv,"-engine") == 0)
  155. {
  156. if (--argc < 1) goto bad;
  157. engine= *(++argv);
  158. }
  159. else if (strcmp(*argv,"-d") == 0)
  160. enc=0;
  161. else if (strcmp(*argv,"-p") == 0)
  162. printkey=1;
  163. else if (strcmp(*argv,"-v") == 0)
  164. verbose=1;
  165. else if (strcmp(*argv,"-nopad") == 0)
  166. nopad=1;
  167. else if (strcmp(*argv,"-salt") == 0)
  168. nosalt=0;
  169. else if (strcmp(*argv,"-nosalt") == 0)
  170. nosalt=1;
  171. else if (strcmp(*argv,"-debug") == 0)
  172. debug=1;
  173. else if (strcmp(*argv,"-P") == 0)
  174. printkey=2;
  175. else if (strcmp(*argv,"-A") == 0)
  176. olb64=1;
  177. else if (strcmp(*argv,"-a") == 0)
  178. base64=1;
  179. else if (strcmp(*argv,"-base64") == 0)
  180. base64=1;
  181. else if (strcmp(*argv,"-bufsize") == 0)
  182. {
  183. if (--argc < 1) goto bad;
  184. bufsize=(unsigned char *)*(++argv);
  185. }
  186. else if (strcmp(*argv,"-k") == 0)
  187. {
  188. if (--argc < 1) goto bad;
  189. str= *(++argv);
  190. }
  191. else if (strcmp(*argv,"-kfile") == 0)
  192. {
  193. static char buf[128];
  194. FILE *infile;
  195. char *file;
  196. if (--argc < 1) goto bad;
  197. file= *(++argv);
  198. infile=fopen(file,"r");
  199. if (infile == NULL)
  200. {
  201. BIO_printf(bio_err,"unable to read key from '%s'\n",
  202. file);
  203. goto bad;
  204. }
  205. buf[0]='\0';
  206. fgets(buf,128,infile);
  207. fclose(infile);
  208. i=strlen(buf);
  209. if ((i > 0) &&
  210. ((buf[i-1] == '\n') || (buf[i-1] == '\r')))
  211. buf[--i]='\0';
  212. if ((i > 0) &&
  213. ((buf[i-1] == '\n') || (buf[i-1] == '\r')))
  214. buf[--i]='\0';
  215. if (i < 1)
  216. {
  217. BIO_printf(bio_err,"zero length password\n");
  218. goto bad;
  219. }
  220. str=buf;
  221. }
  222. else if (strcmp(*argv,"-K") == 0)
  223. {
  224. if (--argc < 1) goto bad;
  225. hkey= *(++argv);
  226. }
  227. else if (strcmp(*argv,"-S") == 0)
  228. {
  229. if (--argc < 1) goto bad;
  230. hsalt= *(++argv);
  231. }
  232. else if (strcmp(*argv,"-iv") == 0)
  233. {
  234. if (--argc < 1) goto bad;
  235. hiv= *(++argv);
  236. }
  237. else if ((argv[0][0] == '-') &&
  238. ((c=EVP_get_cipherbyname(&(argv[0][1]))) != NULL))
  239. {
  240. cipher=c;
  241. }
  242. else if (strcmp(*argv,"-none") == 0)
  243. cipher=NULL;
  244. else
  245. {
  246. BIO_printf(bio_err,"unknown option '%s'\n",*argv);
  247. bad:
  248. BIO_printf(bio_err,"options are\n");
  249. BIO_printf(bio_err,"%-14s input file\n","-in <file>");
  250. BIO_printf(bio_err,"%-14s output file\n","-out <file>");
  251. BIO_printf(bio_err,"%-14s pass phrase source\n","-pass <arg>");
  252. BIO_printf(bio_err,"%-14s encrypt\n","-e");
  253. BIO_printf(bio_err,"%-14s decrypt\n","-d");
  254. BIO_printf(bio_err,"%-14s base64 encode/decode, depending on encryption flag\n","-a/-base64");
  255. BIO_printf(bio_err,"%-14s key is the next argument\n","-k");
  256. BIO_printf(bio_err,"%-14s key is the first line of the file argument\n","-kfile");
  257. BIO_printf(bio_err,"%-14s key/iv in hex is the next argument\n","-K/-iv");
  258. BIO_printf(bio_err,"%-14s print the iv/key (then exit if -P)\n","-[pP]");
  259. BIO_printf(bio_err,"%-14s buffer size\n","-bufsize <n>");
  260. BIO_printf(bio_err,"%-14s use engine e, possibly a hardware device.\n","-engine e");
  261. BIO_printf(bio_err,"Cipher Types\n");
  262. OBJ_NAME_do_all_sorted(OBJ_NAME_TYPE_CIPHER_METH,
  263. show_ciphers,
  264. bio_err);
  265. BIO_printf(bio_err,"\n");
  266. goto end;
  267. }
  268. argc--;
  269. argv++;
  270. }
  271. if (engine != NULL)
  272. {
  273. if((e = ENGINE_by_id(engine)) == NULL)
  274. {
  275. BIO_printf(bio_err,"invalid engine \"%s\"\n",
  276. engine);
  277. goto end;
  278. }
  279. if(!ENGINE_set_default(e, ENGINE_METHOD_ALL))
  280. {
  281. BIO_printf(bio_err,"can't use that engine\n");
  282. goto end;
  283. }
  284. BIO_printf(bio_err,"engine \"%s\" set.\n", engine);
  285. /* Free our "structural" reference. */
  286. ENGINE_free(e);
  287. }
  288. if (bufsize != NULL)
  289. {
  290. unsigned long n;
  291. for (n=0; *bufsize; bufsize++)
  292. {
  293. i= *bufsize;
  294. if ((i <= '9') && (i >= '0'))
  295. n=n*10+i-'0';
  296. else if (i == 'k')
  297. {
  298. n*=1024;
  299. bufsize++;
  300. break;
  301. }
  302. }
  303. if (*bufsize != '\0')
  304. {
  305. BIO_printf(bio_err,"invalid 'bufsize' specified.\n");
  306. goto end;
  307. }
  308. /* It must be large enough for a base64 encoded line */
  309. if (n < 80) n=80;
  310. bsize=(int)n;
  311. if (verbose) BIO_printf(bio_err,"bufsize=%d\n",bsize);
  312. }
  313. strbuf=OPENSSL_malloc(SIZE);
  314. buff=(unsigned char *)OPENSSL_malloc(EVP_ENCODE_LENGTH(bsize));
  315. if ((buff == NULL) || (strbuf == NULL))
  316. {
  317. BIO_printf(bio_err,"OPENSSL_malloc failure %ld\n",(long)EVP_ENCODE_LENGTH(bsize));
  318. goto end;
  319. }
  320. in=BIO_new(BIO_s_file());
  321. out=BIO_new(BIO_s_file());
  322. if ((in == NULL) || (out == NULL))
  323. {
  324. ERR_print_errors(bio_err);
  325. goto end;
  326. }
  327. if (debug)
  328. {
  329. BIO_set_callback(in,BIO_debug_callback);
  330. BIO_set_callback(out,BIO_debug_callback);
  331. BIO_set_callback_arg(in,bio_err);
  332. BIO_set_callback_arg(out,bio_err);
  333. }
  334. if (inf == NULL)
  335. BIO_set_fp(in,stdin,BIO_NOCLOSE);
  336. else
  337. {
  338. if (BIO_read_filename(in,inf) <= 0)
  339. {
  340. perror(inf);
  341. goto end;
  342. }
  343. }
  344. if(!str && passarg) {
  345. if(!app_passwd(bio_err, passarg, NULL, &pass, NULL)) {
  346. BIO_printf(bio_err, "Error getting password\n");
  347. goto end;
  348. }
  349. str = pass;
  350. }
  351. if ((str == NULL) && (cipher != NULL) && (hkey == NULL))
  352. {
  353. for (;;)
  354. {
  355. char buf[200];
  356. sprintf(buf,"enter %s %s password:",
  357. OBJ_nid2ln(EVP_CIPHER_nid(cipher)),
  358. (enc)?"encryption":"decryption");
  359. strbuf[0]='\0';
  360. i=EVP_read_pw_string((char *)strbuf,SIZE,buf,enc);
  361. if (i == 0)
  362. {
  363. if (strbuf[0] == '\0')
  364. {
  365. ret=1;
  366. goto end;
  367. }
  368. str=strbuf;
  369. break;
  370. }
  371. if (i < 0)
  372. {
  373. BIO_printf(bio_err,"bad password read\n");
  374. goto end;
  375. }
  376. }
  377. }
  378. if (outf == NULL)
  379. {
  380. BIO_set_fp(out,stdout,BIO_NOCLOSE);
  381. #ifdef OPENSSL_SYS_VMS
  382. {
  383. BIO *tmpbio = BIO_new(BIO_f_linebuffer());
  384. out = BIO_push(tmpbio, out);
  385. }
  386. #endif
  387. }
  388. else
  389. {
  390. if (BIO_write_filename(out,outf) <= 0)
  391. {
  392. perror(outf);
  393. goto end;
  394. }
  395. }
  396. rbio=in;
  397. wbio=out;
  398. if (base64)
  399. {
  400. if ((b64=BIO_new(BIO_f_base64())) == NULL)
  401. goto end;
  402. if (debug)
  403. {
  404. BIO_set_callback(b64,BIO_debug_callback);
  405. BIO_set_callback_arg(b64,bio_err);
  406. }
  407. if (olb64)
  408. BIO_set_flags(b64,BIO_FLAGS_BASE64_NO_NL);
  409. if (enc)
  410. wbio=BIO_push(b64,wbio);
  411. else
  412. rbio=BIO_push(b64,rbio);
  413. }
  414. if (cipher != NULL)
  415. {
  416. /* Note that str is NULL if a key was passed on the command
  417. * line, so we get no salt in that case. Is this a bug?
  418. */
  419. if (str != NULL)
  420. {
  421. /* Salt handling: if encrypting generate a salt and
  422. * write to output BIO. If decrypting read salt from
  423. * input BIO.
  424. */
  425. unsigned char *sptr;
  426. if(nosalt) sptr = NULL;
  427. else {
  428. if(enc) {
  429. if(hsalt) {
  430. if(!set_hex(hsalt,salt,PKCS5_SALT_LEN)) {
  431. BIO_printf(bio_err,
  432. "invalid hex salt value\n");
  433. goto end;
  434. }
  435. } else if (RAND_pseudo_bytes(salt, PKCS5_SALT_LEN) < 0)
  436. goto end;
  437. /* If -P option then don't bother writing */
  438. if((printkey != 2)
  439. && (BIO_write(wbio,magic,
  440. sizeof magic-1) != sizeof magic-1
  441. || BIO_write(wbio,
  442. (char *)salt,
  443. PKCS5_SALT_LEN) != PKCS5_SALT_LEN)) {
  444. BIO_printf(bio_err,"error writing output file\n");
  445. goto end;
  446. }
  447. } else if(BIO_read(rbio,mbuf,sizeof mbuf) != sizeof mbuf
  448. || BIO_read(rbio,
  449. (unsigned char *)salt,
  450. PKCS5_SALT_LEN) != PKCS5_SALT_LEN) {
  451. BIO_printf(bio_err,"error reading input file\n");
  452. goto end;
  453. } else if(memcmp(mbuf,magic,sizeof magic-1)) {
  454. BIO_printf(bio_err,"bad magic number\n");
  455. goto end;
  456. }
  457. sptr = salt;
  458. }
  459. EVP_BytesToKey(cipher,EVP_md5(),sptr,
  460. (unsigned char *)str,
  461. strlen(str),1,key,iv);
  462. /* zero the complete buffer or the string
  463. * passed from the command line
  464. * bug picked up by
  465. * Larry J. Hughes Jr. <hughes@indiana.edu> */
  466. if (str == strbuf)
  467. memset(str,0,SIZE);
  468. else
  469. memset(str,0,strlen(str));
  470. }
  471. if ((hiv != NULL) && !set_hex(hiv,iv,sizeof iv))
  472. {
  473. BIO_printf(bio_err,"invalid hex iv value\n");
  474. goto end;
  475. }
  476. if ((hkey != NULL) && !set_hex(hkey,key,sizeof key))
  477. {
  478. BIO_printf(bio_err,"invalid hex key value\n");
  479. goto end;
  480. }
  481. if ((benc=BIO_new(BIO_f_cipher())) == NULL)
  482. goto end;
  483. BIO_set_cipher(benc,cipher,key,iv,enc);
  484. if (nopad)
  485. {
  486. EVP_CIPHER_CTX *ctx;
  487. BIO_get_cipher_ctx(benc, &ctx);
  488. EVP_CIPHER_CTX_set_padding(ctx, 0);
  489. }
  490. if (debug)
  491. {
  492. BIO_set_callback(benc,BIO_debug_callback);
  493. BIO_set_callback_arg(benc,bio_err);
  494. }
  495. if (printkey)
  496. {
  497. if (!nosalt)
  498. {
  499. printf("salt=");
  500. for (i=0; i<PKCS5_SALT_LEN; i++)
  501. printf("%02X",salt[i]);
  502. printf("\n");
  503. }
  504. if (cipher->key_len > 0)
  505. {
  506. printf("key=");
  507. for (i=0; i<cipher->key_len; i++)
  508. printf("%02X",key[i]);
  509. printf("\n");
  510. }
  511. if (cipher->iv_len > 0)
  512. {
  513. printf("iv =");
  514. for (i=0; i<cipher->iv_len; i++)
  515. printf("%02X",iv[i]);
  516. printf("\n");
  517. }
  518. if (printkey == 2)
  519. {
  520. ret=0;
  521. goto end;
  522. }
  523. }
  524. }
  525. /* Only encrypt/decrypt as we write the file */
  526. if (benc != NULL)
  527. wbio=BIO_push(benc,wbio);
  528. for (;;)
  529. {
  530. inl=BIO_read(rbio,(char *)buff,bsize);
  531. if (inl <= 0) break;
  532. if (BIO_write(wbio,(char *)buff,inl) != inl)
  533. {
  534. BIO_printf(bio_err,"error writing output file\n");
  535. goto end;
  536. }
  537. }
  538. if (!BIO_flush(wbio))
  539. {
  540. BIO_printf(bio_err,"bad decrypt\n");
  541. goto end;
  542. }
  543. ret=0;
  544. if (verbose)
  545. {
  546. BIO_printf(bio_err,"bytes read :%8ld\n",BIO_number_read(in));
  547. BIO_printf(bio_err,"bytes written:%8ld\n",BIO_number_written(out));
  548. }
  549. end:
  550. ERR_print_errors(bio_err);
  551. if (strbuf != NULL) OPENSSL_free(strbuf);
  552. if (buff != NULL) OPENSSL_free(buff);
  553. if (in != NULL) BIO_free(in);
  554. if (out != NULL) BIO_free_all(out);
  555. if (benc != NULL) BIO_free(benc);
  556. if (b64 != NULL) BIO_free(b64);
  557. if(pass) OPENSSL_free(pass);
  558. EXIT(ret);
  559. }
  560. int set_hex(char *in, unsigned char *out, int size)
  561. {
  562. int i,n;
  563. unsigned char j;
  564. n=strlen(in);
  565. if (n > (size*2))
  566. {
  567. BIO_printf(bio_err,"hex string is too long\n");
  568. return(0);
  569. }
  570. memset(out,0,size);
  571. for (i=0; i<n; i++)
  572. {
  573. j=(unsigned char)*in;
  574. *(in++)='\0';
  575. if (j == 0) break;
  576. if ((j >= '0') && (j <= '9'))
  577. j-='0';
  578. else if ((j >= 'A') && (j <= 'F'))
  579. j=j-'A'+10;
  580. else if ((j >= 'a') && (j <= 'f'))
  581. j=j-'a'+10;
  582. else
  583. {
  584. BIO_printf(bio_err,"non-hex digit\n");
  585. return(0);
  586. }
  587. if (i&1)
  588. out[i/2]|=j;
  589. else
  590. out[i/2]=(j<<4);
  591. }
  592. return(1);
  593. }