diff options
author | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2003-03-12 10:57:56 +0000 |
---|---|---|
committer | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2003-03-12 10:57:56 +0000 |
commit | f2b8289f8cc87c07b54714859fee9c6e053717bf (patch) | |
tree | 69a0cdb436b0f4303dd7b93be27073f677d7bd6e | |
parent | edb61853219e078ae2d478d998a8ed06315c68f5 (diff) | |
download | gnutls-f2b8289f8cc87c07b54714859fee9c6e053717bf.tar.gz |
* Added ability to generate RSA keys.
* Increased the maximum parameter size in order to read some large keys
by some CAs. Patch by Ian Peters <itp@ximian.com>.
* Rolled back some of yesterdays changes. The gnutls_x509_privkey, was
replaced (again) by the gnutls_privkey.
-rw-r--r-- | NEWS | 3 | ||||
-rw-r--r-- | includes/gnutls/x509.h | 6 | ||||
-rw-r--r-- | lib/auth_cert.c | 14 | ||||
-rw-r--r-- | lib/auth_cert.h | 4 | ||||
-rw-r--r-- | lib/auth_dhe.c | 2 | ||||
-rw-r--r-- | lib/auth_rsa.c | 11 | ||||
-rw-r--r-- | lib/auth_rsa_export.c | 2 | ||||
-rw-r--r-- | lib/gnutls_cert.c | 4 | ||||
-rw-r--r-- | lib/gnutls_cert.h | 24 | ||||
-rw-r--r-- | lib/gnutls_mpi.h | 1 | ||||
-rw-r--r-- | lib/gnutls_sig.c | 8 | ||||
-rw-r--r-- | lib/gnutls_sig.h | 4 | ||||
-rw-r--r-- | lib/gnutls_x509.c | 57 | ||||
-rw-r--r-- | lib/x509/privkey.c | 349 | ||||
-rw-r--r-- | lib/x509/verify.c | 4 | ||||
-rw-r--r-- | lib/x509/x509.c | 2 | ||||
-rw-r--r-- | lib/x509/x509.h | 14 | ||||
-rw-r--r-- | libextra/auth_srp_rsa.c | 2 | ||||
-rw-r--r-- | libextra/gnutls_openpgp.c | 12 |
19 files changed, 471 insertions, 52 deletions
@@ -6,6 +6,9 @@ Version 0.9.1 - Corrected a broken buffer check in _gnutls_io_read_buffered(), which caused some unexpected packet length errors. Report and patch by Ian Peters <itp@ximian.com>. +- Added ability to generate RSA keys. +- Increased the maximum parameter size in order to read some large keys + by some CAs. Patch by Ian Peters <itp@ximian.com>. Version 0.9.0 (03/03/2003) - This version is not binary compatible with the previous ones. diff --git a/includes/gnutls/x509.h b/includes/gnutls/x509.h index ecc2cc6254..66b920e2cf 100644 --- a/includes/gnutls/x509.h +++ b/includes/gnutls/x509.h @@ -200,6 +200,12 @@ int gnutls_x509_privkey_import(gnutls_x509_privkey key, const gnutls_datum * dat gnutls_x509_crt_fmt format); int gnutls_x509_privkey_get_pk_algorithm( gnutls_x509_privkey key); +int gnutls_x509_privkey_generate( gnutls_x509_privkey key, gnutls_pk_algorithm algo, + int bits); + +int gnutls_x509_privkey_export( gnutls_x509_privkey key, + gnutls_x509_crt_fmt format, unsigned char* output_data, int* output_data_size); + #ifdef __cplusplus } diff --git a/lib/auth_cert.c b/lib/auth_cert.c index 2cc7804340..c20be5aff9 100644 --- a/lib/auth_cert.c +++ b/lib/auth_cert.c @@ -410,7 +410,7 @@ int _gnutls_gen_x509_crt(gnutls_session session, opaque ** data) int ret, i; opaque *pdata; gnutls_cert *apr_cert_list; - gnutls_x509_privkey apr_pkey; + gnutls_privkey *apr_pkey; int apr_cert_list_length; /* find the appropriate certificate */ @@ -462,7 +462,7 @@ int _gnutls_gen_openpgp_certificate(gnutls_session session, opaque ** data) int ret; opaque *pdata; gnutls_cert *apr_cert_list; - gnutls_x509_privkey apr_pkey; + gnutls_privkey* apr_pkey; int apr_cert_list_length; /* find the appropriate certificate */ @@ -512,7 +512,7 @@ int _gnutls_gen_openpgp_certificate_fpr(gnutls_session session, int ret, fpr_size, packet_size; opaque *pdata; gnutls_cert *apr_cert_list; - gnutls_x509_privkey apr_pkey; + gnutls_privkey* apr_pkey; int apr_cert_list_length; /* find the appropriate certificate */ @@ -1038,7 +1038,7 @@ int _gnutls_gen_cert_client_cert_vrfy(gnutls_session session, { int ret; gnutls_cert *apr_cert_list; - gnutls_x509_privkey apr_pkey; + gnutls_privkey* apr_pkey; int apr_cert_list_length, size; gnutls_datum signature; @@ -1204,7 +1204,7 @@ int _gnutls_gen_cert_server_cert_req(gnutls_session session, int _gnutls_find_apr_cert(gnutls_session session, gnutls_cert ** apr_cert_list, int *apr_cert_list_length, - gnutls_x509_privkey * apr_pkey) + gnutls_privkey ** apr_pkey) { const gnutls_certificate_credentials cred; int ind; @@ -1242,7 +1242,7 @@ int _gnutls_find_apr_cert(gnutls_session session, *apr_cert_list = cred->cert_list[ind]; *apr_cert_list_length = cred->cert_list_length[ind]; - *apr_pkey = cred->pkey[ind]; + *apr_pkey = &cred->pkey[ind]; } } } else { /* CLIENT SIDE */ @@ -1266,7 +1266,7 @@ int _gnutls_find_apr_cert(gnutls_session session, *apr_cert_list = cred->cert_list[ind]; *apr_cert_list_length = cred->cert_list_length[ind]; - *apr_pkey = cred->pkey[ind]; + *apr_pkey = &cred->pkey[ind]; } } diff --git a/lib/auth_cert.h b/lib/auth_cert.h index 8bee758041..a667aa394e 100644 --- a/lib/auth_cert.h +++ b/lib/auth_cert.h @@ -25,7 +25,7 @@ typedef struct { * This is the same with the number of pkeys. */ - gnutls_x509_privkey * pkey; + gnutls_privkey * pkey; /* private keys. It contains ncerts private * keys. pkey[i] corresponds to certificate in * cert_list[i][0]. @@ -89,7 +89,7 @@ int _gnutls_gen_cert_server_cert_req(gnutls_session, opaque **); int _gnutls_proc_cert_cert_req(gnutls_session, opaque *, size_t); int _gnutls_proc_cert_client_cert_vrfy(gnutls_session, opaque *, size_t); int _gnutls_proc_cert_server_certificate(gnutls_session, opaque *, size_t); -int _gnutls_find_apr_cert( gnutls_session session, gnutls_cert** apr_cert_list, int *apr_cert_list_length, gnutls_x509_privkey* apr_pkey); +int _gnutls_find_apr_cert( gnutls_session session, gnutls_cert** apr_cert_list, int *apr_cert_list_length, gnutls_privkey** apr_pkey); const gnutls_cert * _gnutls_server_find_cert( struct gnutls_session_int*, gnutls_pk_algorithm); #define _gnutls_proc_cert_client_certificate _gnutls_proc_cert_server_certificate diff --git a/lib/auth_dhe.c b/lib/auth_dhe.c index 56dad83e10..4e7323297a 100644 --- a/lib/auth_dhe.c +++ b/lib/auth_dhe.c @@ -82,7 +82,7 @@ static int gen_dhe_server_kx(gnutls_session session, opaque ** data) int ret = 0, data_size; int bits; gnutls_cert *apr_cert_list; - gnutls_x509_privkey apr_pkey; + gnutls_privkey* apr_pkey; int apr_cert_list_length; gnutls_datum signature, ddata; CERTIFICATE_AUTH_INFO info; diff --git a/lib/auth_rsa.c b/lib/auth_rsa.c index af93ee722b..1c1ec48a08 100644 --- a/lib/auth_rsa.c +++ b/lib/auth_rsa.c @@ -65,7 +65,8 @@ extern OPENPGP_CERT2GNUTLS_CERT _E_gnutls_openpgp_cert2gnutls_cert; /* This function reads the RSA parameters from peer's certificate; */ -int _gnutls_get_public_rsa_params(gnutls_session session, GNUTLS_MPI params[MAX_PARAMS_SIZE], int* params_len) +int _gnutls_get_public_rsa_params(gnutls_session session, + GNUTLS_MPI params[MAX_PUBLIC_PARAMS_SIZE], int* params_len) { int ret; CERTIFICATE_AUTH_INFO info; @@ -191,8 +192,8 @@ const gnutls_certificate_credentials cred; /* non export cipher suites. */ - *params_size = cred->pkey[index]->params_size; - *params = cred->pkey[index]->params; + *params_size = cred->pkey[index].params_size; + *params = cred->pkey[index].params; return 0; } @@ -277,8 +278,8 @@ int _gnutls_gen_rsa_client_kx(gnutls_session session, opaque ** data) { CERTIFICATE_AUTH_INFO auth = session->key->auth_info; gnutls_datum sdata; /* data to send */ - GNUTLS_MPI params[MAX_PARAMS_SIZE]; - int params_len = MAX_PARAMS_SIZE; + GNUTLS_MPI params[MAX_PUBLIC_PARAMS_SIZE]; + int params_len = MAX_PUBLIC_PARAMS_SIZE; int ret, i; gnutls_protocol_version ver; diff --git a/lib/auth_rsa_export.c b/lib/auth_rsa_export.c index ef1ba7e35e..3c49e72170 100644 --- a/lib/auth_rsa_export.c +++ b/lib/auth_rsa_export.c @@ -74,7 +74,7 @@ static int gen_rsa_export_server_kx(gnutls_session session, opaque ** data) uint8 *data_e, *data_m; int ret = 0, data_size; gnutls_cert *apr_cert_list; - gnutls_x509_privkey apr_pkey; + gnutls_privkey* apr_pkey; int apr_cert_list_length; gnutls_datum signature, ddata; CERTIFICATE_AUTH_INFO info; diff --git a/lib/gnutls_cert.c b/lib/gnutls_cert.c index a12162e179..8cf6167e79 100644 --- a/lib/gnutls_cert.c +++ b/lib/gnutls_cert.c @@ -81,7 +81,7 @@ void gnutls_certificate_free_credentials(gnutls_certificate_credentials sc) _gnutls_free_datum( &sc->keyring); for (i = 0; i < sc->ncerts; i++) { - gnutls_x509_privkey_deinit(sc->pkey[i]); + gnutls_privkey_deinit( &sc->pkey[i]); } gnutls_free( sc->pkey); @@ -478,7 +478,7 @@ int _gnutls_x509_cert2gnutls_cert(gnutls_cert * gcert, const gnutls_datum *derCe gcert->subject_pk_algorithm = gnutls_x509_crt_get_pk_algorithm( cert, NULL); if (flags & CERT_ONLY_PUBKEY || flags == 0) { - gcert->params_size = MAX_PARAMS_SIZE; + gcert->params_size = MAX_PUBLIC_PARAMS_SIZE; ret = _gnutls_x509_crt_get_mpis( cert, gcert->params, &gcert->params_size); if (ret < 0) { gnutls_assert(); diff --git a/lib/gnutls_cert.h b/lib/gnutls_cert.h index c2a6c9cd03..44ac3ce0af 100644 --- a/lib/gnutls_cert.h +++ b/lib/gnutls_cert.h @@ -51,6 +51,28 @@ typedef struct gnutls_cert { } gnutls_cert; +typedef struct gnutls_privkey_int { + MPI params[MAX_PRIV_PARAMS_SIZE];/* the size of params depends on the public + * key algorithm + */ + /* + * RSA: [0] is modulus + * [1] is public exponent + * [2] is private exponent + * [3] is prime1 (p) + * [4] is prime2 (q) + * [5] is coefficient (u == inverse of p mod q) + * DSA: [0] is p + * [1] is q + * [2] is g + * [3] is y (public key) + * [4] is x (private key) + */ + int params_size; /* holds the number of params */ + + gnutls_pk_algorithm pk_algorithm; +} gnutls_privkey; + struct gnutls_session_int; /* because gnutls_session is not defined when this file is included */ typedef enum ConvFlags { @@ -64,6 +86,8 @@ int _gnutls_x509_cert2gnutls_cert(gnutls_cert * gcert, const gnutls_datum *derCe void _gnutls_free_cert(gnutls_cert* cert); int _gnutls_cert_get_dn(gnutls_cert * cert, gnutls_datum * odn); +void _gnutls_privkey_deinit(gnutls_privkey *key); + int _gnutls_cert_supported_kx( const gnutls_cert* cert, gnutls_kx_algorithm **alg, int *alg_size); #endif diff --git a/lib/gnutls_mpi.h b/lib/gnutls_mpi.h index c92a9d8ada..7ec3982d84 100644 --- a/lib/gnutls_mpi.h +++ b/lib/gnutls_mpi.h @@ -22,6 +22,7 @@ #define _gnutls_mpi_mulm gcry_mpi_mulm #define _gnutls_mpi_mul gcry_mpi_mul #define _gnutls_mpi_add gcry_mpi_add +#define _gnutls_mpi_add_ui gcry_mpi_add_ui #define _gnutls_mpi_mul_ui gcry_mpi_mul_ui # define _gnutls_mpi_alloc_like(x) _gnutls_mpi_new(_gnutls_mpi_get_nbits(x)) diff --git a/lib/gnutls_sig.c b/lib/gnutls_sig.c index 49283f00f0..a70d1fd2ad 100644 --- a/lib/gnutls_sig.c +++ b/lib/gnutls_sig.c @@ -34,13 +34,13 @@ #include <gnutls_sig.h> -int _gnutls_generate_sig( gnutls_cert* cert, gnutls_x509_privkey pkey, const gnutls_datum* hash_concat, gnutls_datum *signature); +int _gnutls_generate_sig( gnutls_cert* cert, gnutls_privkey* pkey, const gnutls_datum* hash_concat, gnutls_datum *signature); /* Generates a signature of all the previous sent packets in the * handshake procedure. */ -int _gnutls_generate_sig_from_hdata( gnutls_session session, gnutls_cert* cert, gnutls_x509_privkey pkey, gnutls_datum *signature) { +int _gnutls_generate_sig_from_hdata( gnutls_session session, gnutls_cert* cert, gnutls_privkey* pkey, gnutls_datum *signature) { gnutls_datum dconcat; int ret; opaque concat[36]; @@ -88,7 +88,7 @@ GNUTLS_MAC_HANDLE td_sha; /* Generates a signature of all the random data and the parameters. * Used in DHE_* ciphersuites. */ -int _gnutls_generate_sig_params( gnutls_session session, gnutls_cert* cert, gnutls_x509_privkey pkey, gnutls_datum* params, gnutls_datum *signature) +int _gnutls_generate_sig_params( gnutls_session session, gnutls_cert* cert, gnutls_privkey* pkey, gnutls_datum* params, gnutls_datum *signature) { gnutls_datum dconcat; int ret; @@ -148,7 +148,7 @@ opaque concat[36]; * Cert is the certificate of the corresponding private key. It is only checked if * it supports signing. */ -int _gnutls_generate_sig( gnutls_cert* cert, gnutls_x509_privkey pkey, const gnutls_datum* hash_concat, gnutls_datum *signature) +int _gnutls_generate_sig( gnutls_cert* cert, gnutls_privkey* pkey, const gnutls_datum* hash_concat, gnutls_datum *signature) { int ret; gnutls_datum tmpdata; diff --git a/lib/gnutls_sig.h b/lib/gnutls_sig.h index 8b6a1603f3..e839c38d88 100644 --- a/lib/gnutls_sig.h +++ b/lib/gnutls_sig.h @@ -3,8 +3,8 @@ # include <auth_cert.h> gnutls_certificate_status gnutls_x509_verify_signature(gnutls_cert* cert, gnutls_cert* issuer); -int _gnutls_generate_sig_from_hdata( gnutls_session session, gnutls_cert* cert, gnutls_x509_privkey pkey, gnutls_datum *signature); -int _gnutls_generate_sig_params( gnutls_session session, gnutls_cert* cert, gnutls_x509_privkey pkey, gnutls_datum* params, gnutls_datum *signature); +int _gnutls_generate_sig_from_hdata( gnutls_session session, gnutls_cert* cert, gnutls_privkey *pkey, gnutls_datum *signature); +int _gnutls_generate_sig_params( gnutls_session session, gnutls_cert* cert, gnutls_privkey *pkey, gnutls_datum* params, gnutls_datum *signature); int _gnutls_verify_sig_hdata( gnutls_session session, gnutls_cert *cert, gnutls_datum* signature); int _gnutls_verify_sig_params( gnutls_session session, gnutls_cert *cert, const gnutls_datum* params, gnutls_datum* signature); diff --git a/lib/gnutls_x509.c b/lib/gnutls_x509.c index 5b028375b7..5865143fd3 100644 --- a/lib/gnutls_x509.c +++ b/lib/gnutls_x509.c @@ -152,9 +152,9 @@ int _gnutls_x509_cert_verify_peers(gnutls_session session) */ static int _gnutls_check_key_cert_match( gnutls_certificate_credentials res) { -int pk = res->cert_list[res->ncerts-1][0].subject_pk_algorithm; +uint pk = res->cert_list[res->ncerts-1][0].subject_pk_algorithm; - if (gnutls_x509_privkey_get_pk_algorithm(res->pkey[res->ncerts-1]) != pk) + if (res->pkey[res->ncerts-1].pk_algorithm != pk) { gnutls_assert(); return GNUTLS_E_CERTIFICATE_KEY_MISMATCH; @@ -430,6 +430,43 @@ int read_cert_mem(gnutls_certificate_credentials res, const char *cert, int cert } +static int privkey_cpy( gnutls_privkey* dest, gnutls_x509_privkey src) +{ +int i, ret; + + memset( dest, 0, sizeof(gnutls_privkey)); + + for(i=0;i<src->params_size;i++) { + dest->params[i] = _gnutls_mpi_copy( src->params[i]); + if (dest->params[i] == NULL) { + gnutls_assert(); + ret = GNUTLS_E_MEMORY_ERROR; + goto cleanup; + } + } + + dest->pk_algorithm = src->pk_algorithm; + dest->params_size = src->params_size; + + return 0; + + cleanup: + + for (i=0;i<src->params_size;i++) { + _gnutls_mpi_release( &dest->params[i]); + } + return ret; +} + +void _gnutls_privkey_deinit(gnutls_privkey *key) +{ +int i; + + for (i = 0; i < key->params_size; i++) { + _gnutls_mpi_release( &key->params[i]); + } +} + /* Reads a PEM encoded PKCS-1 RSA private key from memory * 2002-01-26: Added ability to read DSA keys. @@ -440,16 +477,17 @@ static int read_key_mem(gnutls_certificate_credentials res, const char *key, int { int ret; gnutls_datum tmp; + gnutls_x509_privkey tmpkey; /* allocate space for the pkey list */ - res->pkey = gnutls_realloc_fast( res->pkey, (res->ncerts+1)*sizeof(gnutls_x509_privkey)); + res->pkey = gnutls_realloc_fast( res->pkey, (res->ncerts+1)*sizeof(gnutls_privkey)); if (res->pkey==NULL) { gnutls_assert(); return GNUTLS_E_MEMORY_ERROR; } - ret = gnutls_x509_privkey_init( &res->pkey[res->ncerts]); + ret = gnutls_x509_privkey_init( &tmpkey); //res->pkey[res->ncerts]); if (ret < 0) { gnutls_assert(); return ret; @@ -458,15 +496,18 @@ static int read_key_mem(gnutls_certificate_credentials res, const char *key, int tmp.data = (opaque*)key; tmp.size = key_size; - ret = gnutls_x509_privkey_import( res->pkey[res->ncerts], &tmp, type); + ret = gnutls_x509_privkey_import( tmpkey, &tmp, type); if (ret < 0) { gnutls_assert(); - gnutls_x509_privkey_deinit( res->pkey[res->ncerts]); - res->pkey[res->ncerts] = NULL; + gnutls_x509_privkey_deinit( tmpkey); return ret; } + privkey_cpy( &res->pkey[res->ncerts], tmpkey); + + gnutls_x509_privkey_deinit( tmpkey); + return 0; } @@ -608,7 +649,7 @@ void gnutls_certificate_free_keys(gnutls_certificate_credentials sc) sc->cert_list = NULL; for (i = 0; i < sc->ncerts; i++) { - gnutls_x509_privkey_deinit(sc->pkey[i]); + _gnutls_privkey_deinit( &sc->pkey[i]); } gnutls_free( sc->pkey); diff --git a/lib/x509/privkey.c b/lib/x509/privkey.c index b55de979de..1ce006cc80 100644 --- a/lib/x509/privkey.c +++ b/lib/x509/privkey.c @@ -23,13 +23,13 @@ #include <gnutls_datum.h> #include <gnutls_global.h> #include <gnutls_errors.h> +#include <gnutls_rsa_export.h> #include <common.h> #include <gnutls_x509.h> #include <x509_b64.h> #include <x509.h> #include <dn.h> #include <extensions.h> -#include <gnutls_privkey.h> /** * gnutls_x509_privkey_init - This function initializes a gnutls_crl structure @@ -45,6 +45,7 @@ int gnutls_x509_privkey_init(gnutls_x509_privkey * key) *key = gnutls_calloc( 1, sizeof(gnutls_x509_privkey_int)); if (*key) { + (*key)->key = ASN1_TYPE_EMPTY; (*key)->pk_algorithm = GNUTLS_PK_UNKNOWN; return 0; /* success */ } @@ -56,7 +57,7 @@ int gnutls_x509_privkey_init(gnutls_x509_privkey * key) * gnutls_x509_privkey_deinit - This function deinitializes memory used by a gnutls_x509_privkey structure * @key: The structure to be initialized * - * This function will deinitialize a CRL structure. + * This function will deinitialize a private key structure. * **/ void gnutls_x509_privkey_deinit(gnutls_x509_privkey key) @@ -67,6 +68,7 @@ int i; _gnutls_mpi_release( &key->params[i]); } + asn1_delete_structure(&key->key); gnutls_free(key); } @@ -355,7 +357,7 @@ int gnutls_x509_privkey_import(gnutls_x509_privkey key, const gnutls_datum * dat /** * gnutls_x509_privkey_get_pk_algorithm - This function returns the key's PublicKey algorithm - * @cert: should contain a gnutls_x509_privkey structure + * @key: should contain a gnutls_x509_privkey structure * * This function will return the public key algorithm of a private * key. @@ -368,3 +370,344 @@ int gnutls_x509_privkey_get_pk_algorithm( gnutls_x509_privkey key) { return key->pk_algorithm; } + + +/** + * gnutls_x509_privkey_export - This function will export the private key + * @key: Holds the key + * @format: the format of output params. One of PEM or DER. + * @output_data: will contain a private key PEM or DER encoded + * @output_data_size: holds the size of output_data (and will be replaced by the actual size of parameters) + * + * This function will export the private key to a PKCS1 structure for RSA keys, + * or an integer sequence for DSA keys. The DSA keys are in the same format + * with the parameters used by openssl. + * + * If the buffer provided is not long enough to hold the output, then + * GNUTLS_E_SHORT_MEMORY_BUFFER will be returned. + * + * If the structure is PEM encoded, it will have a header + * of "BEGIN RSA PRIVATE KEY". + * + * In case of failure a negative value will be returned, and + * 0 on success. + * + **/ +int gnutls_x509_privkey_export( gnutls_x509_privkey key, + gnutls_x509_crt_fmt format, unsigned char* output_data, int* output_data_size) +{ + int result; + + if (format == GNUTLS_X509_FMT_DER) { + if ((result=asn1_der_coding( key->key, "", output_data, output_data_size, NULL)) != ASN1_SUCCESS) { + gnutls_assert(); + + if (result == ASN1_MEM_ERROR) + return GNUTLS_E_SHORT_MEMORY_BUFFER; + + return _gnutls_asn2err(result); + } + + } else { /* PEM */ + opaque tmp[5*1024]; + opaque *out; + int len; + char * msg; + + len = sizeof(tmp) - 1; + if ((result=asn1_der_coding( key->key, "", tmp, &len, NULL)) != ASN1_SUCCESS) { + gnutls_assert(); + return _gnutls_asn2err(result); + } + + if (key->pk_algorithm == GNUTLS_PK_RSA) + msg = "RSA PRIVATE KEY"; + else if (key->pk_algorithm == GNUTLS_PK_DSA) + msg = "DSA PRIVATE KEY"; + else msg = NULL; + + result = _gnutls_fbase64_encode( msg, + tmp, len, &out); + + if (result < 0) { + gnutls_assert(); + return result; + } + + if (result == 0) { /* oooops */ + gnutls_assert(); + return GNUTLS_E_INTERNAL_ERROR; + } + + if (result + 1 > *output_data_size) { + gnutls_assert(); + gnutls_free(out); + *output_data_size = result; + return GNUTLS_E_SHORT_MEMORY_BUFFER; + } + + *output_data_size = result; + + if (output_data) { + memcpy( output_data, out, result); + output_data[result] = 0; + } + gnutls_free( out); + + } + + return 0; +} + +static int _encode_rsa( ASN1_TYPE* c2, MPI* params) +{ + int result, i; + size_t size[8], total, tmp_size; + opaque * m_data, *pube_data, *prie_data; + opaque* p1_data, *p2_data, *u_data, *exp1_data, *exp2_data; + opaque * all_data = NULL; + GNUTLS_MPI exp1 = NULL, exp2 = NULL, q1 = NULL, p1 = NULL; + opaque null = '\0'; + + /* Read all the sizes */ + total = 0; + for (i=0;i<6;i++) { + _gnutls_mpi_print( NULL, &size[i], params[i]); + total += size[i]; + } + + /* Now generate exp1 and exp2 + */ + exp1 = _gnutls_mpi_alloc_like( params[0]); /* like modulus */ + if (exp1 == NULL) { + gnutls_assert(); + result = GNUTLS_E_MEMORY_ERROR; + goto cleanup; + } + + exp2 = _gnutls_mpi_alloc_like( params[0]); + if (exp2 == NULL) { + gnutls_assert(); + result = GNUTLS_E_MEMORY_ERROR; + goto cleanup; + } + + q1 = _gnutls_mpi_alloc_like( params[4]); + if (q1 == NULL) { + gnutls_assert(); + result = GNUTLS_E_MEMORY_ERROR; + goto cleanup; + } + + p1 = _gnutls_mpi_alloc_like( params[3]); + if (p1 == NULL) { + gnutls_assert(); + result = GNUTLS_E_MEMORY_ERROR; + goto cleanup; + } + + _gnutls_mpi_add_ui( p1, params[3], -1); + _gnutls_mpi_add_ui( q1, params[4], -1); + + _gnutls_mpi_mod( exp1, params[2], p1); + _gnutls_mpi_mod( exp2, params[2], q1); + + + /* calculate exp's size */ + _gnutls_mpi_print( NULL, &size[6], exp1); + total += size[6]; + + _gnutls_mpi_print( NULL, &size[7], exp2); + total += size[7]; + + /* Encoding phase. + * allocate data enough to hold everything + */ + all_data = gnutls_alloca( total); + if (all_data == NULL) { + gnutls_assert(); + result = GNUTLS_E_MEMORY_ERROR; + goto cleanup; + } + + m_data = &all_data[0]; + pube_data = &all_data[size[0]]; + prie_data = &all_data[size[1]]; + p1_data = &all_data[size[2]]; + p2_data = &all_data[size[3]]; + u_data = &all_data[size[4]]; + exp1_data = &all_data[size[5]]; + exp2_data = &all_data[size[6]]; + + _gnutls_mpi_print( m_data, &tmp_size, params[0]); + _gnutls_mpi_print( pube_data, &tmp_size, params[1]); + _gnutls_mpi_print( prie_data, &tmp_size, params[2]); + _gnutls_mpi_print( p1_data, &tmp_size, params[3]); + _gnutls_mpi_print( p2_data, &tmp_size, params[4]); + _gnutls_mpi_print( u_data, &tmp_size, params[5]); + _gnutls_mpi_print( exp1_data, &tmp_size, exp1); + _gnutls_mpi_print( exp2_data, &tmp_size, exp2); + + /* Ok. Now we have the data. Create the asn1 structures + */ + + if ((result = asn1_create_element + (_gnutls_get_gnutls_asn(), "GNUTLS.RSAPrivateKey", c2)) + != ASN1_SUCCESS) { + gnutls_assert(); + result = _gnutls_asn2err(result); + goto cleanup; + } + + /* Write PRIME + */ + if ((result = asn1_write_value(*c2, "modulus", + m_data, size[0])) != ASN1_SUCCESS) + { + gnutls_assert(); + result = _gnutls_asn2err(result); + goto cleanup; + } + + if ((result = asn1_write_value(*c2, "publicExponent", + pube_data, size[1])) != ASN1_SUCCESS) + { + gnutls_assert(); + result = _gnutls_asn2err(result); + goto cleanup; + } + + if ((result = asn1_write_value(*c2, "privateExponent", + prie_data, size[2])) != ASN1_SUCCESS) + { + gnutls_assert(); + result = _gnutls_asn2err(result); + goto cleanup; + } + + if ((result = asn1_write_value(*c2, "prime1", + p1_data, size[3])) != ASN1_SUCCESS) + { + gnutls_assert(); + result = _gnutls_asn2err(result); + goto cleanup; + } + + if ((result = asn1_write_value(*c2, "prime2", + p2_data, size[4])) != ASN1_SUCCESS) + { + gnutls_assert(); + result = _gnutls_asn2err(result); + goto cleanup; + } + + if ((result = asn1_write_value(*c2, "exponent1", + exp1_data, size[6])) != ASN1_SUCCESS) + { + gnutls_assert(); + result = _gnutls_asn2err(result); + goto cleanup; + } + + if ((result = asn1_write_value(*c2, "exponent2", + exp2_data, size[7])) != ASN1_SUCCESS) + { + gnutls_assert(); + result = _gnutls_asn2err(result); + goto cleanup; + } + + if ((result = asn1_write_value(*c2, "coefficient", + u_data, size[5])) != ASN1_SUCCESS) + { + gnutls_assert(); + result = _gnutls_asn2err(result); + goto cleanup; + } + + gnutls_afree(all_data); + + if ((result = asn1_write_value(*c2, "otherPrimeInfos", + NULL, 0)) != ASN1_SUCCESS) { + gnutls_assert(); + result = _gnutls_asn2err(result); + goto cleanup; + } + + if ((result = asn1_write_value(*c2, "version", + &null, 1)) != ASN1_SUCCESS) { + gnutls_assert(); + result = _gnutls_asn2err(result); + goto cleanup; + } + + return 0; + + cleanup: + _gnutls_mpi_release( &exp1); + _gnutls_mpi_release( &exp2); + _gnutls_mpi_release( &q1); + _gnutls_mpi_release( &p1); + asn1_delete_structure(c2); + gnutls_afree( all_data); + + return result; +} + + +/** + * gnutls_x509_privkey_generate - This function will generate a private key + * @key: should contain a gnutls_x509_privkey structure + * @algo: is one of RSA or DSA. + * @bits: the size of the modulus + * + * This function will generate a random private key. Note that + * this function must be called on an empty private key. + * + * Returns 0 on success or a negative value on error. + * + **/ +int gnutls_x509_privkey_generate( gnutls_x509_privkey key, gnutls_pk_algorithm algo, + int bits) +{ +int ret; + + switch( algo) { + case GNUTLS_PK_DSA: + return GNUTLS_E_UNIMPLEMENTED_FEATURE; + case GNUTLS_PK_RSA: + ret = _gnutls_rsa_generate_params( key->params, bits); + + if (ret < 0) { + gnutls_assert(); + return ret; + } + + ret = _encode_rsa( &key->key, key->params); + if (ret < 0) { + gnutls_assert(); + goto cleanup; + } + key->params_size = 6; + key->pk_algorithm = GNUTLS_PK_RSA; + + break; + default: + gnutls_assert(); + return GNUTLS_E_INVALID_REQUEST; + } + + return 0; + + cleanup: + key->pk_algorithm = GNUTLS_PK_UNKNOWN; + key->params_size = 0; + _gnutls_mpi_release(&key->params[0]); + _gnutls_mpi_release(&key->params[1]); + _gnutls_mpi_release(&key->params[2]); + _gnutls_mpi_release(&key->params[3]); + _gnutls_mpi_release(&key->params[4]); + _gnutls_mpi_release(&key->params[5]); + + return ret; +} diff --git a/lib/x509/verify.c b/lib/x509/verify.c index e0cfaedf0b..536025abdc 100644 --- a/lib/x509/verify.c +++ b/lib/x509/verify.c @@ -487,12 +487,12 @@ static int _gnutls_x509_verify_signature( const gnutls_datum* tbs, const gnutls_datum* signature, gnutls_x509_crt issuer) { -GNUTLS_MPI issuer_params[MAX_PARAMS_SIZE]; +GNUTLS_MPI issuer_params[MAX_PUBLIC_PARAMS_SIZE]; int ret, issuer_params_size, i; /* Read the MPI parameters from the issuer's certificate. */ - issuer_params_size = MAX_PARAMS_SIZE; + issuer_params_size = MAX_PUBLIC_PARAMS_SIZE; ret = _gnutls_x509_crt_get_mpis(issuer, issuer_params, &issuer_params_size); if ( ret < 0) { diff --git a/lib/x509/x509.c b/lib/x509/x509.c index c3241331c1..4c71a4cc68 100644 --- a/lib/x509/x509.c +++ b/lib/x509/x509.c @@ -460,7 +460,7 @@ int gnutls_x509_crt_get_pk_algorithm( gnutls_x509_crt cert, int* bits) opaque str[MAX_X509_CERT_SIZE]; int algo; int len = sizeof(str); - GNUTLS_MPI params[MAX_PARAMS_SIZE]; + GNUTLS_MPI params[MAX_PUBLIC_PARAMS_SIZE]; len = sizeof(str) - 1; result = diff --git a/lib/x509/x509.h b/lib/x509/x509.h index 1d4772d4e9..2aa3601355 100644 --- a/lib/x509/x509.h +++ b/lib/x509/x509.h @@ -19,9 +19,9 @@ typedef struct gnutls_x509_crt_int { /* Raw encoded parameter. */ -#define MAX_PARAMETER_SIZE 1200 +#define MAX_PARAMETER_SIZE 2400 -#define MAX_PARAMS_SIZE 6 /* ok for RSA and DSA */ +#define MAX_PRIV_PARAMS_SIZE 6 /* ok for RSA and DSA */ /* parameters should not be larger than this limit */ #define DSA_PRIVATE_PARAMS 5 @@ -29,16 +29,16 @@ typedef struct gnutls_x509_crt_int { #define RSA_PRIVATE_PARAMS 6 #define RSA_PUBLIC_PARAMS 2 -#if MAX_PARAMS_SIZE - RSA_PRIVATE_PARAMS < 0 -# error INCREASE MAX_PARAMS +#if MAX_PRIV_PARAMS_SIZE - RSA_PRIVATE_PARAMS < 0 +# error INCREASE MAX_PRIV_PARAMS #endif -#if MAX_PARAMS_SIZE - DSA_PRIVATE_PARAMS < 0 -# error INCREASE MAX_PARAMS +#if MAX_PRIV_PARAMS_SIZE - DSA_PRIVATE_PARAMS < 0 +# error INCREASE MAX_PRIV_PARAMS #endif typedef struct gnutls_x509_privkey_int { - MPI params[MAX_PARAMS_SIZE];/* the size of params depends on the public + MPI params[MAX_PRIV_PARAMS_SIZE];/* the size of params depends on the public * key algorithm */ /* diff --git a/libextra/auth_srp_rsa.c b/libextra/auth_srp_rsa.c index ecabeb4437..750e5cfd45 100644 --- a/libextra/auth_srp_rsa.c +++ b/libextra/auth_srp_rsa.c @@ -81,7 +81,7 @@ ssize_t ret, data_size; gnutls_datum signature, ddata; const gnutls_certificate_credentials cred; gnutls_cert *apr_cert_list; -gnutls_private_key *apr_pkey; +gnutls_privkey *apr_pkey; int apr_cert_list_length; ret = _gnutls_gen_srp_server_kx( session, data); diff --git a/libextra/gnutls_openpgp.c b/libextra/gnutls_openpgp.c index fb8f447140..bd7341bd51 100644 --- a/libextra/gnutls_openpgp.c +++ b/libextra/gnutls_openpgp.c @@ -335,7 +335,7 @@ openpgp_pk_to_gnutls_cert( gnutls_cert *cert, cdkPKT_public_key *pk ) * GnuTLS specific data which is need to perform secret key operations. -*/ int -_gnutls_openpgp_key2gnutls_key( gnutls_private_key *pkey, +_gnutls_openpgp_key2gnutls_key( gnutls_privkey *pkey, gnutls_datum *raw_key ) { CDK_KBNODE snode; @@ -568,7 +568,7 @@ gnutls_certificate_set_openpgp_key_mem( gnutls_certificate_credentials res, i = 1; while( (p = cdk_kbnode_walk( knode, &ctx, 0 )) ) { pkt = cdk_kbnode_get_packet( p ); - if( i > MAX_PARAMS_SIZE ) + if( i > MAX_PUBLIC_PARAMS_SIZE ) break; if( pkt->pkttype == CDK_PKT_PUBLIC_KEY ) { int n = res->ncerts; @@ -586,7 +586,7 @@ gnutls_certificate_set_openpgp_key_mem( gnutls_certificate_credentials res, res->ncerts++; res->pkey = gnutls_realloc_fast(res->pkey, - (res->ncerts)*sizeof(gnutls_private_key)); + (res->ncerts)*sizeof(gnutls_privkey)); if( !res->pkey ) { gnutls_assert(); return GNUTLS_E_MEMORY_ERROR; @@ -673,7 +673,7 @@ gnutls_certificate_set_openpgp_key_file( gnutls_certificate_credentials res, i = 1; rc = cdk_keydb_get_keyblock( inp, &knode ); while( knode && (p = cdk_kbnode_walk( knode, &ctx, 0 )) ) { - if( i > MAX_PARAMS_SIZE ) + if( i > MAX_PUBLIC_PARAMS_SIZE ) break; pkt = cdk_kbnode_get_packet( p ); if( pkt->pkttype == CDK_PKT_PUBLIC_KEY ) { @@ -710,7 +710,7 @@ gnutls_certificate_set_openpgp_key_file( gnutls_certificate_credentials res, stream_to_datum( inp, &raw ); cdk_stream_close( inp ); - n = (res->ncerts + 1) * sizeof (gnutls_private_key); + n = (res->ncerts + 1) * sizeof (gnutls_privkey); res->pkey = gnutls_realloc_fast( res->pkey, n ); if( !res->pkey ) { gnutls_assert(); @@ -1942,7 +1942,7 @@ void gnutls_openpgp_set_recv_key_function( gnutls_session session, #else /*!HAVE_LIBOPENCDK*/ int -_gnutls_openpgp_key2gnutls_key( gnutls_private_key *pkey, +_gnutls_openpgp_key2gnutls_key( gnutls_privkey *pkey, gnutls_datum raw_key ) { return GNUTLS_E_UNIMPLEMENTED_FEATURE; |