=pod

=head1 NAME

OSSL_PARAM_allocate_from_text
- OSSL_PARAM construction utilities

=head1 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);

=head1 DESCRIPTION

With OpenSSL before version 3.0, parameters were passed down to or
retrieved from algorithm implementations via control functions.
Some of these control functions existed in variants that took string
parameters, for example L<EVP_PKEY_CTX_ctrl_str(3)>.

OpenSSL 3.0 introduces a new mechanism to do the same thing with an
array of parameters that contain name, value, value type and value
size (see L<OSSL_PARAM(3)> for more information).

OSSL_PARAM_allocate_from_text() uses I<key> to look up an item in
I<paramdefs>.  If an item was found, it converts I<value> to something
suitable for that item's I<data_type>, and stores the result in
I<< to->data >> as well as its size in I<< to->data_size >>.
I<< to->key >> and I<< to->data_type >> are assigned the corresponding
values from the item that was found, and I<< to->return_size >> is set
to zero.

I<< to->data >> is always allocated using L<OPENSSL_zalloc(3)> and
needs to be freed by the caller when it's not useful any more, using
L<OPENSSL_free(3)>.

If I<found> is not NULL, I<*found> is set to 1 if I<key> could be
located in I<paramdefs>, and to 0 otherwise.

=head2 The use of I<key> and I<value> in detail

OSSL_PARAM_allocate_from_text() takes note if I<key> starts with
"hex", and will only use the rest of I<key> to look up an item in
I<paramdefs> in that case.  As an example, if I<key> is "hexid", "id"
will be looked up in I<paramdefs>.

When an item in I<paramdefs> has been found, I<value> is converted
depending on that item's I<data_type>, as follows:

=over 4

=item B<OSSL_PARAM_INTEGER> and B<OSSL_PARAM_UNSIGNED_INTEGER>

If I<key> didn't start with "hex", I<value> is assumed to contain
I<value_n> decimal characters, which are decoded, and the resulting
bytes become the number stored in the I<< to->data >> storage.

If I<value> starts with "0x", it is assumed to contain I<value_n>
hexadecimal characters.

If I<key> started with "hex", I<value> is assumed to contain
I<value_n> hexadecimal characters without the "0x" prefix.

If I<value> contains characters that couldn't be decoded as
hexadecimal or decimal characters, OSSL_PARAM_allocate_from_text()
considers that an error.

=item B<OSSL_PARAM_UTF8_STRING>

If I<key> started with "hex", OSSL_PARAM_allocate_from_text()
considers that an error.

Otherwise, I<value> is considered a C string and is copied to the
I<< to->data >> storage.
On systems where the native character encoding is EBCDIC, the bytes in
I<< to->data >> are converted to ASCII.

=item B<OSSL_PARAM_OCTET_STRING>

If I<key> started with "hex", I<value> is assumed to contain
I<value_n> hexadecimal characters, which are decoded, and the
resulting bytes are stored in the I<< to->data >> storage.
If I<value> contains characters that couldn't be decoded as
hexadecimal or decimal characters, OSSL_PARAM_allocate_from_text()
considers that an error.

If I<key> didn't start with "hex", I<value_n> bytes from I<value> are
copied to the I<< to->data >> storage.

=back

=head1 RETURN VALUES

OSSL_PARAM_allocate_from_text() returns 1 if I<key> was found in
I<paramdefs> and there was no other failure, otherwise 0.

=head1 NOTES

The parameter descriptor array comes from functions dedicated to
return them.
The following B<OSSL_PARAM> attributes are used:

=over 4

=item I<key>

=item I<data_type>

=item I<data_size>

=back

All other attributes are ignored.

The I<data_size> attribute can be zero, meaning that the parameter it
describes expects arbitrary length data.

=head1 EXAMPLES

Code that looked 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:

  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);


=head1 SEE ALSO

L<OSSL_PARAM(3)>, L<OSSL_PARAM_int(3)>

=head1 COPYRIGHT

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
L<https://www.openssl.org/source/license.html>.

=cut
