Пример #1
0
/* This function gets the signature parameters and encodes
 * them into a way for _gnutls_pk_verify to use.
 */
static cdk_error_t
sig_to_datum (gnutls_datum_t * r_sig, cdk_pkt_signature_t sig)
{
    int err;
    cdk_error_t rc;

    if (!r_sig || !sig)
        return CDK_Inv_Value;

    rc = 0;
    if (is_RSA (sig->pubkey_algo))
    {
        err = _gnutls_mpi_dprint (sig->mpi[0], r_sig);
        if (err < 0)
            rc = map_gnutls_error (err);
    }
    else if (is_DSA (sig->pubkey_algo))
    {
        err = _gnutls_encode_ber_rs (r_sig, sig->mpi[0], sig->mpi[1]);
        if (err < 0)
            rc = map_gnutls_error (err);
    }
    else
        rc = CDK_Inv_Algo;
    return rc;
}
Пример #2
0
Файл: pk.c Проект: dezelin/maily
/* in case of DSA puts into data, r,s
 */
static int
_wrap_gcry_pk_sign (gnutls_pk_algorithm_t algo, gnutls_datum_t * signature,
                    const gnutls_datum_t * vdata,
                    const gnutls_pk_params_st * pk_params)
{
  gcry_sexp_t s_hash = NULL, s_key = NULL, s_sig = NULL;
  gcry_sexp_t list = NULL;
  int rc = -1, ret;
  bigint_t hash;
  bigint_t res[2] = { NULL, NULL };

  if (_gnutls_mpi_scan_nz (&hash, vdata->data, vdata->size) != 0)
    {
      gnutls_assert ();
      return GNUTLS_E_MPI_SCAN_FAILED;
    }

  /* make a sexp from pkey */
  switch (algo)
    {
    case GNUTLS_PK_DSA:
      if (pk_params->params_nr >= 5)
        rc = gcry_sexp_build (&s_key, NULL,
                              "(private-key(dsa(p%m)(q%m)(g%m)(y%m)(x%m)))",
                              pk_params->params[0], pk_params->params[1],
                              pk_params->params[2], pk_params->params[3],
                              pk_params->params[4]);
      else
        {
          gnutls_assert ();
        }

      break;
    case GNUTLS_PK_RSA:
      if (pk_params->params_nr >= 6)
        rc = gcry_sexp_build (&s_key, NULL,
                              "(private-key(rsa((n%m)(e%m)(d%m)(p%m)(q%m)(u%m))))",
                              pk_params->params[0], pk_params->params[1],
                              pk_params->params[2], pk_params->params[3],
                              pk_params->params[4], pk_params->params[5]);
      else
        {
          gnutls_assert ();
        }
      break;

    default:
      gnutls_assert ();
      ret = GNUTLS_E_INTERNAL_ERROR;
      goto cleanup;
    }

  if (rc != 0)
    {
      gnutls_assert ();
      ret = GNUTLS_E_INTERNAL_ERROR;
      goto cleanup;
    }

  /* put the data into a simple list */
  if (gcry_sexp_build (&s_hash, NULL, "%m", hash))
    {
      gnutls_assert ();
      ret = GNUTLS_E_INTERNAL_ERROR;
      goto cleanup;
    }


  /* pass it to libgcrypt */
  rc = gcry_pk_sign (&s_sig, s_hash, s_key);
  if (rc != 0)
    {
      gnutls_assert ();
      ret = GNUTLS_E_PK_SIGN_FAILED;
      goto cleanup;
    }

  ret = GNUTLS_E_INTERNAL_ERROR;

  switch (algo)
    {
    case GNUTLS_PK_DSA:
      {
        list = gcry_sexp_find_token (s_sig, "r", 0);
        if (list == NULL)
          {
            gnutls_assert ();
            ret = GNUTLS_E_INTERNAL_ERROR;
            goto cleanup;
          }

        res[0] = gcry_sexp_nth_mpi (list, 1, GCRYMPI_FMT_USG);
        gcry_sexp_release (list);

        list = gcry_sexp_find_token (s_sig, "s", 0);
        if (list == NULL)
          {
            gnutls_assert ();
            ret = GNUTLS_E_INTERNAL_ERROR;
            goto cleanup;
          }

        res[1] = gcry_sexp_nth_mpi (list, 1, GCRYMPI_FMT_USG);
        gcry_sexp_release (list);

        ret = _gnutls_encode_ber_rs (signature, res[0], res[1]);
        if (ret < 0)
          {
            gnutls_assert ();
            goto cleanup;
          }
      }
      break;

    case GNUTLS_PK_RSA:
      {
        list = gcry_sexp_find_token (s_sig, "s", 0);
        if (list == NULL)
          {
            gnutls_assert ();
            ret = GNUTLS_E_INTERNAL_ERROR;
            goto cleanup;
          }

        res[0] = gcry_sexp_nth_mpi (list, 1, GCRYMPI_FMT_USG);
        gcry_sexp_release (list);

        ret = _gnutls_mpi_dprint (res[0], signature);
        if (ret < 0)
          {
            gnutls_assert ();
            goto cleanup;
          }
      }
      break;

    default:
      gnutls_assert ();
      ret = GNUTLS_E_INTERNAL_ERROR;
      goto cleanup;
    }

  ret = 0;

cleanup:
  _gnutls_mpi_release (&hash);
  if (res[0])
    _gnutls_mpi_release (&res[0]);
  if (res[1])
    _gnutls_mpi_release (&res[1]);
  if (s_sig)
    gcry_sexp_release (s_sig);
  if (s_hash)
    gcry_sexp_release (s_hash);
  if (s_key)
    gcry_sexp_release (s_key);

  return ret;
}
Пример #3
0
Файл: pk.c Проект: intgr/gnutls
/* in case of DSA puts into data, r,s
 */
