Example #1
0
/* Get the "nbits" parameter from an s-expression of the format:
 *
 *   (algo
 *     (parameter_name_1 ....)
 *      ....
 *     (parameter_name_n ....))
 *
 * Example:
 *
 *   (rsa
 *     (nbits 4:2048))
 *
 * On success the value for nbits is stored at R_NBITS.  If no nbits
 * parameter is found, the function returns success and stores 0 at
 * R_NBITS.  For parsing errors the function returns an error code and
 * stores 0 at R_NBITS.
 */
gpg_err_code_t
_gcry_pk_util_get_nbits (gcry_sexp_t list, unsigned int *r_nbits)
{
  char buf[50];
  const char *s;
  size_t n;

  *r_nbits = 0;

  list = sexp_find_token (list, "nbits", 0);
  if (!list)
    return 0; /* No NBITS found.  */

  s = sexp_nth_data (list, 1, &n);
  if (!s || n >= DIM (buf) - 1 )
    {
      /* NBITS given without a cdr.  */
      sexp_release (list);
      return GPG_ERR_INV_OBJ;
    }
  memcpy (buf, s, n);
  buf[n] = 0;
  *r_nbits = (unsigned int)strtoul (buf, NULL, 0);
  sexp_release (list);
  return 0;
}
Example #2
0
/* Get the optional "rsa-use-e" parameter from an s-expression of the
 * format:
 *
 *   (algo
 *     (parameter_name_1 ....)
 *      ....
 *     (parameter_name_n ....))
 *
 * Example:
 *
 *   (rsa
 *     (nbits 4:2048)
 *     (rsa-use-e 2:41))
 *
 * On success the value for nbits is stored at R_E.  If no rsa-use-e
 * parameter is found, the function returns success and stores 65537 at
 * R_E.  For parsing errors the function returns an error code and
 * stores 0 at R_E.
 */
gpg_err_code_t
_gcry_pk_util_get_rsa_use_e (gcry_sexp_t list, unsigned long *r_e)
{
  char buf[50];
  const char *s;
  size_t n;

  *r_e = 0;

  list = sexp_find_token (list, "rsa-use-e", 0);
  if (!list)
    {
      *r_e = 65537; /* Not given, use the value generated by old versions. */
      return 0;
    }

  s = sexp_nth_data (list, 1, &n);
  if (!s || n >= DIM (buf) - 1 )
    {
      /* No value or value too large.  */
      sexp_release (list);
      return GPG_ERR_INV_OBJ;
    }
  memcpy (buf, s, n);
  buf[n] = 0;
  *r_e = strtoul (buf, NULL, 0);
  sexp_release (list);
  return 0;
}
Example #3
0
/* Get a string from the car.  The returned value is a malloced string
   and needs to be freed by the caller.  */
char *
gcry_sexp_nth_string (const gcry_sexp_t list, int number)
{
  const char *s;
  size_t n;
  char *buf;

  s = sexp_nth_data (list, number, &n);
  if (!s || n < 1 || (n+1) < 1)
    return NULL;
  buf = gcry_malloc (n+1);
  if (!buf)
    return NULL;
  memcpy (buf, s, n);
  buf[n] = 0;
  return buf;
}
Example #4
0
/* Get the nth element of a list which needs to be a simple object.
   The returned value is a malloced buffer and needs to be freed by
   the caller.  This is basically the same as gcry_sexp_nth_data but
   with an allocated result. */
void *
gcry_sexp_nth_buffer (const gcry_sexp_t list, int number, size_t *rlength)
{
  const char *s;
  size_t n;
  char *buf;

  *rlength = 0;
  s = sexp_nth_data (list, number, &n);
  if (!s || !n)
    return NULL;
  buf = gcry_malloc (n);
  if (!buf)
    return NULL;
  memcpy (buf, s, n);
  *rlength = n;
  return buf;
}
Example #5
0
/*
 * Get a MPI from the car
 */
