diff options
author | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2003-03-14 12:53:16 +0000 |
---|---|---|
committer | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2003-03-14 12:53:16 +0000 |
commit | dc7e1c02d1e2a65673f2102eaeb2ca9c9a4e7bc6 (patch) | |
tree | becb0242224c3ca84b7f52b2d35241b7caea27f8 /lib/x509/sign.c | |
parent | 932b1d116bb19c629b4fc9646d9525e52ba157f2 (diff) | |
download | gnutls-dc7e1c02d1e2a65673f2102eaeb2ca9c9a4e7bc6.tar.gz |
Added some stuff needed in PKCS#10 certificate request generation. Some other fixes as well.
Diffstat (limited to 'lib/x509/sign.c')
-rw-r--r-- | lib/x509/sign.c | 193 |
1 files changed, 193 insertions, 0 deletions
diff --git a/lib/x509/sign.c b/lib/x509/sign.c new file mode 100644 index 0000000000..78af41144c --- /dev/null +++ b/lib/x509/sign.c @@ -0,0 +1,193 @@ +/* + * Copyright (C) 2003 Nikos Mavroyanopoulos <nmav@hellug.gr> + * + * This file is part of GNUTLS. + * + * The GNUTLS library 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +/* All functions which relate to X.509 certificate signing stuff are + * included here + */ + +#include <gnutls_int.h> +#include <gnutls_errors.h> +#include <gnutls_cert.h> +#include <libtasn1.h> +#include <gnutls_global.h> +#include <gnutls_num.h> /* GMAX */ +#include <gnutls_sig.h> +#include <gnutls_str.h> +#include <gnutls_datum.h> +#include <dn.h> +#include <x509.h> +#include <mpi.h> +#include <sign.h> +#include <verify.h> + +/* Writes the digest information and the digest in a DER encoded + * structure. The digest info is allocated and stored into the info structure. + */ +static int encode_ber_digest_info( gnutls_mac_algorithm hash, + const gnutls_datum* digest, gnutls_datum *info) +{ +ASN1_TYPE dinfo = ASN1_TYPE_EMPTY; +int result; +char* algo; + + switch(hash) { + case GNUTLS_MAC_MD5: + algo = OID_MD5; + break; + case GNUTLS_MAC_MD2: + algo = OID_MD2; + break; + case GNUTLS_MAC_SHA: + algo = OID_SHA1; + break; + default: + return GNUTLS_E_UNIMPLEMENTED_FEATURE; + } + + if ((result=asn1_create_element( _gnutls_get_gnutls_asn(), + "GNUTLS.DigestInfo", &dinfo))!=ASN1_SUCCESS) { + gnutls_assert(); + return _gnutls_asn2err(result); + } + + result = + asn1_write_value( dinfo, "digestAlgorithm.algorithm", algo, 1); + if (result != ASN1_SUCCESS) { + gnutls_assert(); + asn1_delete_structure(&dinfo); + return _gnutls_asn2err(result); + } + + result = + asn1_write_value( dinfo, "digest", digest->data, digest->size); + if (result != ASN1_SUCCESS) { + gnutls_assert(); + asn1_delete_structure(&dinfo); + return _gnutls_asn2err(result); + } + + info->size = 128; + info->data = gnutls_malloc( info->size); + if (info->data == NULL) { + gnutls_assert(); + asn1_delete_structure(&dinfo); + return GNUTLS_E_MEMORY_ERROR; + } + + result = asn1_der_coding( dinfo, "", info->data, &info->size, NULL); + if (result != ASN1_SUCCESS) { + gnutls_assert(); + asn1_delete_structure(&dinfo); + return _gnutls_asn2err(result); + } + + asn1_delete_structure(&dinfo); + + return 0; +} + +/* if hash==MD5 then we do RSA-MD5 + * if hash==SHA then we do RSA-SHA + * params[0] is modulus + * params[1] is public key + */ +static int +_pkcs1_rsa_sign( gnutls_mac_algorithm hash, const gnutls_datum* text, + GNUTLS_MPI *params, int params_len, gnutls_datum* signature) +{ + int ret; + opaque _digest[MAX_HASH_SIZE]; + GNUTLS_HASH_HANDLE hd; + gnutls_datum digest, info; + + hd = _gnutls_hash_init( hash); + if (hd == NULL) { + gnutls_assert(); + return GNUTLS_E_HASH_FAILED; + } + + _gnutls_hash( hd, text->data, text->size); + _gnutls_hash_deinit( hd, _digest); + + digest.data = _digest; + digest.size = _gnutls_hash_get_algo_len(hash); + + /* Encode the digest as a DigestInfo + */ + if ( (ret = encode_ber_digest_info( hash, &digest, &info)) != 0) { + gnutls_assert(); + return ret; + } + + if ( (ret=_gnutls_sign( GNUTLS_PK_RSA, params, params_len, &info, signature)) < 0) { + gnutls_assert(); + _gnutls_free_datum( &info); + return ret; + } + + _gnutls_free_datum( &info); + + return 0; +} + +/* Signs the given data using the parameters from the signer's + * private key. + * + * returns 0 on success. + * + * 'tbs' is the data to be signed + * 'signature' will hold the signature! + * 'hash' is only used in PKCS1 RSA signing. + */ +int _gnutls_x509_sign( const gnutls_datum* tbs, gnutls_mac_algorithm hash, + gnutls_x509_privkey signer, gnutls_datum* signature) +{ +int ret; + + switch( signer->pk_algorithm) + { + case GNUTLS_PK_RSA: + + ret = _pkcs1_rsa_sign( hash, tbs, signer->params, signer->params_size, + signature); + if (ret < 0) { + gnutls_assert(); + return ret; + } + return 0; + break; + + case GNUTLS_PK_DSA: + ret = _gnutls_dsa_sign( signature, tbs, signer->params, signer->params_size); + if (ret < 0) { + gnutls_assert(); + return ret; + } + + return 0; + break; + default: + gnutls_assert(); + return GNUTLS_E_INTERNAL_ERROR; + } + +} + |