static int
_wrap_nettle_pk_sign (gnutls_pk_algorithm_t algo,
                      gnutls_datum_t * signature,
                      const gnutls_datum_t * vdata,
                      const gnutls_pk_params_st * pk_params)
{
  int ret;
  unsigned int hash;
  unsigned int hash_len;

  switch (algo)
    {
    case GNUTLS_PK_EC: /* we do ECDSA */
      {
        ecc_key priv;
        struct dsa_signature sig;
        int curve_id = pk_params->flags;

        if (is_supported_curve(curve_id) == 0)
          return gnutls_assert_val(GNUTLS_E_ECC_UNSUPPORTED_CURVE);

        _ecc_params_to_privkey(pk_params, &priv);

        dsa_signature_init (&sig);

        hash = _gnutls_dsa_q_to_hash (algo, pk_params, &hash_len);
        if (hash_len > vdata->size)
          {
            gnutls_assert ();
            _gnutls_debug_log("Security level of algorithm requires hash %s(%d) or better\n", gnutls_mac_get_name(hash), hash_len);
            hash_len = vdata->size;
          }

        ret = ecc_sign_hash(vdata->data, hash_len,
                            &sig, NULL, rnd_func, &priv, curve_id);
        if (ret != 0)
          {
            gnutls_assert ();
            ret = GNUTLS_E_PK_SIGN_FAILED;
            goto ecdsa_fail;
          }

        ret = _gnutls_encode_ber_rs (signature, &sig.r, &sig.s);

      ecdsa_fail:
        dsa_signature_clear (&sig);
        _ecc_params_clear( &priv);

        if (ret < 0)
          {
            gnutls_assert ();
            goto cleanup;
          }
        break;
      }
    case GNUTLS_PK_DSA:
      {
        struct dsa_public_key pub;
        struct dsa_private_key priv;
        struct dsa_signature sig;

        memset(&priv, 0, sizeof(priv));
        memset(&pub, 0, sizeof(pub));
        _dsa_params_to_pubkey (pk_params, &pub);
        _dsa_params_to_privkey (pk_params, &priv);

        dsa_signature_init (&sig);

        hash = _gnutls_dsa_q_to_hash (algo, pk_params, &hash_len);
        if (hash_len > vdata->size)
          {
            gnutls_assert ();
            _gnutls_debug_log("Security level of algorithm requires hash %s(%d) or better\n", gnutls_mac_get_name(hash), hash_len);
            hash_len = vdata->size;
          }

        ret =
          _dsa_sign (&pub, &priv, NULL, rnd_func,
                     hash_len, vdata->data, &sig);
        if (ret == 0)
          {
            gnutls_assert ();
            ret = GNUTLS_E_PK_SIGN_FAILED;
            goto dsa_fail;
          }

        ret = _gnutls_encode_ber_rs (signature, &sig.r, &sig.s);

      dsa_fail:
        dsa_signature_clear (&sig);

        if (ret < 0)
          {
            gnutls_assert ();
            goto cleanup;
          }
        break;
      }
    case GNUTLS_PK_RSA:
      {
        struct rsa_private_key priv;
        struct rsa_public_key pub;
        mpz_t s;

        _rsa_params_to_privkey (pk_params, &priv);
        _rsa_params_to_pubkey (pk_params, &pub);
        
        mpz_init(s);

        ret = rsa_pkcs1_sign_tr(&pub, &priv, NULL, rnd_func,
                                vdata->size, vdata->data, s);
        if (ret == 0)
          {
            gnutls_assert();
            ret = GNUTLS_E_PK_SIGN_FAILED;
            goto rsa_fail;
          }

        ret = _gnutls_mpi_dprint (s, signature);

rsa_fail:
        mpz_clear(s);

        if (ret < 0)
          {
            gnutls_assert ();
            goto cleanup;
          }

        break;
      }
    default:
      gnutls_assert ();
      ret = GNUTLS_E_INTERNAL_ERROR;
      goto cleanup;
    }

  ret = 0;

cleanup:

  return ret;
}
Пример #4
0
/* in case of DSA puts into data, r,s
 */
