/* * Copyright (C) 2003, 2004, 2005, 2007, 2008, 2009, 2010 Free Software * Foundation, Inc. * * Author: Nikos Mavrogiannopoulos * * This file is part of GnuTLS. * * The GnuTLS is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * as published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA * */ #include #include #include #include #include #include "common.h" #include "x509_int.h" #include #include /* Reads an Integer from the DER encoded data */ int _gnutls_x509_read_der_int (opaque * der, int dersize, bigint_t * out) { int result; ASN1_TYPE spk = ASN1_TYPE_EMPTY; /* == INTEGER */ if ((result = asn1_create_element (_gnutls_get_gnutls_asn (), "GNUTLS.DSAPublicKey", &spk)) != ASN1_SUCCESS) { gnutls_assert (); return _gnutls_asn2err (result); } result = asn1_der_decoding (&spk, der, dersize, NULL); if (result != ASN1_SUCCESS) { gnutls_assert (); asn1_delete_structure (&spk); return _gnutls_asn2err (result); } /* Read Y */ if ((result = _gnutls_x509_read_int (spk, "", out)) < 0) { gnutls_assert (); asn1_delete_structure (&spk); return _gnutls_asn2err (result); } asn1_delete_structure (&spk); return 0; } /* Extracts DSA and RSA parameters from a certificate. */ int _gnutls_get_asn_mpis (ASN1_TYPE asn, const char *root, gnutls_pk_params_st * params) { int result; char name[256]; gnutls_datum_t tmp = { NULL, 0 }; gnutls_pk_algorithm_t pk_algorithm; gnutls_pk_params_init(params); result = _gnutls_x509_get_pk_algorithm (asn, root, NULL); if (result < 0) { gnutls_assert (); return result; } pk_algorithm = result; /* Read the algorithm's parameters */ _asnstr_append_name (name, sizeof (name), root, ".subjectPublicKey"); result = _gnutls_x509_read_value (asn, name, &tmp, 2); if (result < 0) { gnutls_assert (); return result; } if ((result = _gnutls_x509_read_pubkey (pk_algorithm, tmp.data, tmp.size, params)) < 0) { gnutls_assert (); goto error; } /* Now read the parameters */ _gnutls_free_datum (&tmp); _asnstr_append_name (name, sizeof (name), root, ".algorithm.parameters"); /* FIXME: If the parameters are not included in the certificate * then the issuer's parameters should be used. This is not * done yet. */ if (pk_algorithm != GNUTLS_PK_RSA) /* RSA doesn't use parameters */ { result = _gnutls_x509_read_value (asn, name, &tmp, 0); if (result < 0) { gnutls_assert (); goto error; } if ((result = _gnutls_x509_read_pubkey_params (pk_algorithm, tmp.data, tmp.size, params)) < 0) { gnutls_assert (); goto error; } } result = 0; error: _gnutls_free_datum (&tmp); return result; } /* Extracts DSA and RSA parameters from a certificate. */ int _gnutls_x509_crt_get_mpis (gnutls_x509_crt_t cert, gnutls_pk_params_st * params) { /* Read the algorithm's OID */ return _gnutls_get_asn_mpis (cert->cert, "tbsCertificate.subjectPublicKeyInfo", params); } #ifdef ENABLE_PKI /* Extracts DSA and RSA parameters from a certificate. */ int _gnutls_x509_crq_get_mpis (gnutls_x509_crq_t cert, gnutls_pk_params_st* params) { /* Read the algorithm's OID */ return _gnutls_get_asn_mpis (cert->crq, "certificationRequestInfo.subjectPKInfo", params); } #endif /* * This function writes and encodes the parameters for DSS or RSA keys. * This is the "signatureAlgorithm" fields. */ int _gnutls_x509_write_sig_params (ASN1_TYPE dst, const char *dst_name, gnutls_pk_algorithm_t pk_algorithm, gnutls_digest_algorithm_t dig) { int result; char name[128]; const char *pk; _gnutls_str_cpy (name, sizeof (name), dst_name); _gnutls_str_cat (name, sizeof (name), ".algorithm"); pk = _gnutls_x509_sign_to_oid (pk_algorithm, HASH2MAC (dig)); if (pk == NULL) { gnutls_assert (); _gnutls_debug_log ("Cannot find OID for sign algorithm pk: %d dig: %d\n", (int) pk_algorithm, (int) dig); return GNUTLS_E_INVALID_REQUEST; } /* write the OID. */ result = asn1_write_value (dst, name, pk, 1); if (result != ASN1_SUCCESS) { gnutls_assert (); return _gnutls_asn2err (result); } _gnutls_str_cpy (name, sizeof (name), dst_name); _gnutls_str_cat (name, sizeof (name), ".parameters"); if (pk_algorithm == GNUTLS_PK_RSA) result = asn1_write_value (dst, name, ASN1_NULL, ASN1_NULL_SIZE); else result = asn1_write_value (dst, name, NULL, 0); if (result != ASN1_SUCCESS && result != ASN1_ELEMENT_NOT_FOUND) { /* Here we ignore the element not found error, since this * may have been disabled before. */ gnutls_assert (); return _gnutls_asn2err (result); } return 0; } /* this function reads a (small) unsigned integer * from asn1 structs. Combines the read and the convertion * steps. */ int _gnutls_x509_read_uint (ASN1_TYPE node, const char *value, unsigned int *ret) { int len, result; opaque *tmpstr; len = 0; result = asn1_read_value (node, value, NULL, &len); if (result != ASN1_MEM_ERROR) { gnutls_assert (); return _gnutls_asn2err (result); } tmpstr = gnutls_malloc (len); if (tmpstr == NULL) { gnutls_assert (); return GNUTLS_E_MEMORY_ERROR; } result = asn1_read_value (node, value, tmpstr, &len); if (result != ASN1_SUCCESS) { gnutls_assert (); gnutls_free (tmpstr); return _gnutls_asn2err (result); } if (len == 1) *ret = tmpstr[0]; else if (len == 2) *ret = _gnutls_read_uint16 (tmpstr); else if (len == 3) *ret = _gnutls_read_uint24 (tmpstr); else if (len == 4) *ret = _gnutls_read_uint32 (tmpstr); else { gnutls_assert (); gnutls_free (tmpstr); return GNUTLS_E_INTERNAL_ERROR; } gnutls_free (tmpstr); return 0; } /* Writes the specified integer into the specified node. */ int _gnutls_x509_write_uint32 (ASN1_TYPE node, const char *value, uint32_t num) { opaque tmpstr[4]; int result; _gnutls_write_uint32 (num, tmpstr); result = asn1_write_value (node, value, tmpstr, 4); if (result != ASN1_SUCCESS) { gnutls_assert (); return _gnutls_asn2err (result); } return 0; }