Beispiel #1
0
/**
  * gnutls_x509_crq_import - This function will import a DER or PEM encoded Certificate request
  * @crq: The structure to store the parsed certificate request.
  * @data: The DER or PEM encoded certificate.
  * @format: One of DER or PEM
  *
  * This function will convert the given DER or PEM encoded Certificate
  * to the native gnutls_x509_crq_t format. The output will be stored in @cert.
  *
  * If the Certificate is PEM encoded it should have a header of "NEW CERTIFICATE REQUEST".
  *
  * Returns 0 on success.
  *
  **/
int
gnutls_x509_crq_import (gnutls_x509_crq_t crq,
                        const gnutls_datum_t * data,
                        gnutls_x509_crt_fmt_t format)
{
    int result = 0, need_free = 0;
    gnutls_datum_t _data;

    if (crq == NULL)
    {
        gnutls_assert ();
        return GNUTLS_E_INVALID_REQUEST;
    }

    _data.data = data->data;
    _data.size = data->size;

    /* If the Certificate is in PEM format then decode it
     */
    if (format == GNUTLS_X509_FMT_PEM)
    {
        opaque *out;

        /* Try the first header */
        result = _gnutls_fbase64_decode (PEM_CRQ, data->data, data->size, &out);

        if (result <= 0)		/* Go for the second header */
            result =
                _gnutls_fbase64_decode (PEM_CRQ2, data->data, data->size, &out);

        if (result <= 0)
        {
            if (result == 0)
                result = GNUTLS_E_INTERNAL_ERROR;
            gnutls_assert ();
            return result;
        }

        _data.data = out;
        _data.size = result;

        need_free = 1;
    }

    result = asn1_der_decoding (&crq->crq, _data.data, _data.size, NULL);
    if (result != ASN1_SUCCESS)
    {
        result = _gnutls_asn2err (result);
        gnutls_assert ();
        goto cleanup;
    }

    result = 0;

cleanup:
    if (need_free)
        _gnutls_free_datum (&_data);
    return result;
}
Beispiel #2
0
/**
 * gnutls_pem_base64_decode:
 * @header: A null terminated string with the PEM header (eg. CERTIFICATE)
 * @b64_data: contain the encoded data
 * @result: the place where decoded data will be copied
 * @result_size: holds the size of the result
 *
 * This function will decode the given encoded data.  If the header
 * given is non null this function will search for "-----BEGIN header"
 * and decode only this part.  Otherwise it will decode the first PEM
 * packet found.
 *
 * Returns: On success %GNUTLS_E_SUCCESS (0) is returned,
 *   %GNUTLS_E_SHORT_MEMORY_BUFFER is returned if the buffer given is
 *   not long enough, or 0 on success.
 **/
int
gnutls_pem_base64_decode (const char *header,
                          const gnutls_datum_t * b64_data,
                          unsigned char *result, size_t * result_size)
{
  gnutls_datum_t res;
  int ret;

  ret =
    _gnutls_fbase64_decode (header, b64_data->data, b64_data->size, &res);
  if (ret < 0)
    return gnutls_assert_val(ret);

  if (result == NULL || *result_size < (unsigned) res.size)
    {
      gnutls_free (res.data);
      *result_size = res.size;
      return GNUTLS_E_SHORT_MEMORY_BUFFER;
    }
  else
    {
      memcpy (result, res.data, res.size);
      gnutls_free (res.data);
      *result_size = res.size;
    }

  return 0;
}
Beispiel #3
0
/**
  * gnutls_pkcs12_import - This function will import a DER or PEM encoded PKCS12 structure
  * @pkcs12: The structure to store the parsed PKCS12.
  * @data: The DER or PEM encoded PKCS12.
  * @format: One of DER or PEM
  * @flags: an ORed sequence of gnutls_privkey_pkcs8_flags
  *
  * This function will convert the given DER or PEM encoded PKCS12
  * to the native gnutls_pkcs12_t format. The output will be stored in 'pkcs12'.
  *
  * If the PKCS12 is PEM encoded it should have a header of "PKCS12".
  *
  * Returns 0 on success.
  *
  **/
