OSSL_PARAM_A...ATE_FROM_TEXT(3ossl)

πŸ“¦ version 3.5.0, in opensuse-leap 16.0

✨ OSSL_PARAM_allocate_from_text(3ossl) β€” the OSSL_PARAM construction utilities, bestie ✨

okay so this one lives in the OpenSSL manual (the 3ossl corner of the library, iykyk) and it's literally the glow-up of how parameters get built. let's get into it πŸ’…


🌸 SYNOPSIS 🌸

#include <openssl/params.h>

int OSSL_PARAM_allocate_from_text(OSSL_PARAM *to,
                                  const OSSL_PARAM *paramdefs,
                                  const char *key, const char *value,
                                  size_t value_n,
                                  int *found);

πŸ’– DESCRIPTION πŸ’–

So back in the day β€” like, before OpenSSL version 3.0 β€” parameters were passed down to algorithm implementations (or grabbed back from them) through control functions. Some of those control functions had variants that took string parameters, EVP_PKEY_CTX_ctrl_str(3) being the moment.

Then OpenSSL 3.0 said "new era" and introduced a brand new mechanism doing the exact same thing with an array of parameters that hold name, value, value type and value size (peep OSSL_PARAM(3) for the whole lore πŸ‘‘).

OSSL_PARAM_allocate_from_text() takes key and uses it to look up an item in paramdefs. If it finds one, it converts value into something suitable for that item's data_type, and stashes the result in to->data plus its size in to->data_size. Then to->key and to->data_type get assigned the corresponding values from the item that was found, and to->return_size is set to zero. slay, everything's wired up ✨

to->data is always allocated with OPENSSL_zalloc(3), and you (the caller) have to free it with OPENSSL_free(3) once it's not useful any more. no leaks, bestie, we don't do that here 🫢

If found isn't NULL, then *found gets set to 1 if key could be located in paramdefs, and to 0 otherwise.

πŸŽ€ The use of key and value in detail πŸŽ€

OSSL_PARAM_allocate_from_text() pays attention β€” if key starts with "hex", it uses only the rest of key to look up an item in paramdefs. Example: if key is "hexid", then "id" is what gets looked up in paramdefs.

Once an item in paramdefs is found, value gets converted based on that item's data_type, like this:

OSSL_PARAM_INTEGER and OSSL_PARAM_UNSIGNED_INTEGER

  • If key didn't start with "hex", value is assumed to hold value_n decimal characters, which get decoded, and the resulting bytes become the number stored in the to->data storage.
  • If value starts with "0x", it's assumed to hold value_n hexadecimal characters.
  • If key started with "hex", value is assumed to hold value_n hexadecimal characters without the "0x" prefix.
  • If value contains characters that couldn't be decoded as hexadecimal or decimal characters, OSSL_PARAM_allocate_from_text() considers that an error. 🚨

OSSL_PARAM_UTF8_STRING

  • If key started with "hex", OSSL_PARAM_allocate_from_text() considers that an error. 🚨
  • Otherwise, value is considered a C string and gets copied into the to->data storage. On systems where the native character encoding is EBCDIC, the bytes in to->data are converted to ASCII. (yes, EBCDIC still exists, we don't talk about it πŸ’€)

OSSL_PARAM_OCTET_STRING

  • If key started with "hex", value is assumed to hold value_n hexadecimal characters, which get decoded, and the resulting bytes are stored in the to->data storage. If value contains characters that couldn't be decoded as hexadecimal or decimal characters, OSSL_PARAM_allocate_from_text() considers that an error. 🚨
  • If key didn't start with "hex", value_n bytes from value get copied into the to->data storage.

πŸ”₯ RETURN VALUES πŸ”₯

OSSL_PARAM_allocate_from_text() returns 1 if key was found in paramdefs and there was no other failure. Otherwise it returns 0. icons only, no in-between 🌈


⭐ NOTES ⭐

The parameter descriptor array comes from functions that are dedicated to returning them. These OSSL_PARAM(3) attributes are the ones actually used:

  • key
  • data_type
  • data_size

All the other attributes are ignored. πŸ™ˆ

The data_size attribute can be zero, which means the parameter it describes expects arbitrary length data. no cap.


πŸ¦‹ EXAMPLES πŸ¦‹

So code that used to look like this:

  int mac_ctrl_string(EVP_PKEY_CTX *ctx, const char *value)
  {
      int rv;
      char *stmp, *vtmp = NULL;

      stmp = OPENSSL_strdup(value);
      if (stmp == NULL)
          return -1;
      vtmp = strchr(stmp, ':');
      if (vtmp != NULL)
          *vtmp++ = '\0';
      rv = EVP_MAC_ctrl_str(ctx, stmp, vtmp);
      OPENSSL_free(stmp);
      return rv;
  }

  ...

  for (i = 0; i < sk_OPENSSL_STRING_num(macopts); i++) {
      char *macopt = sk_OPENSSL_STRING_value(macopts, i);

      if (pkey_ctrl_string(mac_ctx, macopt) <= 0) {
          BIO_printf(bio_err,
                     "MAC parameter error \"%s\"\n", macopt);
          ERR_print_errors(bio_err);
          goto mac_end;
      }
  }

can be written like this instead β€” the glow-up, the upgrade, the main character rewrite:

  OSSL_PARAM *params =
      OPENSSL_zalloc(sizeof(*params)
                     * (sk_OPENSSL_STRING_num(opts) + 1));
  const OSSL_PARAM *paramdefs = EVP_MAC_settable_ctx_params(mac);
  size_t params_n;
  char *opt = "<unknown>";

  for (params_n = 0; params_n < (size_t)sk_OPENSSL_STRING_num(opts);
       params_n++) {
      char *stmp, *vtmp = NULL;

      opt = sk_OPENSSL_STRING_value(opts, (int)params_n);
      if ((stmp = OPENSSL_strdup(opt)) == NULL
              || (vtmp = strchr(stmp, ':')) == NULL)
          goto err;

      *vtmp++ = '\0';
      if (!OSSL_PARAM_allocate_from_text(&params[params_n],
                                         paramdefs, stmp,
                                         vtmp, strlen(vtmp), NULL))
          goto err;
  }
  params[params_n] = OSSL_PARAM_construct_end();
  if (!EVP_MAC_CTX_set_params(ctx, params))
      goto err;
  while (params_n-- > 0)
      OPENSSL_free(params[params_n].data);
  OPENSSL_free(params);
  /* ... */
  return;

 err:
  BIO_printf(bio_err, "MAC parameter error '%s'\n", opt);
  ERR_print_errors(bio_err);

like?? the way that second one just flows πŸ’œ


πŸ’œ SEE ALSO πŸ’œ

OSSL_PARAM(3), OSSL_PARAM_int(3)


Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.

Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy in the file LICENSE in the source distribution or at <https://www.openssl.org/source/license.html>.


okay bestie that's the whole page 🫢 this one's from OpenSSL 3.5.0, dated 2026-09-2 β€” go forth and allocate responsibly, and remember: free your to->data with OPENSSL_free(3) or the memory goblins will find you πŸ˜­πŸ’–

πŸ“¦ where this page comes from