xref: /freebsd/crypto/openssl/ssl/ssl_sess.c (revision daf1cffce2e07931f27c6c6998652e90df6ba87e)
1 /* ssl/ssl_sess.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 <openssl/lhash.h>
61 #include <openssl/rand.h>
62 #include "ssl_locl.h"
63 
64 static void SSL_SESSION_list_remove(SSL_CTX *ctx, SSL_SESSION *s);
65 static void SSL_SESSION_list_add(SSL_CTX *ctx,SSL_SESSION *s);
66 static int remove_session_lock(SSL_CTX *ctx, SSL_SESSION *c, int lck);
67 static int ssl_session_num=0;
68 static STACK *ssl_session_meth=NULL;
69 
70 SSL_SESSION *SSL_get_session(SSL *ssl)
71 	{
72 	return(ssl->session);
73 	}
74 
75 int SSL_SESSION_get_ex_new_index(long argl, char *argp, int (*new_func)(),
76 	     int (*dup_func)(), void (*free_func)())
77 	{
78 	ssl_session_num++;
79 	return(CRYPTO_get_ex_new_index(ssl_session_num-1,
80 		&ssl_session_meth,
81 		argl,argp,new_func,dup_func,free_func));
82 	}
83 
84 int SSL_SESSION_set_ex_data(SSL_SESSION *s, int idx, void *arg)
85 	{
86 	return(CRYPTO_set_ex_data(&s->ex_data,idx,arg));
87 	}
88 
89 void *SSL_SESSION_get_ex_data(SSL_SESSION *s, int idx)
90 	{
91 	return(CRYPTO_get_ex_data(&s->ex_data,idx));
92 	}
93 
94 SSL_SESSION *SSL_SESSION_new(void)
95 	{
96 	SSL_SESSION *ss;
97 
98 	ss=(SSL_SESSION *)Malloc(sizeof(SSL_SESSION));
99 	if (ss == NULL)
100 		{
101 		SSLerr(SSL_F_SSL_SESSION_NEW,ERR_R_MALLOC_FAILURE);
102 		return(0);
103 		}
104 	memset(ss,0,sizeof(SSL_SESSION));
105 
106 	ss->references=1;
107 	ss->timeout=60*5+4; /* 5 minute timeout by default */
108 	ss->time=time(NULL);
109 	ss->prev=NULL;
110 	ss->next=NULL;
111 	ss->compress_meth=0;
112 	CRYPTO_new_ex_data(ssl_session_meth,(char *)ss,&ss->ex_data);
113 	return(ss);
114 	}
115 
116 int ssl_get_new_session(SSL *s, int session)
117 	{
118 	/* This gets used by clients and servers. */
119 
120 	SSL_SESSION *ss=NULL;
121 
122 	if ((ss=SSL_SESSION_new()) == NULL) return(0);
123 
124 	/* If the context has a default timeout, use it */
125 	if (s->ctx->session_timeout == 0)
126 		ss->timeout=SSL_get_default_timeout(s);
127 	else
128 		ss->timeout=s->ctx->session_timeout;
129 
130 	if (s->session != NULL)
131 		{
132 		SSL_SESSION_free(s->session);
133 		s->session=NULL;
134 		}
135 
136 	if (session)
137 		{
138 		if (s->version == SSL2_VERSION)
139 			{
140 			ss->ssl_version=SSL2_VERSION;
141 			ss->session_id_length=SSL2_SSL_SESSION_ID_LENGTH;
142 			}
143 		else if (s->version == SSL3_VERSION)
144 			{
145 			ss->ssl_version=SSL3_VERSION;
146 			ss->session_id_length=SSL3_SSL_SESSION_ID_LENGTH;
147 			}
148 		else if (s->version == TLS1_VERSION)
149 			{
150 			ss->ssl_version=TLS1_VERSION;
151 			ss->session_id_length=SSL3_SSL_SESSION_ID_LENGTH;
152 			}
153 		else
154 			{
155 			SSLerr(SSL_F_SSL_GET_NEW_SESSION,SSL_R_UNSUPPORTED_SSL_VERSION);
156 			SSL_SESSION_free(ss);
157 			return(0);
158 			}
159 
160 		for (;;)
161 			{
162 			SSL_SESSION *r;
163 
164 			RAND_bytes(ss->session_id,ss->session_id_length);
165 			CRYPTO_r_lock(CRYPTO_LOCK_SSL_CTX);
166 			r=(SSL_SESSION *)lh_retrieve(s->ctx->sessions,
167 				(char *)ss);
168 			CRYPTO_r_unlock(CRYPTO_LOCK_SSL_CTX);
169 			if (r == NULL) break;
170 			/* else - woops a session_id match */
171 			/* XXX should also check external cache!
172 			 * (But the probability of a collision is negligible, anyway...) */
173 			}
174 		}
175 	else
176 		{
177 		ss->session_id_length=0;
178 		}
179 
180 	memcpy(ss->sid_ctx,s->sid_ctx,s->sid_ctx_length);
181 	ss->sid_ctx_length=s->sid_ctx_length;
182 	s->session=ss;
183 	ss->ssl_version=s->version;
184 
185 	return(1);
186 	}
187 
188 int ssl_get_prev_session(SSL *s, unsigned char *session_id, int len)
189 	{
190 	/* This is used only by servers. */
191 
192 	SSL_SESSION *ret=NULL,data;
193 	int fatal = 0;
194 
195 	/* conn_init();*/
196 	data.ssl_version=s->version;
197 	data.session_id_length=len;
198 	if (len > SSL_MAX_SSL_SESSION_ID_LENGTH)
199 		goto err;
200 	memcpy(data.session_id,session_id,len);
201 
202 	if (!(s->ctx->session_cache_mode & SSL_SESS_CACHE_NO_INTERNAL_LOOKUP))
203 		{
204 		CRYPTO_r_lock(CRYPTO_LOCK_SSL_CTX);
205 		ret=(SSL_SESSION *)lh_retrieve(s->ctx->sessions,(char *)&data);
206 		if (ret != NULL)
207 		    /* don't allow other threads to steal it: */
208 		    CRYPTO_add(&ret->references,1,CRYPTO_LOCK_SSL_SESSION);
209 		CRYPTO_r_unlock(CRYPTO_LOCK_SSL_CTX);
210 		}
211 
212 	if (ret == NULL)
213 		{
214 		int copy=1;
215 
216 		s->ctx->stats.sess_miss++;
217 		ret=NULL;
218 		if (s->ctx->get_session_cb != NULL
219 		    && (ret=s->ctx->get_session_cb(s,session_id,len,&copy))
220 		       != NULL)
221 			{
222 			s->ctx->stats.sess_cb_hit++;
223 
224 			/* Increment reference count now if the session callback
225 			 * asks us to do so (note that if the session structures
226 			 * returned by the callback are shared between threads,
227 			 * it must handle the reference count itself [i.e. copy == 0],
228 			 * or things won't be thread-safe). */
229 			if (copy)
230 				CRYPTO_add(&ret->references,1,CRYPTO_LOCK_SSL_SESSION);
231 
232 			/* The following should not return 1, otherwise,
233 			 * things are very strange */
234 			SSL_CTX_add_session(s->ctx,ret);
235 			}
236 		if (ret == NULL)
237 			goto err;
238 		}
239 
240 	/* Now ret is non-NULL, and we own one of its reference counts. */
241 
242 	if((s->verify_mode&SSL_VERIFY_PEER)
243 	   && (!s->sid_ctx_length || ret->sid_ctx_length != s->sid_ctx_length
244 	       || memcmp(ret->sid_ctx,s->sid_ctx,ret->sid_ctx_length)))
245 	    {
246 		/* We've found the session named by the client, but we don't
247 		 * want to use it in this context. */
248 
249 		if (s->sid_ctx_length == 0)
250 			{
251 			/* application should have used SSL[_CTX]_set_session_id_context
252 			 * -- we could tolerate this and just pretend we never heard
253 			 * of this session, but then applications could effectively
254 			 * disable the session cache by accident without anyone noticing */
255 
256 			SSLerr(SSL_F_SSL_GET_PREV_SESSION,SSL_R_SESSION_ID_CONTEXT_UNINITIALIZED);
257 			fatal = 1;
258 			goto err;
259 			}
260 		else
261 			{
262 #if 0 /* The client cannot always know when a session is not appropriate,
263 	   * so we shouldn't generate an error message. */
264 
265 			SSLerr(SSL_F_SSL_GET_PREV_SESSION,SSL_R_ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT);
266 #endif
267 			goto err; /* treat like cache miss */
268 			}
269 		}
270 
271 	if (ret->cipher == NULL)
272 		{
273 		unsigned char buf[5],*p;
274 		unsigned long l;
275 
276 		p=buf;
277 		l=ret->cipher_id;
278 		l2n(l,p);
279 		if ((ret->ssl_version>>8) == SSL3_VERSION_MAJOR)
280 			ret->cipher=ssl_get_cipher_by_char(s,&(buf[2]));
281 		else
282 			ret->cipher=ssl_get_cipher_by_char(s,&(buf[1]));
283 		if (ret->cipher == NULL)
284 			goto err;
285 		}
286 
287 
288 #if 0 /* This is way too late. */
289 
290 	/* If a thread got the session, then 'swaped', and another got
291 	 * it and then due to a time-out decided to 'Free' it we could
292 	 * be in trouble.  So I'll increment it now, then double decrement
293 	 * later - am I speaking rubbish?. */
294 	CRYPTO_add(&ret->references,1,CRYPTO_LOCK_SSL_SESSION);
295 #endif
296 
297 	if ((long)(ret->time+ret->timeout) < (long)time(NULL)) /* timeout */
298 		{
299 		s->ctx->stats.sess_timeout++;
300 		/* remove it from the cache */
301 		SSL_CTX_remove_session(s->ctx,ret);
302 		goto err;
303 		}
304 
305 	s->ctx->stats.sess_hit++;
306 
307 	/* ret->time=time(NULL); */ /* rezero timeout? */
308 	/* again, just leave the session
309 	 * if it is the same session, we have just incremented and
310 	 * then decremented the reference count :-) */
311 	if (s->session != NULL)
312 		SSL_SESSION_free(s->session);
313 	s->session=ret;
314 	return(1);
315 
316  err:
317 	if (ret != NULL)
318 		SSL_SESSION_free(ret);
319 	if (fatal)
320 		return -1;
321 	else
322 		return 0;
323 	}
324 
325 int SSL_CTX_add_session(SSL_CTX *ctx, SSL_SESSION *c)
326 	{
327 	int ret=0;
328 	SSL_SESSION *s;
329 
330 	/* conn_init(); */
331 	CRYPTO_add(&c->references,1,CRYPTO_LOCK_SSL_SESSION);
332 
333 	CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX);
334 	s=(SSL_SESSION *)lh_insert(ctx->sessions,(char *)c);
335 
336 	/* Put on the end of the queue unless it is already in the cache */
337 	if (s == NULL)
338 		SSL_SESSION_list_add(ctx,c);
339 
340 	/* If the same session if is being 're-added', Free the old
341 	 * one when the last person stops using it.
342 	 * This will also work if it is alread in the cache.
343 	 * The references will go up and then down :-) */
344 	if (s != NULL)
345 		{
346 		SSL_SESSION_free(s);
347 		ret=0;
348 		}
349 	else
350 		{
351 		ret=1;
352 
353 		if (SSL_CTX_sess_get_cache_size(ctx) > 0)
354 			{
355 			while (SSL_CTX_sess_number(ctx) >
356 				SSL_CTX_sess_get_cache_size(ctx))
357 				{
358 				if (!remove_session_lock(ctx,
359 					ctx->session_cache_tail, 0))
360 					break;
361 				else
362 					ctx->stats.sess_cache_full++;
363 				}
364 			}
365 		}
366 	CRYPTO_w_unlock(CRYPTO_LOCK_SSL_CTX);
367 	return(ret);
368 	}
369 
370 int SSL_CTX_remove_session(SSL_CTX *ctx, SSL_SESSION *c)
371 {
372 	return remove_session_lock(ctx, c, 1);
373 }
374 
375 static int remove_session_lock(SSL_CTX *ctx, SSL_SESSION *c, int lck)
376 	{
377 	SSL_SESSION *r;
378 	int ret=0;
379 
380 	if ((c != NULL) && (c->session_id_length != 0))
381 		{
382 		if(lck) CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX);
383 		r=(SSL_SESSION *)lh_delete(ctx->sessions,(char *)c);
384 		if (r != NULL)
385 			{
386 			ret=1;
387 			SSL_SESSION_list_remove(ctx,c);
388 			}
389 
390 		if(lck) CRYPTO_w_unlock(CRYPTO_LOCK_SSL_CTX);
391 
392 		if (ret)
393 			{
394 			r->not_resumable=1;
395 			if (ctx->remove_session_cb != NULL)
396 				ctx->remove_session_cb(ctx,r);
397 			SSL_SESSION_free(r);
398 			}
399 		}
400 	else
401 		ret=0;
402 	return(ret);
403 	}
404 
405 void SSL_SESSION_free(SSL_SESSION *ss)
406 	{
407 	int i;
408 
409 	if(ss == NULL)
410 	    return;
411 
412 	i=CRYPTO_add(&ss->references,-1,CRYPTO_LOCK_SSL_SESSION);
413 #ifdef REF_PRINT
414 	REF_PRINT("SSL_SESSION",ss);
415 #endif
416 	if (i > 0) return;
417 #ifdef REF_CHECK
418 	if (i < 0)
419 		{
420 		fprintf(stderr,"SSL_SESSION_free, bad reference count\n");
421 		abort(); /* ok */
422 		}
423 #endif
424 
425 	CRYPTO_free_ex_data(ssl_session_meth,(char *)ss,&ss->ex_data);
426 
427 	memset(ss->key_arg,0,SSL_MAX_KEY_ARG_LENGTH);
428 	memset(ss->master_key,0,SSL_MAX_MASTER_KEY_LENGTH);
429 	memset(ss->session_id,0,SSL_MAX_SSL_SESSION_ID_LENGTH);
430 	if (ss->sess_cert != NULL) ssl_sess_cert_free(ss->sess_cert);
431 	if (ss->peer != NULL) X509_free(ss->peer);
432 	if (ss->ciphers != NULL) sk_SSL_CIPHER_free(ss->ciphers);
433 	memset(ss,0,sizeof(*ss));
434 	Free(ss);
435 	}
436 
437 int SSL_set_session(SSL *s, SSL_SESSION *session)
438 	{
439 	int ret=0;
440 	SSL_METHOD *meth;
441 
442 	if (session != NULL)
443 		{
444 		meth=s->ctx->method->get_ssl_method(session->ssl_version);
445 		if (meth == NULL)
446 			meth=s->method->get_ssl_method(session->ssl_version);
447 		if (meth == NULL)
448 			{
449 			SSLerr(SSL_F_SSL_SET_SESSION,SSL_R_UNABLE_TO_FIND_SSL_METHOD);
450 			return(0);
451 			}
452 
453 		if (meth != s->method)
454 			{
455 			if (!SSL_set_ssl_method(s,meth))
456 				return(0);
457 			if (s->ctx->session_timeout == 0)
458 				session->timeout=SSL_get_default_timeout(s);
459 			else
460 				session->timeout=s->ctx->session_timeout;
461 			}
462 
463 		/* CRYPTO_w_lock(CRYPTO_LOCK_SSL);*/
464 		CRYPTO_add(&session->references,1,CRYPTO_LOCK_SSL_SESSION);
465 		if (s->session != NULL)
466 			SSL_SESSION_free(s->session);
467 		s->session=session;
468 		/* CRYPTO_w_unlock(CRYPTO_LOCK_SSL);*/
469 		ret=1;
470 		}
471 	else
472 		{
473 		if (s->session != NULL)
474 			{
475 			SSL_SESSION_free(s->session);
476 			s->session=NULL;
477 			}
478 
479 		meth=s->ctx->method;
480 		if (meth != s->method)
481 			{
482 			if (!SSL_set_ssl_method(s,meth))
483 				return(0);
484 			}
485 		ret=1;
486 		}
487 	return(ret);
488 	}
489 
490 long SSL_SESSION_set_timeout(SSL_SESSION *s, long t)
491 	{
492 	if (s == NULL) return(0);
493 	s->timeout=t;
494 	return(1);
495 	}
496 
497 long SSL_SESSION_get_timeout(SSL_SESSION *s)
498 	{
499 	if (s == NULL) return(0);
500 	return(s->timeout);
501 	}
502 
503 long SSL_SESSION_get_time(SSL_SESSION *s)
504 	{
505 	if (s == NULL) return(0);
506 	return(s->time);
507 	}
508 
509 long SSL_SESSION_set_time(SSL_SESSION *s, long t)
510 	{
511 	if (s == NULL) return(0);
512 	s->time=t;
513 	return(t);
514 	}
515 
516 long SSL_CTX_set_timeout(SSL_CTX *s, long t)
517 	{
518 	long l;
519 	if (s == NULL) return(0);
520 	l=s->session_timeout;
521 	s->session_timeout=t;
522 	return(l);
523 	}
524 
525 long SSL_CTX_get_timeout(SSL_CTX *s)
526 	{
527 	if (s == NULL) return(0);
528 	return(s->session_timeout);
529 	}
530 
531 typedef struct timeout_param_st
532 	{
533 	SSL_CTX *ctx;
534 	long time;
535 	LHASH *cache;
536 	} TIMEOUT_PARAM;
537 
538 static void timeout(SSL_SESSION *s, TIMEOUT_PARAM *p)
539 	{
540 	if ((p->time == 0) || (p->time > (s->time+s->timeout))) /* timeout */
541 		{
542 		/* The reason we don't call SSL_CTX_remove_session() is to
543 		 * save on locking overhead */
544 		lh_delete(p->cache,(char *)s);
545 		SSL_SESSION_list_remove(p->ctx,s);
546 		s->not_resumable=1;
547 		if (p->ctx->remove_session_cb != NULL)
548 			p->ctx->remove_session_cb(p->ctx,s);
549 		SSL_SESSION_free(s);
550 		}
551 	}
552 
553 void SSL_CTX_flush_sessions(SSL_CTX *s, long t)
554 	{
555 	unsigned long i;
556 	TIMEOUT_PARAM tp;
557 
558 	tp.ctx=s;
559 	tp.cache=s->sessions;
560 	if (tp.cache == NULL) return;
561 	tp.time=t;
562 	CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX);
563 	i=tp.cache->down_load;
564 	tp.cache->down_load=0;
565 	lh_doall_arg(tp.cache,(void (*)())timeout,(char *)&tp);
566 	tp.cache->down_load=i;
567 	CRYPTO_w_unlock(CRYPTO_LOCK_SSL_CTX);
568 	}
569 
570 int ssl_clear_bad_session(SSL *s)
571 	{
572 	if (	(s->session != NULL) &&
573 		!(s->shutdown & SSL_SENT_SHUTDOWN) &&
574 		!(SSL_in_init(s) || SSL_in_before(s)))
575 		{
576 		SSL_CTX_remove_session(s->ctx,s->session);
577 		return(1);
578 		}
579 	else
580 		return(0);
581 	}
582 
583 /* locked by SSL_CTX in the calling function */
584 static void SSL_SESSION_list_remove(SSL_CTX *ctx, SSL_SESSION *s)
585 	{
586 	if ((s->next == NULL) || (s->prev == NULL)) return;
587 
588 	if (s->next == (SSL_SESSION *)&(ctx->session_cache_tail))
589 		{ /* last element in list */
590 		if (s->prev == (SSL_SESSION *)&(ctx->session_cache_head))
591 			{ /* only one element in list */
592 			ctx->session_cache_head=NULL;
593 			ctx->session_cache_tail=NULL;
594 			}
595 		else
596 			{
597 			ctx->session_cache_tail=s->prev;
598 			s->prev->next=(SSL_SESSION *)&(ctx->session_cache_tail);
599 			}
600 		}
601 	else
602 		{
603 		if (s->prev == (SSL_SESSION *)&(ctx->session_cache_head))
604 			{ /* first element in list */
605 			ctx->session_cache_head=s->next;
606 			s->next->prev=(SSL_SESSION *)&(ctx->session_cache_head);
607 			}
608 		else
609 			{ /* middle of list */
610 			s->next->prev=s->prev;
611 			s->prev->next=s->next;
612 			}
613 		}
614 	s->prev=s->next=NULL;
615 	}
616 
617 static void SSL_SESSION_list_add(SSL_CTX *ctx, SSL_SESSION *s)
618 	{
619 	if ((s->next != NULL) && (s->prev != NULL))
620 		SSL_SESSION_list_remove(ctx,s);
621 
622 	if (ctx->session_cache_head == NULL)
623 		{
624 		ctx->session_cache_head=s;
625 		ctx->session_cache_tail=s;
626 		s->prev=(SSL_SESSION *)&(ctx->session_cache_head);
627 		s->next=(SSL_SESSION *)&(ctx->session_cache_tail);
628 		}
629 	else
630 		{
631 		s->next=ctx->session_cache_head;
632 		s->next->prev=s;
633 		s->prev=(SSL_SESSION *)&(ctx->session_cache_head);
634 		ctx->session_cache_head=s;
635 		}
636 	}
637 
638