int
gnutls_pkcs12_import (gnutls_pkcs12_t pkcs12,
		      const gnutls_datum_t * data,
		      gnutls_x509_crt_fmt_t format, unsigned int flags)
{
  int result = 0, need_free = 0;
  gnutls_datum_t _data;

  _data.data = data->data;
  _data.size = data->size;

  if (pkcs12 == NULL)
    {
      gnutls_assert ();
      return GNUTLS_E_INVALID_REQUEST;
    }

  /* If the PKCS12 is in PEM format then decode it
   */
  if (format == GNUTLS_X509_FMT_PEM)
    {
      opaque *out;

      result = _gnutls_fbase64_decode (PEM_PKCS12, data->data, data->size,
				       &out);

      if (result <= 0)
	{
	  if (result == 0)
	    result = GNUTLS_E_INTERNAL_ERROR;
	  gnutls_assert ();
	  return result;
	}

      _data.data = out;
      _data.size = result;

      need_free = 1;
    }

  result = asn1_der_decoding (&pkcs12->pkcs12, _data.data, _data.size, NULL);
  if (result != ASN1_SUCCESS)
    {
      result = _gnutls_asn2err (result);
      gnutls_assert ();
      goto cleanup;
    }

  if (need_free)
    _gnutls_free_datum (&_data);

  return 0;

cleanup:
  if (need_free)
    _gnutls_free_datum (&_data);
  return result;
}
Beispiel #4
0
/**
 * gnutls_x509_crl_import:
 * @crl: The structure to store the parsed CRL.
 * @data: The DER or PEM encoded CRL.
 * @format: One of DER or PEM
 *
 * This function will convert the given DER or PEM encoded CRL
 * to the native #gnutls_x509_crl_t format. The output will be stored in 'crl'.
 *
 * If the CRL is PEM encoded it should have a header of "X509 CRL".
 *
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
 *   negative error value.
 **/
int
gnutls_x509_crl_import(gnutls_x509_crl_t crl,
		       const gnutls_datum_t * data,
		       gnutls_x509_crt_fmt_t format)
{
	int result = 0, need_free = 0;
	gnutls_datum_t _data;

	_data.data = data->data;
	_data.size = data->size;

	if (crl == NULL) {
		gnutls_assert();
		return GNUTLS_E_INVALID_REQUEST;
	}

	/* If the CRL is in PEM format then decode it
	 */
	if (format == GNUTLS_X509_FMT_PEM) {
		result =
		    _gnutls_fbase64_decode(PEM_CRL, data->data, data->size,
					   &_data);

		if (result < 0) {
			gnutls_assert();
			return result;
		}

		need_free = 1;
	}

	result =
	    asn1_der_decoding(&crl->crl, _data.data, _data.size, NULL);
	if (result != ASN1_SUCCESS) {
		result = _gnutls_asn2err(result);
		gnutls_assert();
		goto cleanup;
	}

	result = _gnutls_x509_get_raw_dn2(crl->crl, &_data,
					  "tbsCertList.issuer.rdnSequence",
					  &crl->raw_issuer_dn);
	if (result < 0) {
		gnutls_assert();
		goto cleanup;
	}

	if (need_free)
		_gnutls_free_datum(&_data);

	return 0;

      cleanup:
	if (need_free)
		_gnutls_free_datum(&_data);
	_gnutls_free_datum(&crl->raw_issuer_dn);
	return result;
}
Beispiel #5
0
/**
 * gnutls_pkcs12_import:
 * @pkcs12: The structure to store the parsed PKCS12.
 * @data: The DER or PEM encoded PKCS12.
 * @format: One of DER or PEM
 * @flags: an ORed sequence of gnutls_privkey_pkcs8_flags
 *
 * This function will convert the given DER or PEM encoded PKCS12
 * to the native gnutls_pkcs12_t format. The output will be stored in 'pkcs12'.
 *
 * If the PKCS12 is PEM encoded it should have a header of "PKCS12".
 *
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
 *   negative error value.
 **/
int
gnutls_pkcs12_import (gnutls_pkcs12_t pkcs12,
                      const gnutls_datum_t * data,
                      gnutls_x509_crt_fmt_t format, unsigned int flags)
{
  int result = 0, need_free = 0;
  gnutls_datum_t _data;
  char error_str[ASN1_MAX_ERROR_DESCRIPTION_SIZE];

  _data.data = data->data;
  _data.size = data->size;

  if (pkcs12 == NULL)
    {
      gnutls_assert ();
      return GNUTLS_E_INVALID_REQUEST;
    }

  /* If the PKCS12 is in PEM format then decode it
   */
  if (format == GNUTLS_X509_FMT_PEM)
    {
      result = _gnutls_fbase64_decode (PEM_PKCS12, data->data, data->size,
                                       &_data);

      if (result < 0)
        {
          gnutls_assert ();
          return result;
        }

      need_free = 1;
    }

  result =
    asn1_der_decoding (&pkcs12->pkcs12, _data.data, _data.size, error_str);
  if (result != ASN1_SUCCESS)
    {
      result = _gnutls_asn2err (result);
      _gnutls_debug_log ("DER error: %s\n", error_str);
      gnutls_assert ();
      goto cleanup;
    }

  if (need_free)
    _gnutls_free_datum (&_data);

  return 0;

cleanup:
  if (need_free)
    _gnutls_free_datum (&_data);
  return result;
}
Beispiel #6
0
/**
 * gnutls_pkcs7_import:
 * @pkcs7: The structure to store the parsed PKCS7.
 * @data: The DER or PEM encoded PKCS7.
 * @format: One of DER or PEM
 *
 * This function will convert the given DER or PEM encoded PKCS7 to
 * the native #gnutls_pkcs7_t format.  The output will be stored in
 * @pkcs7.
 *
 * If the PKCS7 is PEM encoded it should have a header of "PKCS7".
 *
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
 *   negative error value.
 **/