gcry_mpi_t
gcry_sexp_nth_mpi (gcry_sexp_t list, int number, int mpifmt)
{
  const char *s;
  size_t n;
  gcry_mpi_t a;

  if ( !mpifmt )
    mpifmt = GCRYMPI_FMT_STD;

  s = sexp_nth_data (list, number, &n);
  if (!s)
    return NULL;

  if ( gcry_mpi_scan ( &a, mpifmt, s, n, NULL ) )
    return NULL;

  return a;
}
Example #6
0
/* Take the hash value and convert into an MPI, suitable for
   passing to the low level functions.  We currently support the
   old style way of passing just a MPI and the modern interface which
   allows to pass flags so that we can choose between raw and pkcs1
   padding - may be more padding options later.

   (<mpi>)
   or
   (data
    [(flags [raw, direct, pkcs1, oaep, pss, no-blinding, rfc6979, eddsa])]
    [(hash <algo> <value>)]
    [(value <text>)]
    [(hash-algo <algo>)]
    [(label <label>)]
    [(salt-length <length>)]
    [(random-override <data>)]
   )

   Either the VALUE or the HASH element must be present for use
   with signatures.  VALUE is used for encryption.

   HASH-ALGO is specific to OAEP and EDDSA.

   LABEL is specific to OAEP.

   SALT-LENGTH is for PSS.

   RANDOM-OVERRIDE is used to replace random nonces for regression
   testing.  */
gcry_err_code_t
_gcry_pk_util_data_to_mpi (gcry_sexp_t input, gcry_mpi_t *ret_mpi,
                           struct pk_encoding_ctx *ctx)
{
  gcry_err_code_t rc = 0;
  gcry_sexp_t ldata, lhash, lvalue;
  size_t n;
  const char *s;
  int unknown_flag = 0;
  int parsed_flags = 0;

  *ret_mpi = NULL;
  ldata = sexp_find_token (input, "data", 0);
  if (!ldata)
    { /* assume old style */
      *ret_mpi = sexp_nth_mpi (input, 0, 0);
      return *ret_mpi ? GPG_ERR_NO_ERROR : GPG_ERR_INV_OBJ;
    }

  /* See whether there is a flags list.  */
  {
    gcry_sexp_t lflags = sexp_find_token (ldata, "flags", 0);
    if (lflags)
      {
        if (_gcry_pk_util_parse_flaglist (lflags,
                                          &parsed_flags, &ctx->encoding))
          unknown_flag = 1;
        sexp_release (lflags);
      }
  }

  if (ctx->encoding == PUBKEY_ENC_UNKNOWN)
    ctx->encoding = PUBKEY_ENC_RAW; /* default to raw */

  /* Get HASH or MPI */
  lhash = sexp_find_token (ldata, "hash", 0);
  lvalue = lhash? NULL : sexp_find_token (ldata, "value", 0);

