Use approved API for EVP digest operations in FIPS builds.
[openssl.git] / crypto / evp / evp_enc.c
1 /* crypto/evp/evp_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
59 #include <stdio.h>
60 #include "cryptlib.h"
61 #include <openssl/evp.h>
62 #include <openssl/err.h>
63 #include <openssl/rand.h>
64 #ifndef OPENSSL_NO_ENGINE
65 #include <openssl/engine.h>
66 #endif
67 #ifdef OPENSSL_FIPS
68 #include <openssl/fips.h>
69 #endif
70 #include "evp_locl.h"
71
72 const char EVP_version[]="EVP" OPENSSL_VERSION_PTEXT;
73
74 void EVP_CIPHER_CTX_init(EVP_CIPHER_CTX *ctx)
75         {
76         memset(ctx,0,sizeof(EVP_CIPHER_CTX));
77         /* ctx->cipher=NULL; */
78         }
79
80 EVP_CIPHER_CTX *EVP_CIPHER_CTX_new(void)
81         {
82         EVP_CIPHER_CTX *ctx=OPENSSL_malloc(sizeof *ctx);
83         if (ctx)
84                 EVP_CIPHER_CTX_init(ctx);
85         return ctx;
86         }
87
88 int EVP_CipherInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
89              const unsigned char *key, const unsigned char *iv, int enc)
90         {
91         if (cipher)
92                 EVP_CIPHER_CTX_init(ctx);
93         return EVP_CipherInit_ex(ctx,cipher,NULL,key,iv,enc);
94         }
95
96 int EVP_CipherInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher, ENGINE *impl,
97              const unsigned char *key, const unsigned char *iv, int enc)
98         {
99         if (enc == -1)
100                 enc = ctx->encrypt;
101         else
102                 {
103                 if (enc)
104                         enc = 1;
105                 ctx->encrypt = enc;
106                 }
107 #ifndef OPENSSL_NO_ENGINE
108         /* Whether it's nice or not, "Inits" can be used on "Final"'d contexts
109          * so this context may already have an ENGINE! Try to avoid releasing
110          * the previous handle, re-querying for an ENGINE, and having a
111          * reinitialisation, when it may all be unecessary. */
112         if (ctx->engine && ctx->cipher && (!cipher ||
113                         (cipher && (cipher->nid == ctx->cipher->nid))))
114                 goto skip_to_init;
115 #endif
116         if (cipher)
117                 {
118                 /* Ensure a context left lying around from last time is cleared
119                  * (the previous check attempted to avoid this if the same
120                  * ENGINE and EVP_CIPHER could be used). */
121                 EVP_CIPHER_CTX_cleanup(ctx);
122
123                 /* Restore encrypt field: it is zeroed by cleanup */
124                 ctx->encrypt = enc;
125 #ifndef OPENSSL_NO_ENGINE
126                 if(impl)
127                         {
128                         if (!ENGINE_init(impl))
129                                 {
130                                 EVPerr(EVP_F_EVP_CIPHERINIT_EX, EVP_R_INITIALIZATION_ERROR);
131                                 return 0;
132                                 }
133                         }
134                 else
135                         /* Ask if an ENGINE is reserved for this job */
136                         impl = ENGINE_get_cipher_engine(cipher->nid);
137                 if(impl)
138                         {
139                         /* There's an ENGINE for this job ... (apparently) */
140                         const EVP_CIPHER *c = ENGINE_get_cipher(impl, cipher->nid);
141                         if(!c)
142                                 {
143                                 /* One positive side-effect of US's export
144                                  * control history, is that we should at least
145                                  * be able to avoid using US mispellings of
146                                  * "initialisation"? */
147                                 EVPerr(EVP_F_EVP_CIPHERINIT_EX, EVP_R_INITIALIZATION_ERROR);
148                                 return 0;
149                                 }
150                         /* We'll use the ENGINE's private cipher definition */
151                         cipher = c;
152                         /* Store the ENGINE functional reference so we know
153                          * 'cipher' came from an ENGINE and we need to release
154                          * it when done. */
155                         ctx->engine = impl;
156                         }
157                 else
158                         ctx->engine = NULL;
159 #endif
160
161 #ifdef OPENSSL_FIPS
162                 return FIPS_cipherinit(ctx, cipher, key, iv, enc);
163 #else
164                 ctx->cipher=cipher;
165                 if (ctx->cipher->ctx_size)
166                         {
167                         ctx->cipher_data=OPENSSL_malloc(ctx->cipher->ctx_size);
168                         if (!ctx->cipher_data)
169                                 {
170                                 EVPerr(EVP_F_EVP_CIPHERINIT_EX, ERR_R_MALLOC_FAILURE);
171                                 return 0;
172                                 }
173                         }
174                 else
175                         {
176                         ctx->cipher_data = NULL;
177                         }
178                 ctx->key_len = cipher->key_len;
179                 ctx->flags = 0;
180                 if(ctx->cipher->flags & EVP_CIPH_CTRL_INIT)
181                         {
182                         if(!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_INIT, 0, NULL))
183                                 {
184                                 EVPerr(EVP_F_EVP_CIPHERINIT_EX, EVP_R_INITIALIZATION_ERROR);
185                                 return 0;
186                                 }
187                         }
188 #endif
189                 }
190         else if(!ctx->cipher)
191                 {
192                 EVPerr(EVP_F_EVP_CIPHERINIT_EX, EVP_R_NO_CIPHER_SET);
193                 return 0;
194                 }
195 #ifndef OPENSSL_NO_ENGINE
196 skip_to_init:
197 #endif
198 #ifdef OPENSSL_FIPS
199         return FIPS_cipherinit(ctx, cipher, key, iv, enc);
200 #else
201         /* we assume block size is a power of 2 in *cryptUpdate */
202         OPENSSL_assert(ctx->cipher->block_size == 1
203             || ctx->cipher->block_size == 8
204             || ctx->cipher->block_size == 16);
205
206         if(!(EVP_CIPHER_CTX_flags(ctx) & EVP_CIPH_CUSTOM_IV)) {
207                 switch(EVP_CIPHER_CTX_mode(ctx)) {
208
209                         case EVP_CIPH_STREAM_CIPHER:
210                         case EVP_CIPH_ECB_MODE:
211                         break;
212
213                         case EVP_CIPH_CFB_MODE:
214                         case EVP_CIPH_OFB_MODE:
215
216                         ctx->num = 0;
217                         /* fall-through */
218
219                         case EVP_CIPH_CBC_MODE:
220
221                         OPENSSL_assert(EVP_CIPHER_CTX_iv_length(ctx) <=
222                                         (int)sizeof(ctx->iv));
223                         if(iv) memcpy(ctx->oiv, iv, EVP_CIPHER_CTX_iv_length(ctx));
224                         memcpy(ctx->iv, ctx->oiv, EVP_CIPHER_CTX_iv_length(ctx));
225                         break;
226
227                         case EVP_CIPH_CTR_MODE:
228                         /* Don't reuse IV for CTR mode */
229                         if(iv)
230                                 memcpy(ctx->iv, iv, EVP_CIPHER_CTX_iv_length(ctx));
231                         break;
232
233                         default:
234                         return 0;
235                         break;
236                 }
237         }
238
239         if(key || (ctx->cipher->flags & EVP_CIPH_ALWAYS_CALL_INIT)) {
240                 if(!ctx->cipher->init(ctx,key,iv,enc)) return 0;
241         }
242         ctx->buf_len=0;
243         ctx->final_used=0;
244         ctx->block_mask=ctx->cipher->block_size-1;
245         return 1;
246 #endif
247         }
248
249 int EVP_CipherUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl,
250              const unsigned char *in, int inl)
251         {
252         if (ctx->encrypt)
253                 return EVP_EncryptUpdate(ctx,out,outl,in,inl);
254         else    return EVP_DecryptUpdate(ctx,out,outl,in,inl);
255         }
256
257 int EVP_CipherFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl)
258         {
259         if (ctx->encrypt)
260                 return EVP_EncryptFinal_ex(ctx,out,outl);
261         else    return EVP_DecryptFinal_ex(ctx,out,outl);
262         }
263
264 int EVP_CipherFinal(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl)
265         {
266         if (ctx->encrypt)
267                 return EVP_EncryptFinal(ctx,out,outl);
268         else    return EVP_DecryptFinal(ctx,out,outl);
269         }
270
271 int EVP_EncryptInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
272              const unsigned char *key, const unsigned char *iv)
273         {
274         return EVP_CipherInit(ctx, cipher, key, iv, 1);
275         }
276
277 int EVP_EncryptInit_ex(EVP_CIPHER_CTX *ctx,const EVP_CIPHER *cipher, ENGINE *impl,
278                 const unsigned char *key, const unsigned char *iv)
279         {
280         return EVP_CipherInit_ex(ctx, cipher, impl, key, iv, 1);
281         }
282
283 int EVP_DecryptInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
284              const unsigned char *key, const unsigned char *iv)
285         {
286         return EVP_CipherInit(ctx, cipher, key, iv, 0);
287         }
288
289 int EVP_DecryptInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher, ENGINE *impl,
290              const unsigned char *key, const unsigned char *iv)
291         {
292         return EVP_CipherInit_ex(ctx, cipher, impl, key, iv, 0);
293         }
294
295 int EVP_EncryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl,
296              const unsigned char *in, int inl)
297         {
298         int i,j,bl;
299
300         if (inl <= 0)
301                 {
302                 *outl = 0;
303                 return inl == 0;
304                 }
305
306         if(ctx->buf_len == 0 && (inl&(ctx->block_mask)) == 0)
307                 {
308                 if(ctx->cipher->do_cipher(ctx,out,in,inl))
309                         {
310                         *outl=inl;
311                         return 1;
312                         }
313                 else
314                         {
315                         *outl=0;
316                         return 0;
317                         }
318                 }
319         i=ctx->buf_len;
320         bl=ctx->cipher->block_size;
321         OPENSSL_assert(bl <= (int)sizeof(ctx->buf));
322         if (i != 0)
323                 {
324                 if (i+inl < bl)
325                         {
326                         memcpy(&(ctx->buf[i]),in,inl);
327                         ctx->buf_len+=inl;
328                         *outl=0;
329                         return 1;
330                         }
331                 else
332                         {
333                         j=bl-i;
334                         memcpy(&(ctx->buf[i]),in,j);
335                         if(!ctx->cipher->do_cipher(ctx,out,ctx->buf,bl)) return 0;
336                         inl-=j;
337                         in+=j;
338                         out+=bl;
339                         *outl=bl;
340                         }
341                 }
342         else
343                 *outl = 0;
344         i=inl&(bl-1);
345         inl-=i;
346         if (inl > 0)
347                 {
348                 if(!ctx->cipher->do_cipher(ctx,out,in,inl)) return 0;
349                 *outl+=inl;
350                 }
351
352         if (i != 0)
353                 memcpy(ctx->buf,&(in[inl]),i);
354         ctx->buf_len=i;
355         return 1;
356         }
357
358 int EVP_EncryptFinal(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl)
359         {
360         int ret;
361         ret = EVP_EncryptFinal_ex(ctx, out, outl);
362         return ret;
363         }
364
365 int EVP_EncryptFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl)
366         {
367         int n,ret;
368         unsigned int i, b, bl;
369
370         b=ctx->cipher->block_size;
371         OPENSSL_assert(b <= sizeof ctx->buf);
372         if (b == 1)
373                 {
374                 *outl=0;
375                 return 1;
376                 }
377         bl=ctx->buf_len;
378         if (ctx->flags & EVP_CIPH_NO_PADDING)
379                 {
380                 if(bl)
381                         {
382                         EVPerr(EVP_F_EVP_ENCRYPTFINAL_EX,EVP_R_DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH);
383                         return 0;
384                         }
385                 *outl = 0;
386                 return 1;
387                 }
388
389         n=b-bl;
390         for (i=bl; i<b; i++)
391                 ctx->buf[i]=n;
392         ret=ctx->cipher->do_cipher(ctx,out,ctx->buf,b);
393
394
395         if(ret)
396                 *outl=b;
397
398         return ret;
399         }
400
401 int EVP_DecryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl,
402              const unsigned char *in, int inl)
403         {
404         int fix_len;
405         unsigned int b;
406
407         if (inl <= 0)
408                 {
409                 *outl = 0;
410                 return inl == 0;
411                 }
412
413         if (ctx->flags & EVP_CIPH_NO_PADDING)
414                 return EVP_EncryptUpdate(ctx, out, outl, in, inl);
415
416         b=ctx->cipher->block_size;
417         OPENSSL_assert(b <= sizeof ctx->final);
418
419         if(ctx->final_used)
420                 {
421                 memcpy(out,ctx->final,b);
422                 out+=b;
423                 fix_len = 1;
424                 }
425         else
426                 fix_len = 0;
427
428
429         if(!EVP_EncryptUpdate(ctx,out,outl,in,inl))
430                 return 0;
431
432         /* if we have 'decrypted' a multiple of block size, make sure
433          * we have a copy of this last block */
434         if (b > 1 && !ctx->buf_len)
435                 {
436                 *outl-=b;
437                 ctx->final_used=1;
438                 memcpy(ctx->final,&out[*outl],b);
439                 }
440         else
441                 ctx->final_used = 0;
442
443         if (fix_len)
444                 *outl += b;
445                 
446         return 1;
447         }
448
449 int EVP_DecryptFinal(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl)
450         {
451         int ret;
452         ret = EVP_DecryptFinal_ex(ctx, out, outl);
453         return ret;
454         }
455
456 int EVP_DecryptFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl)
457         {
458         int i,n;
459         unsigned int b;
460
461         *outl=0;
462         b=ctx->cipher->block_size;
463         if (ctx->flags & EVP_CIPH_NO_PADDING)
464                 {
465                 if(ctx->buf_len)
466                         {
467                         EVPerr(EVP_F_EVP_DECRYPTFINAL_EX,EVP_R_DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH);
468                         return 0;
469                         }
470                 *outl = 0;
471                 return 1;
472                 }
473         if (b > 1)
474                 {
475                 if (ctx->buf_len || !ctx->final_used)
476                         {
477                         EVPerr(EVP_F_EVP_DECRYPTFINAL_EX,EVP_R_WRONG_FINAL_BLOCK_LENGTH);
478                         return(0);
479                         }
480                 OPENSSL_assert(b <= sizeof ctx->final);
481                 n=ctx->final[b-1];
482                 if (n == 0 || n > (int)b)
483                         {
484                         EVPerr(EVP_F_EVP_DECRYPTFINAL_EX,EVP_R_BAD_DECRYPT);
485                         return(0);
486                         }
487                 for (i=0; i<n; i++)
488                         {
489                         if (ctx->final[--b] != n)
490                                 {
491                                 EVPerr(EVP_F_EVP_DECRYPTFINAL_EX,EVP_R_BAD_DECRYPT);
492                                 return(0);
493                                 }
494                         }
495                 n=ctx->cipher->block_size-n;
496                 for (i=0; i<n; i++)
497                         out[i]=ctx->final[i];
498                 *outl=n;
499                 }
500         else
501                 *outl=0;
502         return(1);
503         }
504
505 void EVP_CIPHER_CTX_free(EVP_CIPHER_CTX *ctx)
506         {
507         if (ctx)
508                 {
509                 EVP_CIPHER_CTX_cleanup(ctx);
510                 OPENSSL_free(ctx);
511                 }
512         }
513
514 int EVP_CIPHER_CTX_cleanup(EVP_CIPHER_CTX *c)
515         {
516         if (c->cipher != NULL)
517                 {
518                 if(c->cipher->cleanup && !c->cipher->cleanup(c))
519                         return 0;
520                 /* Cleanse cipher context data */
521                 if (c->cipher_data)
522                         OPENSSL_cleanse(c->cipher_data, c->cipher->ctx_size);
523                 }
524         if (c->cipher_data)
525                 OPENSSL_free(c->cipher_data);
526 #ifndef OPENSSL_NO_ENGINE
527         if (c->engine)
528                 /* The EVP_CIPHER we used belongs to an ENGINE, release the
529                  * functional reference we held for this reason. */
530                 ENGINE_finish(c->engine);
531 #endif
532         memset(c,0,sizeof(EVP_CIPHER_CTX));
533         return 1;
534         }
535
536 int EVP_CIPHER_CTX_set_key_length(EVP_CIPHER_CTX *c, int keylen)
537         {
538         if(c->cipher->flags & EVP_CIPH_CUSTOM_KEY_LENGTH) 
539                 return EVP_CIPHER_CTX_ctrl(c, EVP_CTRL_SET_KEY_LENGTH, keylen, NULL);
540         if(c->key_len == keylen) return 1;
541         if((keylen > 0) && (c->cipher->flags & EVP_CIPH_VARIABLE_LENGTH))
542                 {
543                 c->key_len = keylen;
544                 return 1;
545                 }
546         EVPerr(EVP_F_EVP_CIPHER_CTX_SET_KEY_LENGTH,EVP_R_INVALID_KEY_LENGTH);
547         return 0;
548         }
549
550 int EVP_CIPHER_CTX_set_padding(EVP_CIPHER_CTX *ctx, int pad)
551         {
552         if (pad) ctx->flags &= ~EVP_CIPH_NO_PADDING;
553         else ctx->flags |= EVP_CIPH_NO_PADDING;
554         return 1;
555         }
556
557 int EVP_CIPHER_CTX_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr)
558 {
559         int ret;
560         if(!ctx->cipher) {
561                 EVPerr(EVP_F_EVP_CIPHER_CTX_CTRL, EVP_R_NO_CIPHER_SET);
562                 return 0;
563         }
564
565         if(!ctx->cipher->ctrl) {
566                 EVPerr(EVP_F_EVP_CIPHER_CTX_CTRL, EVP_R_CTRL_NOT_IMPLEMENTED);
567                 return 0;
568         }
569
570         ret = ctx->cipher->ctrl(ctx, type, arg, ptr);
571         if(ret == -1) {
572                 EVPerr(EVP_F_EVP_CIPHER_CTX_CTRL, EVP_R_CTRL_OPERATION_NOT_IMPLEMENTED);
573                 return 0;
574         }
575         return ret;
576 }
577
578 int EVP_CIPHER_CTX_rand_key(EVP_CIPHER_CTX *ctx, unsigned char *key)
579         {
580         if (ctx->cipher->flags & EVP_CIPH_RAND_KEY)
581                 return EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_RAND_KEY, 0, key);
582         if (RAND_bytes(key, ctx->key_len) <= 0)
583                 return 0;
584         return 1;
585         }
586
587 int EVP_CIPHER_CTX_copy(EVP_CIPHER_CTX *out, const EVP_CIPHER_CTX *in)
588         {
589         if ((in == NULL) || (in->cipher == NULL))
590                 {
591                 EVPerr(EVP_F_EVP_CIPHER_CTX_COPY,EVP_R_INPUT_NOT_INITIALIZED);
592                 return 0;
593                 }
594 #ifndef OPENSSL_NO_ENGINE
595         /* Make sure it's safe to copy a cipher context using an ENGINE */
596         if (in->engine && !ENGINE_init(in->engine))
597                 {
598                 EVPerr(EVP_F_EVP_CIPHER_CTX_COPY,ERR_R_ENGINE_LIB);
599                 return 0;
600                 }
601 #endif
602
603         EVP_CIPHER_CTX_cleanup(out);
604         memcpy(out,in,sizeof *out);
605
606         if (in->cipher_data && in->cipher->ctx_size)
607                 {
608                 out->cipher_data=OPENSSL_malloc(in->cipher->ctx_size);
609                 if (!out->cipher_data)
610                         {
611                         EVPerr(EVP_F_EVP_CIPHER_CTX_COPY,ERR_R_MALLOC_FAILURE);
612                         return 0;
613                         }
614                 memcpy(out->cipher_data,in->cipher_data,in->cipher->ctx_size);
615                 }
616
617         if (in->cipher->flags & EVP_CIPH_CUSTOM_COPY)
618                 return in->cipher->ctrl((EVP_CIPHER_CTX *)in, EVP_CTRL_COPY, 0, out);
619         return 1;
620         }
621