int
gnutls_pkcs7_import(gnutls_pkcs7_t pkcs7, const gnutls_datum_t * data,
		    gnutls_x509_crt_fmt_t format)
{
	int result = 0, need_free = 0;
	gnutls_datum_t _data;

	if (pkcs7 == NULL)
		return GNUTLS_E_INVALID_REQUEST;

	_data.data = data->data;
	_data.size = data->size;

	/* If the PKCS7 is in PEM format then decode it
	 */
	if (format == GNUTLS_X509_FMT_PEM) {
		result =
		    _gnutls_fbase64_decode(PEM_PKCS7, data->data,
					   data->size, &_data);

		if (result <= 0) {
			gnutls_assert();
			return result;
		}

		need_free = 1;
	}


	result =
	    asn1_der_decoding(&pkcs7->pkcs7, _data.data, _data.size, NULL);
	if (result != ASN1_SUCCESS) {
		result = _gnutls_asn2err(result);
		gnutls_assert();
		goto cleanup;
	}

	if (need_free)
		_gnutls_free_datum(&_data);

	return 0;

      cleanup:
	if (need_free)
		_gnutls_free_datum(&_data);
	return result;
}
Beispiel #7
0
/**
 * gnutls_pem_base64_decode_alloc:
 * @header: The PEM header (eg. CERTIFICATE)
 * @b64_data: contains the encoded data
 * @result: the place where decoded data lie
 *
 * This function will decode the given encoded data. The decoded data
 * will be allocated, and stored into result.  If the header given is
 * non null this function will search for "-----BEGIN header" and
 * decode only this part. Otherwise it will decode the first PEM
 * packet found.
 *
 * You should use gnutls_free() to free the returned data.
 *
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise
 *   an error code is returned.
 **/
int
gnutls_pem_base64_decode_alloc (const char *header,
                                const gnutls_datum_t * b64_data,
                                gnutls_datum_t * result)
{
  int ret;

  if (result == NULL)
    return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);

  ret =
    _gnutls_fbase64_decode (header, b64_data->data, b64_data->size, result);
  if (ret < 0)
    return gnutls_assert_val(ret);

  return 0;
}
/**
 * gnutls_x509_privkey_import:
 * @key: The structure to store the parsed key
 * @data: The DER or PEM encoded certificate.
 * @format: One of DER or PEM
 *
 * This function will convert the given DER or PEM encoded key to the
 * native #gnutls_x509_privkey_t format. The output will be stored in
 * @key .
 *
 * If the key is PEM encoded it should have a header that contains "PRIVATE
 * KEY". Note that this function falls back to PKCS #8 decoding without
 * password, if the default format fails to import.
 *
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
 *   negative error value.
 **/
