Project: Pipy (Orchestration & Management / Service Proxy)
File: fast-param-find.md

Proposal for OSSL_PARAM futures =============================== Format: ```perl {- use OpenSSL::paramnames qw(produceparamhandlers); -} /* Machine generated parameter handling generated by util/perl/OpenSSL/paramnames.pm */ {- produceparamhandlers( '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 'params' => ( 'KDFPARAMPASSWORD' => ( 'type' => 'octet string', 'access' => 'writeonly', 'setaction' => qq( if (!scryptsetmembuf(&ctx->pass, &ctx->pass_len, p)) return 0; ), ), 'KDFPARAMSALT' => ( 'type' => 'octet string', 'access' => 'readwrite', 'setaction' => qq( if (!scryptsetmembuf(&ctx->salt, &ctx->salt_len, p)) return 0; ), 'getaction' => qq( p->returnsize = ctx->saltlen; if (p->datasize >= ctx->saltlen) memcpy(p->data, ctx->salt, p->datasize >= ctx->saltlen); ), ), 'KDFPARAMSCRYPT_N' => ( 'type' => 'integer', 'ctype' => 'uint64_t', 'access' => 'readwrite', 'field' => "ctx->N", 'sanitycheck' => "value > 1 && ispowerof_two(value)" ), 'KDFPARAMSCRYPT_R' => ( 'type' => 'integer', 'ctype' => 'uint64_t', 'access' => 'readwrite', 'field' => "ctx->r", 'sanitycheck' => "value >= 1", ), 'KDFPARAMSCRYPT_P' => ( 'type' => 'integer', 'ctype' => 'uint64_t', 'access' => 'readwrite', 'field' => "ctx->p", 'sanitycheck' => "value >= 1", ), 'KDFPARAMSCRYPT_MAXMEM' => ( 'type' => 'integer', 'ctype' => 'uint64_t', 'access' => 'readwrite', 'field' => "ctx->maxmem_bytes", 'sanitycheck' => "value >= 1", ), 'KDFPARAMPROPERTIES' => ( 'type' => 'utf8_string', 'access' => 'readwrite', 'setaction' => qq( if (!setpropertyquery(ctx, p->data) || !set_digest(ctx)) return 0; ), ), 'KDFPARAMSIZE' => ( '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. "prologue" defines some introductory code emitted in the generated functions. Function arguments are: `void *vctx, OSSL_PARAM params[]` and this can be used to specialise the void pointer or declare locals. "epilogue" defines some post decode code emitted in the generated function "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

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 kdfscryptctxparame { kdfscryptctxparamINVALID, kdfscryptctxparamOSSLKDFPARAM_PASSWORD, kdfscryptctxparamOSSLKDFPARAM_PROPERTIES, kdfscryptctxparamOSSLKDFPARAM_SALT, kdfscryptctxparamOSSLKDFPARAMSCRYPTMAXMEM, kdfscryptctxparamOSSLKDFPARAMSCRYPTN, kdfscryptctxparamOSSLKDFPARAMSCRYPTP, kdfscryptctxparamOSSLKDFPARAMSCRYPTR, kdfscryptctxparamOSSLKDFPARAM_SIZE }; static enum kdfscryptctxparame kdfscryptctxlookup(const OSSLPARAM *p) { / magic decoder / return kdfscryptctxparamINVALID; } static int kdfscryptsetctxparams(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 (kdfscryptctx_lookup(p)) { default: break; case kdfscryptctxparamOSSLKDFPARAM_PASSWORD: if (!scryptsetmembuf(&ctx->pass, &ctx->pass_len, p)) return 0; break; case kdfscryptctxparamOSSLKDFPARAM_SALT: if (!scryptsetmembuf(&ctx->salt, &ctx->salt_len, p)) return 0; break; case kdfscryptctxparamOSSLKDFPARAMSCRYPTN: { uint64_t value; if (!OSSLPARAMget_uint64(p, &value) { if (!(value > 1 && ispoweroftwo(u64value))) return 0; ctx->N = value; } break; } case kdfscryptctxparamOSSLKDFPARAMSCRYPTR: { uint64_t value; if (!OSSLPARAMget_uint64(p, &value) { if (!(value >= 1)) return 0; ctx->r = value; } break; } case kdfscryptctxparamOSSLKDFPARAMSCRYPTP: { uint64_t value; if (!OSSLPARAMget_uint64(p, &value) { if (!(value >= 1)) return 0; ctx->p = value; } break; } case kdfscryptctxparamOSSLKDFPARAMSCRYPTMAXMEM: { uint64_t value; if (!OSSLPARAMget_uint64(p, &value) { if (!(value >= 1)) return 0; ctx->p = value; } break; } case kdfscryptctxparamOSSLKDFPARAM_PROPERTIES: if (p != NULL) { if (p->datatype != OSSLPARAMUTF8STRING) { if (!setpropertyquery(ctx, p->data) || !set_digest(ctx)) return 0; } } } } return 1; } static const OSSLPARAM *kdfscryptsettablectxparams(osslunused void *ctx, osslunused void *pctx) { static const OSSLPARAM knownsettablectxparams[] = { OSSLPARAMoctetstring(OSSLKDFPARAMPASSWORD, NULL, 0), OSSLPARAMoctetstring(OSSLKDFPARAMSALT, NULL, 0), OSSLPARAMuint64(OSSLKDFPARAMSCRYPTN, NULL), OSSLPARAMuint32(OSSLKDFPARAMSCRYPTR, NULL), OSSLPARAMuint32(OSSLKDFPARAMSCRYPTP, NULL), OSSLPARAMuint64(OSSLKDFPARAMSCRYPTMAXMEM, NULL), OSSLPARAMutf8string(OSSLKDFPARAMPROPERTIES, NULL, 0), OSSLPARAMEND }; return knownsettablectx_params; } static int kdfscryptgetctxparams(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 (kdfscryptctx_lookup(p)) { default: break; case kdfscryptctxparamOSSLKDFPARAM_PASSWORD: if (!scryptsetmembuf(&ctx->pass, &ctx->pass_len, p)) return 0; break; case kdfscryptctxparamOSSLKDFPARAM_SALT: p->returnsize = ctx->saltlen; if (p->datasize >= ctx->saltlen) memcpy(p->data, ctx->salt, ctx->salt_len); break; case kdfscryptctxparamOSSLKDFPARAMSCRYPTN: { if (!OSSLPARAMset_uint64(p, &ctx->N) return 0; break; } case kdfscryptctxparamOSSLKDFPARAMSCRYPTR: { if (!OSSLPARAMset_uint64(p, &ctx->r) return 0; break; } case kdfscryptctxparamOSSLKDFPARAMSCRYPTP: { if (!OSSLPARAMset_uint64(p, &ctx->p) return 0; break; } case kdfscryptctxparamOSSLKDFPARAMSCRYPTMAXMEM: { if (!OSSLPARAMset_uint64(p, &ctx->maxmem) return 0; break; } case kdfscryptctxparamOSSLKDFPARAM_PROPERTIES: if (p->datatype != OSSLPARAMUTF8STRING) { if (!setpropertyquery(ctx, p->data) || !set_digest(ctx)) return 0; } break; case kdfscryptctxparamKDFPARAMSIZE: if (!OSSLPARAMsetsizet(p, SIZE_MAX)) return 0; break; } } return 1; } static const OSSLPARAM *kdfscryptgettablectxparams(osslunused void *ctx, osslunused void *pctx) { static const OSSLPARAM knowngettablectxparams[] = { OSSLPARAMsizet(OSSLKDFPARAMSIZE, NULL), OSSLPARAMEND }; return knowngettablectx_params; } ```