/*
- * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2019-2020 The OpenSSL Project Authors. All Rights Reserved.
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
#include <openssl/err.h>
#include "internal/propertyerr.h"
#include "internal/property.h"
-#include "internal/ctype.h"
+#include "crypto/ctype.h"
#include "internal/nelem.h"
-#include "property_lcl.h"
+#include "property_local.h"
#include "e_os.h"
typedef enum {
OSSL_PROPERTY_IDX name_idx;
PROPERTY_TYPE type;
PROPERTY_OPER oper;
+ unsigned int optional : 1;
union {
int64_t int_val; /* Signed integer */
OSSL_PROPERTY_IDX str_val; /* String */
struct ossl_property_list_st {
int n;
+ unsigned int has_optional : 1;
PROPERTY_DEFINITION properties[1];
};
for (;;) {
if (!ossl_isalpha(*s)) {
- PROPerr(PROP_F_PARSE_NAME, PROP_R_NOT_AN_IDENTIFIER);
+ ERR_raise_data(ERR_LIB_PROP, PROP_R_NOT_AN_IDENTIFIER,
+ "HERE-->%s", *t);
return 0;
}
do {
s++;
}
name[i] = '\0';
- *t = skip_space(s);
- if (!err) {
- *idx = ossl_property_name(ctx, name, user_name && create);
- return 1;
+ if (err) {
+ ERR_raise_data(ERR_LIB_PROP, PROP_R_NAME_TOO_LONG, "HERE-->%s", *t);
+ return 0;
}
- PROPerr(PROP_F_PARSE_NAME, PROP_R_NAME_TOO_LONG);
- return 0;
+ *t = skip_space(s);
+ *idx = ossl_property_name(ctx, name, user_name && create);
+ return 1;
}
static int parse_number(const char *t[], PROPERTY_DEFINITION *res)
v = v * 10 + (*s++ - '0');
} while (ossl_isdigit(*s));
if (!ossl_isspace(*s) && *s != '\0' && *s != ',') {
- PROPerr(PROP_F_PARSE_NUMBER, PROP_R_NOT_A_DECIMAL_DIGIT);
+ ERR_raise_data(ERR_LIB_PROP, PROP_R_NOT_A_DECIMAL_DIGIT,
+ "HERE-->%s", *t);
return 0;
}
*t = skip_space(s);
v += ossl_tolower(*s) - 'a';
} while (ossl_isxdigit(*++s));
if (!ossl_isspace(*s) && *s != '\0' && *s != ',') {
- PROPerr(PROP_F_PARSE_HEX, PROP_R_NOT_AN_HEXADECIMAL_DIGIT);
+ ERR_raise_data(ERR_LIB_PROP, PROP_R_NOT_AN_HEXADECIMAL_DIGIT,
+ "HERE-->%s", *t);
return 0;
}
*t = skip_space(s);
v = (v << 3) + (*s - '0');
} while (ossl_isdigit(*++s) && *s != '9' && *s != '8');
if (!ossl_isspace(*s) && *s != '\0' && *s != ',') {
- PROPerr(PROP_F_PARSE_OCT, PROP_R_NOT_AN_OCTAL_DIGIT);
+ ERR_raise_data(ERR_LIB_PROP, PROP_R_NOT_AN_OCTAL_DIGIT,
+ "HERE-->%s", *t);
return 0;
}
*t = skip_space(s);
s++;
}
if (*s == '\0') {
- PROPerr(PROP_F_PARSE_STRING,
- PROP_R_NO_MATCHING_STRING_DELIMETER);
+ ERR_raise_data(ERR_LIB_PROP, PROP_R_NO_MATCHING_STRING_DELIMITER,
+ "HERE-->%c%s", delim, *t);
return 0;
}
v[i] = '\0';
- *t = skip_space(s + 1);
- if (err)
- PROPerr(PROP_F_PARSE_STRING, PROP_R_STRING_TOO_LONG);
- else
+ if (err) {
+ ERR_raise_data(ERR_LIB_PROP, PROP_R_STRING_TOO_LONG, "HERE-->%s", *t);
+ } else {
res->v.str_val = ossl_property_value(ctx, v, create);
+ }
+ *t = skip_space(s + 1);
res->type = PROPERTY_TYPE_STRING;
return !err;
}
s++;
}
if (!ossl_isspace(*s) && *s != '\0' && *s != ',') {
- PROPerr(PROP_F_PARSE_UNQUOTED, PROP_R_NOT_AN_ASCII_CHARACTER);
+ ERR_raise_data(ERR_LIB_PROP, PROP_R_NOT_AN_ASCII_CHARACTER,
+ "HERE-->%s", s);
return 0;
}
v[i] = 0;
- *t = skip_space(s);
- if (err)
- PROPerr(PROP_F_PARSE_UNQUOTED, PROP_R_STRING_TOO_LONG);
- else
+ if (err) {
+ ERR_raise_data(ERR_LIB_PROP, PROP_R_STRING_TOO_LONG, "HERE-->%s", *t);
+ } else {
res->v.str_val = ossl_property_value(ctx, v, create);
+ }
+ *t = skip_space(s);
res->type = PROPERTY_TYPE_STRING;
return !err;
}
if (r != NULL) {
sk_PROPERTY_DEFINITION_sort(sk);
- for (i = 0; i < n; i++)
+ r->has_optional = 0;
+ for (i = 0; i < n; i++) {
r->properties[i] = *sk_PROPERTY_DEFINITION_value(sk, i);
+ r->has_optional |= r->properties[i].optional;
+ }
r->n = n;
}
return r;
s = skip_space(s);
done = *s == '\0';
while (!done) {
+ const char *start = s;
+
prop = OPENSSL_malloc(sizeof(*prop));
if (prop == NULL)
goto err;
memset(&prop->v, 0, sizeof(prop->v));
+ prop->optional = 0;
if (!parse_name(ctx, &s, 1, &prop->name_idx))
goto err;
prop->oper = PROPERTY_OPER_EQ;
if (prop->name_idx == 0) {
- PROPerr(PROP_F_OSSL_PARSE_PROPERTY, PROP_R_PARSE_FAILED);
+ ERR_raise_data(ERR_LIB_PROP, PROP_R_PARSE_FAILED,
+ "Unknown name HERE-->%s", start);
goto err;
}
if (match_ch(&s, '=')) {
if (!parse_value(ctx, &s, prop, 1)) {
- PROPerr(PROP_F_OSSL_PARSE_PROPERTY, PROP_R_NO_VALUE);
+ ERR_raise_data(ERR_LIB_PROP, PROP_R_NO_VALUE,
+ "HERE-->%s", start);
goto err;
}
} else {
done = !match_ch(&s, ',');
}
if (*s != '\0') {
- PROPerr(PROP_F_OSSL_PARSE_PROPERTY, PROP_R_TRAILING_CHARACTERS);
+ ERR_raise_data(ERR_LIB_PROP, PROP_R_TRAILING_CHARACTERS,
+ "HERE-->%s", s);
goto err;
}
res = stack_to_property_list(sk);
if (match_ch(&s, '-')) {
prop->oper = PROPERTY_OVERRIDE;
+ prop->optional = 0;
if (!parse_name(ctx, &s, 0, &prop->name_idx))
goto err;
goto skip_value;
}
+ prop->optional = match_ch(&s, '?');
if (!parse_name(ctx, &s, 0, &prop->name_idx))
goto err;
done = !match_ch(&s, ',');
}
if (*s != '\0') {
- PROPerr(PROP_F_OSSL_PARSE_QUERY, PROP_R_TRAILING_CHARACTERS);
+ ERR_raise_data(ERR_LIB_PROP, PROP_R_TRAILING_CHARACTERS,
+ "HERE-->%s", s);
goto err;
}
res = stack_to_property_list(sk);
return res;
}
-int ossl_property_match(const OSSL_PROPERTY_LIST *query,
- const OSSL_PROPERTY_LIST *defn)
+/* Does a property query have any optional clauses */
+int ossl_property_has_optional(const OSSL_PROPERTY_LIST *query)
+{
+ return query->has_optional ? 1 : 0;
+}
+
+/*
+ * Compare a query against a definition.
+ * Return the number of clauses matched or -1 if a mandatory clause is false.
+ */
+int ossl_property_match_count(const OSSL_PROPERTY_LIST *query,
+ const OSSL_PROPERTY_LIST *defn)
{
const PROPERTY_DEFINITION *const q = query->properties;
const PROPERTY_DEFINITION *const d = defn->properties;
- int i = 0, j = 0;
+ int i = 0, j = 0, matches = 0;
PROPERTY_OPER oper;
while (i < query->n) {
const int eq = q[i].type == d[j].type
&& memcmp(&q[i].v, &d[j].v, sizeof(q[i].v)) == 0;
- if ((eq && oper != PROPERTY_OPER_EQ)
- || (!eq && oper != PROPERTY_OPER_NE))
- return 0;
+ if ((eq && oper == PROPERTY_OPER_EQ)
+ || (!eq && oper == PROPERTY_OPER_NE))
+ matches++;
+ else if (!q[i].optional)
+ return -1;
i++;
j++;
continue;
/*
* Handle the cases of a missing value and a query with no corresponding
- * definition. The former fails for any comparision except inequality,
+ * definition. The former fails for any comparison except inequality,
* the latter is treated as a comparison against the Boolean false.
*/
if (q[i].type == PROPERTY_TYPE_VALUE_UNDEFINED) {
- if (oper != PROPERTY_OPER_NE)
- return 0;
+ if (oper == PROPERTY_OPER_NE)
+ matches++;
+ else if (!q[i].optional)
+ return -1;
} else if (q[i].type != PROPERTY_TYPE_STRING
|| (oper == PROPERTY_OPER_EQ
&& q[i].v.str_val != ossl_property_false)
|| (oper == PROPERTY_OPER_NE
&& q[i].v.str_val == ossl_property_false)) {
- return 0;
+ if (!q[i].optional)
+ return -1;
+ } else {
+ matches++;
}
i++;
}
- return 1;
+ return matches;
}
void ossl_property_free(OSSL_PROPERTY_LIST *p)
int ossl_property_parse_init(OPENSSL_CTX *ctx)
{
static const char *const predefined_names[] = {
- "default", /* Being provided by the default built-in provider */
- "legacy", /* Provided by the legacy provider */
- "provider", /* Name of provider (default, fips) */
+ "provider", /* Name of provider (default, legacy, fips) */
"version", /* Version number of this provider */
- "fips", /* FIPS supporting provider */
- "engine", /* An old style engine masquerading as a provider */
+ "fips", /* FIPS validated or FIPS supporting algorithm */
+ "format", /* output format for serializers */
+ "type", /* output type for serializers */
};
size_t i;