int
gnutls_x509_privkey_import (gnutls_x509_privkey_t key,
                            const gnutls_datum_t * data,
                            gnutls_x509_crt_fmt_t format)
{
  int result = 0, need_free = 0;
  gnutls_datum_t _data;

  if (key == NULL)
    {
      gnutls_assert ();
      return GNUTLS_E_INVALID_REQUEST;
    }

  _data.data = data->data;
  _data.size = data->size;

  key->pk_algorithm = GNUTLS_PK_UNKNOWN;

  /* If the Certificate is in PEM format then decode it
   */
  if (format == GNUTLS_X509_FMT_PEM)
    {
      uint8_t *out;

      /* Try the first header */
      result =
        _gnutls_fbase64_decode (PEM_KEY_RSA, data->data, data->size, &out);

      if (result >= 0)
        key->pk_algorithm = GNUTLS_PK_RSA;

      if (result == GNUTLS_E_BASE64_UNEXPECTED_HEADER_ERROR)
        {
          /* try for the second header */
          result =
            _gnutls_fbase64_decode (PEM_KEY_DSA, data->data, data->size,
                                    &out);

          if (result >= 0)
            key->pk_algorithm = GNUTLS_PK_DSA;

          if (result == GNUTLS_E_BASE64_UNEXPECTED_HEADER_ERROR)
            {
              /* try for the second header */
              result =
                _gnutls_fbase64_decode (PEM_KEY_ECC, data->data, data->size,
                                    &out);
              if (result >= 0)
                key->pk_algorithm = GNUTLS_PK_EC;
             }
        }

      if (result < 0)
        {
          gnutls_assert ();
          goto failover;
        }

      _data.data = out;
      _data.size = result;

      need_free = 1;
    }

  if (key->pk_algorithm == GNUTLS_PK_RSA)
    {
      key->key = _gnutls_privkey_decode_pkcs1_rsa_key (&_data, key);
      if (key->key == NULL)
        gnutls_assert ();
    }
  else if (key->pk_algorithm == GNUTLS_PK_DSA)
    {
      key->key = decode_dsa_key (&_data, key);
      if (key->key == NULL)
        gnutls_assert ();
    }
  else if (key->pk_algorithm == GNUTLS_PK_EC)
    {
      key->key = _gnutls_privkey_decode_ecc_key (&_data, key);
      if (key->key == NULL)
        gnutls_assert ();
    }
  else
    {
      /* Try decoding with both, and accept the one that
       * succeeds.
       */
      key->pk_algorithm = GNUTLS_PK_RSA;
      key->key = _gnutls_privkey_decode_pkcs1_rsa_key (&_data, key);

      if (key->key == NULL)
        {
          key->pk_algorithm = GNUTLS_PK_DSA;
          key->key = decode_dsa_key (&_data, key);
          if (key->key == NULL)
            {
              key->pk_algorithm = GNUTLS_PK_EC;
              key->key = _gnutls_privkey_decode_ecc_key (&_data, key);
              if (key->key == NULL)
                gnutls_assert ();
            }
        }
    }

  if (key->key == NULL)
    {
      gnutls_assert ();
      result = GNUTLS_E_ASN1_DER_ERROR;
      goto failover;
    }

  if (need_free)
    _gnutls_free_datum (&_data);

  /* The key has now been decoded.
   */

  return 0;

failover:
  /* Try PKCS #8 */
  if (result == GNUTLS_E_BASE64_UNEXPECTED_HEADER_ERROR)
    {
      _gnutls_debug_log ("Falling back to PKCS #8 key decoding\n");
      result = gnutls_x509_privkey_import_pkcs8 (key, data, format,
                                                 NULL, GNUTLS_PKCS_PLAIN);
    }

  if (need_free)
    _gnutls_free_datum (&_data);

  return result;
}
Beispiel #9
0
/**
  * gnutls_x509_privkey_import - This function will import a DER or PEM encoded key
  * @key: The structure to store the parsed key
  * @data: The DER or PEM encoded certificate.
  * @format: One of DER or PEM
  *
  * This function will convert the given DER or PEM encoded key
  * to the native gnutls_x509_privkey_t format. The output will be stored in @key .
  *
  * If the key is PEM encoded it should have a header of "RSA PRIVATE KEY", or
  * "DSA PRIVATE KEY".
  *
  * Returns 0 on success.
  *
  **/
int
gnutls_x509_privkey_import (gnutls_x509_privkey_t key,
			    const gnutls_datum_t * data,
			    gnutls_x509_crt_fmt_t format)
{
  int result = 0, need_free = 0;
  gnutls_datum_t _data;

  if (key == NULL)
    {
      gnutls_assert ();
      return GNUTLS_E_INVALID_REQUEST;
    }

  _data.data = data->data;
  _data.size = data->size;

  key->pk_algorithm = GNUTLS_PK_UNKNOWN;

  /* If the Certificate is in PEM format then decode it
   */
  if (format == GNUTLS_X509_FMT_PEM)
    {
      opaque *out;

      /* Try the first header */
      result =
	_gnutls_fbase64_decode (PEM_KEY_RSA, data->data, data->size, &out);
      key->pk_algorithm = GNUTLS_PK_RSA;

      if (result <= 0)
	{
	  /* try for the second header */
	  result =
	    _gnutls_fbase64_decode (PEM_KEY_DSA, data->data, data->size,
				    &out);
	  key->pk_algorithm = GNUTLS_PK_DSA;

	  if (result <= 0)
	    {
	      if (result == 0)
		result = GNUTLS_E_INTERNAL_ERROR;
	      gnutls_assert ();
	      return result;
	    }
	}

      _data.data = out;
      _data.size = result;

      need_free = 1;
    }

  if (key->pk_algorithm == GNUTLS_PK_RSA)
    {
      key->key = _gnutls_privkey_decode_pkcs1_rsa_key (&_data, key);
      if (key->key == NULL)
	{
	  gnutls_assert ();
	  result = GNUTLS_E_ASN1_DER_ERROR;
	  goto cleanup;
	}
    }
  else if (key->pk_algorithm == GNUTLS_PK_DSA)
    {
      key->key = decode_dsa_key (&_data, key);
      if (key->key == NULL)
	{
	  gnutls_assert ();
	  result = GNUTLS_E_ASN1_DER_ERROR;
	  goto cleanup;
	}
    }
  else
    {
      /* Try decoding with both, and accept the one that 
       * succeeds.
       */
      key->pk_algorithm = GNUTLS_PK_DSA;
      key->key = decode_dsa_key (&_data, key);

      if (key->key == NULL)
	{
	  key->pk_algorithm = GNUTLS_PK_RSA;
	  key->key = _gnutls_privkey_decode_pkcs1_rsa_key (&_data, key);
	  if (key->key == NULL)
	    {
	      gnutls_assert ();
	      result = GNUTLS_E_ASN1_DER_ERROR;
	      goto cleanup;
	    }
	}
    }

  if (need_free)
    _gnutls_free_datum (&_data);

  /* The key has now been decoded.
   */

  return 0;

cleanup:
  key->pk_algorithm = GNUTLS_PK_UNKNOWN;
  if (need_free)
    _gnutls_free_datum (&_data);
  return result;
}
Beispiel #10
0
/**
 * gnutls_dh_params_import_pkcs3 - import DH params from a pkcs3 structure
 * @params: A structure where the parameters will be copied to
 * @pkcs3_params: should contain a PKCS3 DHParams structure PEM or DER encoded
 * @format: the format of params. PEM or DER.
 *
 * This function will extract the DHParams found in a PKCS3 formatted
 * structure. This is the format generated by "openssl dhparam" tool.
 *
 * If the structure is PEM encoded, it should have a header
 * of "BEGIN DH PARAMETERS".
 *
 * Returns: On success, %GNUTLS_E_SUCCESS (zero) is returned,
 *   otherwise an error code is returned.
 **/