  if (!(!lhash ^ !lvalue))
    rc = GPG_ERR_INV_OBJ; /* none or both given */
  else if (unknown_flag)
    rc = GPG_ERR_INV_FLAG;
  else if (ctx->encoding == PUBKEY_ENC_RAW
           && (parsed_flags & PUBKEY_FLAG_EDDSA))
    {
      /* Prepare for EdDSA.  */
      gcry_sexp_t list;
      void *value;
      size_t valuelen;

      if (!lvalue)
        {
          rc = GPG_ERR_INV_OBJ;
          goto leave;
        }
      /* Get HASH-ALGO. */
      list = sexp_find_token (ldata, "hash-algo", 0);
      if (list)
        {
          s = sexp_nth_data (list, 1, &n);
          if (!s)
            rc = GPG_ERR_NO_OBJ;
          else
            {
              ctx->hash_algo = get_hash_algo (s, n);
              if (!ctx->hash_algo)
                rc = GPG_ERR_DIGEST_ALGO;
            }
          sexp_release (list);
        }
      else
        rc = GPG_ERR_INV_OBJ;
      if (rc)
        goto leave;

      /* Get VALUE.  */
      value = sexp_nth_buffer (lvalue, 1, &valuelen);
      if (!value)
        {
          /* We assume that a zero length message is meant by
             "(value)".  This is commonly used by test vectors.  Note
             that S-expression do not allow zero length items. */
          valuelen = 0;
          value = xtrymalloc (1);
          if (!value)
            rc = gpg_err_code_from_syserror ();
        }
      else if ((valuelen * 8) < valuelen)
        {
          xfree (value);
          rc = GPG_ERR_TOO_LARGE;
        }
      if (rc)
        goto leave;

      /* Note that mpi_set_opaque takes ownership of VALUE.  */
      *ret_mpi = mpi_set_opaque (NULL, value, valuelen*8);
    }
  else if (ctx->encoding == PUBKEY_ENC_RAW && lhash
           && ((parsed_flags & PUBKEY_FLAG_RAW_FLAG)
               || (parsed_flags & PUBKEY_FLAG_RFC6979)))
    {
      /* Raw encoding along with a hash element.  This is commonly
         used for DSA.  For better backward error compatibility we
         allow this only if either the rfc6979 flag has been given or
         the raw flags was explicitly given.  */
      if (sexp_length (lhash) != 3)
        rc = GPG_ERR_INV_OBJ;
      else if ( !(s=sexp_nth_data (lhash, 1, &n)) || !n )
        rc = GPG_ERR_INV_OBJ;
      else
        {
          void *value;
          size_t valuelen;

	  ctx->hash_algo = get_hash_algo (s, n);
          if (!ctx->hash_algo)
            rc = GPG_ERR_DIGEST_ALGO;
          else if (!(value=sexp_nth_buffer (lhash, 2, &valuelen)))
            rc = GPG_ERR_INV_OBJ;
          else if ((valuelen * 8) < valuelen)
            {
              xfree (value);
              rc = GPG_ERR_TOO_LARGE;
            }
          else
            *ret_mpi = mpi_set_opaque (NULL, value, valuelen*8);
        }
    }
  else if (ctx->encoding == PUBKEY_ENC_RAW && lvalue)
    {
      /* RFC6969 may only be used with the a hash value and not the
         MPI based value.  */
      if (parsed_flags & PUBKEY_FLAG_RFC6979)
        {
          rc = GPG_ERR_CONFLICT;
          goto leave;
        }

      /* Get the value */
      *ret_mpi = sexp_nth_mpi (lvalue, 1, GCRYMPI_FMT_USG);
      if (!*ret_mpi)
        rc = GPG_ERR_INV_OBJ;
    }
  else if (ctx->encoding == PUBKEY_ENC_PKCS1 && lvalue
	   && ctx->op == PUBKEY_OP_ENCRYPT)
    {
      const void * value;
      size_t valuelen;
      gcry_sexp_t list;
      void *random_override = NULL;
      size_t random_override_len = 0;

      if ( !(value=sexp_nth_data (lvalue, 1, &valuelen)) || !valuelen )
        rc = GPG_ERR_INV_OBJ;
      else
        {
          /* Get optional RANDOM-OVERRIDE.  */
          list = sexp_find_token (ldata, "random-override", 0);
          if (list)
            {
              s = sexp_nth_data (list, 1, &n);
              if (!s)
                rc = GPG_ERR_NO_OBJ;
              else if (n > 0)
                {
                  random_override = xtrymalloc (n);
                  if (!random_override)
                    rc = gpg_err_code_from_syserror ();
                  else
                    {
                      memcpy (random_override, s, n);
                      random_override_len = n;
                    }
                }
              sexp_release (list);
              if (rc)
                goto leave;
            }

          rc = _gcry_rsa_pkcs1_encode_for_enc (ret_mpi, ctx->nbits,
                                               value, valuelen,
                                               random_override,
                                               random_override_len);
          xfree (random_override);
        }
    }
  else if (ctx->encoding == PUBKEY_ENC_PKCS1 && lhash
	   && (ctx->op == PUBKEY_OP_SIGN || ctx->op == PUBKEY_OP_VERIFY))
    {
      if (sexp_length (lhash) != 3)
        rc = GPG_ERR_INV_OBJ;
      else if ( !(s=sexp_nth_data (lhash, 1, &n)) || !n )
        rc = GPG_ERR_INV_OBJ;
      else
        {
          const void * value;
          size_t valuelen;

	  ctx->hash_algo = get_hash_algo (s, n);

          if (!ctx->hash_algo)
            rc = GPG_ERR_DIGEST_ALGO;
          else if ( !(value=sexp_nth_data (lhash, 2, &valuelen))
                    || !valuelen )
            rc = GPG_ERR_INV_OBJ;
          else
	    rc = _gcry_rsa_pkcs1_encode_for_sig (ret_mpi, ctx->nbits,
                                                 value, valuelen,
                                                 ctx->hash_algo);
        }
    }
  else if (ctx->encoding == PUBKEY_ENC_OAEP && lvalue
	   && ctx->op == PUBKEY_OP_ENCRYPT)
    {
      const void * value;
      size_t valuelen;

      if ( !(value=sexp_nth_data (lvalue, 1, &valuelen)) || !valuelen )
	rc = GPG_ERR_INV_OBJ;
      else
	{
	  gcry_sexp_t list;
          void *random_override = NULL;
          size_t random_override_len = 0;

	  /* Get HASH-ALGO. */
	  list = sexp_find_token (ldata, "hash-algo", 0);
	  if (list)
	    {
	      s = sexp_nth_data (list, 1, &n);
	      if (!s)
		rc = GPG_ERR_NO_OBJ;
	      else
		{
		  ctx->hash_algo = get_hash_algo (s, n);
		  if (!ctx->hash_algo)
		    rc = GPG_ERR_DIGEST_ALGO;
		}
	      sexp_release (list);
	      if (rc)
		goto leave;
	    }

	  /* Get LABEL. */
	  list = sexp_find_token (ldata, "label", 0);
	  if (list)
	    {
	      s = sexp_nth_data (list, 1, &n);
	      if (!s)
		rc = GPG_ERR_NO_OBJ;
	      else if (n > 0)
		{
		  ctx->label = xtrymalloc (n);
		  if (!ctx->label)
		    rc = gpg_err_code_from_syserror ();
		  else
		    {
		      memcpy (ctx->label, s, n);
		      ctx->labellen = n;
		    }
		}
	      sexp_release (list);
	      if (rc)
		goto leave;
	    }
          /* Get optional RANDOM-OVERRIDE.  */
          list = sexp_find_token (ldata, "random-override", 0);
          if (list)
            {
              s = sexp_nth_data (list, 1, &n);
              if (!s)
                rc = GPG_ERR_NO_OBJ;
              else if (n > 0)
                {
                  random_override = xtrymalloc (n);
                  if (!random_override)
                    rc = gpg_err_code_from_syserror ();
                  else
                    {
                      memcpy (random_override, s, n);
                      random_override_len = n;
                    }
                }
              sexp_release (list);
              if (rc)
                goto leave;
            }

	  rc = _gcry_rsa_oaep_encode (ret_mpi, ctx->nbits, ctx->hash_algo,
                                      value, valuelen,
                                      ctx->label, ctx->labellen,
                                      random_override, random_override_len);

          xfree (random_override);
	}
    }
  else if (ctx->encoding == PUBKEY_ENC_PSS && lhash
	   && ctx->op == PUBKEY_OP_SIGN)
    {
      if (sexp_length (lhash) != 3)
        rc = GPG_ERR_INV_OBJ;
      else if ( !(s=sexp_nth_data (lhash, 1, &n)) || !n )
        rc = GPG_ERR_INV_OBJ;
      else
        {
          const void * value;
          size_t valuelen;
          void *random_override = NULL;
          size_t random_override_len = 0;

	  ctx->hash_algo = get_hash_algo (s, n);

          if (!ctx->hash_algo)
            rc = GPG_ERR_DIGEST_ALGO;
          else if ( !(value=sexp_nth_data (lhash, 2, &valuelen))
                    || !valuelen )
            rc = GPG_ERR_INV_OBJ;
          else
	    {
	      gcry_sexp_t list;

	      /* Get SALT-LENGTH. */
	      list = sexp_find_token (ldata, "salt-length", 0);
	      if (list)
		{
		  s = sexp_nth_data (list, 1, &n);
		  if (!s)
		    {
		      rc = GPG_ERR_NO_OBJ;
		      goto leave;
		    }
		  ctx->saltlen = (unsigned int)strtoul (s, NULL, 10);
		  sexp_release (list);
		}

              /* Get optional RANDOM-OVERRIDE.  */
              list = sexp_find_token (ldata, "random-override", 0);
              if (list)
                {
                  s = sexp_nth_data (list, 1, &n);
                  if (!s)
                    rc = GPG_ERR_NO_OBJ;
                  else if (n > 0)
                    {
                      random_override = xtrymalloc (n);
                      if (!random_override)
                        rc = gpg_err_code_from_syserror ();
                      else
                        {
                          memcpy (random_override, s, n);
                          random_override_len = n;
                        }
                    }
                  sexp_release (list);
                  if (rc)
                    goto leave;
                }

              /* Encode the data.  (NBITS-1 is due to 8.1.1, step 1.) */
	      rc = _gcry_rsa_pss_encode (ret_mpi, ctx->nbits - 1,
                                         ctx->hash_algo,
                                         value, valuelen, ctx->saltlen,
                                         random_override, random_override_len);

              xfree (random_override);
	    }
        }
    }
  else if (ctx->encoding == PUBKEY_ENC_PSS && lhash
	   && ctx->op == PUBKEY_OP_VERIFY)
    {
      if (sexp_length (lhash) != 3)
        rc = GPG_ERR_INV_OBJ;
      else if ( !(s=sexp_nth_data (lhash, 1, &n)) || !n )
        rc = GPG_ERR_INV_OBJ;
      else
        {
	  ctx->hash_algo = get_hash_algo (s, n);

          if (!ctx->hash_algo)
            rc = GPG_ERR_DIGEST_ALGO;
	  else
	    {
	      *ret_mpi = sexp_nth_mpi (lhash, 2, GCRYMPI_FMT_USG);
	      if (!*ret_mpi)
		rc = GPG_ERR_INV_OBJ;
	      ctx->verify_cmp = pss_verify_cmp;
	      ctx->verify_arg = *ret_mpi;
	    }
	}
    }
  else
    rc = GPG_ERR_CONFLICT;