static int
_wrap_nettle_pk_sign (gnutls_pk_algorithm_t algo,
                      gnutls_datum_t * signature,
                      const gnutls_datum_t * vdata,
                      const gnutls_pk_params_st * pk_params)
{
  int ret;
  unsigned int hash;
  unsigned int hash_len;

  switch (algo)
    {
    case GNUTLS_PK_EC: /* we do ECDSA */
      {
        ecc_key priv;
        struct dsa_signature sig;

        _ecc_params_to_privkey(pk_params, &priv);

        dsa_signature_init (&sig);

        hash = _gnutls_dsa_q_to_hash (algo, pk_params, &hash_len);
        if (hash_len > vdata->size)
          {
            gnutls_assert ();
            _gnutls_debug_log("Security level of algorithm requires hash %s(%d) or better\n", gnutls_mac_get_name(hash), hash_len);
            hash_len = vdata->size;
          }

        ret = ecc_sign_hash(vdata->data, hash_len, 
                            &sig, NULL, rnd_func, &priv);
        if (ret != 0)
          {
            gnutls_assert ();
            ret = GNUTLS_E_PK_SIGN_FAILED;
            goto ecdsa_fail;
          }

        ret = _gnutls_encode_ber_rs (signature, &sig.r, &sig.s);

      ecdsa_fail:
        dsa_signature_clear (&sig);
        _ecc_params_clear( &priv);

        if (ret < 0)
          {
            gnutls_assert ();
            goto cleanup;
          }
        break;
      }
    case GNUTLS_PK_DSA:
      {
        struct dsa_public_key pub;
        struct dsa_private_key priv;
        struct dsa_signature sig;

        memset(&priv, 0, sizeof(priv));
        memset(&pub, 0, sizeof(pub));
        _dsa_params_to_pubkey (pk_params, &pub);
        _dsa_params_to_privkey (pk_params, &priv);

        dsa_signature_init (&sig);

        hash = _gnutls_dsa_q_to_hash (algo, pk_params, &hash_len);
        if (hash_len > vdata->size)
          {
            gnutls_assert ();
            _gnutls_debug_log("Security level of algorithm requires hash %s(%d) or better\n", gnutls_mac_get_name(hash), hash_len);
            hash_len = vdata->size;
          }

        ret =
          _dsa_sign (&pub, &priv, NULL, rnd_func,
                     hash_len, vdata->data, &sig);
        if (ret == 0)
          {
            gnutls_assert ();
            ret = GNUTLS_E_PK_SIGN_FAILED;
            goto dsa_fail;
          }

        ret = _gnutls_encode_ber_rs (signature, &sig.r, &sig.s);

      dsa_fail:
        dsa_signature_clear (&sig);

        if (ret < 0)
          {
            gnutls_assert ();
            goto cleanup;
          }
        break;
      }
    case GNUTLS_PK_RSA:
      {
        struct rsa_private_key priv;
        bigint_t hash, nc, ri;

        if (_gnutls_mpi_scan_nz (&hash, vdata->data, vdata->size) != 0)
          {
            gnutls_assert ();
            return GNUTLS_E_MPI_SCAN_FAILED;
          }

        memset(&priv, 0, sizeof(priv));
        _rsa_params_to_privkey (pk_params, &priv);

        nc = rsa_blind (hash, pk_params->params[1] /*e */ ,
                        pk_params->params[0] /*m */ , &ri);

        _gnutls_mpi_release (&hash);

        if (nc == NULL)
          {
            gnutls_assert ();
            ret = GNUTLS_E_MEMORY_ERROR;
            goto rsa_fail;
          }

        rsa_compute_root (&priv, TOMPZ (nc), TOMPZ (nc));

        rsa_unblind (nc, ri, pk_params->params[0] /*m */ );

        ret = _gnutls_mpi_dprint (nc, signature);

rsa_fail:
        _gnutls_mpi_release (&nc);
        _gnutls_mpi_release (&ri);

        if (ret < 0)
          {
            gnutls_assert ();
            goto cleanup;
          }

        break;
      }
    default:
      gnutls_assert ();
      ret = GNUTLS_E_INTERNAL_ERROR;
      goto cleanup;
    }

  ret = 0;

cleanup:

  return ret;
}
/*-
 * _gnutls_pkcs11_privkey_sign_hash:
 * @key: Holds the key
 * @hash: holds the data to be signed (should be output of a hash)
 * @signature: will contain the signature allocated with gnutls_malloc()
 *
 * This function will sign the given data using a signature algorithm
 * supported by the private key. It is assumed that the given data
 * are the output of a hash function.
 *
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
 *   negative error value.
 -*/