int
gnutls_dh_params_import_pkcs3 (gnutls_dh_params_t params,
                               const gnutls_datum_t * pkcs3_params,
                               gnutls_x509_crt_fmt_t format)
{
    ASN1_TYPE c2;
    int result, need_free = 0;
    gnutls_datum_t _params;

    if (format == GNUTLS_X509_FMT_PEM)
    {
        opaque *out;

        result = _gnutls_fbase64_decode ("DH PARAMETERS",
                                         pkcs3_params->data,
                                         pkcs3_params->size, &out);

        if (result <= 0)
        {
            if (result == 0)
                result = GNUTLS_E_INTERNAL_ERROR;
            gnutls_assert ();
            return result;
        }

        _params.data = out;
        _params.size = result;

        need_free = 1;

    }
    else
    {
        _params.data = pkcs3_params->data;
        _params.size = pkcs3_params->size;
    }

    if ((result = asn1_create_element
                  (_gnutls_get_gnutls_asn (), "GNUTLS.DHParameter", &c2))
            != ASN1_SUCCESS)
    {
        gnutls_assert ();
        if (need_free != 0)
        {
            gnutls_free (_params.data);
            _params.data = NULL;
        }
        return _gnutls_asn2err (result);
    }

    result = asn1_der_decoding (&c2, _params.data, _params.size, NULL);

    if (need_free != 0)
    {
        gnutls_free (_params.data);
        _params.data = NULL;
    }

    if (result != ASN1_SUCCESS)
    {
        /* couldn't decode DER */

        _gnutls_x509_log ("DHParams: Decoding error %d\n", result);
        gnutls_assert ();
        asn1_delete_structure (&c2);
        return _gnutls_asn2err (result);
    }

    /* Read PRIME
     */
    result = _gnutls_x509_read_int (c2, "prime", &params->params[0]);
    if (result < 0)
    {
        asn1_delete_structure (&c2);
        gnutls_assert ();
        return result;
    }

    /* read the generator
     */
    result = _gnutls_x509_read_int (c2, "base", &params->params[1]);
    if (result < 0)
    {
        asn1_delete_structure (&c2);
        _gnutls_mpi_release (&params->params[0]);
        gnutls_assert ();
        return result;
    }

    asn1_delete_structure (&c2);

    return 0;
}
Beispiel #11
0
/**
 * gnutls_dh_params_import_pkcs3:
 * @params: The parameters
 * @pkcs3_params: should contain a PKCS3 DHParams structure PEM or DER encoded
 * @format: the format of params. PEM or DER.
 *
 * This function will extract the DHParams found in a PKCS3 formatted
 * structure. This is the format generated by "openssl dhparam" tool.
 *
 * If the structure is PEM encoded, it should have a header
 * of "BEGIN DH PARAMETERS".
 *
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned,
 *   otherwise a negative error code is returned.
 **/