 leave:
  sexp_release (ldata);
  sexp_release (lhash);
  sexp_release (lvalue);

  if (!rc)
    ctx->flags = parsed_flags;
  else
    {
      xfree (ctx->label);
      ctx->label = NULL;
    }

  return rc;
}
Example #7
0
/* Parser for a flag list.  On return the encoding is stored at
   R_ENCODING and the flags are stored at R_FLAGS.  If any of them is
   not needed, NULL may be passed.  The function returns 0 on success
   or an error code. */
gpg_err_code_t
_gcry_pk_util_parse_flaglist (gcry_sexp_t list,
                              int *r_flags, enum pk_encoding *r_encoding)
{
  gpg_err_code_t rc = 0;
  const char *s;
  size_t n;
  int i;
  int encoding = PUBKEY_ENC_UNKNOWN;
  int flags = 0;
  int igninvflag = 0;

  for (i = list ? sexp_length (list)-1 : 0; i > 0; i--)
    {
      s = sexp_nth_data (list, i, &n);
      if (!s)
        continue; /* Not a data element. */

      switch (n)
        {
        case 3:
          if (!memcmp (s, "pss", 3) && encoding == PUBKEY_ENC_UNKNOWN)
            {
              encoding = PUBKEY_ENC_PSS;
              flags |= PUBKEY_FLAG_FIXEDLEN;
            }
          else if (!memcmp (s, "raw", 3) && encoding == PUBKEY_ENC_UNKNOWN)
            {
              encoding = PUBKEY_ENC_RAW;
              flags |= PUBKEY_FLAG_RAW_FLAG; /* Explicitly given.  */
            }
          else if (!igninvflag)
            rc = GPG_ERR_INV_FLAG;
          break;

        case 4:
          if (!memcmp (s, "comp", 4))
            flags |= PUBKEY_FLAG_COMP;
          else if (!memcmp (s, "oaep", 4) && encoding == PUBKEY_ENC_UNKNOWN)
            {
              encoding = PUBKEY_ENC_OAEP;
              flags |= PUBKEY_FLAG_FIXEDLEN;
            }
          else if (!memcmp (s, "gost", 4))
            {
              encoding = PUBKEY_ENC_RAW;
              flags |= PUBKEY_FLAG_GOST;
            }
          else if (!igninvflag)
            rc = GPG_ERR_INV_FLAG;
          break;

        case 5:
          if (!memcmp (s, "eddsa", 5))
            {
              encoding = PUBKEY_ENC_RAW;
              flags |= PUBKEY_FLAG_EDDSA;
            }
          else if (!memcmp (s, "pkcs1", 5) && encoding == PUBKEY_ENC_UNKNOWN)
            {
              encoding = PUBKEY_ENC_PKCS1;
              flags |= PUBKEY_FLAG_FIXEDLEN;
            }
          else if (!memcmp (s, "param", 5))
            flags |= PUBKEY_FLAG_PARAM;
          else if (!igninvflag)
            rc = GPG_ERR_INV_FLAG;
          break;

        case 6:
          if (!memcmp (s, "nocomp", 6))
            flags |= PUBKEY_FLAG_NOCOMP;
          else if (!igninvflag)
            rc = GPG_ERR_INV_FLAG;
          break;

        case 7:
          if (!memcmp (s, "rfc6979", 7))
            flags |= PUBKEY_FLAG_RFC6979;
          else if (!memcmp (s, "noparam", 7))
            ; /* Ignore - it is the default.  */
          else if (!igninvflag)
            rc = GPG_ERR_INV_FLAG;
          break;

        case 8:
          if (!memcmp (s, "use-x931", 8))
            flags |= PUBKEY_FLAG_USE_X931;
          else if (!igninvflag)
            rc = GPG_ERR_INV_FLAG;
          break;

        case 10:
          if (!memcmp (s, "igninvflag", 10))
            igninvflag = 1;
          else if (!memcmp (s, "no-keytest", 10))
            flags |= PUBKEY_FLAG_NO_KEYTEST;
          /* In 1.7.0 we will return an INV_FLAG on error but we
             do not fix that bug here in 1.6.4  */
          break;

        case 11:
          if (!memcmp (s, "no-blinding", 11))
            flags |= PUBKEY_FLAG_NO_BLINDING;
          else if (!memcmp (s, "use-fips186", 11))
            flags |= PUBKEY_FLAG_USE_FIPS186;
          else if (!igninvflag)
            rc = GPG_ERR_INV_FLAG;
          break;

        case 13:
          if (!memcmp (s, "use-fips186-2", 13))
            flags |= PUBKEY_FLAG_USE_FIPS186_2;
          else if (!memcmp (s, "transient-key", 13))
            flags |= PUBKEY_FLAG_TRANSIENT_KEY;
          else if (!igninvflag)
            rc = GPG_ERR_INV_FLAG;
          break;

        default:
          if (!igninvflag)
            rc = GPG_ERR_INV_FLAG;
          break;
        }
    }

  if (r_flags)
    *r_flags = flags;
  if (r_encoding)
    *r_encoding = encoding;

  return rc;
}
Example #8
0
/* Parse a "enc-val" s-expression and store the inner parameter list
   at R_PARMS.  ALGO_NAMES is used to verify that the algorithm in
   "enc-val" is valid.  Returns 0 on success and stores a new list at
   R_PARMS which must be freed by the caller.  On error R_PARMS is set
   to NULL and an error code returned.  If R_ECCFLAGS is not NULL flag
   values are set into it; as of now they are only used with ecc
   algorithms.

     (enc-val
       [(flags [raw, pkcs1, oaep, no-blinding])]
       [(hash-algo <algo>)]
       [(label <label>)]
        (<algo>
          (<param_name1> <mpi>)
          ...
          (<param_namen> <mpi>)))

   HASH-ALGO and LABEL are specific to OAEP.  CTX will be updated with
   encoding information.  */
