1 /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
2  * project 2006.
3  */
4 /* ====================================================================
5  * Copyright (c) 2006 The OpenSSL Project.  All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  *
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in
16  *    the documentation and/or other materials provided with the
17  *    distribution.
18  *
19  * 3. All advertising materials mentioning features or use of this
20  *    software must display the following acknowledgment:
21  *    "This product includes software developed by the OpenSSL Project
22  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
23  *
24  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
25  *    endorse or promote products derived from this software without
26  *    prior written permission. For written permission, please contact
27  *    licensing@OpenSSL.org.
28  *
29  * 5. Products derived from this software may not be called "OpenSSL"
30  *    nor may "OpenSSL" appear in their names without prior written
31  *    permission of the OpenSSL Project.
32  *
33  * 6. Redistributions of any form whatsoever must retain the following
34  *    acknowledgment:
35  *    "This product includes software developed by the OpenSSL Project
36  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
37  *
38  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
39  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
40  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
41  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
42  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
43  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
44  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
45  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
46  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
47  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
48  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
49  * OF THE POSSIBILITY OF SUCH DAMAGE.
50  * ====================================================================
51  *
52  * This product includes cryptographic software written by Eric Young
53  * (eay@cryptsoft.com).  This product includes software written by Tim
54  * Hudson (tjh@cryptsoft.com).
55  *
56  */
57 
58 #include <stdio.h>
59 #include "cryptlib.h"
60 #include <openssl/x509.h>
61 #include <openssl/asn1.h>
62 #include <openssl/dsa.h>
63 #include <openssl/bn.h>
64 #ifndef OPENSSL_NO_CMS
65 #include <openssl/cms.h>
66 #endif
67 #include "asn1_locl.h"
68 
69 static int dsa_pub_decode(EVP_PKEY *pkey, X509_PUBKEY *pubkey)
70 	{
71 	const unsigned char *p, *pm;
72 	int pklen, pmlen;
73 	int ptype;
74 	void *pval;
75 	ASN1_STRING *pstr;
76 	X509_ALGOR *palg;
77 	ASN1_INTEGER *public_key = NULL;
78 
79 	DSA *dsa = NULL;
80 
81 	if (!X509_PUBKEY_get0_param(NULL, &p, &pklen, &palg, pubkey))
82 		return 0;
83 	X509_ALGOR_get0(NULL, &ptype, &pval, palg);
84 
85 
86 	if (ptype == V_ASN1_SEQUENCE)
87 		{
88 		pstr = pval;
89 		pm = pstr->data;
90 		pmlen = pstr->length;
91 
92 		if (!(dsa = d2i_DSAparams(NULL, &pm, pmlen)))
93 			{
94 			DSAerr(DSA_F_DSA_PUB_DECODE, DSA_R_DECODE_ERROR);
95 			goto err;
96 			}
97 
98 		}
99 	else if ((ptype == V_ASN1_NULL) || (ptype == V_ASN1_UNDEF))
100 		{
101 		if (!(dsa = DSA_new()))
102 			{
103 			DSAerr(DSA_F_DSA_PUB_DECODE, ERR_R_MALLOC_FAILURE);
104 			goto err;
105 			}
106 		}
107 	else
108 		{
109 		DSAerr(DSA_F_DSA_PUB_DECODE, DSA_R_PARAMETER_ENCODING_ERROR);
110 		goto err;
111 		}
112 
113 	if (!(public_key=d2i_ASN1_INTEGER(NULL, &p, pklen)))
114 		{
115 		DSAerr(DSA_F_DSA_PUB_DECODE, DSA_R_DECODE_ERROR);
116 		goto err;
117 		}
118 
119 	if (!(dsa->pub_key = ASN1_INTEGER_to_BN(public_key, NULL)))
120 		{
121 		DSAerr(DSA_F_DSA_PUB_DECODE, DSA_R_BN_DECODE_ERROR);
122 		goto err;
123 		}
124 
125 	ASN1_INTEGER_free(public_key);
126 	EVP_PKEY_assign_DSA(pkey, dsa);
127 	return 1;
128 
129 	err:
130 	if (public_key)
131 		ASN1_INTEGER_free(public_key);
132 	if (dsa)
133 		DSA_free(dsa);
134 	return 0;
135 
136 	}
137 
138 static int dsa_pub_encode(X509_PUBKEY *pk, const EVP_PKEY *pkey)
139 	{
140 	DSA *dsa;
141 	void *pval = NULL;
142 	int ptype;
143 	unsigned char *penc = NULL;
144 	int penclen;
145 
146 	dsa=pkey->pkey.dsa;
147 	if (pkey->save_parameters && dsa->p && dsa->q && dsa->g)
148 		{
149 		ASN1_STRING *str;
150 		str = ASN1_STRING_new();
151 		str->length = i2d_DSAparams(dsa, &str->data);
152 		if (str->length <= 0)
153 			{
154 			DSAerr(DSA_F_DSA_PUB_ENCODE, ERR_R_MALLOC_FAILURE);
155 			goto err;
156 			}
157 		pval = str;
158 		ptype = V_ASN1_SEQUENCE;
159 		}
160 	else
161 		ptype = V_ASN1_UNDEF;
162 
163 	dsa->write_params=0;
164 
165 	penclen = i2d_DSAPublicKey(dsa, &penc);
166 
167 	if (penclen <= 0)
168 		{
169 		DSAerr(DSA_F_DSA_PUB_ENCODE, ERR_R_MALLOC_FAILURE);
170 		goto err;
171 		}
172 
173 	if (X509_PUBKEY_set0_param(pk, OBJ_nid2obj(EVP_PKEY_DSA),
174 				ptype, pval, penc, penclen))
175 		return 1;
176 
177 	err:
178 	if (penc)
179 		OPENSSL_free(penc);
180 	if (pval)
181 		ASN1_STRING_free(pval);
182 
183 	return 0;
184 	}
185 
186 /* In PKCS#8 DSA: you just get a private key integer and parameters in the
187  * AlgorithmIdentifier the pubkey must be recalculated.
188  */
189 
190 static int dsa_priv_decode(EVP_PKEY *pkey, PKCS8_PRIV_KEY_INFO *p8)
191 	{
192 	const unsigned char *p, *pm;
193 	int pklen, pmlen;
194 	int ptype;
195 	void *pval;
196 	ASN1_STRING *pstr;
197 	X509_ALGOR *palg;
198 	ASN1_INTEGER *privkey = NULL;
199 	BN_CTX *ctx = NULL;
200 
201 	STACK_OF(ASN1_TYPE) *ndsa = NULL;
202 	DSA *dsa = NULL;
203 
204 	if (!PKCS8_pkey_get0(NULL, &p, &pklen, &palg, p8))
205 		return 0;
206 	X509_ALGOR_get0(NULL, &ptype, &pval, palg);
207 
208 	/* Check for broken DSA PKCS#8, UGH! */
209 	if (*p == (V_ASN1_SEQUENCE|V_ASN1_CONSTRUCTED))
210 		{
211 		ASN1_TYPE *t1, *t2;
212 	    	if(!(ndsa = d2i_ASN1_SEQUENCE_ANY(NULL, &p, pklen)));
213 			goto decerr;
214 		if (sk_ASN1_TYPE_num(ndsa) != 2)
215 			goto decerr;
216 		/* Handle Two broken types:
217 	    	 * SEQUENCE {parameters, priv_key}
218 		 * SEQUENCE {pub_key, priv_key}
219 		 */
220 
221 		t1 = sk_ASN1_TYPE_value(ndsa, 0);
222 		t2 = sk_ASN1_TYPE_value(ndsa, 1);
223 		if (t1->type == V_ASN1_SEQUENCE)
224 			{
225 			p8->broken = PKCS8_EMBEDDED_PARAM;
226 			pval = t1->value.ptr;
227 			}
228 		else if (ptype == V_ASN1_SEQUENCE)
229 			p8->broken = PKCS8_NS_DB;
230 		else
231 			goto decerr;
232 
233 		if (t2->type != V_ASN1_INTEGER)
234 			goto decerr;
235 
236 		privkey = t2->value.integer;
237 		}
238 	else
239 		{
240 		if (!(privkey=d2i_ASN1_INTEGER(NULL, &p, pklen)))
241 			goto decerr;
242 		if (ptype != V_ASN1_SEQUENCE)
243 			goto decerr;
244 		}
245 
246 	pstr = pval;
247 	pm = pstr->data;
248 	pmlen = pstr->length;
249 	if (!(dsa = d2i_DSAparams(NULL, &pm, pmlen)))
250 		goto decerr;
251 	/* We have parameters now set private key */
252 	if (!(dsa->priv_key = ASN1_INTEGER_to_BN(privkey, NULL)))
253 		{
254 		DSAerr(DSA_F_DSA_PRIV_DECODE,DSA_R_BN_ERROR);
255 		goto dsaerr;
256 		}
257 	/* Calculate public key */
258 	if (!(dsa->pub_key = BN_new()))
259 		{
260 		DSAerr(DSA_F_DSA_PRIV_DECODE, ERR_R_MALLOC_FAILURE);
261 		goto dsaerr;
262 		}
263 	if (!(ctx = BN_CTX_new()))
264 		{
265 		DSAerr(DSA_F_DSA_PRIV_DECODE, ERR_R_MALLOC_FAILURE);
266 		goto dsaerr;
267 		}
268 
269 	if (!BN_mod_exp(dsa->pub_key, dsa->g, dsa->priv_key, dsa->p, ctx))
270 		{
271 		DSAerr(DSA_F_DSA_PRIV_DECODE,DSA_R_BN_ERROR);
272 		goto dsaerr;
273 		}
274 
275 	EVP_PKEY_assign_DSA(pkey, dsa);
276 	BN_CTX_free (ctx);
277 	if(ndsa)
278 		sk_ASN1_TYPE_pop_free(ndsa, ASN1_TYPE_free);
279 	else
280 		ASN1_INTEGER_free(privkey);
281 
282 	return 1;
283 
284 	decerr:
285 	DSAerr(DSA_F_DSA_PRIV_DECODE, EVP_R_DECODE_ERROR);
286 	dsaerr:
287 	BN_CTX_free (ctx);
288 	if (privkey)
289 		ASN1_INTEGER_free(privkey);
290 	sk_ASN1_TYPE_pop_free(ndsa, ASN1_TYPE_free);
291 	DSA_free(dsa);
292 	return 0;
293 	}
294 
295 static int dsa_priv_encode(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pkey)
296 {
297 	ASN1_STRING *params = NULL;
298 	ASN1_INTEGER *prkey = NULL;
299 	unsigned char *dp = NULL;
300 	int dplen;
301 
302 	params = ASN1_STRING_new();
303 
304 	if (!params)
305 		{
306 		DSAerr(DSA_F_DSA_PRIV_ENCODE,ERR_R_MALLOC_FAILURE);
307 		goto err;
308 		}
309 
310 	params->length = i2d_DSAparams(pkey->pkey.dsa, &params->data);
311 	if (params->length <= 0)
312 		{
313 		DSAerr(DSA_F_DSA_PRIV_ENCODE,ERR_R_MALLOC_FAILURE);
314 		goto err;
315 		}
316 	params->type = V_ASN1_SEQUENCE;
317 
318 	/* Get private key into integer */
319 	prkey = BN_to_ASN1_INTEGER(pkey->pkey.dsa->priv_key, NULL);
320 
321 	if (!prkey)
322 		{
323 		DSAerr(DSA_F_DSA_PRIV_ENCODE,DSA_R_BN_ERROR);
324 		goto err;
325 		}
326 
327 	dplen = i2d_ASN1_INTEGER(prkey, &dp);
328 
329 	ASN1_INTEGER_free(prkey);
330 
331 	if (!PKCS8_pkey_set0(p8, OBJ_nid2obj(NID_dsa), 0,
332 				V_ASN1_SEQUENCE, params, dp, dplen))
333 		goto err;
334 
335 	return 1;
336 
337 err:
338 	if (dp != NULL)
339 		OPENSSL_free(dp);
340 	if (params != NULL)
341 		ASN1_STRING_free(params);
342 	if (prkey != NULL)
343 		ASN1_INTEGER_free(prkey);
344 	return 0;
345 }
346 
347 static int int_dsa_size(const EVP_PKEY *pkey)
348 	{
349 	return(DSA_size(pkey->pkey.dsa));
350 	}
351 
352 static int dsa_bits(const EVP_PKEY *pkey)
353 	{
354 	return BN_num_bits(pkey->pkey.dsa->p);
355 	}
356 
357 static int dsa_missing_parameters(const EVP_PKEY *pkey)
358 	{
359 	DSA *dsa;
360 	dsa=pkey->pkey.dsa;
361 	if ((dsa->p == NULL) || (dsa->q == NULL) || (dsa->g == NULL))
362 			return 1;
363 	return 0;
364 	}
365 
366 static int dsa_copy_parameters(EVP_PKEY *to, const EVP_PKEY *from)
367 	{
368 	BIGNUM *a;
369 
370 	if ((a=BN_dup(from->pkey.dsa->p)) == NULL)
371 		return 0;
372 	if (to->pkey.dsa->p != NULL)
373 		BN_free(to->pkey.dsa->p);
374 	to->pkey.dsa->p=a;
375 
376 	if ((a=BN_dup(from->pkey.dsa->q)) == NULL)
377 		return 0;
378 	if (to->pkey.dsa->q != NULL)
379 		BN_free(to->pkey.dsa->q);
380 	to->pkey.dsa->q=a;
381 
382 	if ((a=BN_dup(from->pkey.dsa->g)) == NULL)
383 		return 0;
384 	if (to->pkey.dsa->g != NULL)
385 		BN_free(to->pkey.dsa->g);
386 	to->pkey.dsa->g=a;
387 	return 1;
388 	}
389 
390 static int dsa_cmp_parameters(const EVP_PKEY *a, const EVP_PKEY *b)
391 	{
392 	if (	BN_cmp(a->pkey.dsa->p,b->pkey.dsa->p) ||
393 		BN_cmp(a->pkey.dsa->q,b->pkey.dsa->q) ||
394 		BN_cmp(a->pkey.dsa->g,b->pkey.dsa->g))
395 		return 0;
396 	else
397 		return 1;
398 	}
399 
400 static int dsa_pub_cmp(const EVP_PKEY *a, const EVP_PKEY *b)
401 	{
402 	if (BN_cmp(b->pkey.dsa->pub_key,a->pkey.dsa->pub_key) != 0)
403 		return 0;
404 	else
405 		return 1;
406 	}
407 
408 static void int_dsa_free(EVP_PKEY *pkey)
409 	{
410 	DSA_free(pkey->pkey.dsa);
411 	}
412 
413 static void update_buflen(const BIGNUM *b, size_t *pbuflen)
414 	{
415 	size_t i;
416 	if (!b)
417 		return;
418 	if (*pbuflen < (i = (size_t)BN_num_bytes(b)))
419 			*pbuflen = i;
420 	}
421 
422 static int do_dsa_print(BIO *bp, const DSA *x, int off, int ptype)
423 	{
424 	unsigned char *m=NULL;
425 	int ret=0;
426 	size_t buf_len=0;
427 	const char *ktype = NULL;
428 
429 	const BIGNUM *priv_key, *pub_key;
430 
431 	if (ptype == 2)
432 		priv_key = x->priv_key;
433 	else
434 		priv_key = NULL;
435 
436 	if (ptype > 0)
437 		pub_key = x->pub_key;
438 	else
439 		pub_key = NULL;
440 
441 	if (ptype == 2)
442 		ktype = "Private-Key";
443 	else if (ptype == 1)
444 		ktype = "Public-Key";
445 	else
446 		ktype = "DSA-Parameters";
447 
448 	update_buflen(x->p, &buf_len);
449 	update_buflen(x->q, &buf_len);
450 	update_buflen(x->g, &buf_len);
451 	update_buflen(priv_key, &buf_len);
452 	update_buflen(pub_key, &buf_len);
453 
454 	m=(unsigned char *)OPENSSL_malloc(buf_len+10);
455 	if (m == NULL)
456 		{
457 		DSAerr(DSA_F_DO_DSA_PRINT,ERR_R_MALLOC_FAILURE);
458 		goto err;
459 		}
460 
461 	if (priv_key)
462 		{
463 		if(!BIO_indent(bp,off,128))
464 		   goto err;
465 		if (BIO_printf(bp,"%s: (%d bit)\n",ktype, BN_num_bits(x->p))
466 			<= 0) goto err;
467 		}
468 
469 	if (!ASN1_bn_print(bp,"priv:",priv_key,m,off))
470 		goto err;
471 	if (!ASN1_bn_print(bp,"pub: ",pub_key,m,off))
472 		goto err;
473 	if (!ASN1_bn_print(bp,"P:   ",x->p,m,off)) goto err;
474 	if (!ASN1_bn_print(bp,"Q:   ",x->q,m,off)) goto err;
475 	if (!ASN1_bn_print(bp,"G:   ",x->g,m,off)) goto err;
476 	ret=1;
477 err:
478 	if (m != NULL) OPENSSL_free(m);
479 	return(ret);
480 	}
481 
482 static int dsa_param_decode(EVP_PKEY *pkey,
483 					const unsigned char **pder, int derlen)
484 	{
485 	DSA *dsa;
486 	if (!(dsa = d2i_DSAparams(NULL, pder, derlen)))
487 		{
488 		DSAerr(DSA_F_DSA_PARAM_DECODE, ERR_R_DSA_LIB);
489 		return 0;
490 		}
491 	EVP_PKEY_assign_DSA(pkey, dsa);
492 	return 1;
493 	}
494 
495 static int dsa_param_encode(const EVP_PKEY *pkey, unsigned char **pder)
496 	{
497 	return i2d_DSAparams(pkey->pkey.dsa, pder);
498 	}
499 
500 static int dsa_param_print(BIO *bp, const EVP_PKEY *pkey, int indent,
501 							ASN1_PCTX *ctx)
502 	{
503 	return do_dsa_print(bp, pkey->pkey.dsa, indent, 0);
504 	}
505 
506 static int dsa_pub_print(BIO *bp, const EVP_PKEY *pkey, int indent,
507 							ASN1_PCTX *ctx)
508 	{
509 	return do_dsa_print(bp, pkey->pkey.dsa, indent, 1);
510 	}
511 
512 
513 static int dsa_priv_print(BIO *bp, const EVP_PKEY *pkey, int indent,
514 							ASN1_PCTX *ctx)
515 	{
516 	return do_dsa_print(bp, pkey->pkey.dsa, indent, 2);
517 	}
518 
519 static int old_dsa_priv_decode(EVP_PKEY *pkey,
520 					const unsigned char **pder, int derlen)
521 	{
522 	DSA *dsa;
523 	if (!(dsa = d2i_DSAPrivateKey (NULL, pder, derlen)))
524 		{
525 		DSAerr(DSA_F_OLD_DSA_PRIV_DECODE, ERR_R_DSA_LIB);
526 		return 0;
527 		}
528 	EVP_PKEY_assign_DSA(pkey, dsa);
529 	return 1;
530 	}
531 
532 static int old_dsa_priv_encode(const EVP_PKEY *pkey, unsigned char **pder)
533 	{
534 	return i2d_DSAPrivateKey(pkey->pkey.dsa, pder);
535 	}
536 
537 static int dsa_pkey_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2)
538 	{
539 	switch (op)
540 		{
541 		case ASN1_PKEY_CTRL_PKCS7_SIGN:
542 		if (arg1 == 0)
543 			{
544 			int snid, hnid;
545 			X509_ALGOR *alg1, *alg2;
546 			PKCS7_SIGNER_INFO_get0_algs(arg2, NULL, &alg1, &alg2);
547 			if (alg1 == NULL || alg1->algorithm == NULL)
548 				return -1;
549 			hnid = OBJ_obj2nid(alg1->algorithm);
550 			if (hnid == NID_undef)
551 				return -1;
552 			if (!OBJ_find_sigid_by_algs(&snid, hnid, EVP_PKEY_id(pkey)))
553 				return -1;
554 			X509_ALGOR_set0(alg2, OBJ_nid2obj(snid), V_ASN1_UNDEF, 0);
555 			}
556 		return 1;
557 #ifndef OPENSSL_NO_CMS
558 		case ASN1_PKEY_CTRL_CMS_SIGN:
559 		if (arg1 == 0)
560 			{
561 			int snid, hnid;
562 			X509_ALGOR *alg1, *alg2;
563 			CMS_SignerInfo_get0_algs(arg2, NULL, NULL, &alg1, &alg2);
564 			if (alg1 == NULL || alg1->algorithm == NULL)
565 				return -1;
566 			hnid = OBJ_obj2nid(alg1->algorithm);
567 			if (hnid == NID_undef)
568 				return -1;
569 			if (!OBJ_find_sigid_by_algs(&snid, hnid, EVP_PKEY_id(pkey)))
570 				return -1;
571 			X509_ALGOR_set0(alg2, OBJ_nid2obj(snid), V_ASN1_UNDEF, 0);
572 			}
573 		return 1;
574 #endif
575 
576 		case ASN1_PKEY_CTRL_DEFAULT_MD_NID:
577 		*(int *)arg2 = NID_sha1;
578 		return 2;
579 
580 		default:
581 		return -2;
582 
583 		}
584 
585 	}
586 
587 /* NB these are sorted in pkey_id order, lowest first */
588 
589 const EVP_PKEY_ASN1_METHOD dsa_asn1_meths[] =
590 	{
591 
592 		{
593 		EVP_PKEY_DSA2,
594 		EVP_PKEY_DSA,
595 		ASN1_PKEY_ALIAS
596 		},
597 
598 		{
599 		EVP_PKEY_DSA1,
600 		EVP_PKEY_DSA,
601 		ASN1_PKEY_ALIAS
602 		},
603 
604 		{
605 		EVP_PKEY_DSA4,
606 		EVP_PKEY_DSA,
607 		ASN1_PKEY_ALIAS
608 		},
609 
610 		{
611 		EVP_PKEY_DSA3,
612 		EVP_PKEY_DSA,
613 		ASN1_PKEY_ALIAS
614 		},
615 
616 		{
617 		EVP_PKEY_DSA,
618 		EVP_PKEY_DSA,
619 		0,
620 
621 		"DSA",
622 		"OpenSSL DSA method",
623 
624 		dsa_pub_decode,
625 		dsa_pub_encode,
626 		dsa_pub_cmp,
627 		dsa_pub_print,
628 
629 		dsa_priv_decode,
630 		dsa_priv_encode,
631 		dsa_priv_print,
632 
633 		int_dsa_size,
634 		dsa_bits,
635 
636 		dsa_param_decode,
637 		dsa_param_encode,
638 		dsa_missing_parameters,
639 		dsa_copy_parameters,
640 		dsa_cmp_parameters,
641 		dsa_param_print,
642 
643 		int_dsa_free,
644 		dsa_pkey_ctrl,
645 		old_dsa_priv_decode,
646 		old_dsa_priv_encode
647 		}
648 	};
649 
650