int
gnutls_dh_params_import_pkcs3(gnutls_dh_params_t params,
			      const gnutls_datum_t * pkcs3_params,
			      gnutls_x509_crt_fmt_t format)
{
	ASN1_TYPE c2;
	int result, need_free = 0;
	unsigned int q_bits;
	gnutls_datum_t _params;

	if (format == GNUTLS_X509_FMT_PEM) {

		result = _gnutls_fbase64_decode("DH PARAMETERS",
						pkcs3_params->data,
						pkcs3_params->size,
						&_params);

		if (result < 0) {
			gnutls_assert();
			return result;
		}

		need_free = 1;
	} else {
		_params.data = pkcs3_params->data;
		_params.size = pkcs3_params->size;
	}

	if ((result = asn1_create_element
	     (_gnutls_get_gnutls_asn(), "GNUTLS.DHParameter", &c2))
	    != ASN1_SUCCESS) {
		gnutls_assert();
		if (need_free != 0) {
			gnutls_free(_params.data);
			_params.data = NULL;
		}
		return _gnutls_asn2err(result);
	}

	/* PKCS#3 doesn't specify whether DHParameter is encoded as
	 * BER or DER, thus we don't restrict libtasn1 to DER subset */
	result = asn1_der_decoding(&c2, _params.data, _params.size, NULL);

	if (need_free != 0) {
		gnutls_free(_params.data);
		_params.data = NULL;
	}

	if (result != ASN1_SUCCESS) {
		/* couldn't decode DER */

		_gnutls_debug_log("DHParams: Decoding error %d\n", result);
		gnutls_assert();
		asn1_delete_structure(&c2);
		return _gnutls_asn2err(result);
	}

	/* Read q length */
	result = _gnutls_x509_read_uint(c2, "privateValueLength", &q_bits);
	if (result < 0) {
		gnutls_assert();
		params->q_bits = 0;
	} else
		params->q_bits = q_bits;

	/* Read PRIME 
	 */
	result = _gnutls_x509_read_int(c2, "prime", &params->params[0]);
	if (result < 0) {
		asn1_delete_structure(&c2);
		gnutls_assert();
		return result;
	}

	if (_gnutls_mpi_cmp_ui(params->params[0], 0) == 0) {
		asn1_delete_structure(&c2);
		return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);
	}

	/* read the generator
	 */
	result = _gnutls_x509_read_int(c2, "base", &params->params[1]);
	if (result < 0) {
		asn1_delete_structure(&c2);
		_gnutls_mpi_release(&params->params[0]);
		gnutls_assert();
		return result;
	}

	if (_gnutls_mpi_cmp_ui(params->params[1], 0) == 0) {
		asn1_delete_structure(&c2);
		_gnutls_mpi_release(&params->params[0]);
		return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);
	}

	asn1_delete_structure(&c2);

	return 0;
}
Beispiel #12
0
/**
 * gnutls_pkcs8_info:
 * @data: Holds the PKCS #8 data
 * @format: the format of the PKCS #8 data
 * @schema: indicate the schema as one of %gnutls_pkcs_encrypt_flags_t
 * @cipher: the cipher used as %gnutls_cipher_algorithm_t
 * @salt: PBKDF2 salt (if non-NULL then @salt_size initially holds its size)
 * @salt_size: PBKDF2 salt size
 * @iter_count: PBKDF2 iteration count
 * @oid: if non-NULL it will contain an allocated null-terminated variable with the OID
 *
 * This function will provide information on the algorithms used
 * in a particular PKCS #8 structure. If the structure algorithms
 * are unknown the code %GNUTLS_E_UNKNOWN_CIPHER_TYPE will be returned,
 * and only @oid, will be set. That is, @oid will be set on encrypted PKCS #8
 * structures whether supported or not. It must be deinitialized using gnutls_free().
 * The other variables are only set on supported structures.
 *
 * Returns: %GNUTLS_E_INVALID_REQUEST if the provided structure isn't an encrypted key,
 *  %GNUTLS_E_UNKNOWN_CIPHER_TYPE if the structure's encryption isn't supported, or
 *  another negative error code in case of a failure. Zero on success.
 *
 * Since: 3.4.0
 **/