gpg_err_code_t
_gcry_pk_util_preparse_encval (gcry_sexp_t sexp, const char **algo_names,
                               gcry_sexp_t *r_parms,
                               struct pk_encoding_ctx *ctx)
{
  gcry_err_code_t rc = 0;
  gcry_sexp_t l1 = NULL;
  gcry_sexp_t l2 = NULL;
  char *name = NULL;
  size_t n;
  int parsed_flags = 0;
  int i;

  *r_parms = NULL;

  /* Check that the first element is valid.  */
  l1 = sexp_find_token (sexp, "enc-val" , 0);
  if (!l1)
    {
      rc = GPG_ERR_INV_OBJ; /* Does not contain an encrypted value object.  */
      goto leave;
    }

  l2 = sexp_nth (l1, 1);
  if (!l2)
    {
      rc = GPG_ERR_NO_OBJ;  /* No cadr for the data object.  */
      goto leave;
    }

  /* Extract identifier of sublist.  */
  name = sexp_nth_string (l2, 0);
  if (!name)
    {
      rc = GPG_ERR_INV_OBJ; /* Invalid structure of object.  */
      goto leave;
    }

  if (!strcmp (name, "flags"))
    {
      const char *s;

      /* There is a flags element - process it.  */
      rc = _gcry_pk_util_parse_flaglist (l2, &parsed_flags, &ctx->encoding);
      if (rc)
        goto leave;
      if (ctx->encoding == PUBKEY_ENC_PSS)
        {
          rc = GPG_ERR_CONFLICT;
          goto leave;
        }

      /* Get the OAEP parameters HASH-ALGO and LABEL, if any. */
      if (ctx->encoding == PUBKEY_ENC_OAEP)
	{
	  /* Get HASH-ALGO. */
          sexp_release (l2);
	  l2 = sexp_find_token (l1, "hash-algo", 0);
	  if (l2)
	    {
	      s = sexp_nth_data (l2, 1, &n);
	      if (!s)
		rc = GPG_ERR_NO_OBJ;
	      else
		{
		  ctx->hash_algo = get_hash_algo (s, n);
		  if (!ctx->hash_algo)
		    rc = GPG_ERR_DIGEST_ALGO;
		}
	      if (rc)
		goto leave;
	    }

	  /* Get LABEL. */
          sexp_release (l2);
	  l2 = sexp_find_token (l1, "label", 0);
	  if (l2)
	    {
	      s = sexp_nth_data (l2, 1, &n);
	      if (!s)
		rc = GPG_ERR_NO_OBJ;
	      else if (n > 0)
		{
		  ctx->label = xtrymalloc (n);
		  if (!ctx->label)
		    rc = gpg_err_code_from_syserror ();
		  else
		    {
		      memcpy (ctx->label, s, n);
		      ctx->labellen = n;
		    }
		}
	      if (rc)
		goto leave;
	    }
	}

      /* Get the next which has the actual data - skip HASH-ALGO and LABEL. */
      for (i = 2; (sexp_release (l2), l2 = sexp_nth (l1, i)); i++)
	{
	  s = sexp_nth_data (l2, 0, &n);
	  if (!(n == 9 && !memcmp (s, "hash-algo", 9))
	      && !(n == 5 && !memcmp (s, "label", 5))
	      && !(n == 15 && !memcmp (s, "random-override", 15)))
	    break;
	}
      if (!l2)
        {
          rc = GPG_ERR_NO_OBJ; /* No cadr for the data object. */
          goto leave;
        }

      /* Extract sublist identifier.  */
      xfree (name);
      name = sexp_nth_string (l2, 0);
      if (!name)
        {
          rc = GPG_ERR_INV_OBJ; /* Invalid structure of object. */
          goto leave;
        }
    }
  else /* No flags - flag as legacy structure.  */
    parsed_flags |= PUBKEY_FLAG_LEGACYRESULT;