int
_gnutls_pkcs11_privkey_sign_hash (gnutls_pkcs11_privkey_t key,
                                  const gnutls_datum_t * hash,
                                  gnutls_datum_t * signature)
{
  ck_rv_t rv;
  int ret;
  struct ck_mechanism mech;
  unsigned long siglen;
  struct ck_function_list *module;
  ck_session_handle_t pks;
  ck_object_handle_t obj;

  FIND_OBJECT (module, pks, obj, key);

  mech.mechanism = pk_to_mech(key->pk_algorithm);
  mech.parameter = NULL;
  mech.parameter_len = 0;

  /* Initialize signing operation; using the private key discovered
   * earlier. */
  rv = pkcs11_sign_init (module, pks, &mech, obj);
  if (rv != CKR_OK)
    {
      gnutls_assert ();
      ret = pkcs11_rv_to_err (rv);
      goto cleanup;
    }

  /* Work out how long the signature must be: */
  rv = pkcs11_sign (module, pks, hash->data, hash->size, NULL, &siglen);
  if (rv != CKR_OK)
    {
      gnutls_assert ();
      ret = pkcs11_rv_to_err (rv);
      goto cleanup;
    }

  signature->data = gnutls_malloc (siglen);
  signature->size = siglen;

  rv = pkcs11_sign (module, pks, hash->data, hash->size, signature->data, &siglen);
  if (rv != CKR_OK)
    {
      gnutls_free (signature->data);
      gnutls_assert ();
      ret = pkcs11_rv_to_err (rv);
      goto cleanup;
    }

  signature->size = siglen;
  
  if (key->pk_algorithm == GNUTLS_PK_EC || key->pk_algorithm == GNUTLS_PK_DSA)
    {
      bigint_t r,s;

      if (siglen % 2 != 0)
        {
          gnutls_assert();
          ret = GNUTLS_E_PK_SIGN_FAILED;
          goto cleanup;
        }

      ret = read_rs(&r, &s, signature->data, signature->size);
      if (ret < 0)
        {
          gnutls_assert();
          goto cleanup;
        }
      
      gnutls_free(signature->data);
      ret = _gnutls_encode_ber_rs (signature, r, s);
      _gnutls_mpi_release(&r);
      _gnutls_mpi_release(&s);
      
      if (ret < 0)
        {
          gnutls_assert();
          goto cleanup;
        }
    }

  ret = 0;

cleanup:
  pkcs11_close_session (module, pks);

  return ret;
}