int
gnutls_pkcs8_info(const gnutls_datum_t * data, gnutls_x509_crt_fmt_t format,
		  unsigned int *schema, unsigned int *cipher,
		  void *salt, unsigned int *salt_size,
		  unsigned int *iter_count,
		  char **oid)
{
	int ret = 0, need_free = 0;
	gnutls_datum_t _data;
	const struct pkcs_cipher_schema_st *p = NULL;
	struct pbkdf2_params kdf;

	memset(&kdf, 0, sizeof(kdf));

	if (oid)
		*oid = NULL;

	_data.data = data->data;
	_data.size = data->size;

	/* If the Certificate is in PEM format then decode it
	 */
	if (format == GNUTLS_X509_FMT_PEM) {
		/* Try the first header 
		 */
		ret =
		    _gnutls_fbase64_decode(PEM_UNENCRYPTED_PKCS8,
					   data->data, data->size, &_data);

		if (ret < 0) {	/* Try the encrypted header 
					 */
			ret =
			    _gnutls_fbase64_decode(PEM_PKCS8, data->data,
						   data->size, &_data);

			if (ret < 0) {
				gnutls_assert();
				return ret;
			}
		}

		need_free = 1;
	}

	ret = pkcs8_key_info(&_data, &p, &kdf, oid);
	if (ret == GNUTLS_E_DECRYPTION_FAILED)
		ret = GNUTLS_E_INVALID_REQUEST;
	if (ret < 0) {
		gnutls_assert();
		goto cleanup;
	}

	assert(p != NULL);

	if (need_free)
		_gnutls_free_datum(&_data);

	if (schema)
		*schema = p->flag;

	if (cipher)
		*cipher = p->cipher;

	if (iter_count)
		*iter_count = kdf.iter_count;

	if (salt) {
		if (*salt_size >= (unsigned)kdf.salt_size) {
			memcpy(salt, kdf.salt, kdf.salt_size);
		} else {
			*salt_size = kdf.salt_size;
			ret = gnutls_assert_val(GNUTLS_E_SHORT_MEMORY_BUFFER);
			goto cleanup;
		}
	}

	if (salt_size)
		*salt_size = kdf.salt_size;

	return 0;

 cleanup:
	if (ret != GNUTLS_E_UNKNOWN_CIPHER_TYPE && oid) {
		gnutls_free(*oid);
	}
	if (need_free)
		_gnutls_free_datum(&_data);
	return ret;
}
Beispiel #13
0
/**
 * gnutls_x509_privkey_import_pkcs8:
 * @key: The data to store the parsed key
 * @data: The DER or PEM encoded key.
 * @format: One of DER or PEM
 * @password: the password to decrypt the key (if it is encrypted).
 * @flags: 0 if encrypted or GNUTLS_PKCS_PLAIN if not encrypted.
 *
 * This function will convert the given DER or PEM encoded PKCS8 2.0
 * encrypted key to the native gnutls_x509_privkey_t format. The
 * output will be stored in @key.  Both RSA and DSA keys can be
 * imported, and flags can only be used to indicate an unencrypted
 * key.
 *
 * The @password can be either ASCII or UTF-8 in the default PBES2
 * encryption schemas, or ASCII for the PKCS12 schemas.
 *
 * If the Certificate is PEM encoded it should have a header of
 * "ENCRYPTED PRIVATE KEY", or "PRIVATE KEY". You only need to
 * specify the flags if the key is DER encoded, since in that case
 * the encryption status cannot be auto-detected.
 *
 * If the %GNUTLS_PKCS_PLAIN flag is specified and the supplied data
 * are encrypted then %GNUTLS_E_DECRYPTION_FAILED is returned.
 *
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
 *   negative error value.
 **/
int
gnutls_x509_privkey_import_pkcs8(gnutls_x509_privkey_t key,
				 const gnutls_datum_t * data,
				 gnutls_x509_crt_fmt_t format,
				 const char *password, unsigned int flags)
{
	int result = 0, need_free = 0;
	gnutls_datum_t _data;

	if (key == NULL) {
		gnutls_assert();
		return GNUTLS_E_INVALID_REQUEST;
	}

	_data.data = data->data;
	_data.size = data->size;

	key->params.algo = GNUTLS_PK_UNKNOWN;

	/* If the Certificate is in PEM format then decode it
	 */
	if (format == GNUTLS_X509_FMT_PEM) {
		/* Try the first header 
		 */
		result =
		    _gnutls_fbase64_decode(PEM_UNENCRYPTED_PKCS8,
					   data->data, data->size, &_data);

		if (result < 0) {	/* Try the encrypted header 
					 */
			result =
			    _gnutls_fbase64_decode(PEM_PKCS8, data->data,
						   data->size, &_data);

			if (result < 0) {
				gnutls_assert();
				return result;
			}
		} else if (flags == 0)
			flags |= GNUTLS_PKCS_PLAIN;

		need_free = 1;
	}

	if (key->expanded) {
		_gnutls_x509_privkey_reinit(key);
	}
	key->expanded = 1;

	/* Here we don't check for password == NULL to maintain a backwards
	 * compatibility behavior, with old versions that were encrypting using
	 * a NULL password.
	 */
	if (flags & GNUTLS_PKCS_PLAIN) {
		result = decode_private_key_info(&_data, key);
		if (result < 0) {	/* check if it is encrypted */
			if (pkcs8_key_decode(&_data, "", key, 0) == 0)
				result = GNUTLS_E_DECRYPTION_FAILED;
		}
	} else {		/* encrypted. */
		result = pkcs8_key_decode(&_data, password, key, 1);
	}

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

	/* This part is necessary to get the public key on certain algorithms.
	 * In the import above we only get the private key. */
	result =
	    _gnutls_pk_fixup(key->params.algo, GNUTLS_IMPORT, &key->params);
	if (result < 0) {
		gnutls_assert();
		goto cleanup;
	}

	if (need_free)
		_gnutls_free_datum(&_data);

	/* The key has now been decoded.
	 */
	return 0;

 cleanup:
	asn1_delete_structure2(&key->key, ASN1_DELETE_FLAG_ZEROIZE);
	key->params.algo = GNUTLS_PK_UNKNOWN;
	if (need_free)
		_gnutls_free_datum(&_data);
	return result;
}
Beispiel #14
0
/**
 * gnutls_x509_crl_import:
 * @crl: The structure to store the parsed CRL.
 * @data: The DER or PEM encoded CRL.
 * @format: One of DER or PEM
 *
 * This function will convert the given DER or PEM encoded CRL
 * to the native #gnutls_x509_crl_t format. The output will be stored in 'crl'.
 *
 * If the CRL is PEM encoded it should have a header of "X509 CRL".
 *
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
 *   negative error value.
 **/
