2023-05-11 15:14:26 +08:00
|
|
|
Proposal for OSSL_PARAM futures
|
|
|
|
===============================
|
|
|
|
|
|
|
|
Format:
|
|
|
|
|
|
|
|
```perl
|
|
|
|
{-
|
|
|
|
use OpenSSL::paramnames qw(produce_param_handlers);
|
|
|
|
-}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Machine generated parameter handling
|
|
|
|
* generated by util/perl/OpenSSL/paramnames.pm
|
|
|
|
*/
|
|
|
|
{-
|
|
|
|
produce_param_handlers(
|
|
|
|
'name' => 'kdf_scrypt',
|
|
|
|
'functions' => 'both', # getter or setter being the other options
|
|
|
|
'prologue' => "KDF_SCRYPT *ctx = vctx;",
|
|
|
|
"static" => "yes", # "yes" to generate static functions (default) or
|
|
|
|
# "no" to not
|
|
|
|
'params' => (
|
|
|
|
'KDF_PARAM_PASSWORD' => (
|
|
|
|
'type' => 'octet string',
|
|
|
|
'access' => 'writeonly',
|
|
|
|
'setaction' => qq(
|
|
|
|
if (!scrypt_set_membuf(&ctx->pass, &ctx->pass_len, p))
|
|
|
|
return 0;
|
|
|
|
),
|
|
|
|
),
|
|
|
|
|
|
|
|
'KDF_PARAM_SALT' => (
|
|
|
|
'type' => 'octet string',
|
|
|
|
'access' => 'readwrite',
|
|
|
|
'setaction' => qq(
|
|
|
|
if (!scrypt_set_membuf(&ctx->salt, &ctx->salt_len, p))
|
|
|
|
return 0;
|
|
|
|
),
|
|
|
|
'getaction' => qq(
|
|
|
|
p->return_size = ctx->salt_len;
|
|
|
|
if (p->data_size >= ctx->salt_len)
|
|
|
|
memcpy(p->data, ctx->salt, p->data_size >= ctx->salt_len);
|
|
|
|
),
|
|
|
|
),
|
|
|
|
|
|
|
|
'KDF_PARAM_SCRYPT_N' => (
|
|
|
|
'type' => 'integer',
|
|
|
|
'ctype' => 'uint64_t',
|
|
|
|
'access' => 'readwrite',
|
|
|
|
'field' => "ctx->N",
|
|
|
|
'sanitycheck' => "value > 1 && is_power_of_two(value)"
|
|
|
|
),
|
|
|
|
|
|
|
|
'KDF_PARAM_SCRYPT_R' => (
|
|
|
|
'type' => 'integer',
|
|
|
|
'ctype' => 'uint64_t',
|
|
|
|
'access' => 'readwrite',
|
|
|
|
'field' => "ctx->r",
|
|
|
|
'sanitycheck' => "value >= 1",
|
|
|
|
),
|
|
|
|
|
|
|
|
'KDF_PARAM_SCRYPT_P' => (
|
|
|
|
'type' => 'integer',
|
|
|
|
'ctype' => 'uint64_t',
|
|
|
|
'access' => 'readwrite',
|
|
|
|
'field' => "ctx->p",
|
|
|
|
'sanitycheck' => "value >= 1",
|
|
|
|
),
|
|
|
|
|
|
|
|
'KDF_PARAM_SCRYPT_MAXMEM' => (
|
|
|
|
'type' => 'integer',
|
|
|
|
'ctype' => 'uint64_t',
|
|
|
|
'access' => 'readwrite',
|
|
|
|
'field' => "ctx->maxmem_bytes",
|
|
|
|
'sanitycheck' => "value >= 1",
|
|
|
|
),
|
|
|
|
|
|
|
|
'KDF_PARAM_PROPERTIES' => (
|
|
|
|
'type' => 'utf8_string',
|
|
|
|
'access' => 'readwrite',
|
|
|
|
'setaction' => qq(
|
|
|
|
if (!set_property_query(ctx, p->data) || !set_digest(ctx))
|
|
|
|
return 0;
|
|
|
|
),
|
|
|
|
),
|
|
|
|
|
|
|
|
'KDF_PARAM_SIZE' => (
|
|
|
|
'type' => 'integer',
|
|
|
|
'ctype' => 'size_t',
|
|
|
|
'access' => 'readonly',
|
|
|
|
'field' => "SIZE_MAX",
|
|
|
|
),
|
|
|
|
);
|
|
|
|
);
|
|
|
|
-}
|
|
|
|
/* End of generated code */
|
|
|
|
```
|
|
|
|
|
|
|
|
THe top level attributes are:
|
|
|
|
|
|
|
|
- "name" is the name the functions will derive from e.g. "kdf_scrypt" to this
|
|
|
|
will be appended _[gs]et[_ctx]_params
|
|
|
|
- "functions" is the functions to generate. By default both setters and
|
|
|
|
getters but either can be omitted.
|
2023-06-29 14:55:12 +08:00
|
|
|
- "prologue" defines some introductory code emitted in the generated functions.
|
2023-05-11 15:14:26 +08:00
|
|
|
Function arguments are: `void *vctx, OSSL_PARAM params[]` and this
|
|
|
|
can be used to specialise the void pointer or declare locals.
|
2023-06-29 14:55:12 +08:00
|
|
|
- "epilogue" defines some post decode code emitted in the generated function
|
2023-05-11 15:14:26 +08:00
|
|
|
- "params" defines the parameters both gettable and settable
|
|
|
|
|
|
|
|
Within the "params" the fields specify each parameter by label.
|
|
|
|
|
|
|
|
Each parameter is then specialised with attributes:
|
|
|
|
|
|
|
|
- "type" is the OSSL_PARAM type
|
|
|
|
- "ctype" is the underlying C type (e.g. for an integer parameter size_t
|
|
|
|
could be the C type)
|
|
|
|
- "access" is readwrite, readonly or writeonly. This determines if the
|
|
|
|
parameter is a settable, gettable or both
|
|
|
|
- "field" is an accessor to the field itself
|
|
|
|
- "sanitycheck" is a validation check for the parameter. If present, code
|
|
|
|
will be generated `if (!(sanitycheck)) return 0;`
|
|
|
|
The local variable `var` will contain the C value if specified.
|
|
|
|
- "setaction" is C code to execute when the parameter is being set. It will
|
|
|
|
define an OSSL_PARAM pointer p to set.
|
|
|
|
- "code" set to "no" skips code generation for this parameter, it defaults
|
|
|
|
to "yes" which generates handlers. This is useful when a parameter
|
|
|
|
is duplicated with differenting types (e.g. utf8 string and integer).
|
|
|
|
- "published" set to "yes" includes the parameter in the gettable/settable
|
|
|
|
lists. Set to "no" and it isn't included (but will still be processed).
|
|
|
|
It defaults to "yes".
|
|
|
|
|
|
|
|
- Flags include:
|
|
|
|
- nostatic: do not make the function static
|
|
|
|
- nocode: do not generate code for this parameter
|
|
|
|
- This allows, e.g., two different types for a parameter (int & string)
|
|
|
|
- unpublished: do not generate this parameter in the gettable/settable list
|
|
|
|
- "engine" is the only one like this
|
|
|
|
- readonly: create a getter but not a setter
|
|
|
|
- writeonly: create a setting but not a getter
|
|
|
|
|
|
|
|
The idea is that the gettable and get functions will be simultaneously
|
|
|
|
generated along with fast decoder to look up parameter names quickly.
|
|
|
|
|
|
|
|
The getter and setter functions will be pre-populated with some local variable:
|
|
|
|
|
|
|
|
```c
|
|
|
|
OSSL_PARAM *p; /* The matching parameter */
|
|
|
|
type val; /* The value of the parameter after a get/set call */
|
|
|
|
/* (for C types) */
|
|
|
|
```
|
|
|
|
|
|
|
|
A worked example for scrypt:
|
|
|
|
|
|
|
|
Would generate something along the lines of:
|
|
|
|
|
|
|
|
```c
|
|
|
|
enum kdf_scrypt_ctx_param_e {
|
|
|
|
kdf_scrypt_ctx_param_INVALID,
|
|
|
|
kdf_scrypt_ctx_param_OSSL_KDF_PARAM_PASSWORD,
|
|
|
|
kdf_scrypt_ctx_param_OSSL_KDF_PARAM_PROPERTIES,
|
|
|
|
kdf_scrypt_ctx_param_OSSL_KDF_PARAM_SALT,
|
|
|
|
kdf_scrypt_ctx_param_OSSL_KDF_PARAM_SCRYPT_MAXMEM,
|
|
|
|
kdf_scrypt_ctx_param_OSSL_KDF_PARAM_SCRYPT_N,
|
|
|
|
kdf_scrypt_ctx_param_OSSL_KDF_PARAM_SCRYPT_P,
|
|
|
|
kdf_scrypt_ctx_param_OSSL_KDF_PARAM_SCRYPT_R,
|
|
|
|
kdf_scrypt_ctx_param_OSSL_KDF_PARAM_SIZE
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
static enum kdf_scrypt_ctx_param_e kdf_scrypt_ctx_lookup(const OSSL_PARAM *p) {
|
|
|
|
/* magic decoder */
|
|
|
|
return kdf_scrypt_ctx_param_INVALID;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int kdf_scrypt_set_ctx_params(void *vctx, const OSSL_PARAM params[])
|
|
|
|
{
|
|
|
|
const OSSL_PARAM *p;
|
|
|
|
KDF_SCRYPT *ctx = vctx;
|
|
|
|
|
|
|
|
if (params == NULL)
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
for (p = params; p->key != NULL; p++) {
|
|
|
|
switch (kdf_scrypt_ctx_lookup(p)) {
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
|
|
|
|
case kdf_scrypt_ctx_param_OSSL_KDF_PARAM_PASSWORD:
|
|
|
|
if (!scrypt_set_membuf(&ctx->pass, &ctx->pass_len, p))
|
|
|
|
return 0;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case kdf_scrypt_ctx_param_OSSL_KDF_PARAM_SALT:
|
|
|
|
if (!scrypt_set_membuf(&ctx->salt, &ctx->salt_len, p))
|
|
|
|
return 0;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case kdf_scrypt_ctx_param_OSSL_KDF_PARAM_SCRYPT_N: {
|
|
|
|
uint64_t value;
|
|
|
|
|
|
|
|
if (!OSSL_PARAM_get_uint64(p, &value) {
|
|
|
|
if (!(value > 1 && is_power_of_two(u64_value)))
|
|
|
|
return 0;
|
|
|
|
ctx->N = value;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case kdf_scrypt_ctx_param_OSSL_KDF_PARAM_SCRYPT_R: {
|
|
|
|
uint64_t value;
|
|
|
|
|
|
|
|
if (!OSSL_PARAM_get_uint64(p, &value) {
|
|
|
|
if (!(value >= 1))
|
|
|
|
return 0;
|
|
|
|
ctx->r = value;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case kdf_scrypt_ctx_param_OSSL_KDF_PARAM_SCRYPT_P: {
|
|
|
|
uint64_t value;
|
|
|
|
|
|
|
|
if (!OSSL_PARAM_get_uint64(p, &value) {
|
|
|
|
if (!(value >= 1))
|
|
|
|
return 0;
|
|
|
|
ctx->p = value;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case kdf_scrypt_ctx_param_OSSL_KDF_PARAM_SCRYPT_MAXMEM: {
|
|
|
|
uint64_t value;
|
|
|
|
|
|
|
|
if (!OSSL_PARAM_get_uint64(p, &value) {
|
|
|
|
if (!(value >= 1))
|
|
|
|
return 0;
|
|
|
|
ctx->p = value;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case kdf_scrypt_ctx_param_OSSL_KDF_PARAM_PROPERTIES:
|
|
|
|
if (p != NULL) {
|
|
|
|
if (p->data_type != OSSL_PARAM_UTF8_STRING) {
|
|
|
|
if (!set_property_query(ctx, p->data) || !set_digest(ctx))
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static const OSSL_PARAM *kdf_scrypt_settable_ctx_params(ossl_unused void *ctx,
|
|
|
|
ossl_unused void *p_ctx)
|
|
|
|
{
|
|
|
|
static const OSSL_PARAM known_settable_ctx_params[] = {
|
|
|
|
OSSL_PARAM_octet_string(OSSL_KDF_PARAM_PASSWORD, NULL, 0),
|
|
|
|
OSSL_PARAM_octet_string(OSSL_KDF_PARAM_SALT, NULL, 0),
|
|
|
|
OSSL_PARAM_uint64(OSSL_KDF_PARAM_SCRYPT_N, NULL),
|
|
|
|
OSSL_PARAM_uint32(OSSL_KDF_PARAM_SCRYPT_R, NULL),
|
|
|
|
OSSL_PARAM_uint32(OSSL_KDF_PARAM_SCRYPT_P, NULL),
|
|
|
|
OSSL_PARAM_uint64(OSSL_KDF_PARAM_SCRYPT_MAXMEM, NULL),
|
|
|
|
OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_PROPERTIES, NULL, 0),
|
|
|
|
OSSL_PARAM_END
|
|
|
|
};
|
|
|
|
return known_settable_ctx_params;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int kdf_scrypt_get_ctx_params(void *vctx, OSSL_PARAM params[])
|
|
|
|
{
|
|
|
|
const OSSL_PARAM *p;
|
|
|
|
KDF_SCRYPT *ctx = vctx;
|
|
|
|
|
|
|
|
if (params == NULL)
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
for (p = params; p->key != NULL; p++) {
|
|
|
|
switch (kdf_scrypt_ctx_lookup(p)) {
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
|
|
|
|
case kdf_scrypt_ctx_param_OSSL_KDF_PARAM_PASSWORD:
|
|
|
|
if (!scrypt_set_membuf(&ctx->pass, &ctx->pass_len, p))
|
|
|
|
return 0;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case kdf_scrypt_ctx_param_OSSL_KDF_PARAM_SALT:
|
|
|
|
p->return_size = ctx->salt_len;
|
|
|
|
if (p->data_size >= ctx->salt_len)
|
|
|
|
memcpy(p->data, ctx->salt, ctx->salt_len);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case kdf_scrypt_ctx_param_OSSL_KDF_PARAM_SCRYPT_N: {
|
|
|
|
if (!OSSL_PARAM_set_uint64(p, &ctx->N)
|
|
|
|
return 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case kdf_scrypt_ctx_param_OSSL_KDF_PARAM_SCRYPT_R: {
|
|
|
|
if (!OSSL_PARAM_set_uint64(p, &ctx->r)
|
|
|
|
return 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case kdf_scrypt_ctx_param_OSSL_KDF_PARAM_SCRYPT_P: {
|
|
|
|
if (!OSSL_PARAM_set_uint64(p, &ctx->p)
|
|
|
|
return 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case kdf_scrypt_ctx_param_OSSL_KDF_PARAM_SCRYPT_MAXMEM: {
|
|
|
|
if (!OSSL_PARAM_set_uint64(p, &ctx->maxmem)
|
|
|
|
return 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case kdf_scrypt_ctx_param_OSSL_KDF_PARAM_PROPERTIES:
|
|
|
|
if (p->data_type != OSSL_PARAM_UTF8_STRING) {
|
|
|
|
if (!set_property_query(ctx, p->data) || !set_digest(ctx))
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case kdf_scrypt_ctx_param_KDF_PARAM_SIZE:
|
|
|
|
if (!OSSL_PARAM_set_size_t(p, SIZE_MAX))
|
|
|
|
return 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static const OSSL_PARAM *kdf_scrypt_gettable_ctx_params(ossl_unused void *ctx,
|
|
|
|
ossl_unused void *p_ctx)
|
|
|
|
{
|
|
|
|
static const OSSL_PARAM known_gettable_ctx_params[] = {
|
|
|
|
OSSL_PARAM_size_t(OSSL_KDF_PARAM_SIZE, NULL),
|
|
|
|
OSSL_PARAM_END
|
|
|
|
};
|
|
|
|
return known_gettable_ctx_params;
|
|
|
|
}
|
|
|
|
```
|