  for (i=0; algo_names[i]; i++)
    if (!stricmp (name, algo_names[i]))
      break;
  if (!algo_names[i])
    {
      rc = GPG_ERR_CONFLICT; /* "enc-val" uses an unexpected algo. */
      goto leave;
    }

  *r_parms = l2;
  l2 = NULL;
  ctx->flags |= parsed_flags;
  rc = 0;

 leave:
  xfree (name);
  sexp_release (l2);
  sexp_release (l1);
  return rc;
}
Example #9
0
/* Return the so called KEYGRIP which is the SHA-1 hash of the public
   key parameters expressed in a way depending on the algorithm.

   ARRAY must either be 20 bytes long or NULL; in the latter case a
   newly allocated array of that size is returned, otherwise ARRAY or
   NULL is returned to indicate an error which is most likely an
   unknown algorithm.  The function accepts public or secret keys. */
unsigned char *
_gcry_pk_get_keygrip (gcry_sexp_t key, unsigned char *array)
{
  gcry_sexp_t list = NULL;
  gcry_sexp_t l2 = NULL;
  gcry_pk_spec_t *spec = NULL;
  const char *s;
  char *name = NULL;
  int idx;
  const char *elems;
  gcry_md_hd_t md = NULL;
  int okay = 0;

  /* Check that the first element is valid. */
  list = sexp_find_token (key, "public-key", 0);
  if (! list)
    list = sexp_find_token (key, "private-key", 0);
  if (! list)
    list = sexp_find_token (key, "protected-private-key", 0);
  if (! list)
    list = sexp_find_token (key, "shadowed-private-key", 0);
  if (! list)
    return NULL; /* No public- or private-key object. */

  l2 = sexp_cadr (list);
  sexp_release (list);
  list = l2;
  l2 = NULL;

  name = _gcry_sexp_nth_string (list, 0);
  if (!name)
    goto fail; /* Invalid structure of object. */

  spec = spec_from_name (name);
  if (!spec)
    goto fail; /* Unknown algorithm.  */

  elems = spec->elements_grip;
  if (!elems)
    goto fail; /* No grip parameter.  */

  if (_gcry_md_open (&md, GCRY_MD_SHA1, 0))
    goto fail;

  if (spec->comp_keygrip)
    {
      /* Module specific method to compute a keygrip.  */
      if (spec->comp_keygrip (md, list))
        goto fail;
    }
  else
    {
      /* Generic method to compute a keygrip.  */
      for (idx = 0, s = elems; *s; s++, idx++)
        {
          const char *data;
          size_t datalen;
          char buf[30];

          l2 = sexp_find_token (list, s, 1);
          if (! l2)
            goto fail;
          data = sexp_nth_data (l2, 1, &datalen);
          if (! data)
            goto fail;

          _snprintf (buf, sizeof buf, "(1:%c%u:", *s, (unsigned int)datalen);
          _gcry_md_write (md, buf, strlen (buf));
          _gcry_md_write (md, data, datalen);
          sexp_release (l2);
          l2 = NULL;
          _gcry_md_write (md, ")", 1);
        }
    }

  if (!array)
    {
      array = xtrymalloc (20);
      if (! array)
        goto fail;
    }

  memcpy (array, _gcry_md_read (md, GCRY_MD_SHA1), 20);
  okay = 1;

 fail:
  xfree (name);
  sexp_release (l2);
  _gcry_md_close (md);
  sexp_release (list);
  return okay? array : NULL;
}
Example #10
0
/* Get data from the car.  The returned value is valid as long as the
   list is not modified.  */
const char *
gcry_sexp_nth_data (const gcry_sexp_t list, int number, size_t *datalen )
{
  return sexp_nth_data (list, number, datalen);
}