QUIC DEMUX: (Server support) Add support for default handler
[openssl.git] / crypto / property / property_parse.c
1 /*
2  * Copyright 2019-2022 The OpenSSL Project Authors. All Rights Reserved.
3  * Copyright (c) 2019, Oracle and/or its affiliates.  All rights reserved.
4  *
5  * Licensed under the Apache License 2.0 (the "License").  You may not use
6  * this file except in compliance with the License.  You can obtain a copy
7  * in the file LICENSE in the source distribution or at
8  * https://www.openssl.org/source/license.html
9  */
10
11 #include <string.h>
12 #include <stdio.h>
13 #include <stdarg.h>
14 #include <openssl/err.h>
15 #include "internal/propertyerr.h"
16 #include "internal/property.h"
17 #include "crypto/ctype.h"
18 #include "internal/nelem.h"
19 #include "property_local.h"
20 #include "internal/e_os.h"
21
22 DEFINE_STACK_OF(OSSL_PROPERTY_DEFINITION)
23
24 static const char *skip_space(const char *s)
25 {
26     while (ossl_isspace(*s))
27         s++;
28     return s;
29 }
30
31 static int match_ch(const char *t[], char m)
32 {
33     const char *s = *t;
34
35     if (*s == m) {
36         *t = skip_space(s + 1);
37         return 1;
38     }
39     return 0;
40 }
41
42 #define MATCH(s, m) match(s, m, sizeof(m) - 1)
43
44 static int match(const char *t[], const char m[], size_t m_len)
45 {
46     const char *s = *t;
47
48     if (OPENSSL_strncasecmp(s, m, m_len) == 0) {
49         *t = skip_space(s + m_len);
50         return 1;
51     }
52     return 0;
53 }
54
55 static int parse_name(OSSL_LIB_CTX *ctx, const char *t[], int create,
56                       OSSL_PROPERTY_IDX *idx)
57 {
58     char name[100];
59     int err = 0;
60     size_t i = 0;
61     const char *s = *t;
62     int user_name = 0;
63
64     for (;;) {
65         if (!ossl_isalpha(*s)) {
66             ERR_raise_data(ERR_LIB_PROP, PROP_R_NOT_AN_IDENTIFIER,
67                            "HERE-->%s", *t);
68             return 0;
69         }
70         do {
71             if (i < sizeof(name) - 1)
72                 name[i++] = ossl_tolower(*s);
73             else
74                 err = 1;
75         } while (*++s == '_' || ossl_isalnum(*s));
76         if (*s != '.')
77             break;
78         user_name = 1;
79         if (i < sizeof(name) - 1)
80             name[i++] = *s;
81         else
82             err = 1;
83         s++;
84     }
85     name[i] = '\0';
86     if (err) {
87         ERR_raise_data(ERR_LIB_PROP, PROP_R_NAME_TOO_LONG, "HERE-->%s", *t);
88         return 0;
89     }
90     *t = skip_space(s);
91     *idx = ossl_property_name(ctx, name, user_name && create);
92     return 1;
93 }
94
95 static int parse_number(const char *t[], OSSL_PROPERTY_DEFINITION *res)
96 {
97     const char *s = *t;
98     int64_t v = 0;
99
100     if (!ossl_isdigit(*s))
101         return 0;
102     do {
103         v = v * 10 + (*s++ - '0');
104     } while (ossl_isdigit(*s));
105     if (!ossl_isspace(*s) && *s != '\0' && *s != ',') {
106         ERR_raise_data(ERR_LIB_PROP, PROP_R_NOT_A_DECIMAL_DIGIT,
107                        "HERE-->%s", *t);
108         return 0;
109     }
110     *t = skip_space(s);
111     res->type = OSSL_PROPERTY_TYPE_NUMBER;
112     res->v.int_val = v;
113     return 1;
114 }
115
116 static int parse_hex(const char *t[], OSSL_PROPERTY_DEFINITION *res)
117 {
118     const char *s = *t;
119     int64_t v = 0;
120
121     if (!ossl_isxdigit(*s))
122         return 0;
123     do {
124         v <<= 4;
125         if (ossl_isdigit(*s))
126             v += *s - '0';
127         else
128             v += ossl_tolower(*s) - 'a';
129     } while (ossl_isxdigit(*++s));
130     if (!ossl_isspace(*s) && *s != '\0' && *s != ',') {
131         ERR_raise_data(ERR_LIB_PROP, PROP_R_NOT_AN_HEXADECIMAL_DIGIT,
132                        "HERE-->%s", *t);
133         return 0;
134     }
135     *t = skip_space(s);
136     res->type = OSSL_PROPERTY_TYPE_NUMBER;
137     res->v.int_val = v;
138     return 1;
139 }
140
141 static int parse_oct(const char *t[], OSSL_PROPERTY_DEFINITION *res)
142 {
143     const char *s = *t;
144     int64_t v = 0;
145
146     if (*s == '9' || *s == '8' || !ossl_isdigit(*s))
147         return 0;
148     do {
149         v = (v << 3) + (*s - '0');
150     } while (ossl_isdigit(*++s) && *s != '9' && *s != '8');
151     if (!ossl_isspace(*s) && *s != '\0' && *s != ',') {
152         ERR_raise_data(ERR_LIB_PROP, PROP_R_NOT_AN_OCTAL_DIGIT,
153                        "HERE-->%s", *t);
154         return 0;
155     }
156     *t = skip_space(s);
157     res->type = OSSL_PROPERTY_TYPE_NUMBER;
158     res->v.int_val = v;
159     return 1;
160 }
161
162 static int parse_string(OSSL_LIB_CTX *ctx, const char *t[], char delim,
163                         OSSL_PROPERTY_DEFINITION *res, const int create)
164 {
165     char v[1000];
166     const char *s = *t;
167     size_t i = 0;
168     int err = 0;
169
170     while (*s != '\0' && *s != delim) {
171         if (i < sizeof(v) - 1)
172             v[i++] = *s;
173         else
174             err = 1;
175         s++;
176     }
177     if (*s == '\0') {
178         ERR_raise_data(ERR_LIB_PROP, PROP_R_NO_MATCHING_STRING_DELIMITER,
179                        "HERE-->%c%s", delim, *t);
180         return 0;
181     }
182     v[i] = '\0';
183     if (err) {
184         ERR_raise_data(ERR_LIB_PROP, PROP_R_STRING_TOO_LONG, "HERE-->%s", *t);
185     } else {
186         res->v.str_val = ossl_property_value(ctx, v, create);
187     }
188     *t = skip_space(s + 1);
189     res->type = OSSL_PROPERTY_TYPE_STRING;
190     return !err;
191 }
192
193 static int parse_unquoted(OSSL_LIB_CTX *ctx, const char *t[],
194                           OSSL_PROPERTY_DEFINITION *res, const int create)
195 {
196     char v[1000];
197     const char *s = *t;
198     size_t i = 0;
199     int err = 0;
200
201     if (*s == '\0' || *s == ',')
202         return 0;
203     while (ossl_isprint(*s) && !ossl_isspace(*s) && *s != ',') {
204         if (i < sizeof(v) - 1)
205             v[i++] = ossl_tolower(*s);
206         else
207             err = 1;
208         s++;
209     }
210     if (!ossl_isspace(*s) && *s != '\0' && *s != ',') {
211         ERR_raise_data(ERR_LIB_PROP, PROP_R_NOT_AN_ASCII_CHARACTER,
212                        "HERE-->%s", s);
213         return 0;
214     }
215     v[i] = 0;
216     if (err)
217         ERR_raise_data(ERR_LIB_PROP, PROP_R_STRING_TOO_LONG, "HERE-->%s", *t);
218     else if ((res->v.str_val = ossl_property_value(ctx, v, create)) == 0)
219         err = 1;
220     *t = skip_space(s);
221     res->type = OSSL_PROPERTY_TYPE_STRING;
222     return !err;
223 }
224
225 static int parse_value(OSSL_LIB_CTX *ctx, const char *t[],
226                        OSSL_PROPERTY_DEFINITION *res, int create)
227 {
228     const char *s = *t;
229     int r = 0;
230
231     if (*s == '"' || *s == '\'') {
232         s++;
233         r = parse_string(ctx, &s, s[-1], res, create);
234     } else if (*s == '+') {
235         s++;
236         r = parse_number(&s, res);
237     } else if (*s == '-') {
238         s++;
239         r = parse_number(&s, res);
240         res->v.int_val = -res->v.int_val;
241     } else if (*s == '0' && s[1] == 'x') {
242         s += 2;
243         r = parse_hex(&s, res);
244     } else if (*s == '0' && ossl_isdigit(s[1])) {
245         s++;
246         r = parse_oct(&s, res);
247     } else if (ossl_isdigit(*s)) {
248         return parse_number(t, res);
249     } else if (ossl_isalpha(*s))
250         return parse_unquoted(ctx, t, res, create);
251     if (r)
252         *t = s;
253     return r;
254 }
255
256 static int pd_compare(const OSSL_PROPERTY_DEFINITION *const *p1,
257                       const OSSL_PROPERTY_DEFINITION *const *p2)
258 {
259     const OSSL_PROPERTY_DEFINITION *pd1 = *p1;
260     const OSSL_PROPERTY_DEFINITION *pd2 = *p2;
261
262     if (pd1->name_idx < pd2->name_idx)
263         return -1;
264     if (pd1->name_idx > pd2->name_idx)
265         return 1;
266     return 0;
267 }
268
269 static void pd_free(OSSL_PROPERTY_DEFINITION *pd)
270 {
271     OPENSSL_free(pd);
272 }
273
274 /*
275  * Convert a stack of property definitions and queries into a fixed array.
276  * The items are sorted for efficient query.  The stack is not freed.
277  * This function also checks for duplicated names and returns an error if
278  * any exist.
279  */
280 static OSSL_PROPERTY_LIST *
281 stack_to_property_list(OSSL_LIB_CTX *ctx,
282                        STACK_OF(OSSL_PROPERTY_DEFINITION) *sk)
283 {
284     const int n = sk_OSSL_PROPERTY_DEFINITION_num(sk);
285     OSSL_PROPERTY_LIST *r;
286     OSSL_PROPERTY_IDX prev_name_idx = 0;
287     int i;
288
289     r = OPENSSL_malloc(sizeof(*r)
290                        + (n <= 0 ? 0 : n - 1) * sizeof(r->properties[0]));
291     if (r != NULL) {
292         sk_OSSL_PROPERTY_DEFINITION_sort(sk);
293
294         r->has_optional = 0;
295         for (i = 0; i < n; i++) {
296             r->properties[i] = *sk_OSSL_PROPERTY_DEFINITION_value(sk, i);
297             r->has_optional |= r->properties[i].optional;
298
299             /* Check for duplicated names */
300             if (i > 0 && r->properties[i].name_idx == prev_name_idx) {
301                 OPENSSL_free(r);
302                 ERR_raise_data(ERR_LIB_PROP, PROP_R_PARSE_FAILED,
303                                "Duplicated name `%s'",
304                                ossl_property_name_str(ctx, prev_name_idx));
305                 return NULL;
306             }
307             prev_name_idx = r->properties[i].name_idx;
308         }
309         r->num_properties = n;
310     }
311     return r;
312 }
313
314 OSSL_PROPERTY_LIST *ossl_parse_property(OSSL_LIB_CTX *ctx, const char *defn)
315 {
316     OSSL_PROPERTY_DEFINITION *prop = NULL;
317     OSSL_PROPERTY_LIST *res = NULL;
318     STACK_OF(OSSL_PROPERTY_DEFINITION) *sk;
319     const char *s = defn;
320     int done;
321
322     if (s == NULL || (sk = sk_OSSL_PROPERTY_DEFINITION_new(&pd_compare)) == NULL)
323         return NULL;
324
325     s = skip_space(s);
326     done = *s == '\0';
327     while (!done) {
328         const char *start = s;
329
330         prop = OPENSSL_malloc(sizeof(*prop));
331         if (prop == NULL)
332             goto err;
333         memset(&prop->v, 0, sizeof(prop->v));
334         prop->optional = 0;
335         if (!parse_name(ctx, &s, 1, &prop->name_idx))
336             goto err;
337         prop->oper = OSSL_PROPERTY_OPER_EQ;
338         if (prop->name_idx == 0) {
339             ERR_raise_data(ERR_LIB_PROP, PROP_R_PARSE_FAILED,
340                            "Unknown name HERE-->%s", start);
341             goto err;
342         }
343         if (match_ch(&s, '=')) {
344             if (!parse_value(ctx, &s, prop, 1)) {
345                 ERR_raise_data(ERR_LIB_PROP, PROP_R_NO_VALUE,
346                                "HERE-->%s", start);
347                 goto err;
348             }
349         } else {
350             /* A name alone means a true Boolean */
351             prop->type = OSSL_PROPERTY_TYPE_STRING;
352             prop->v.str_val = OSSL_PROPERTY_TRUE;
353         }
354
355         if (!sk_OSSL_PROPERTY_DEFINITION_push(sk, prop))
356             goto err;
357         prop = NULL;
358         done = !match_ch(&s, ',');
359     }
360     if (*s != '\0') {
361         ERR_raise_data(ERR_LIB_PROP, PROP_R_TRAILING_CHARACTERS,
362                        "HERE-->%s", s);
363         goto err;
364     }
365     res = stack_to_property_list(ctx, sk);
366
367 err:
368     OPENSSL_free(prop);
369     sk_OSSL_PROPERTY_DEFINITION_pop_free(sk, &pd_free);
370     return res;
371 }
372
373 OSSL_PROPERTY_LIST *ossl_parse_query(OSSL_LIB_CTX *ctx, const char *s,
374                                      int create_values)
375 {
376     STACK_OF(OSSL_PROPERTY_DEFINITION) *sk;
377     OSSL_PROPERTY_LIST *res = NULL;
378     OSSL_PROPERTY_DEFINITION *prop = NULL;
379     int done;
380
381     if (s == NULL || (sk = sk_OSSL_PROPERTY_DEFINITION_new(&pd_compare)) == NULL)
382         return NULL;
383
384     s = skip_space(s);
385     done = *s == '\0';
386     while (!done) {
387         prop = OPENSSL_malloc(sizeof(*prop));
388         if (prop == NULL)
389             goto err;
390         memset(&prop->v, 0, sizeof(prop->v));
391
392         if (match_ch(&s, '-')) {
393             prop->oper = OSSL_PROPERTY_OVERRIDE;
394             prop->optional = 0;
395             if (!parse_name(ctx, &s, 1, &prop->name_idx))
396                 goto err;
397             goto skip_value;
398         }
399         prop->optional = match_ch(&s, '?');
400         if (!parse_name(ctx, &s, 1, &prop->name_idx))
401             goto err;
402
403         if (match_ch(&s, '=')) {
404             prop->oper = OSSL_PROPERTY_OPER_EQ;
405         } else if (MATCH(&s, "!=")) {
406             prop->oper = OSSL_PROPERTY_OPER_NE;
407         } else {
408             /* A name alone is a Boolean comparison for true */
409             prop->oper = OSSL_PROPERTY_OPER_EQ;
410             prop->type = OSSL_PROPERTY_TYPE_STRING;
411             prop->v.str_val = OSSL_PROPERTY_TRUE;
412             goto skip_value;
413         }
414         if (!parse_value(ctx, &s, prop, create_values))
415             prop->type = OSSL_PROPERTY_TYPE_VALUE_UNDEFINED;
416
417 skip_value:
418         if (!sk_OSSL_PROPERTY_DEFINITION_push(sk, prop))
419             goto err;
420         prop = NULL;
421         done = !match_ch(&s, ',');
422     }
423     if (*s != '\0') {
424         ERR_raise_data(ERR_LIB_PROP, PROP_R_TRAILING_CHARACTERS,
425                        "HERE-->%s", s);
426         goto err;
427     }
428     res = stack_to_property_list(ctx, sk);
429
430 err:
431     OPENSSL_free(prop);
432     sk_OSSL_PROPERTY_DEFINITION_pop_free(sk, &pd_free);
433     return res;
434 }
435
436 /*
437  * Compare a query against a definition.
438  * Return the number of clauses matched or -1 if a mandatory clause is false.
439  */
440 int ossl_property_match_count(const OSSL_PROPERTY_LIST *query,
441                               const OSSL_PROPERTY_LIST *defn)
442 {
443     const OSSL_PROPERTY_DEFINITION *const q = query->properties;
444     const OSSL_PROPERTY_DEFINITION *const d = defn->properties;
445     int i = 0, j = 0, matches = 0;
446     OSSL_PROPERTY_OPER oper;
447
448     while (i < query->num_properties) {
449         if ((oper = q[i].oper) == OSSL_PROPERTY_OVERRIDE) {
450             i++;
451             continue;
452         }
453         if (j < defn->num_properties) {
454             if (q[i].name_idx > d[j].name_idx) {  /* skip defn, not in query */
455                 j++;
456                 continue;
457             }
458             if (q[i].name_idx == d[j].name_idx) { /* both in defn and query */
459                 const int eq = q[i].type == d[j].type
460                                && memcmp(&q[i].v, &d[j].v, sizeof(q[i].v)) == 0;
461
462                 if ((eq && oper == OSSL_PROPERTY_OPER_EQ)
463                     || (!eq && oper == OSSL_PROPERTY_OPER_NE))
464                     matches++;
465                 else if (!q[i].optional)
466                     return -1;
467                 i++;
468                 j++;
469                 continue;
470             }
471         }
472
473         /*
474          * Handle the cases of a missing value and a query with no corresponding
475          * definition.  The former fails for any comparison except inequality,
476          * the latter is treated as a comparison against the Boolean false.
477          */
478         if (q[i].type == OSSL_PROPERTY_TYPE_VALUE_UNDEFINED) {
479             if (oper == OSSL_PROPERTY_OPER_NE)
480                 matches++;
481             else if (!q[i].optional)
482                 return -1;
483         } else if (q[i].type != OSSL_PROPERTY_TYPE_STRING
484                    || (oper == OSSL_PROPERTY_OPER_EQ
485                        && q[i].v.str_val != OSSL_PROPERTY_FALSE)
486                    || (oper == OSSL_PROPERTY_OPER_NE
487                        && q[i].v.str_val == OSSL_PROPERTY_FALSE)) {
488             if (!q[i].optional)
489                 return -1;
490         } else {
491             matches++;
492         }
493         i++;
494     }
495     return matches;
496 }
497
498 void ossl_property_free(OSSL_PROPERTY_LIST *p)
499 {
500     OPENSSL_free(p);
501 }
502
503 /*
504  * Merge two property lists.
505  * If there is a common name, the one from the first list is used.
506  */
507 OSSL_PROPERTY_LIST *ossl_property_merge(const OSSL_PROPERTY_LIST *a,
508                                         const OSSL_PROPERTY_LIST *b)
509 {
510     const OSSL_PROPERTY_DEFINITION *const ap = a->properties;
511     const OSSL_PROPERTY_DEFINITION *const bp = b->properties;
512     const OSSL_PROPERTY_DEFINITION *copy;
513     OSSL_PROPERTY_LIST *r;
514     int i, j, n;
515     const int t = a->num_properties + b->num_properties;
516
517     r = OPENSSL_malloc(sizeof(*r)
518                        + (t == 0 ? 0 : t - 1) * sizeof(r->properties[0]));
519     if (r == NULL)
520         return NULL;
521
522     r->has_optional = 0;
523     for (i = j = n = 0; i < a->num_properties || j < b->num_properties; n++) {
524         if (i >= a->num_properties) {
525             copy = &bp[j++];
526         } else if (j >= b->num_properties) {
527             copy = &ap[i++];
528         } else if (ap[i].name_idx <= bp[j].name_idx) {
529             if (ap[i].name_idx == bp[j].name_idx)
530                 j++;
531             copy = &ap[i++];
532         } else {
533             copy = &bp[j++];
534         }
535         memcpy(r->properties + n, copy, sizeof(r->properties[0]));
536         r->has_optional |= copy->optional;
537     }
538     r->num_properties = n;
539     if (n != t)
540         r = OPENSSL_realloc(r, sizeof(*r) + (n - 1) * sizeof(r->properties[0]));
541     return r;
542 }
543
544 int ossl_property_parse_init(OSSL_LIB_CTX *ctx)
545 {
546     static const char *const predefined_names[] = {
547         "provider",     /* Name of provider (default, legacy, fips) */
548         "version",      /* Version number of this provider */
549         "fips",         /* FIPS validated or FIPS supporting algorithm */
550         "output",       /* Output type for encoders */
551         "input",        /* Input type for decoders */
552         "structure",    /* Structure name for encoders and decoders */
553     };
554     size_t i;
555
556     for (i = 0; i < OSSL_NELEM(predefined_names); i++)
557         if (ossl_property_name(ctx, predefined_names[i], 1) == 0)
558             goto err;
559
560     /*
561      * Pre-populate the two Boolean values. We must do them before any other
562      * values and in this order so that we get the same index as the global
563      * OSSL_PROPERTY_TRUE and OSSL_PROPERTY_FALSE values
564      */
565     if ((ossl_property_value(ctx, "yes", 1) != OSSL_PROPERTY_TRUE)
566         || (ossl_property_value(ctx, "no", 1) != OSSL_PROPERTY_FALSE))
567         goto err;
568
569     return 1;
570 err:
571     return 0;
572 }
573
574 static void put_char(char ch, char **buf, size_t *remain, size_t *needed)
575 {
576     if (*remain == 0) {
577         ++*needed;
578         return;
579     }
580     if (*remain == 1)
581         **buf = '\0';
582     else
583         **buf = ch;
584     ++*buf;
585     ++*needed;
586     --*remain;
587 }
588
589 static void put_str(const char *str, char **buf, size_t *remain, size_t *needed)
590 {
591     size_t olen, len;
592
593     len = olen = strlen(str);
594     *needed += len;
595
596     if (*remain == 0)
597         return;
598
599     if (*remain < len + 1)
600         len = *remain - 1;
601
602     if (len > 0) {
603         memcpy(*buf, str, len);
604         *buf += len;
605         *remain -= len;
606     }
607
608     if (len < olen && *remain == 1) {
609         **buf = '\0';
610         ++*buf;
611         --*remain;
612     }
613 }
614
615 static void put_num(int64_t val, char **buf, size_t *remain, size_t *needed)
616 {
617     int64_t tmpval = val;
618     size_t len = 1;
619
620     if (tmpval < 0) {
621         len++;
622         tmpval = -tmpval;
623     }
624     for (; tmpval > 9; len++, tmpval /= 10);
625
626     *needed += len;
627
628     if (*remain == 0)
629         return;
630
631     BIO_snprintf(*buf, *remain, "%lld", (long long int)val);
632     if (*remain < len) {
633         *buf += *remain;
634         *remain = 0;
635     } else {
636         *buf += len;
637         *remain -= len;
638     }
639 }
640
641 size_t ossl_property_list_to_string(OSSL_LIB_CTX *ctx,
642                                     const OSSL_PROPERTY_LIST *list, char *buf,
643                                     size_t bufsize)
644 {
645     int i;
646     const OSSL_PROPERTY_DEFINITION *prop = NULL;
647     size_t needed = 0;
648     const char *val;
649
650     if (list == NULL) {
651         if (bufsize > 0)
652             *buf = '\0';
653         return 1;
654     }
655     if (list->num_properties != 0)
656         prop = &list->properties[list->num_properties - 1];
657     for (i = 0; i < list->num_properties; i++, prop--) {
658         /* Skip invalid names */
659         if (prop->name_idx == 0)
660             continue;
661
662         if (needed > 0)
663             put_char(',', &buf, &bufsize, &needed);
664
665         if (prop->optional)
666             put_char('?', &buf, &bufsize, &needed);
667         else if (prop->oper == OSSL_PROPERTY_OVERRIDE)
668             put_char('-', &buf, &bufsize, &needed);
669
670         val = ossl_property_name_str(ctx, prop->name_idx);
671         if (val == NULL)
672             return 0;
673         put_str(val, &buf, &bufsize, &needed);
674
675         switch (prop->oper) {
676             case OSSL_PROPERTY_OPER_NE:
677                 put_char('!', &buf, &bufsize, &needed);
678                 /* fall through */
679             case OSSL_PROPERTY_OPER_EQ:
680                 put_char('=', &buf, &bufsize, &needed);
681                 /* put value */
682                 switch (prop->type) {
683                 case OSSL_PROPERTY_TYPE_STRING:
684                     val = ossl_property_value_str(ctx, prop->v.str_val);
685                     if (val == NULL)
686                         return 0;
687                     put_str(val, &buf, &bufsize, &needed);
688                     break;
689
690                 case OSSL_PROPERTY_TYPE_NUMBER:
691                     put_num(prop->v.int_val, &buf, &bufsize, &needed);
692                     break;
693
694                 default:
695                     return 0;
696                 }
697                 break;
698             default:
699                 /* do nothing */
700                 break;
701         }
702     }
703
704     put_char('\0', &buf, &bufsize, &needed);
705     return needed;
706 }