int
gnutls_x509_crl_import(gnutls_x509_crl_t crl,
		       const gnutls_datum_t * data,
		       gnutls_x509_crt_fmt_t format)
{
	int result = 0;

	if (crl == NULL) {
		gnutls_assert();
		return GNUTLS_E_INVALID_REQUEST;
	}

	_gnutls_free_datum(&crl->der);

	/* If the CRL is in PEM format then decode it
	 */
	if (format == GNUTLS_X509_FMT_PEM) {
		result =
		    _gnutls_fbase64_decode(PEM_CRL, data->data, data->size,
					   &crl->der);

		if (result < 0) {
			gnutls_assert();
			return result;
		}
	} else {
		result = _gnutls_set_datum(&crl->der, data->data, data->size);
		if (result < 0) {
			gnutls_assert();
			return result;
		}
	}

	if (crl->expanded) {
		result = crl_reinit(crl);
		if (result < 0) {
			gnutls_assert();
			goto cleanup;
		}
	}
	crl->expanded = 1;

	result =
	    asn1_der_decoding(&crl->crl, crl->der.data, crl->der.size, NULL);
	if (result != ASN1_SUCCESS) {
		result = _gnutls_asn2err(result);
		gnutls_assert();
		goto cleanup;
	}

	result = _gnutls_x509_get_raw_field2(crl->crl, &crl->der,
					  "tbsCertList.issuer.rdnSequence",
					  &crl->raw_issuer_dn);
	if (result < 0) {
		gnutls_assert();
		goto cleanup;
	}

	return 0;

      cleanup:
	_gnutls_free_datum(&crl->der);
	return result;
}
Beispiel #15
0
/* Reads a base64 encoded certificate list from memory and stores it to
 * a gnutls_cert structure. Returns the number of certificate parsed.
 */
static int
parse_pem_cert_mem (gnutls_cert ** cert_list, unsigned *ncerts,
		    const char *input_cert, int input_cert_size)
{
  int size, siz2, i;
  const char *ptr;
  opaque *ptr2;
  gnutls_datum_t tmp;
  int ret, count;

  /* move to the certificate
   */
  ptr = memmem (input_cert, input_cert_size,
		PEM_CERT_SEP, sizeof (PEM_CERT_SEP) - 1);
  if (ptr == NULL)
    ptr = memmem (input_cert, input_cert_size,
		  PEM_CERT_SEP2, sizeof (PEM_CERT_SEP2) - 1);

  if (ptr == NULL)
    {
      gnutls_assert ();
      return GNUTLS_E_BASE64_DECODING_ERROR;
    }
  size = input_cert_size - (ptr - input_cert);

  i = *ncerts + 1;
  count = 0;

  do
    {

      siz2 = _gnutls_fbase64_decode (NULL, ptr, size, &ptr2);

      if (siz2 < 0)
	{
	  gnutls_assert ();
	  return GNUTLS_E_BASE64_DECODING_ERROR;
	}

      *cert_list =
	(gnutls_cert *) gnutls_realloc_fast (*cert_list,
					     i * sizeof (gnutls_cert));

      if (*cert_list == NULL)
	{
	  gnutls_assert ();
	  return GNUTLS_E_MEMORY_ERROR;
	}

      tmp.data = ptr2;
      tmp.size = siz2;

      ret = _gnutls_x509_raw_cert_to_gcert (&cert_list[0][i - 1], &tmp, 0);
      if (ret < 0)
	{
	  gnutls_assert ();
	  return ret;
	}
      _gnutls_free_datum (&tmp);	/* free ptr2 */

      /* now we move ptr after the pem header 
       */
      ptr++;
      /* find the next certificate (if any)
       */
      size = input_cert_size - (ptr - input_cert);

      if (size > 0)
	{
	  char *ptr3;

	  ptr3 = memmem (ptr, size, PEM_CERT_SEP, sizeof (PEM_CERT_SEP) - 1);
	  if (ptr3 == NULL)
	    ptr3 = memmem (ptr, size, PEM_CERT_SEP2,
			   sizeof (PEM_CERT_SEP2) - 1);

	  ptr = ptr3;
	}
      else
	ptr = NULL;

      i++;
      count++;

    }
  while (ptr != NULL);

  *ncerts = i - 1;

  return count;
}