From: Nikos Mavrogiannopoulos Date: Sat, 22 May 2010 13:13:20 +0000 (+0200) Subject: Added gnutls_pubkey_t abstract type to handle public keys. It can currently X-Git-Tag: gnutls_2_11_3~284 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=4a8552433e86a691c25be6eaa9037da43f9cce37;p=thirdparty%2Fgnutls.git Added gnutls_pubkey_t abstract type to handle public keys. It can currently import/export public keys from existing certificate types as well as from PKCS #11 URL. This allows generating a certificate or certificate request from a given public key (currently one could only generate them from a given private key). PKCS#11 API augmented to allow reading arbitrary objects instead of just certificates. Certtool updated to list those objects. --- diff --git a/lib/Makefile.am b/lib/Makefile.am index 70145bdc66..6eeb5a216a 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -83,7 +83,7 @@ COBJECTS = gnutls_record.c gnutls_compress.c debug.c gnutls_cipher.c \ crypto.c random.c pk-libgcrypt.c mpi-libgcrypt.c cryptodev.c \ rnd-libgcrypt.c cipher-libgcrypt.c ext_signature.c \ crypto-api.c ext_safe_renegotiation.c gnutls_mbuffers.c \ - gnutls_privkey.c pkcs11.c pkcs11_privkey.c + gnutls_privkey.c pkcs11.c pkcs11_privkey.c gnutls_pubkey.c if ENABLE_PKCS11 COBJECTS += pkcs11.c pkcs11_privkey.c diff --git a/lib/gnutls_pubkey.c b/lib/gnutls_pubkey.c new file mode 100644 index 0000000000..985f4733ea --- /dev/null +++ b/lib/gnutls_pubkey.c @@ -0,0 +1,670 @@ +/* + * GnuTLS PKCS#11 support + * Copyright (C) 2010 Free Software Foundation + * + * Author: Nikos Mavrogiannopoulos + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library 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 +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define PK_PEM_HEADER "PUBLIC KEY" + + +struct gnutls_pubkey_st { + gnutls_pk_algorithm_t pk_algorithm; + unsigned int bits; /* an indication of the security parameter */ + + /* the size of params depends on the public + * key algorithm + * RSA: [0] is modulus + * [1] is public exponent + * DSA: [0] is p + * [1] is q + * [2] is g + * [3] is public key + */ + bigint_t params[MAX_PUBLIC_PARAMS_SIZE]; + int params_size; /* holds the size of MPI params */ + + unsigned int key_usage; /* bits from GNUTLS_KEY_* */ +}; + +/** + * gnutls_pubkey_get_pk_algorithm: + * @key: should contain a #gnutls_pubkey_t structure + * @bits: If set will return the number of bits of the parameters (may be NULL) + * + * This function will return the public key algorithm of a public + * key and if possible will return a number of bits that indicates + * the security parameter of the key. + * + * Returns: a member of the #gnutls_pk_algorithm_t enumeration on + * success, or a negative value on error. + **/ +int gnutls_pubkey_get_pk_algorithm(gnutls_pubkey_t key, unsigned int *bits) +{ + if (bits) + *bits = key->bits; + + return key->pk_algorithm; +} + +/** + * gnutls_pubkey_get_key_usage: + * @key: should contain a #gnutls_pubkey_t structure + * @usage: If set will return the number of bits of the parameters (may be NULL) + * + * This function will return the key usage of the public key. + * + * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a + * negative error value. + **/ +int gnutls_pubkey_get_key_usage(gnutls_pubkey_t key, unsigned int *usage) +{ + if (usage) + *usage = key->key_usage; + + return 0; +} + +/** + * gnutls_pubkey_init: + * @key: The structure to be initialized + * + * This function will initialize an public key structure. + * + * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a + * negative error value. + **/ +int gnutls_pubkey_init(gnutls_pubkey_t * key) +{ + *key = gnutls_calloc(1, sizeof(struct gnutls_pubkey_st)); + if (*key == NULL) { + gnutls_assert(); + return GNUTLS_E_MEMORY_ERROR; + } + + return 0; +} + +/** + * gnutls_pubkey_deinit: + * @key: The structure to be deinitialized + * + * This function will deinitialize a public key structure. + **/ +void gnutls_pubkey_deinit(gnutls_pubkey_t key) +{ + gnutls_free(key); +} + +/** + * gnutls_pubkey_import_x509: + * @key: The public key + * @crt: The certificate to be imported + * @flags: should be zero + * + * This function will import the given public key to the abstract + * #gnutls_pubkey_t structure. + * + * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a + * negative error value. + **/ +int gnutls_pubkey_import_x509(gnutls_pubkey_t key, gnutls_x509_crt_t crt, + unsigned int flags) +{ + int ret; + + key->pk_algorithm = + gnutls_x509_crt_get_pk_algorithm(crt, &key->bits); + + ret = gnutls_x509_crt_get_key_usage(crt, &key->key_usage, NULL); + if (ret < 0) + key->key_usage = 0; + + key->params_size = sizeof(key->params) / sizeof(key->params[0]); + switch (key->pk_algorithm) { + case GNUTLS_PK_RSA: + ret = + _gnutls_x509_crt_get_mpis(crt, key->params, + &key->params_size); + if (ret < 0) { + gnutls_assert(); + return ret; + } + break; + case GNUTLS_PK_DSA: + ret = + _gnutls_x509_crt_get_mpis(crt, key->params, + &key->params_size); + if (ret < 0) { + gnutls_assert(); + return ret; + } + + break; + default: + gnutls_assert(); + return GNUTLS_E_INVALID_REQUEST; + } + + return 0; +} + +/** + * gnutls_pubkey_import_openpgp: + * @key: The public key + * @crt: The certificate to be imported + * @flags: should be zero + * + * This function will import the given public key to the abstract + * #gnutls_pubkey_t structure. + * + * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a + * negative error value. + **/ +int gnutls_pubkey_import_openpgp(gnutls_pubkey_t key, + gnutls_openpgp_crt_t crt, + gnutls_openpgp_keyid_t keyid, + unsigned int flags) +{ + int ret; + uint32_t kid32[2]; + + ret = gnutls_openpgp_crt_get_preferred_key_id(crt, keyid); + if (ret < 0) { + gnutls_assert(); + return ret; + } + + KEYID_IMPORT(kid32, keyid); + + key->pk_algorithm = + gnutls_openpgp_crt_get_pk_algorithm(crt, &key->bits); + + ret = gnutls_openpgp_crt_get_key_usage(crt, &key->key_usage); + if (ret < 0) + key->key_usage = 0; + + switch (key->pk_algorithm) { + case GNUTLS_PK_RSA: + ret = + _gnutls_openpgp_crt_get_mpis(crt, kid32, key->params, + &key->params_size); + if (ret < 0) { + gnutls_assert(); + return ret; + } + break; + case GNUTLS_PK_DSA: + ret = + _gnutls_openpgp_crt_get_mpis(crt, kid32, key->params, + &key->params_size); + if (ret < 0) { + gnutls_assert(); + return ret; + } + break; + default: + gnutls_assert(); + return GNUTLS_E_INVALID_REQUEST; + } + + return 0; +} + +/** + * gnutls_pubkey_export: + * @key: Holds the certificate + * @format: the format of output params. One of PEM or DER. + * @output_data: will contain a certificate 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 certificate to DER or PEM format. + * + * If the buffer provided is not long enough to hold the output, then + * *output_data_size is updated and GNUTLS_E_SHORT_MEMORY_BUFFER will + * be returned. + * + * If the structure is PEM encoded, it will have a header + * of "BEGIN CERTIFICATE". + * + * Return value: In case of failure a negative value will be + * returned, and 0 on success. + **/ +int +gnutls_pubkey_export(gnutls_pubkey_t key, + gnutls_x509_crt_fmt_t format, void *output_data, + size_t * output_data_size) +{ + int result; + ASN1_TYPE spk = ASN1_TYPE_EMPTY; + + if (key == NULL) { + gnutls_assert(); + return GNUTLS_E_INVALID_REQUEST; + } + + if ((result = asn1_create_element + (_gnutls_get_pkix(), "PKIX1.SubjectPublicKeyInfo", &spk)) + != ASN1_SUCCESS) { + gnutls_assert(); + return _gnutls_asn2err(result); + } + + result = + _gnutls_x509_encode_and_copy_PKI_params(spk, "", + key->pk_algorithm, + key->params, + key->params_size); + if (result < 0) { + gnutls_assert(); + goto cleanup; + } + + result = _gnutls_x509_export_int_named(spk, "", + format, PK_PEM_HEADER, + output_data, + output_data_size); + if (result < 0) { + gnutls_assert(); + goto cleanup; + } + + result = 0; + + cleanup: + asn1_delete_structure(&spk); + + return result; + +} + +/** + * gnutls_pubkey_get_key_id: + * @key: Holds the public key + * @flags: should be 0 for now + * @output_data: will contain the key ID + * @output_data_size: holds the size of output_data (and will be + * replaced by the actual size of parameters) + * + * This function will return a unique ID the depends on the public + * key parameters. This ID can be used in checking whether a + * certificate corresponds to the given public key. + * + * If the buffer provided is not long enough to hold the output, then + * *output_data_size is updated and GNUTLS_E_SHORT_MEMORY_BUFFER will + * be returned. The output will normally be a SHA-1 hash output, + * which is 20 bytes. + * + * Return value: In case of failure a negative value will be + * returned, and 0 on success. + **/ +int +gnutls_pubkey_get_key_id(gnutls_pubkey_t key, unsigned int flags, + unsigned char *output_data, + size_t * output_data_size) +{ + int ret = 0; + + if (key == NULL) { + gnutls_assert(); + return GNUTLS_E_INVALID_REQUEST; + } + + ret = + _gnutls_get_key_id(key->pk_algorithm, key->params, + key->params_size, output_data, + output_data_size); + if (ret < 0) { + gnutls_assert(); + return ret; + } + + return 0; +} + +/** + * gnutls_pubkey_get_pk_rsa_raw: + * @crt: Holds the certificate + * @m: will hold the modulus + * @e: will hold the public exponent + * + * This function will export the RSA public key's parameters found in + * the given structure. The new parameters will be allocated using + * gnutls_malloc() and will be stored in the appropriate datum. + * + * Returns: %GNUTLS_E_SUCCESS on success, otherwise an error. + **/ +int +gnutls_pubkey_get_pk_rsa_raw(gnutls_pubkey_t key, + gnutls_datum_t * m, gnutls_datum_t * e) +{ + int ret; + int i; + + if (key == NULL) { + gnutls_assert(); + return GNUTLS_E_INVALID_REQUEST; + } + + if (key->pk_algorithm != GNUTLS_PK_RSA) { + gnutls_assert(); + return GNUTLS_E_INVALID_REQUEST; + } + + ret = _gnutls_mpi_dprint(key->params[0], m); + if (ret < 0) { + gnutls_assert(); + return ret; + } + + ret = _gnutls_mpi_dprint(key->params[1], e); + if (ret < 0) { + gnutls_assert(); + _gnutls_free_datum(m); + return ret; + } + + return 0; +} + +/** + * gnutls_pubkey_get_pk_dsa_raw: + * @crt: Holds the certificate + * @p: will hold the p + * @q: will hold the q + * @g: will hold the g + * @y: will hold the y + * + * This function will export the DSA public key's parameters found in + * the given certificate. The new parameters will be allocated using + * gnutls_malloc() and will be stored in the appropriate datum. + * + * Returns: %GNUTLS_E_SUCCESS on success, otherwise an error. + **/ +int +gnutls_pubkey_get_pk_dsa_raw(gnutls_pubkey_t key, + gnutls_datum_t * p, gnutls_datum_t * q, + gnutls_datum_t * g, gnutls_datum_t * y) +{ + int ret; + bigint_t params[MAX_PUBLIC_PARAMS_SIZE]; + int params_size = MAX_PUBLIC_PARAMS_SIZE; + int i; + + if (key == NULL) { + gnutls_assert(); + return GNUTLS_E_INVALID_REQUEST; + } + + if (key->pk_algorithm != GNUTLS_PK_DSA) { + gnutls_assert(); + return GNUTLS_E_INVALID_REQUEST; + } + + /* P */ + ret = _gnutls_mpi_dprint(key->params[0], p); + if (ret < 0) { + gnutls_assert(); + return ret; + } + + /* Q */ + ret = _gnutls_mpi_dprint(key->params[1], q); + if (ret < 0) { + gnutls_assert(); + _gnutls_free_datum(p); + return ret; + } + + + /* G */ + ret = _gnutls_mpi_dprint(key->params[2], g); + if (ret < 0) { + gnutls_assert(); + _gnutls_free_datum(p); + _gnutls_free_datum(q); + return ret; + } + + + /* Y */ + ret = _gnutls_mpi_dprint(key->params[3], y); + if (ret < 0) { + gnutls_assert(); + _gnutls_free_datum(p); + _gnutls_free_datum(g); + _gnutls_free_datum(q); + return ret; + } + + return 0; +} + +/** + * gnutls_pubkey_import: + * @key: The structure to store the parsed certificate. + * @data: The DER or PEM encoded certificate. + * @format: One of DER or PEM + * + * This function will convert the given DER or PEM encoded Public key + * to the native gnutls_pubkey_t format.The output will be stored * in @ key. + * If the Certificate is PEM encoded it should have a header of "PUBLIC KEY". + * + * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a + * negative error value. + **/ +int gnutls_pubkey_import(gnutls_pubkey_t key, + const gnutls_datum_t * data, + gnutls_x509_crt_fmt_t format) +{ + int result = 0, need_free = 0; + gnutls_datum_t _data; + ASN1_TYPE spk; + + if (key == 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(PK_PEM_HEADER, 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; + } + + if ((result = asn1_create_element + (_gnutls_get_pkix(), "PKIX1.SubjectPublicKeyInfo", &spk)) + != ASN1_SUCCESS) { + gnutls_assert(); + result = _gnutls_asn2err(result); + goto cleanup; + } + + result = asn1_der_decoding (&spk, _data.data, _data.size, NULL); + if (result != ASN1_SUCCESS) { + gnutls_assert (); + result = _gnutls_asn2err (result); + goto cleanup; + } + + key->params_size = sizeof(key->params) / sizeof(key->params[0]); + result = + _gnutls_get_asn_mpis(spk, "", key->params, &key->params_size); + if (result < 0) { + gnutls_assert(); + goto cleanup; + } + + /* this has already been called by get_asn_mpis() thus it cannot + * fail. + */ + key->pk_algorithm = _gnutls_x509_get_pk_algorithm (spk, "", NULL); + + result = 0; + +cleanup: + asn1_delete_structure(&spk); + + if (need_free) + _gnutls_free_datum(&_data); + return result; +} + +int gnutls_x509_crt_set_pubkey (gnutls_x509_crt_t crt, + gnutls_pubkey_t key) +{ + int result; + + if (crt == NULL) + { + gnutls_assert (); + return GNUTLS_E_INVALID_REQUEST; + } + + result = _gnutls_x509_encode_and_copy_PKI_params (crt->cert, + "tbsCertificate.subjectPublicKeyInfo", + key->pk_algorithm, + key->params, + key->params_size); + + if (result < 0) + { + gnutls_assert (); + return result; + } + + if (key->key_usage) + gnutls_x509_crt_set_key_usage(crt, key->key_usage); + + return 0; +} + +int gnutls_x509_crq_set_pubkey (gnutls_x509_crq_t crq, + gnutls_pubkey_t key) +{ + int result; + + if (crq == NULL) + { + gnutls_assert (); + return GNUTLS_E_INVALID_REQUEST; + } + + result = _gnutls_x509_encode_and_copy_PKI_params + (crq->crq, + "certificationRequestInfo.subjectPKInfo", + key->pk_algorithm, key->params, key->params_size); + + if (result < 0) + { + gnutls_assert (); + return result; + } + + if (key->key_usage) + gnutls_x509_crq_set_key_usage(crq, key->key_usage); + + return 0; +} + +/** + * gnutls_pubkey_set_key_usage: + * @crt: a certificate of type #gnutls_x509_crt_t + * @usage: an ORed sequence of the GNUTLS_KEY_* elements. + * + * This function will set the keyUsage certificate extension. + * + * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a + * negative error value. + **/ +int +gnutls_pubkey_set_key_usage (gnutls_pubkey_t key, unsigned int usage) +{ + key->key_usage = usage; + + return 0; +} + +int gnutls_pubkey_import_pkcs11_url( gnutls_pubkey_t key, const char* url) +{ + gnutls_pkcs11_obj_t pcrt; + int ret; + + ret = gnutls_pkcs11_obj_init ( &pcrt); + if (ret < 0) { + gnutls_assert(); + return ret; + } + + ret = gnutls_pkcs11_obj_import_url (pcrt, url); + if (ret < 0) { + gnutls_assert(); + goto cleanup; + } + + ret = gnutls_pubkey_import(key, &pcrt->raw, GNUTLS_X509_FMT_DER); + if (ret < 0) { + gnutls_assert(); + goto cleanup; + } + + ret = 0; +cleanup: + + gnutls_pkcs11_obj_deinit(pcrt); + + return ret; +} + diff --git a/lib/gnutls_x509.c b/lib/gnutls_x509.c index 2241d94bfc..9f772a9d1d 100644 --- a/lib/gnutls_x509.c +++ b/lib/gnutls_x509.c @@ -566,10 +566,10 @@ static int read_cas_url (gnutls_certificate_credentials_t res, const char* url) { int ret; gnutls_x509_crt_t * xcrt_list = NULL; -gnutls_pkcs11_crt_t *pcrt_list=NULL; +gnutls_pkcs11_obj_t *pcrt_list=NULL; unsigned int pcrt_list_size = 0; - ret = gnutls_pkcs11_crt_list_import_url( NULL, &pcrt_list_size, url, GNUTLS_PKCS11_CRT_ATTR_TRUSTED); + ret = gnutls_pkcs11_obj_list_import_url( NULL, &pcrt_list_size, url, GNUTLS_PKCS11_OBJ_ATTR_CRT_TRUSTED); if (ret < 0 && ret != GNUTLS_E_SHORT_MEMORY_BUFFER) { gnutls_assert(); return ret; @@ -586,7 +586,7 @@ unsigned int pcrt_list_size = 0; return GNUTLS_E_MEMORY_ERROR; } - ret = gnutls_pkcs11_crt_list_import_url( pcrt_list, &pcrt_list_size, url, GNUTLS_PKCS11_CRT_ATTR_TRUSTED); + ret = gnutls_pkcs11_obj_list_import_url( pcrt_list, &pcrt_list_size, url, GNUTLS_PKCS11_OBJ_ATTR_CRT_TRUSTED); if (ret < 0) { gnutls_assert(); goto cleanup; diff --git a/lib/includes/gnutls/abstract.h b/lib/includes/gnutls/abstract.h index 8e75dce677..8305f9cddd 100644 --- a/lib/includes/gnutls/abstract.h +++ b/lib/includes/gnutls/abstract.h @@ -1,5 +1,5 @@ -#ifndef __GNUTLS_PRIVKEY_H -#define __GNUTLS_PRIVKEY_H +#ifndef __GNUTLS_ABSTRACT_H +#define __GNUTLS_ABSTRACT_H #include #include @@ -7,6 +7,55 @@ #include #include +/* Public key operations */ + +struct gnutls_pubkey_st; +typedef struct gnutls_pubkey_st* gnutls_pubkey_t; + +int gnutls_pubkey_init (gnutls_pubkey_t * key); +void gnutls_pubkey_deinit (gnutls_pubkey_t key); +int gnutls_pubkey_get_pk_algorithm (gnutls_pubkey_t key, unsigned int* bits); + +int gnutls_pubkey_import_x509(gnutls_pubkey_t pkey, gnutls_x509_crt_t crt, unsigned int flags); +int gnutls_pubkey_import_openpgp(gnutls_pubkey_t pkey, + gnutls_openpgp_crt_t crt, + gnutls_openpgp_keyid_t keyid, + unsigned int flags); + +int gnutls_pubkey_get_pk_rsa_raw (gnutls_pubkey_t crt, + gnutls_datum_t * m, gnutls_datum_t * e); +int gnutls_pubkey_get_pk_dsa_raw (gnutls_pubkey_t crt, + gnutls_datum_t * p, gnutls_datum_t * q, + gnutls_datum_t * g, gnutls_datum_t * y); + +int gnutls_pubkey_export (gnutls_pubkey_t key, + gnutls_x509_crt_fmt_t format, + void *output_data, size_t * output_data_size); + +int gnutls_pubkey_get_key_id (gnutls_pubkey_t key, unsigned int flags, + unsigned char *output_data, + size_t * output_data_size); + +int gnutls_pubkey_get_key_usage(gnutls_pubkey_t key, unsigned int *usage); +int gnutls_pubkey_set_key_usage (gnutls_pubkey_t key, unsigned int usage); + +int gnutls_pubkey_import (gnutls_pubkey_t key, + const gnutls_datum_t * data, + gnutls_x509_crt_fmt_t format); + + +int gnutls_pubkey_import_pkcs11_url( gnutls_pubkey_t key, const char* url); + + +int gnutls_x509_crt_set_pubkey (gnutls_x509_crt_t crt, + gnutls_pubkey_t key); + +int gnutls_x509_crq_set_pubkey (gnutls_x509_crq_t crq, + gnutls_pubkey_t key); + + +/* Private key operations */ + struct gnutls_privkey_st; typedef struct gnutls_privkey_st* gnutls_privkey_t; @@ -15,6 +64,7 @@ void gnutls_privkey_deinit (gnutls_privkey_t key); int gnutls_privkey_get_pk_algorithm (gnutls_privkey_t key, unsigned int* bits); gnutls_privkey_type_t gnutls_privkey_get_type (gnutls_privkey_t key); + #define GNUTLS_PRIVKEY_IMPORT_AUTO_RELEASE 1 int gnutls_privkey_import_pkcs11 (gnutls_privkey_t pkey, gnutls_pkcs11_privkey_t key, unsigned int flags); int gnutls_privkey_import_x509 (gnutls_privkey_t pkey, gnutls_x509_privkey_t key, unsigned int flags); diff --git a/lib/includes/gnutls/pkcs11.h b/lib/includes/gnutls/pkcs11.h index 05d4b20270..b5d1d6ef73 100644 --- a/lib/includes/gnutls/pkcs11.h +++ b/lib/includes/gnutls/pkcs11.h @@ -67,8 +67,8 @@ typedef int (*gnutls_pkcs11_pin_callback_t)(void *userdata, int attempt, /** * @brief PKCS#11 certificate reference. */ -struct gnutls_pkcs11_crt_st; -typedef struct gnutls_pkcs11_crt_st* gnutls_pkcs11_crt_t; +struct gnutls_pkcs11_obj_st; +typedef struct gnutls_pkcs11_obj_st* gnutls_pkcs11_obj_t; @@ -132,30 +132,11 @@ int gnutls_pkcs11_add_provider (const char * name, const char * params); * @param certificate Certificate reference to free. * @return gnutls stauts. */ -int gnutls_pkcs11_crt_init ( gnutls_pkcs11_crt_t *certificate); +int gnutls_pkcs11_obj_init ( gnutls_pkcs11_obj_t *certificate); -/** - * @brief Deserialize a certificate reference. - * @param serialized Serialized certificate. - * @param p_certificate Certificate reference. - * @return gnutls status. - */ -int gnutls_pkcs11_crt_import_url (gnutls_pkcs11_crt_t p_certificate, const char * url); - -/** - * @brief Serialize a certificate reference. - * @param certificate Certificate reference to serialize. - * @param serialized Serialize result (string). Use gnutls_free() to free it. - * @return gnutls status. - */ -int gnutls_pkcs11_crt_export_url (gnutls_pkcs11_crt_t certificate, char** url); - -/** - * @brief Free certificate reference. - * @param certificate Certificate reference to free. - * @return gnutls stauts. - */ -void gnutls_pkcs11_crt_deinit ( gnutls_pkcs11_crt_t certificate); +int gnutls_pkcs11_obj_import_url (gnutls_pkcs11_obj_t, const char * url); +int gnutls_pkcs11_obj_export_url (gnutls_pkcs11_obj_t, char** url); +void gnutls_pkcs11_obj_deinit ( gnutls_pkcs11_obj_t); /** * @brief Release array of certificate references. @@ -163,25 +144,27 @@ void gnutls_pkcs11_crt_deinit ( gnutls_pkcs11_crt_t certificate); * @param ncertificates Array size. * @return gnutls status. */ -int gnutls_pkcs11_crt_list_deinit (gnutls_pkcs11_crt_t * certificates, const unsigned int ncertificates); +int gnutls_pkcs11_obj_list_deinit (gnutls_pkcs11_obj_t * , const unsigned int nobjs); typedef enum { - GNUTLS_PKCS11_CRT_ID_HEX=1, - GNUTLS_PKCS11_CRT_LABEL, - GNUTLS_PKCS11_CRT_TOKEN_LABEL, - GNUTLS_PKCS11_CRT_TOKEN_SERIAL, - GNUTLS_PKCS11_CRT_TOKEN_MANUFACTURER, - GNUTLS_PKCS11_CRT_TOKEN_MODEL, - GNUTLS_PKCS11_CRT_ID, -} gnutls_pkcs11_cert_info_t; + GNUTLS_PKCS11_OBJ_ID_HEX=1, + GNUTLS_PKCS11_OBJ_LABEL, + GNUTLS_PKCS11_OBJ_TOKEN_LABEL, + GNUTLS_PKCS11_OBJ_TOKEN_SERIAL, + GNUTLS_PKCS11_OBJ_TOKEN_MANUFACTURER, + GNUTLS_PKCS11_OBJ_TOKEN_MODEL, + GNUTLS_PKCS11_OBJ_ID, +} gnutls_pkcs11_obj_info_t; -int gnutls_pkcs11_crt_get_info(gnutls_pkcs11_crt_t crt, gnutls_pkcs11_cert_info_t itype, void* output, size_t* output_size); +int gnutls_pkcs11_obj_get_info(gnutls_pkcs11_obj_t crt, gnutls_pkcs11_obj_info_t itype, void* output, size_t* output_size); typedef enum { - GNUTLS_PKCS11_CRT_ATTR_ALL=1, - GNUTLS_PKCS11_CRT_ATTR_TRUSTED, /* marked as trusted */ - GNUTLS_PKCS11_CRT_ATTR_WITH_PK, /* with corresponding private key */ -} gnutls_pkcs11_crt_attr_t; + GNUTLS_PKCS11_OBJ_ATTR_CRT_ALL=1, /* all certificates */ + GNUTLS_PKCS11_OBJ_ATTR_CRT_TRUSTED, /* certificates marked as trusted */ + GNUTLS_PKCS11_OBJ_ATTR_CRT_WITH_PRIVKEY, /* certificates with corresponding private key */ + GNUTLS_PKCS11_OBJ_ATTR_PUBKEY, /* public keys */ + GNUTLS_PKCS11_OBJ_ATTR_ALL, /* everything! */ +} gnutls_pkcs11_obj_attr_t; /* token info */ typedef enum { @@ -191,36 +174,32 @@ typedef enum { GNUTLS_PKCS11_TOKEN_MODEL, } gnutls_pkcs11_token_info_t; +typedef enum { + GNUTLS_PKCS11_OBJ_UNKNOWN, + GNUTLS_PKCS11_OBJ_X509_CRT, + GNUTLS_PKCS11_OBJ_PUBKEY, + GNUTLS_PKCS11_OBJ_PRIVKEY, + GNUTLS_PKCS11_OBJ_SECRET_KEY, + GNUTLS_PKCS11_OBJ_DATA, +} gnutls_pkcs11_obj_type_t; + int gnutls_pkcs11_token_get_url (unsigned int seq, char** url); int gnutls_pkcs11_token_get_info(const char* url, gnutls_pkcs11_token_info_t, void* output, size_t *output_size); #define GNUTLS_PKCS11_TOKEN_HW 1 int gnutls_pkcs11_token_get_flags(const char* url, unsigned int *flags); -/** - * @brief Enumerate available certificates. - * @param p_list Location to store the list. - * @param n_list Location to store end list length. - * @param url Enumerate only certificates found in token(s) pointed by url - * @param attributes Only export certificates that match this attribute - * @return gnutls status. - * @note the p_list is should not be initialized. - */ -int gnutls_pkcs11_crt_list_import_url (gnutls_pkcs11_crt_t * p_list, unsigned int *const n_list, const char* url, gnutls_pkcs11_crt_attr_t flags); +int gnutls_pkcs11_obj_list_import_url (gnutls_pkcs11_obj_t * p_list, unsigned int *const n_list, const char* url, gnutls_pkcs11_obj_attr_t flags); -int gnutls_x509_crt_import_pkcs11( gnutls_x509_crt_t crt, gnutls_pkcs11_crt_t pkcs11_crt); +int gnutls_x509_crt_import_pkcs11( gnutls_x509_crt_t crt, gnutls_pkcs11_obj_t pkcs11_crt); int gnutls_x509_crt_import_pkcs11_url( gnutls_x509_crt_t crt, const char* url); -/** - * @brief Return the type of the certificate - * @param certificate Certificate reference. - * @return gnutls status. - */ -gnutls_certificate_type_t gnutls_pkcs11_crt_get_type (gnutls_pkcs11_crt_t certificate); +gnutls_pkcs11_obj_type_t gnutls_pkcs11_obj_get_type (gnutls_pkcs11_obj_t certificate); +const char* gnutls_pkcs11_type_get_name (gnutls_pkcs11_obj_type_t); int gnutls_x509_crt_list_import_pkcs11 (gnutls_x509_crt_t * certs, unsigned int cert_max, - gnutls_pkcs11_crt_t * const pkcs11_certs, + gnutls_pkcs11_obj_t * const pkcs11_certs, unsigned int flags); @@ -228,7 +207,7 @@ int gnutls_x509_crt_list_import_pkcs11 (gnutls_x509_crt_t * certs, int gnutls_pkcs11_privkey_init (gnutls_pkcs11_privkey_t * key); void gnutls_pkcs11_privkey_deinit (gnutls_pkcs11_privkey_t key); int gnutls_pkcs11_privkey_get_pk_algorithm (gnutls_pkcs11_privkey_t key, unsigned int* bits); -int gnutls_pkcs11_privkey_get_info(gnutls_pkcs11_privkey_t crt, gnutls_pkcs11_cert_info_t itype, void* output, size_t* output_size); +int gnutls_pkcs11_privkey_get_info(gnutls_pkcs11_privkey_t crt, gnutls_pkcs11_obj_info_t itype, void* output, size_t* output_size); int gnutls_pkcs11_privkey_import_url (gnutls_pkcs11_privkey_t key, const char* url); diff --git a/lib/libgnutls.map b/lib/libgnutls.map index b900ff3303..503cf2f430 100644 --- a/lib/libgnutls.map +++ b/lib/libgnutls.map @@ -611,17 +611,17 @@ GNUTLS_2_11 gnutls_pkcs11_set_pin_function; gnutls_pkcs11_set_token_function; gnutls_pkcs11_add_provider; - gnutls_pkcs11_crt_init; - gnutls_pkcs11_crt_import_url; - gnutls_pkcs11_crt_export_url; - gnutls_pkcs11_crt_deinit; - gnutls_pkcs11_crt_list_deinit; - gnutls_pkcs11_crt_list_import_url; + gnutls_pkcs11_obj_init; + gnutls_pkcs11_obj_import_url; + gnutls_pkcs11_obj_export_url; + gnutls_pkcs11_obj_deinit; + gnutls_pkcs11_obj_list_deinit; + gnutls_pkcs11_obj_list_import_url; gnutls_x509_crt_import_pkcs11; - gnutls_pkcs11_crt_get_type; + gnutls_pkcs11_obj_get_type; gnutls_x509_crt_list_import_pkcs11; gnutls_x509_crt_import_pkcs11_url; - gnutls_pkcs11_crt_get_info; + gnutls_pkcs11_obj_get_info; gnutls_pkcs11_token_get_info; gnutls_pkcs11_token_get_url; gnutls_pkcs11_privkey_init; @@ -647,7 +647,22 @@ GNUTLS_2_11 gnutls_x509_crq_privkey_sign; gnutls_x509_crl_privkey_sign; gnutls_x509_crt_privkey_sign; + gnutls_pubkey_init; + gnutls_pubkey_deinit; + gnutls_pubkey_get_pk_algorithm; + gnutls_pubkey_import_x509; + gnutls_pubkey_import_openpgp; + gnutls_pubkey_get_pk_rsa_raw; + gnutls_pubkey_get_pk_dsa_raw; + gnutls_pubkey_export; + gnutls_pubkey_get_key_id; + gnutls_pubkey_get_key_usage; + gnutls_pkcs11_type_get_name; + gnutls_pubkey_import_pkcs11_url; + gnutls_pubkey_import; + gnutls_x509_crt_set_pubkey; + gnutls_x509_crq_set_pubkey; } GNUTLS_2_10; GNUTLS_PRIVATE { diff --git a/lib/pkcs11.c b/lib/pkcs11.c index 7af5797750..32b11d26f0 100644 --- a/lib/pkcs11.c +++ b/lib/pkcs11.c @@ -43,14 +43,8 @@ struct gnutls_pkcs11_provider_s { ck_slot_id_t *slots; }; -struct gnutls_pkcs11_crt_st { - gnutls_datum_t raw; - gnutls_certificate_type_t type; - struct pkcs11_url_info info; -}; - struct url_find_data_st { - gnutls_pkcs11_crt_t crt; + gnutls_pkcs11_obj_t crt; }; struct flags_find_data_st { @@ -59,10 +53,10 @@ struct flags_find_data_st { }; struct crt_find_data_st { - gnutls_pkcs11_crt_t *p_list; + gnutls_pkcs11_obj_t *p_list; unsigned int* n_list; unsigned int current; - gnutls_pkcs11_crt_attr_t flags; + gnutls_pkcs11_obj_attr_t flags; struct pkcs11_url_info info; }; @@ -143,8 +137,8 @@ fail: /** - * gnutls_pkcs11_crt_get_info: - * @crt: should contain a #gnutls_pkcs11_crt_t structure + * gnutls_pkcs11_obj_get_info: + * @crt: should contain a #gnutls_pkcs11_obj_t structure * @itype: Denotes the type of information requested * @output: where output will be stored * @output_size: contains the maximum size of the output and will be overwritten with actual @@ -156,20 +150,24 @@ fail: * * Returns: zero on success or a negative value on error. **/ +<<<<<<< HEAD:lib/pkcs11.c int gnutls_pkcs11_crt_get_info(gnutls_pkcs11_crt_t crt, gnutls_pkcs11_cert_info_t itype, +======= +int gnutls_pkcs11_obj_get_info(gnutls_pkcs11_obj_t crt, gnutls_pkcs11_obj_info_t itype, +>>>>>>> Added gnutls_pubkey_t abstract type to handle public keys. It can currently:lib/pkcs11.c void* output, size_t* output_size) { return pkcs11_get_info(&crt->info, itype, output, output_size); } -int pkcs11_get_info(struct pkcs11_url_info *info, gnutls_pkcs11_cert_info_t itype, +int pkcs11_get_info(struct pkcs11_url_info *info, gnutls_pkcs11_obj_info_t itype, void* output, size_t* output_size) { const char* str = NULL; size_t len; switch(itype) { - case GNUTLS_PKCS11_CRT_ID: + case GNUTLS_PKCS11_OBJ_ID: if (*output_size < info->certid_raw_size) { *output_size = info->certid_raw_size; return GNUTLS_E_SHORT_MEMORY_BUFFER; @@ -178,22 +176,22 @@ int pkcs11_get_info(struct pkcs11_url_info *info, gnutls_pkcs11_cert_info_t ityp *output_size = info->certid_raw_size; return 0; - case GNUTLS_PKCS11_CRT_ID_HEX: + case GNUTLS_PKCS11_OBJ_ID_HEX: str = info->id; break; - case GNUTLS_PKCS11_CRT_LABEL: + case GNUTLS_PKCS11_OBJ_LABEL: str = info->label; break; - case GNUTLS_PKCS11_CRT_TOKEN_LABEL: + case GNUTLS_PKCS11_OBJ_TOKEN_LABEL: str = info->token; break; - case GNUTLS_PKCS11_CRT_TOKEN_SERIAL: + case GNUTLS_PKCS11_OBJ_TOKEN_SERIAL: str = info->serial; break; - case GNUTLS_PKCS11_CRT_TOKEN_MANUFACTURER: + case GNUTLS_PKCS11_OBJ_TOKEN_MANUFACTURER: str = info->manufacturer; break; - case GNUTLS_PKCS11_CRT_TOKEN_MODEL: + case GNUTLS_PKCS11_OBJ_TOKEN_MODEL: str = info->model; break; default: @@ -583,6 +581,15 @@ int pkcs11_info_to_url(const struct pkcs11_url_info* info, char** url) init = 1; } + if (info->type[0]) { + ret = append(&str, info->type, "objecttype", init); + if (ret < 0) { + gnutls_assert(); + goto cleanup; + } + init = 1; + } + if (info->id[0] != 0) { ret = _gnutls_string_append_printf(&str, ";id=%s", info->id); if (ret < 0) { @@ -603,7 +610,7 @@ cleanup: } /** - * gnutls_pkcs11_crt_init: + * gnutls_pkcs11_obj_init: * @crt: The structure to be initialized * * This function will initialize a pkcs11 certificate structure. @@ -611,9 +618,9 @@ cleanup: * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a * negative error value. **/ -int gnutls_pkcs11_crt_init(gnutls_pkcs11_crt_t * crt) +int gnutls_pkcs11_obj_init(gnutls_pkcs11_obj_t * crt) { - *crt = gnutls_calloc(1, sizeof(struct gnutls_pkcs11_crt_st)); + *crt = gnutls_calloc(1, sizeof(struct gnutls_pkcs11_obj_st)); if (*crt == NULL) { gnutls_assert(); return GNUTLS_E_MEMORY_ERROR; @@ -623,12 +630,12 @@ int gnutls_pkcs11_crt_init(gnutls_pkcs11_crt_t * crt) } /** - * gnutls_pkcs11_crt_deinit: + * gnutls_pkcs11_obj_deinit: * @key: The structure to be initialized * * This function will deinitialize a certificate structure. **/ -void gnutls_pkcs11_crt_deinit(gnutls_pkcs11_crt_t crt) +void gnutls_pkcs11_obj_deinit(gnutls_pkcs11_obj_t crt) { free(crt); } @@ -711,19 +718,62 @@ finish: return ret; } -/* imports a raw certificate from a token to a pkcs11_crt_t structure. +static const char* pkcs11_obj_type_to_str(gnutls_pkcs11_obj_type_t type) +{ + switch(type) { + case GNUTLS_PKCS11_OBJ_X509_CRT: + return "cert"; + case GNUTLS_PKCS11_OBJ_PUBKEY: + return "public"; + case GNUTLS_PKCS11_OBJ_PRIVKEY: + return "private"; + case GNUTLS_PKCS11_OBJ_SECRET_KEY: + return "secretkey"; + case GNUTLS_PKCS11_OBJ_DATA: + return "data"; + case GNUTLS_PKCS11_OBJ_UNKNOWN: + default: + return "unknown"; + } +} + +/* imports a raw certificate from a token to a pkcs11_obj_t structure. */ -static int pkcs11_crt_import(gnutls_pkcs11_crt_t crt, const gnutls_datum_t* data, +static int pkcs11_obj_import(unsigned int class, gnutls_pkcs11_obj_t crt, const gnutls_datum_t* data, const gnutls_datum_t * id, const gnutls_datum_t * label, struct ck_token_info* tinfo) { char *s; int ret; - crt->type = GNUTLS_CRT_X509; - ret = _gnutls_set_datum(&crt->raw, data->data, data->size); - if (ret < 0) { - gnutls_assert(); - return ret; + switch(class) { + case CKO_CERTIFICATE: + crt->type = GNUTLS_PKCS11_OBJ_X509_CRT; + break; + case CKO_PUBLIC_KEY: + crt->type = GNUTLS_PKCS11_OBJ_PUBKEY; + break; + case CKO_PRIVATE_KEY: + crt->type = GNUTLS_PKCS11_OBJ_PRIVKEY; + break; + case CKO_SECRET_KEY: + crt->type = GNUTLS_PKCS11_OBJ_SECRET_KEY; + break; + case CKO_DATA: + crt->type = GNUTLS_PKCS11_OBJ_DATA; + break; + default: + crt->type = GNUTLS_PKCS11_OBJ_UNKNOWN; + } + + if (crt->type != GNUTLS_PKCS11_OBJ_UNKNOWN) + strcpy(crt->info.type, pkcs11_obj_type_to_str(crt->type)); + + if (data && data->data) { + ret = _gnutls_set_datum(&crt->raw, data->data, data->size); + if (ret < 0) { + gnutls_assert(); + return ret; + } } terminate_string(tinfo->manufacturer_id, sizeof tinfo->manufacturer_id); @@ -737,19 +787,21 @@ static int pkcs11_crt_import(gnutls_pkcs11_crt_t crt, const gnutls_datum_t* data snprintf(crt->info.model, sizeof(crt->info.model), "%s", tinfo->model); snprintf(crt->info.serial, sizeof(crt->info.serial), "%s", tinfo->serial_number); - memcpy(crt->info.label, label->data, label->size); - crt->info.label[label->size] = 0; + if (label && label->data) { + memcpy(crt->info.label, label->data, label->size); + crt->info.label[label->size] = 0; + } - strcpy(crt->info.type, "cert"); + if (id && id->data) { + s = _gnutls_bin2hex(id->data, id->size, crt->info.id, sizeof(crt->info.id), ":"); + if (s == NULL) { + gnutls_assert(); + return GNUTLS_E_PKCS11_ERROR; + } - s = _gnutls_bin2hex(id->data, id->size, crt->info.id, sizeof(crt->info.id), ":"); - if (s == NULL) { - gnutls_assert(); - return GNUTLS_E_PKCS11_ERROR; + memmove(crt->info.certid_raw, id->data, id->size); + crt->info.certid_raw_size = id->size; } - - memmove(crt->info.certid_raw, id->data, id->size); - crt->info.certid_raw_size = id->size; return 0; } @@ -848,7 +900,7 @@ static int find_cert_url(pakchois_session_t *pks, struct token_info *info, void* gnutls_datum_t data = { a[0].value, a[0].value_len }; gnutls_datum_t label = { a[1].value, a[1].value_len }; - ret = pkcs11_crt_import(find_data->crt, &data, &id, &label, &info->tinfo); + ret = pkcs11_obj_import(CKO_CERTIFICATE, find_data->crt, &data, &id, &label, &info->tinfo); if (ret < 0) { gnutls_assert(); goto cleanup; @@ -882,14 +934,14 @@ cleanup: * @url: a PKCS 11 url identifying the key * * This function will "import" a PKCS 11 URL identifying a certificate - * key to the #gnutls_pkcs11_crt_t structure. This does not involve any - * parsing (such as X.509 or OpenPGP) since the #gnutls_pkcs11_crt_t is + * key to the #gnutls_pkcs11_obj_t structure. This does not involve any + * parsing (such as X.509 or OpenPGP) since the #gnutls_pkcs11_obj_t is * format agnostic. Only data are transferred. * * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a * negative error value. **/ -int gnutls_pkcs11_crt_import_url (gnutls_pkcs11_crt_t cert, const char * url) +int gnutls_pkcs11_obj_import_url (gnutls_pkcs11_obj_t cert, const char * url) { int ret; struct url_find_data_st find_data; @@ -1037,7 +1089,7 @@ int gnutls_pkcs11_token_get_info(const char* url, gnutls_pkcs11_token_info_t tty } /** - * gnutls_pkcs11_crt_export_url: + * gnutls_pkcs11_obj_export_url: * @crt: Holds the PKCS 11 certificate * @url: will contain an allocated url * @@ -1046,7 +1098,7 @@ int gnutls_pkcs11_token_get_info(const char* url, gnutls_pkcs11_token_info_t tty * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a * negative error value. **/ -int gnutls_pkcs11_crt_export_url (gnutls_pkcs11_crt_t cert, char ** url) +int gnutls_pkcs11_obj_export_url (gnutls_pkcs11_obj_t cert, char ** url) { int ret; @@ -1060,7 +1112,7 @@ int ret; } /** - * gnutls_pkcs11_crt_get_type: + * gnutls_pkcs11_obj_get_type: * @certificate: Holds the PKCS 11 certificate * * This function will return the type of the certificate being @@ -1068,9 +1120,9 @@ int ret; * * Returns: The type of the certificate. **/ -gnutls_certificate_type_t gnutls_pkcs11_crt_get_type (gnutls_pkcs11_crt_t certificate) +gnutls_pkcs11_obj_type_t gnutls_pkcs11_obj_get_type (gnutls_pkcs11_obj_t obj) { - return certificate->type; + return obj->type; } struct pkey_list { @@ -1174,12 +1226,6 @@ static int find_privkeys(pakchois_session_t *pks, struct token_info* info, struc class = CKO_PRIVATE_KEY; - ret = pkcs11_login(pks, info); - if (ret < 0) { - gnutls_assert(); - return ret; - } - /* Find an object with private key class and a certificate ID * which matches the certificate. */ /* FIXME: also match the cert subject. */ @@ -1252,7 +1298,7 @@ static int find_privkeys(pakchois_session_t *pks, struct token_info* info, struc /* Recover certificate list from tokens */ -static int find_crts(pakchois_session_t *pks, struct token_info *info, void* input) +static int find_objs(pakchois_session_t *pks, struct token_info *info, void* input) { struct crt_find_data_st* find_data = input; struct ck_attribute a[4]; @@ -1267,6 +1313,7 @@ static int find_crts(pakchois_session_t *pks, struct token_info *info, void* inp char label_tmp[PKCS11_LABEL_SIZE]; int ret, i; struct pkey_list plist; /* private key holder */ + int tot_values = 0; if (info == NULL) { /* final call */ if (find_data->current <= *find_data->n_list) @@ -1301,15 +1348,14 @@ static int find_crts(pakchois_session_t *pks, struct token_info *info, void* inp return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; } - if (find_data->info.type[0] != 0) { - if (strcmp(find_data->info.type, "cert") != 0) { + memset(&plist, 0, sizeof(plist)); + if (find_data->flags==GNUTLS_PKCS11_OBJ_ATTR_CRT_WITH_PRIVKEY) { + ret = pkcs11_login(pks, info); + if (ret < 0) { gnutls_assert(); - return GNUTLS_E_UNIMPLEMENTED_FEATURE; + return ret; } - } - memset(&plist, 0, sizeof(plist)); - if (find_data->flags==GNUTLS_PKCS11_CRT_ATTR_WITH_PK) { ret = find_privkeys(pks, info, &plist); if (ret < 0) { gnutls_assert(); @@ -1320,6 +1366,12 @@ static int find_crts(pakchois_session_t *pks, struct token_info *info, void* inp gnutls_assert(); return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; } + } else if (find_data->flags==GNUTLS_PKCS11_OBJ_ATTR_ALL) { + ret = pkcs11_login(pks, info); + if (ret < 0) { + gnutls_assert(); + return ret; + } } cert_data = gnutls_malloc(MAX_CERT_SIZE); @@ -1329,27 +1381,51 @@ static int find_crts(pakchois_session_t *pks, struct token_info *info, void* inp } /* Find objects with cert class and X.509 cert type. */ - class = CKO_CERTIFICATE; - type = CKC_X_509; - trusted = 1; - - a[0].type = CKA_CLASS; - a[0].value = &class; - a[0].value_len = sizeof class; - if (find_data->flags == GNUTLS_PKCS11_CRT_ATTR_ALL || find_data->flags==GNUTLS_PKCS11_CRT_ATTR_WITH_PK) { + if (find_data->flags == GNUTLS_PKCS11_OBJ_ATTR_CRT_ALL || find_data->flags==GNUTLS_PKCS11_OBJ_ATTR_CRT_WITH_PRIVKEY) { + class = CKO_CERTIFICATE; + type = CKC_X_509; + trusted = 1; + + a[0].type = CKA_CLASS; + a[0].value = &class; + a[0].value_len = sizeof class; + a[1].type = CKA_CERTIFICATE_TYPE; a[1].value = &type; a[1].value_len = sizeof type; - } + + tot_values = 2; + } else if (find_data->flags == GNUTLS_PKCS11_OBJ_ATTR_CRT_TRUSTED) { + class = CKO_CERTIFICATE; + type = CKC_X_509; + trusted = 1; + + a[0].type = CKA_CLASS; + a[0].value = &class; + a[0].value_len = sizeof class; - if (find_data->flags == GNUTLS_PKCS11_CRT_ATTR_TRUSTED) { a[1].type = CKA_TRUSTED; a[1].value = &trusted; a[1].value_len = sizeof trusted; + + tot_values = 2; + } else if (find_data->flags == GNUTLS_PKCS11_OBJ_ATTR_PUBKEY) { + class = CKO_PUBLIC_KEY; + + a[0].type = CKA_CLASS; + a[0].value = &class; + a[0].value_len = sizeof class; + + tot_values = 1; + } else if (find_data->flags == GNUTLS_PKCS11_OBJ_ATTR_ALL) { + tot_values = 0; + } else { + gnutls_assert(); + return GNUTLS_E_INVALID_REQUEST; } - rv = pakchois_find_objects_init(pks, a, 2); + rv = pakchois_find_objects_init(pks, a, tot_values); if (rv != CKR_OK) { gnutls_assert(); _gnutls_debug_log("pk11: FindObjectsInit failed.\n"); @@ -1358,54 +1434,75 @@ static int find_crts(pakchois_session_t *pks, struct token_info *info, void* inp while (pakchois_find_objects(pks, &obj, 1, &count) == CKR_OK && count == 1) { + gnutls_datum_t label, id, value; + + a[0].type = CKA_LABEL; + a[0].value = label_tmp; + a[0].value_len = sizeof label_tmp; + + if (pakchois_get_attribute_value(pks, obj, a, 1) == CKR_OK) { + label.data = a[0].value; + label.size = a[0].value_len; + } else { + label.data = NULL; + label.size = 0; + } + + a[0].type = CKA_ID; + a[0].value = certid_tmp; + a[0].value_len = sizeof certid_tmp; + if (pakchois_get_attribute_value(pks, obj, a, 1) == CKR_OK) { + id.data = a[0].value; + id.size = a[0].value_len; + } else { + id.data = NULL; + id.size = 0; + } a[0].type = CKA_VALUE; a[0].value = cert_data; a[0].value_len = MAX_CERT_SIZE; - a[1].type = CKA_ID; - a[1].value = certid_tmp; - a[1].value_len = sizeof(certid_tmp); - a[2].type = CKA_LABEL; - a[2].value = label_tmp; - a[2].value_len = sizeof label_tmp; - - if (pakchois_get_attribute_value(pks, obj, a, 3) == CKR_OK) { - gnutls_datum_t data = { a[0].value, a[0].value_len }; - gnutls_datum_t id = { a[1].value, a[1].value_len }; - gnutls_datum_t label = { a[2].value, a[2].value_len }; - - /* XXX check also ID with find_data->info.id */ + if (pakchois_get_attribute_value(pks, obj, a, 1) == CKR_OK) { + value.data = a[0].value; + value.size = a[0].value_len; + } else { + value.data = NULL; + value.size = 0; + } - if (find_data->flags == GNUTLS_PKCS11_CRT_ATTR_WITH_PK) { - for (i=0;iflags == GNUTLS_PKCS11_OBJ_ATTR_ALL) { + a[0].type = CKA_CLASS; + a[0].value = &class; + a[0].value_len = sizeof class; - if (find_data->current < *find_data->n_list) { + pakchois_get_attribute_value(pks, obj, a, 1); + } - ret = gnutls_pkcs11_crt_init(&find_data->p_list[find_data->current]); - if (ret < 0) { - gnutls_assert(); - goto fail; + if (find_data->flags == GNUTLS_PKCS11_OBJ_ATTR_CRT_WITH_PRIVKEY) { + for (i=0;ip_list[find_data->current], &data, &id, &label, &info->tinfo); - if (ret < 0) { - gnutls_assert(); - goto fail; - } + if (find_data->current < *find_data->n_list) { + ret = gnutls_pkcs11_obj_init(&find_data->p_list[find_data->current]); + if (ret < 0) { + gnutls_assert(); + goto fail; } - - find_data->current++; + ret = pkcs11_obj_import(class, find_data->p_list[find_data->current], &value, &id, &label, &info->tinfo); + if (ret < 0) { + gnutls_assert(); + goto fail; + } } - else { - _gnutls_debug_log("pk11: Skipped cert, missing attrs.\n"); - } + + find_data->current++; + } gnutls_free(cert_data); @@ -1423,7 +1520,7 @@ fail: gnutls_free( plist.key_ids); } for (i=0;icurrent;i++) { - gnutls_pkcs11_crt_deinit(find_data->p_list[i]); + gnutls_pkcs11_obj_deinit(find_data->p_list[i]); } find_data->current = 0; @@ -1431,11 +1528,11 @@ fail: } /** - * gnutls_pkcs11_crt_list_import_url: + * gnutls_pkcs11_obj_list_import_url: * @p_list: An uninitialized certificate list (may be NULL) * @n_list: initially should hold the maximum size of the list. Will contain the actual size. * @url: A PKCS 11 url identifying a set of certificates - * @flags: Attributes of type #gnutls_pkcs11_crt_attr_t that can be used to limit output + * @flags: Attributes of type #gnutls_pkcs11_obj_attr_t that can be used to limit output * * This function will initialize and set value to a certificate list * specified by a PKCS 11 URL. @@ -1443,7 +1540,7 @@ fail: * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a * negative error value. **/ -int gnutls_pkcs11_crt_list_import_url (gnutls_pkcs11_crt_t * p_list, unsigned int *n_list, const char* url, gnutls_pkcs11_crt_attr_t flags) +int gnutls_pkcs11_obj_list_import_url (gnutls_pkcs11_obj_t * p_list, unsigned int *n_list, const char* url, gnutls_pkcs11_obj_attr_t flags) { int ret; struct crt_find_data_st find_data; @@ -1464,7 +1561,7 @@ int gnutls_pkcs11_crt_list_import_url (gnutls_pkcs11_crt_t * p_list, unsigned in return ret; } - ret = _pkcs11_traverse_tokens(find_crts, &find_data, 0); + ret = _pkcs11_traverse_tokens(find_objs, &find_data, 0); if (ret < 0) { gnutls_assert(); return ret; @@ -1479,7 +1576,7 @@ int gnutls_pkcs11_crt_list_import_url (gnutls_pkcs11_crt_t * p_list, unsigned in * @url: A PKCS 11 url * * This function will import a PKCS 11 certificate directly from a token - * without involving the #gnutls_pkcs11_crt_t structure. This function will + * without involving the #gnutls_pkcs11_obj_t structure. This function will * fail if the certificate stored is not of X.509 type. * * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a @@ -1487,16 +1584,16 @@ int gnutls_pkcs11_crt_list_import_url (gnutls_pkcs11_crt_t * p_list, unsigned in **/ int gnutls_x509_crt_import_pkcs11_url( gnutls_x509_crt_t crt, const char* url) { - gnutls_pkcs11_crt_t pcrt; + gnutls_pkcs11_obj_t pcrt; int ret; - - ret = gnutls_pkcs11_crt_init ( &pcrt); + + ret = gnutls_pkcs11_obj_init ( &pcrt); if (ret < 0) { gnutls_assert(); return ret; } - ret = gnutls_pkcs11_crt_import_url (pcrt, url); + ret = gnutls_pkcs11_obj_import_url (pcrt, url); if (ret < 0) { gnutls_assert(); goto cleanup; @@ -1511,8 +1608,8 @@ int gnutls_x509_crt_import_pkcs11_url( gnutls_x509_crt_t crt, const char* url) ret = 0; cleanup: - gnutls_pkcs11_crt_deinit(pcrt); - + gnutls_pkcs11_obj_deinit(pcrt); + return ret; } @@ -1520,7 +1617,7 @@ cleanup: /** * gnutls_x509_crt_import_pkcs11: * @crt: A certificate of type #gnutls_x509_crt_t - * @pkcs11_crt: A PKCS 11 certificate + * @pkcs11_obj: A PKCS 11 object that contains a certificate * * This function will import a PKCS 11 certificate to a #gnutls_x509_crt_t * structure. @@ -1528,13 +1625,13 @@ cleanup: * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a * negative error value. **/ -int gnutls_x509_crt_import_pkcs11( gnutls_x509_crt_t crt, gnutls_pkcs11_crt_t pkcs11_crt) +int gnutls_x509_crt_import_pkcs11( gnutls_x509_crt_t crt, gnutls_pkcs11_obj_t pkcs11_crt) { return gnutls_x509_crt_import(crt, &pkcs11_crt->raw, GNUTLS_X509_FMT_DER); } int gnutls_x509_crt_list_import_pkcs11 (gnutls_x509_crt_t * certs, - unsigned int cert_max, gnutls_pkcs11_crt_t * const pkcs11_certs, + unsigned int cert_max, gnutls_pkcs11_obj_t * const pkcs11_certs, unsigned int flags) { int i, j; @@ -1640,3 +1737,21 @@ int gnutls_pkcs11_token_get_flags(const char* url, unsigned int *flags) } +const char* gnutls_pkcs11_type_get_name (gnutls_pkcs11_obj_type_t type) +{ + switch(type) { + case GNUTLS_PKCS11_OBJ_X509_CRT: + return "X.509 Certificate"; + case GNUTLS_PKCS11_OBJ_PUBKEY: + return "Public key"; + case GNUTLS_PKCS11_OBJ_PRIVKEY: + return "Private key"; + case GNUTLS_PKCS11_OBJ_SECRET_KEY: + return "Secret key"; + case GNUTLS_PKCS11_OBJ_DATA: + return "Data"; + case GNUTLS_PKCS11_OBJ_UNKNOWN: + default: + return "Unknown"; + } +} diff --git a/lib/pkcs11_int.h b/lib/pkcs11_int.h index c0708321f1..86cbba1ce4 100644 --- a/lib/pkcs11_int.h +++ b/lib/pkcs11_int.h @@ -29,6 +29,12 @@ struct pkcs11_url_info size_t certid_raw_size; }; +struct gnutls_pkcs11_obj_st { + gnutls_datum_t raw; + gnutls_pkcs11_obj_type_t type; + struct pkcs11_url_info info; +}; + /* thus function is called for every token in the traverse_tokens * function. Once everything is traversed it is called with NULL tinfo. * It should return 0 if found what it was looking for. @@ -38,7 +44,7 @@ typedef int (*find_func_t)(pakchois_session_t *pks, struct token_info* tinfo, vo int _pkcs11_traverse_tokens (find_func_t find_func, void* input, int leave_session); int pkcs11_url_to_info(const char* url, struct pkcs11_url_info* info); -int pkcs11_get_info(struct pkcs11_url_info *info, gnutls_pkcs11_cert_info_t itype, +int pkcs11_get_info(struct pkcs11_url_info *info, gnutls_pkcs11_obj_info_t itype, void* output, size_t* output_size); int pkcs11_login(pakchois_session_t *pks, struct token_info *info); @@ -48,4 +54,5 @@ extern void* token_data; void pkcs11_rescan_slots(void); int pkcs11_info_to_url(const struct pkcs11_url_info* info, char** url); + #endif diff --git a/lib/pkcs11_privkey.c b/lib/pkcs11_privkey.c index 665e3f76cf..2ead5ab8fb 100644 --- a/lib/pkcs11_privkey.c +++ b/lib/pkcs11_privkey.c @@ -112,7 +112,7 @@ int gnutls_pkcs11_privkey_get_pk_algorithm(gnutls_pkcs11_privkey_t key, unsigned * Returns: zero on success or a negative value on error. **/ int gnutls_pkcs11_privkey_get_info(gnutls_pkcs11_privkey_t pkey, - gnutls_pkcs11_cert_info_t itype, + gnutls_pkcs11_obj_info_t itype, void *output, size_t * output_size) { return pkcs11_get_info(&pkey->info, itype, output, output_size); diff --git a/lib/x509/common.c b/lib/x509/common.c index 58aefda57a..b3bea0e4d9 100644 --- a/lib/x509/common.c +++ b/lib/x509/common.c @@ -1138,6 +1138,18 @@ cleanup: return result; } +void _asnstr_append_name(char* name, size_t name_size, const char* part1, const char* part2) +{ + if (part1[0] != 0) + { + _gnutls_str_cpy (name, name_size, part1); + _gnutls_str_cat (name, name_size, part2); + } + else + _gnutls_str_cpy (name, name_size, part2+1 /* remove initial dot */); +} + + /* Encodes and copies the private key parameters into a * subjectPublicKeyInfo structure. * @@ -1163,8 +1175,8 @@ _gnutls_x509_encode_and_copy_PKI_params (ASN1_TYPE dst, /* write the OID */ - _gnutls_str_cpy (name, sizeof (name), dst_name); - _gnutls_str_cat (name, sizeof (name), ".algorithm.algorithm"); + _asnstr_append_name(name, sizeof(name), dst_name, ".algorithm.algorithm"); + result = asn1_write_value (dst, name, pk, 1); if (result != ASN1_SUCCESS) { @@ -1176,8 +1188,8 @@ _gnutls_x509_encode_and_copy_PKI_params (ASN1_TYPE dst, { /* disable parameters, which are not used in RSA. */ - _gnutls_str_cpy (name, sizeof (name), dst_name); - _gnutls_str_cat (name, sizeof (name), ".algorithm.parameters"); + _asnstr_append_name(name, sizeof(name), dst_name, ".algorithm.parameters"); + result = asn1_write_value (dst, name, NULL, 0); if (result != ASN1_SUCCESS) { @@ -1194,8 +1206,7 @@ _gnutls_x509_encode_and_copy_PKI_params (ASN1_TYPE dst, /* Write the DER parameters. (in bits) */ - _gnutls_str_cpy (name, sizeof (name), dst_name); - _gnutls_str_cat (name, sizeof (name), ".subjectPublicKey"); + _asnstr_append_name(name, sizeof(name), dst_name, ".subjectPublicKey"); result = asn1_write_value (dst, name, der.data, der.size * 8); _gnutls_free_datum (&der); @@ -1218,8 +1229,7 @@ _gnutls_x509_encode_and_copy_PKI_params (ASN1_TYPE dst, /* Write the DER parameters. */ - _gnutls_str_cpy (name, sizeof (name), dst_name); - _gnutls_str_cat (name, sizeof (name), ".algorithm.parameters"); + _asnstr_append_name(name, sizeof(name), dst_name, ".algorithm.parameters"); result = asn1_write_value (dst, name, der.data, der.size); _gnutls_free_datum (&der); @@ -1237,8 +1247,7 @@ _gnutls_x509_encode_and_copy_PKI_params (ASN1_TYPE dst, return result; } - _gnutls_str_cpy (name, sizeof (name), dst_name); - _gnutls_str_cat (name, sizeof (name), ".subjectPublicKey"); + _asnstr_append_name(name, sizeof(name), dst_name, ".subjectPublicKey"); result = asn1_write_value (dst, name, der.data, der.size * 8); _gnutls_free_datum (&der); @@ -1271,9 +1280,8 @@ _gnutls_x509_get_pk_algorithm (ASN1_TYPE src, const char *src_name, bigint_t params[MAX_PUBLIC_PARAMS_SIZE]; char name[128]; - _gnutls_str_cpy (name, sizeof (name), src_name); - _gnutls_str_cat (name, sizeof (name), ".algorithm.algorithm"); + _asnstr_append_name(name, sizeof(name), src_name, ".algorithm.algorithm"); len = sizeof (oid); result = asn1_read_value (src, name, oid, &len); @@ -1297,8 +1305,7 @@ _gnutls_x509_get_pk_algorithm (ASN1_TYPE src, const char *src_name, /* Now read the parameters' bits */ - _gnutls_str_cpy (name, sizeof (name), src_name); - _gnutls_str_cat (name, sizeof (name), ".subjectPublicKey"); + _asnstr_append_name(name, sizeof(name), src_name, ".subjectPublicKey"); len = 0; result = asn1_read_value (src, name, NULL, &len); @@ -1323,8 +1330,7 @@ _gnutls_x509_get_pk_algorithm (ASN1_TYPE src, const char *src_name, return GNUTLS_E_MEMORY_ERROR; } - _gnutls_str_cpy (name, sizeof (name), src_name); - _gnutls_str_cat (name, sizeof (name), ".subjectPublicKey"); + _asnstr_append_name(name, sizeof(name), src_name, ".subjectPublicKey"); result = asn1_read_value (src, name, str, &len); diff --git a/lib/x509/common.h b/lib/x509/common.h index e52e32c115..aba51b99c2 100644 --- a/lib/x509/common.h +++ b/lib/x509/common.h @@ -131,4 +131,12 @@ int _gnutls_x509_get_signature (ASN1_TYPE src, const char *src_name, gnutls_digest_algorithm_t _gnutls_dsa_q_to_hash(bigint_t q); +int _gnutls_get_asn_mpis (ASN1_TYPE asn, const char *root, + bigint_t * params, int *params_size); + +int _gnutls_get_key_id (gnutls_pk_algorithm_t pk, bigint_t* params, int params_size, + unsigned char *output_data, size_t * output_data_size); + +void _asnstr_append_name(char* name, size_t name_size, const char* part1, const char* part2); + #endif diff --git a/lib/x509/mpi.c b/lib/x509/mpi.c index 7b4e7d4596..62f581f740 100644 --- a/lib/x509/mpi.c +++ b/lib/x509/mpi.c @@ -206,23 +206,32 @@ _gnutls_x509_read_dsa_pubkey (opaque * der, int dersize, bigint_t * params) /* Extracts DSA and RSA parameters from a certificate. */ -static int -get_mpis (int pk_algorithm, ASN1_TYPE asn, const char *root, +int +_gnutls_get_asn_mpis (ASN1_TYPE asn, const char *root, bigint_t * params, int *params_size) { int result; char name[256]; gnutls_datum_t tmp = { NULL, 0 }; + gnutls_pk_algorithm pk_algorithm; + + result = _gnutls_x509_get_pk_algorithm(asn, root, NULL); + if (result < 0) + { + gnutls_assert(); + return result; + } + + pk_algorithm = result; /* Read the algorithm's parameters */ - snprintf (name, sizeof (name), "%s.subjectPublicKey", root); + _asnstr_append_name(name, sizeof(name), root, ".subjectPublicKey"); result = _gnutls_x509_read_value (asn, name, &tmp, 2); if (result < 0) { gnutls_assert (); - fprintf (stderr, "name: %s\n", name); return result; } @@ -275,7 +284,7 @@ get_mpis (int pk_algorithm, ASN1_TYPE asn, const char *root, */ _gnutls_free_datum (&tmp); - snprintf (name, sizeof (name), "%s.algorithm.parameters", root); + _asnstr_append_name(name, sizeof(name), root, ".algorithm.parameters"); result = _gnutls_x509_read_value (asn, name, &tmp, 0); /* FIXME: If the parameters are not included in the certificate @@ -321,13 +330,9 @@ int _gnutls_x509_crt_get_mpis (gnutls_x509_crt_t cert, bigint_t * params, int *params_size) { - int pk_algorithm; - /* Read the algorithm's OID */ - pk_algorithm = gnutls_x509_crt_get_pk_algorithm (cert, NULL); - - return get_mpis (pk_algorithm, cert->cert, + return _gnutls_get_asn_mpis (cert->cert, "tbsCertificate.subjectPublicKeyInfo", params, params_size); } @@ -340,13 +345,9 @@ int _gnutls_x509_crq_get_mpis (gnutls_x509_crq_t cert, bigint_t * params, int *params_size) { - int pk_algorithm; - /* Read the algorithm's OID */ - pk_algorithm = gnutls_x509_crq_get_pk_algorithm (cert, NULL); - - return get_mpis (pk_algorithm, cert->crq, + return _gnutls_get_asn_mpis (cert->crq, "certificationRequestInfo.subjectPKInfo", params, params_size); } diff --git a/lib/x509/x509.c b/lib/x509/x509.c index 94a8b81b48..9c22ada3f0 100644 --- a/lib/x509/x509.c +++ b/lib/x509/x509.c @@ -2184,22 +2184,19 @@ gnutls_x509_crt_export (gnutls_x509_crt_t cert, output_data, output_data_size); } - -static int -rsadsa_get_key_id (gnutls_x509_crt_t crt, int pk, +int +_gnutls_get_key_id (gnutls_pk_algorithm_t pk, bigint_t* params, int params_size, unsigned char *output_data, size_t * output_data_size) { - bigint_t params[MAX_PUBLIC_PARAMS_SIZE]; - int params_size = MAX_PUBLIC_PARAMS_SIZE; int i, result = 0; gnutls_datum_t der = { NULL, 0 }; digest_hd_st hd; - result = _gnutls_x509_crt_get_mpis (crt, params, ¶ms_size); - if (result < 0) + if (output_data==NULL || *output_data_size < 0) { - gnutls_assert (); - return result; + gnutls_assert(); + *output_data_size = 20; + return GNUTLS_E_SHORT_MEMORY_BUFFER; } if (pk == GNUTLS_PK_RSA) @@ -2240,6 +2237,37 @@ rsadsa_get_key_id (gnutls_x509_crt_t crt, int pk, cleanup: _gnutls_free_datum (&der); + return result; +} + + +static int +rsadsa_get_key_id (gnutls_x509_crt_t crt, int pk, + unsigned char *output_data, size_t * output_data_size) +{ + bigint_t params[MAX_PUBLIC_PARAMS_SIZE]; + int params_size = MAX_PUBLIC_PARAMS_SIZE; + int i, result = 0; + gnutls_datum_t der = { NULL, 0 }; + digest_hd_st hd; + + result = _gnutls_x509_crt_get_mpis (crt, params, ¶ms_size); + if (result < 0) + { + gnutls_assert (); + return result; + } + + result = _gnutls_get_key_id(pk, params, params_size, output_data, output_data_size); + if (result < 0) + { + gnutls_assert (); + goto cleanup; + } + + result = 0; + +cleanup: /* release all allocated MPIs */ @@ -2308,6 +2336,9 @@ gnutls_x509_crt_get_key_id (gnutls_x509_crt_t crt, unsigned int flags, return rsadsa_get_key_id (crt, pk, output_data, output_data_size); } + /* FIXME: what does this code do here? Isn't identical to the code + * in rsadsa_get_key_id? + */ pubkey.size = 0; result = asn1_der_coding (crt->cert, "tbsCertificate.subjectPublicKeyInfo", NULL, &pubkey.size, NULL); diff --git a/lib/x509/x509_int.h b/lib/x509/x509_int.h index ea68d59d23..0ad3f6b284 100644 --- a/lib/x509/x509_int.h +++ b/lib/x509/x509_int.h @@ -303,6 +303,8 @@ int _gnutls_x509_write_uint32 (ASN1_TYPE node, const char *value, int _gnutls_x509_write_sig_params (ASN1_TYPE dst, const char *dst_name, gnutls_pk_algorithm_t pk_algorithm, gnutls_digest_algorithm_t); + + /* pkcs12.h */ #include diff --git a/src/certtool-common.h b/src/certtool-common.h index ae6891e9ab..f5db0abd80 100644 --- a/src/certtool-common.h +++ b/src/certtool-common.h @@ -29,6 +29,7 @@ enum ACTION_PKCS11_LIST, ACTION_PKCS11_TOKENS, ACTION_PKCS11_EXPORT_URL, + ACTION_PUBKEY_INFO, }; #define TYPE_CRT 1 @@ -39,9 +40,10 @@ void pkcs11_list( FILE*outfile, const char* url, int type); void pkcs11_export(FILE* outfile, const char *pkcs11_url); void pkcs11_token_list(FILE* outfile); -#define PKCS11_TYPE_ALL 1 +#define PKCS11_TYPE_CRT_ALL 1 #define PKCS11_TYPE_TRUSTED 2 #define PKCS11_TYPE_PK 3 +#define PKCS11_TYPE_ALL 4 extern unsigned char buffer[]; extern const int buffer_size; diff --git a/src/certtool-gaa.c b/src/certtool-gaa.c index 7af11a5f59..7ccd9e1544 100644 --- a/src/certtool-gaa.c +++ b/src/certtool-gaa.c @@ -141,6 +141,7 @@ void gaa_help(void) __gaa_helpsingle(0, "generate-dh-params", "", "Generate PKCS #3 encoded Diffie-Hellman parameters."); __gaa_helpsingle(0, "get-dh-params", "", "Get the included PKCS #3 encoded Diffie-Hellman parameters."); __gaa_helpsingle(0, "load-privkey", "FILE ", "Private key file to use."); + __gaa_helpsingle(0, "load-pubkey", "FILE ", "Private key file to use."); __gaa_helpsingle(0, "load-request", "FILE ", "Certificate request file to use."); __gaa_helpsingle(0, "load-certificate", "FILE ", "Certificate file to use."); __gaa_helpsingle(0, "load-ca-privkey", "FILE ", "Certificate authority's private key file to use."); @@ -157,6 +158,7 @@ void gaa_help(void) __gaa_helpsingle(0, "smime-to-p7", "", "Convert S/MIME to PKCS #7 structure."); __gaa_helpsingle('k', "key-info", "", "Print information on a private key."); __gaa_helpsingle(0, "pgp-key-info", "", "Print information on a OpenPGP private key."); + __gaa_helpsingle(0, "pubkey-info", "", "Print information on a public key."); __gaa_helpsingle(0, "fix-key", "", "Regenerate the parameters in a private key."); __gaa_helpsingle(0, "v1", "", "Generate an X.509 version 1 certificate (no extensions)."); __gaa_helpsingle(0, "to-p12", "", "Generate a PKCS #12 structure."); @@ -177,8 +179,9 @@ void gaa_help(void) __gaa_helpsingle(0, "pkcs-cipher", "CIPHER ", "Cipher to use for pkcs operations (3des,aes-128,aes-192,aes-256,rc2-40)."); __gaa_helpsingle(0, "pkcs11-provider", "Library ", "Specify the pkcs11 provider library"); __gaa_helpsingle(0, "pkcs11-export-url", "URL ", "Export data specified a pkcs11 URL"); - __gaa_helpsingle(0, "pkcs11-list", "", "List objects specified by a PKCS#11 URL"); - __gaa_helpsingle(0, "pkcs11-list-trusted", "", "List objects marked as trusted, specified by a PKCS#11 URL"); + __gaa_helpsingle(0, "pkcs11-list-certs", "", "List certificates specified by a PKCS#11 URL"); + __gaa_helpsingle(0, "pkcs11-list-trusted", "", "List certificates marked as trusted, specified by a PKCS#11 URL"); + __gaa_helpsingle(0, "pkcs11-list-all-certs", "", "List all certificates specified by a PKCS#11 URL"); __gaa_helpsingle(0, "pkcs11-list-all", "", "List all objects specified by a PKCS#11 URL"); __gaa_helpsingle(0, "pkcs11-list-tokens", "", "List all available tokens"); __gaa_helpsingle('d', "debug", "LEVEL ", "specify the debug level. Default is 1."); @@ -198,54 +201,56 @@ typedef struct _gaainfo gaainfo; struct _gaainfo { -#line 143 "certtool.gaa" +#line 149 "certtool.gaa" int debug; -#line 137 "certtool.gaa" +#line 142 "certtool.gaa" int pkcs11_type; -#line 134 "certtool.gaa" +#line 139 "certtool.gaa" char* pkcs11_url; -#line 131 "certtool.gaa" +#line 136 "certtool.gaa" char* pkcs11_provider; -#line 128 "certtool.gaa" +#line 133 "certtool.gaa" char *pkcs_cipher; -#line 125 "certtool.gaa" +#line 130 "certtool.gaa" char *template; -#line 122 "certtool.gaa" +#line 127 "certtool.gaa" char *infile; -#line 119 "certtool.gaa" +#line 124 "certtool.gaa" char *outfile; -#line 116 "certtool.gaa" +#line 121 "certtool.gaa" int quick_random; -#line 113 "certtool.gaa" +#line 118 "certtool.gaa" int bits; -#line 109 "certtool.gaa" +#line 114 "certtool.gaa" int outcert_format; -#line 105 "certtool.gaa" +#line 110 "certtool.gaa" int incert_format; -#line 102 "certtool.gaa" +#line 107 "certtool.gaa" int export; -#line 99 "certtool.gaa" +#line 104 "certtool.gaa" char *hash; -#line 96 "certtool.gaa" +#line 101 "certtool.gaa" int dsa; -#line 93 "certtool.gaa" +#line 98 "certtool.gaa" int pkcs8; -#line 85 "certtool.gaa" +#line 90 "certtool.gaa" int v1_cert; -#line 82 "certtool.gaa" +#line 87 "certtool.gaa" int fix_key; -#line 67 "certtool.gaa" +#line 70 "certtool.gaa" int crq_extensions; -#line 54 "certtool.gaa" +#line 57 "certtool.gaa" char *pass; -#line 51 "certtool.gaa" +#line 54 "certtool.gaa" char *ca; -#line 48 "certtool.gaa" +#line 51 "certtool.gaa" char *ca_privkey; -#line 45 "certtool.gaa" +#line 48 "certtool.gaa" char *cert; -#line 42 "certtool.gaa" +#line 45 "certtool.gaa" char *request; +#line 42 "certtool.gaa" + char *pubkey; #line 39 "certtool.gaa" char *privkey; #line 17 "certtool.gaa" @@ -306,62 +311,65 @@ static int gaa_error = 0; #define GAA_MULTIPLE_OPTION 3 #define GAA_REST 0 -#define GAA_NB_OPTION 55 +#define GAA_NB_OPTION 58 #define GAAOPTID_version 1 #define GAAOPTID_help 2 #define GAAOPTID_debug 3 #define GAAOPTID_pkcs11_list_tokens 4 #define GAAOPTID_pkcs11_list_all 5 -#define GAAOPTID_pkcs11_list_trusted 6 -#define GAAOPTID_pkcs11_list 7 -#define GAAOPTID_pkcs11_export_url 8 -#define GAAOPTID_pkcs11_provider 9 -#define GAAOPTID_pkcs_cipher 10 -#define GAAOPTID_template 11 -#define GAAOPTID_infile 12 -#define GAAOPTID_outfile 13 -#define GAAOPTID_disable_quick_random 14 -#define GAAOPTID_bits 15 -#define GAAOPTID_outraw 16 -#define GAAOPTID_outder 17 -#define GAAOPTID_inraw 18 -#define GAAOPTID_inder 19 -#define GAAOPTID_export_ciphers 20 -#define GAAOPTID_hash 21 -#define GAAOPTID_dsa 22 -#define GAAOPTID_pkcs8 23 -#define GAAOPTID_to_p8 24 -#define GAAOPTID_to_p12 25 -#define GAAOPTID_v1 26 -#define GAAOPTID_fix_key 27 -#define GAAOPTID_pgp_key_info 28 -#define GAAOPTID_key_info 29 -#define GAAOPTID_smime_to_p7 30 -#define GAAOPTID_p7_info 31 -#define GAAOPTID_p12_info 32 -#define GAAOPTID_no_crq_extensions 33 -#define GAAOPTID_crq_info 34 -#define GAAOPTID_crl_info 35 -#define GAAOPTID_pgp_ring_info 36 -#define GAAOPTID_pgp_certificate_info 37 -#define GAAOPTID_certificate_info 38 -#define GAAOPTID_password 39 -#define GAAOPTID_load_ca_certificate 40 -#define GAAOPTID_load_ca_privkey 41 -#define GAAOPTID_load_certificate 42 -#define GAAOPTID_load_request 43 -#define GAAOPTID_load_privkey 44 -#define GAAOPTID_get_dh_params 45 -#define GAAOPTID_generate_dh_params 46 -#define GAAOPTID_verify_crl 47 -#define GAAOPTID_verify_chain 48 -#define GAAOPTID_generate_request 49 -#define GAAOPTID_generate_privkey 50 -#define GAAOPTID_update_certificate 51 -#define GAAOPTID_generate_crl 52 -#define GAAOPTID_generate_proxy 53 -#define GAAOPTID_generate_certificate 54 -#define GAAOPTID_generate_self_signed 55 +#define GAAOPTID_pkcs11_list_all_certs 6 +#define GAAOPTID_pkcs11_list_trusted 7 +#define GAAOPTID_pkcs11_list_certs 8 +#define GAAOPTID_pkcs11_export_url 9 +#define GAAOPTID_pkcs11_provider 10 +#define GAAOPTID_pkcs_cipher 11 +#define GAAOPTID_template 12 +#define GAAOPTID_infile 13 +#define GAAOPTID_outfile 14 +#define GAAOPTID_disable_quick_random 15 +#define GAAOPTID_bits 16 +#define GAAOPTID_outraw 17 +#define GAAOPTID_outder 18 +#define GAAOPTID_inraw 19 +#define GAAOPTID_inder 20 +#define GAAOPTID_export_ciphers 21 +#define GAAOPTID_hash 22 +#define GAAOPTID_dsa 23 +#define GAAOPTID_pkcs8 24 +#define GAAOPTID_to_p8 25 +#define GAAOPTID_to_p12 26 +#define GAAOPTID_v1 27 +#define GAAOPTID_fix_key 28 +#define GAAOPTID_pubkey_info 29 +#define GAAOPTID_pgp_key_info 30 +#define GAAOPTID_key_info 31 +#define GAAOPTID_smime_to_p7 32 +#define GAAOPTID_p7_info 33 +#define GAAOPTID_p12_info 34 +#define GAAOPTID_no_crq_extensions 35 +#define GAAOPTID_crq_info 36 +#define GAAOPTID_crl_info 37 +#define GAAOPTID_pgp_ring_info 38 +#define GAAOPTID_pgp_certificate_info 39 +#define GAAOPTID_certificate_info 40 +#define GAAOPTID_password 41 +#define GAAOPTID_load_ca_certificate 42 +#define GAAOPTID_load_ca_privkey 43 +#define GAAOPTID_load_certificate 44 +#define GAAOPTID_load_request 45 +#define GAAOPTID_load_pubkey 46 +#define GAAOPTID_load_privkey 47 +#define GAAOPTID_get_dh_params 48 +#define GAAOPTID_generate_dh_params 49 +#define GAAOPTID_verify_crl 50 +#define GAAOPTID_verify_chain 51 +#define GAAOPTID_generate_request 52 +#define GAAOPTID_generate_privkey 53 +#define GAAOPTID_update_certificate 54 +#define GAAOPTID_generate_crl 55 +#define GAAOPTID_generate_proxy 56 +#define GAAOPTID_generate_certificate 57 +#define GAAOPTID_generate_self_signed 58 #line 168 "gaa.skel" @@ -632,6 +640,12 @@ struct GAAOPTION_load_request int size1; }; +struct GAAOPTION_load_pubkey +{ + char* arg1; + int size1; +}; + struct GAAOPTION_load_privkey { char* arg1; @@ -681,6 +695,7 @@ static int gaa_get_option_num(char *str, int status) GAA_CHECK1STR("", GAAOPTID_load_ca_privkey); GAA_CHECK1STR("", GAAOPTID_load_certificate); GAA_CHECK1STR("", GAAOPTID_load_request); + GAA_CHECK1STR("", GAAOPTID_load_pubkey); GAA_CHECK1STR("", GAAOPTID_load_privkey); case GAA_MULTIPLE_OPTION: #line 375 "gaa.skel" @@ -688,8 +703,9 @@ static int gaa_get_option_num(char *str, int status) GAA_CHECK1STR("h", GAAOPTID_help); GAA_CHECK1STR("", GAAOPTID_pkcs11_list_tokens); GAA_CHECK1STR("", GAAOPTID_pkcs11_list_all); + GAA_CHECK1STR("", GAAOPTID_pkcs11_list_all_certs); GAA_CHECK1STR("", GAAOPTID_pkcs11_list_trusted); - GAA_CHECK1STR("", GAAOPTID_pkcs11_list); + GAA_CHECK1STR("", GAAOPTID_pkcs11_list_certs); GAA_CHECK1STR("", GAAOPTID_disable_quick_random); GAA_CHECK1STR("", GAAOPTID_outraw); GAA_CHECK1STR("", GAAOPTID_outder); @@ -702,6 +718,7 @@ static int gaa_get_option_num(char *str, int status) GAA_CHECK1STR("", GAAOPTID_to_p12); GAA_CHECK1STR("", GAAOPTID_v1); GAA_CHECK1STR("", GAAOPTID_fix_key); + GAA_CHECK1STR("", GAAOPTID_pubkey_info); GAA_CHECK1STR("", GAAOPTID_pgp_key_info); GAA_CHECK1STR("k", GAAOPTID_key_info); GAA_CHECK1STR("", GAAOPTID_smime_to_p7); @@ -733,8 +750,9 @@ static int gaa_get_option_num(char *str, int status) GAA_CHECKSTR("debug", GAAOPTID_debug); GAA_CHECKSTR("pkcs11-list-tokens", GAAOPTID_pkcs11_list_tokens); GAA_CHECKSTR("pkcs11-list-all", GAAOPTID_pkcs11_list_all); + GAA_CHECKSTR("pkcs11-list-all-certs", GAAOPTID_pkcs11_list_all_certs); GAA_CHECKSTR("pkcs11-list-trusted", GAAOPTID_pkcs11_list_trusted); - GAA_CHECKSTR("pkcs11-list", GAAOPTID_pkcs11_list); + GAA_CHECKSTR("pkcs11-list-certs", GAAOPTID_pkcs11_list_certs); GAA_CHECKSTR("pkcs11-export-url", GAAOPTID_pkcs11_export_url); GAA_CHECKSTR("pkcs11-provider", GAAOPTID_pkcs11_provider); GAA_CHECKSTR("pkcs-cipher", GAAOPTID_pkcs_cipher); @@ -755,6 +773,7 @@ static int gaa_get_option_num(char *str, int status) GAA_CHECKSTR("to-p12", GAAOPTID_to_p12); GAA_CHECKSTR("v1", GAAOPTID_v1); GAA_CHECKSTR("fix-key", GAAOPTID_fix_key); + GAA_CHECKSTR("pubkey-info", GAAOPTID_pubkey_info); GAA_CHECKSTR("pgp-key-info", GAAOPTID_pgp_key_info); GAA_CHECKSTR("key-info", GAAOPTID_key_info); GAA_CHECKSTR("smime-to-p7", GAAOPTID_smime_to_p7); @@ -771,6 +790,7 @@ static int gaa_get_option_num(char *str, int status) GAA_CHECKSTR("load-ca-privkey", GAAOPTID_load_ca_privkey); GAA_CHECKSTR("load-certificate", GAAOPTID_load_certificate); GAA_CHECKSTR("load-request", GAAOPTID_load_request); + GAA_CHECKSTR("load-pubkey", GAAOPTID_load_pubkey); GAA_CHECKSTR("load-privkey", GAAOPTID_load_privkey); GAA_CHECKSTR("get-dh-params", GAAOPTID_get_dh_params); GAA_CHECKSTR("generate-dh-params", GAAOPTID_generate_dh_params); @@ -809,6 +829,7 @@ static int gaa_try(int gaa_num, int gaa_index, gaainfo *gaaval, char *opt_list) struct GAAOPTION_load_ca_privkey GAATMP_load_ca_privkey; struct GAAOPTION_load_certificate GAATMP_load_certificate; struct GAAOPTION_load_request GAATMP_load_request; + struct GAAOPTION_load_pubkey GAATMP_load_pubkey; struct GAAOPTION_load_privkey GAATMP_load_privkey; #line 393 "gaa.skel" @@ -832,14 +853,14 @@ static int gaa_try(int gaa_num, int gaa_index, gaainfo *gaaval, char *opt_list) { case GAAOPTID_version: OK = 0; -#line 148 "certtool.gaa" +#line 154 "certtool.gaa" { certtool_version(); exit(0); ;}; return GAA_OK; break; case GAAOPTID_help: OK = 0; -#line 146 "certtool.gaa" +#line 152 "certtool.gaa" { gaa_help(); exit(0); ;}; return GAA_OK; @@ -849,35 +870,42 @@ static int gaa_try(int gaa_num, int gaa_index, gaainfo *gaaval, char *opt_list) GAA_TESTMOREARGS; GAA_FILL(GAATMP_debug.arg1, gaa_getint, GAATMP_debug.size1); gaa_index++; -#line 144 "certtool.gaa" +#line 150 "certtool.gaa" { gaaval->debug = GAATMP_debug.arg1 ;}; return GAA_OK; break; case GAAOPTID_pkcs11_list_tokens: OK = 0; -#line 141 "certtool.gaa" +#line 147 "certtool.gaa" { gaaval->action = ACTION_PKCS11_TOKENS; ;}; return GAA_OK; break; case GAAOPTID_pkcs11_list_all: OK = 0; -#line 140 "certtool.gaa" +#line 146 "certtool.gaa" { gaaval->action = ACTION_PKCS11_LIST; gaaval->pkcs11_type=PKCS11_TYPE_ALL; ;}; + return GAA_OK; + break; + case GAAOPTID_pkcs11_list_all_certs: + OK = 0; +#line 145 "certtool.gaa" +{ gaaval->action = ACTION_PKCS11_LIST; gaaval->pkcs11_type=PKCS11_TYPE_CRT_ALL; ;}; + return GAA_OK; break; case GAAOPTID_pkcs11_list_trusted: OK = 0; -#line 139 "certtool.gaa" +#line 144 "certtool.gaa" { gaaval->action = ACTION_PKCS11_LIST; gaaval->pkcs11_type=PKCS11_TYPE_TRUSTED; ;}; return GAA_OK; break; - case GAAOPTID_pkcs11_list: + case GAAOPTID_pkcs11_list_certs: OK = 0; -#line 138 "certtool.gaa" +#line 143 "certtool.gaa" { gaaval->action = ACTION_PKCS11_LIST; gaaval->pkcs11_type=PKCS11_TYPE_PK; ;}; return GAA_OK; @@ -887,7 +915,7 @@ static int gaa_try(int gaa_num, int gaa_index, gaainfo *gaaval, char *opt_list) GAA_TESTMOREARGS; GAA_FILL(GAATMP_pkcs11_export_url.arg1, gaa_getstr, GAATMP_pkcs11_export_url.size1); gaa_index++; -#line 135 "certtool.gaa" +#line 140 "certtool.gaa" { gaaval->action = ACTION_PKCS11_EXPORT_URL; gaaval->pkcs11_url = GAATMP_pkcs11_export_url.arg1; ;}; return GAA_OK; @@ -897,7 +925,7 @@ static int gaa_try(int gaa_num, int gaa_index, gaainfo *gaaval, char *opt_list) GAA_TESTMOREARGS; GAA_FILL(GAATMP_pkcs11_provider.arg1, gaa_getstr, GAATMP_pkcs11_provider.size1); gaa_index++; -#line 132 "certtool.gaa" +#line 137 "certtool.gaa" { gaaval->pkcs11_provider = GAATMP_pkcs11_provider.arg1 ;}; return GAA_OK; @@ -907,7 +935,7 @@ static int gaa_try(int gaa_num, int gaa_index, gaainfo *gaaval, char *opt_list) GAA_TESTMOREARGS; GAA_FILL(GAATMP_pkcs_cipher.arg1, gaa_getstr, GAATMP_pkcs_cipher.size1); gaa_index++; -#line 129 "certtool.gaa" +#line 134 "certtool.gaa" { gaaval->pkcs_cipher = GAATMP_pkcs_cipher.arg1 ;}; return GAA_OK; @@ -917,7 +945,7 @@ static int gaa_try(int gaa_num, int gaa_index, gaainfo *gaaval, char *opt_list) GAA_TESTMOREARGS; GAA_FILL(GAATMP_template.arg1, gaa_getstr, GAATMP_template.size1); gaa_index++; -#line 126 "certtool.gaa" +#line 131 "certtool.gaa" { gaaval->template = GAATMP_template.arg1 ;}; return GAA_OK; @@ -927,7 +955,7 @@ static int gaa_try(int gaa_num, int gaa_index, gaainfo *gaaval, char *opt_list) GAA_TESTMOREARGS; GAA_FILL(GAATMP_infile.arg1, gaa_getstr, GAATMP_infile.size1); gaa_index++; -#line 123 "certtool.gaa" +#line 128 "certtool.gaa" { gaaval->infile = GAATMP_infile.arg1 ;}; return GAA_OK; @@ -937,14 +965,14 @@ static int gaa_try(int gaa_num, int gaa_index, gaainfo *gaaval, char *opt_list) GAA_TESTMOREARGS; GAA_FILL(GAATMP_outfile.arg1, gaa_getstr, GAATMP_outfile.size1); gaa_index++; -#line 120 "certtool.gaa" +#line 125 "certtool.gaa" { gaaval->outfile = GAATMP_outfile.arg1 ;}; return GAA_OK; break; case GAAOPTID_disable_quick_random: OK = 0; -#line 117 "certtool.gaa" +#line 122 "certtool.gaa" { gaaval->quick_random = 0; ;}; return GAA_OK; @@ -954,42 +982,42 @@ static int gaa_try(int gaa_num, int gaa_index, gaainfo *gaaval, char *opt_list) GAA_TESTMOREARGS; GAA_FILL(GAATMP_bits.arg1, gaa_getint, GAATMP_bits.size1); gaa_index++; -#line 114 "certtool.gaa" +#line 119 "certtool.gaa" { gaaval->bits = GAATMP_bits.arg1 ;}; return GAA_OK; break; case GAAOPTID_outraw: OK = 0; -#line 111 "certtool.gaa" +#line 116 "certtool.gaa" { gaaval->outcert_format=1 ;}; return GAA_OK; break; case GAAOPTID_outder: OK = 0; -#line 110 "certtool.gaa" +#line 115 "certtool.gaa" { gaaval->outcert_format=1 ;}; return GAA_OK; break; case GAAOPTID_inraw: OK = 0; -#line 107 "certtool.gaa" +#line 112 "certtool.gaa" { gaaval->incert_format=1 ;}; return GAA_OK; break; case GAAOPTID_inder: OK = 0; -#line 106 "certtool.gaa" +#line 111 "certtool.gaa" { gaaval->incert_format=1 ;}; return GAA_OK; break; case GAAOPTID_export_ciphers: OK = 0; -#line 103 "certtool.gaa" +#line 108 "certtool.gaa" { gaaval->export=1 ;}; return GAA_OK; @@ -999,126 +1027,133 @@ static int gaa_try(int gaa_num, int gaa_index, gaainfo *gaaval, char *opt_list) GAA_TESTMOREARGS; GAA_FILL(GAATMP_hash.arg1, gaa_getstr, GAATMP_hash.size1); gaa_index++; -#line 100 "certtool.gaa" +#line 105 "certtool.gaa" { gaaval->hash = GAATMP_hash.arg1 ;}; return GAA_OK; break; case GAAOPTID_dsa: OK = 0; -#line 97 "certtool.gaa" +#line 102 "certtool.gaa" { gaaval->dsa=1 ;}; return GAA_OK; break; case GAAOPTID_pkcs8: OK = 0; -#line 94 "certtool.gaa" +#line 99 "certtool.gaa" { gaaval->pkcs8=1 ;}; return GAA_OK; break; case GAAOPTID_to_p8: OK = 0; -#line 90 "certtool.gaa" +#line 95 "certtool.gaa" { gaaval->action = ACTION_GENERATE_PKCS8; ;}; return GAA_OK; break; case GAAOPTID_to_p12: OK = 0; -#line 88 "certtool.gaa" +#line 93 "certtool.gaa" { gaaval->action = ACTION_TO_PKCS12; ;}; return GAA_OK; break; case GAAOPTID_v1: OK = 0; -#line 86 "certtool.gaa" +#line 91 "certtool.gaa" { gaaval->v1_cert = 1; ;}; return GAA_OK; break; case GAAOPTID_fix_key: OK = 0; -#line 83 "certtool.gaa" +#line 88 "certtool.gaa" { gaaval->privkey_op=1; gaaval->fix_key = 1; ;}; + return GAA_OK; + break; + case GAAOPTID_pubkey_info: + OK = 0; +#line 85 "certtool.gaa" +{ gaaval->action = ACTION_PUBKEY_INFO; ;}; + return GAA_OK; break; case GAAOPTID_pgp_key_info: OK = 0; -#line 80 "certtool.gaa" +#line 83 "certtool.gaa" { gaaval->privkey_op=1; gaaval->action = ACTION_PGP_PRIVKEY_INFO; ;}; return GAA_OK; break; case GAAOPTID_key_info: OK = 0; -#line 78 "certtool.gaa" +#line 81 "certtool.gaa" { gaaval->privkey_op=1; gaaval->action = ACTION_PRIVKEY_INFO; ;}; return GAA_OK; break; case GAAOPTID_smime_to_p7: OK = 0; -#line 74 "certtool.gaa" +#line 77 "certtool.gaa" { gaaval->action = ACTION_SMIME_TO_P7; ;}; return GAA_OK; break; case GAAOPTID_p7_info: OK = 0; -#line 72 "certtool.gaa" +#line 75 "certtool.gaa" { gaaval->action = ACTION_P7_INFO; ;}; return GAA_OK; break; case GAAOPTID_p12_info: OK = 0; -#line 70 "certtool.gaa" +#line 73 "certtool.gaa" { gaaval->action = ACTION_PKCS12_INFO; ;}; return GAA_OK; break; case GAAOPTID_no_crq_extensions: OK = 0; -#line 68 "certtool.gaa" +#line 71 "certtool.gaa" { gaaval->crq_extensions = 0; ;}; return GAA_OK; break; case GAAOPTID_crq_info: OK = 0; -#line 65 "certtool.gaa" +#line 68 "certtool.gaa" { gaaval->action = ACTION_REQUEST; ;}; return GAA_OK; break; case GAAOPTID_crl_info: OK = 0; -#line 63 "certtool.gaa" +#line 66 "certtool.gaa" { gaaval->action = ACTION_CRL_INFO; ;}; return GAA_OK; break; case GAAOPTID_pgp_ring_info: OK = 0; -#line 61 "certtool.gaa" +#line 64 "certtool.gaa" { gaaval->action = ACTION_RING_INFO; ;}; return GAA_OK; break; case GAAOPTID_pgp_certificate_info: OK = 0; -#line 59 "certtool.gaa" +#line 62 "certtool.gaa" { gaaval->action = ACTION_PGP_INFO; ;}; return GAA_OK; break; case GAAOPTID_certificate_info: OK = 0; -#line 57 "certtool.gaa" +#line 60 "certtool.gaa" { gaaval->action = ACTION_CERT_INFO; ;}; return GAA_OK; @@ -1128,7 +1163,7 @@ static int gaa_try(int gaa_num, int gaa_index, gaainfo *gaaval, char *opt_list) GAA_TESTMOREARGS; GAA_FILL(GAATMP_password.arg1, gaa_getstr, GAATMP_password.size1); gaa_index++; -#line 55 "certtool.gaa" +#line 58 "certtool.gaa" { gaaval->pass = GAATMP_password.arg1 ;}; return GAA_OK; @@ -1138,7 +1173,7 @@ static int gaa_try(int gaa_num, int gaa_index, gaainfo *gaaval, char *opt_list) GAA_TESTMOREARGS; GAA_FILL(GAATMP_load_ca_certificate.arg1, gaa_getstr, GAATMP_load_ca_certificate.size1); gaa_index++; -#line 52 "certtool.gaa" +#line 55 "certtool.gaa" { gaaval->ca = GAATMP_load_ca_certificate.arg1 ;}; return GAA_OK; @@ -1148,7 +1183,7 @@ static int gaa_try(int gaa_num, int gaa_index, gaainfo *gaaval, char *opt_list) GAA_TESTMOREARGS; GAA_FILL(GAATMP_load_ca_privkey.arg1, gaa_getstr, GAATMP_load_ca_privkey.size1); gaa_index++; -#line 49 "certtool.gaa" +#line 52 "certtool.gaa" { gaaval->ca_privkey = GAATMP_load_ca_privkey.arg1 ;}; return GAA_OK; @@ -1158,7 +1193,7 @@ static int gaa_try(int gaa_num, int gaa_index, gaainfo *gaaval, char *opt_list) GAA_TESTMOREARGS; GAA_FILL(GAATMP_load_certificate.arg1, gaa_getstr, GAATMP_load_certificate.size1); gaa_index++; -#line 46 "certtool.gaa" +#line 49 "certtool.gaa" { gaaval->cert = GAATMP_load_certificate.arg1 ;}; return GAA_OK; @@ -1168,9 +1203,19 @@ static int gaa_try(int gaa_num, int gaa_index, gaainfo *gaaval, char *opt_list) GAA_TESTMOREARGS; GAA_FILL(GAATMP_load_request.arg1, gaa_getstr, GAATMP_load_request.size1); gaa_index++; -#line 43 "certtool.gaa" +#line 46 "certtool.gaa" { gaaval->request = GAATMP_load_request.arg1 ;}; + return GAA_OK; + break; + case GAAOPTID_load_pubkey: + OK = 0; + GAA_TESTMOREARGS; + GAA_FILL(GAATMP_load_pubkey.arg1, gaa_getstr, GAATMP_load_pubkey.size1); + gaa_index++; +#line 43 "certtool.gaa" +{ gaaval->pubkey = GAATMP_load_pubkey.arg1 ;}; + return GAA_OK; break; case GAAOPTID_load_privkey: @@ -1284,13 +1329,13 @@ int gaa(int argc, char **argv, gaainfo *gaaval) if(inited == 0) { -#line 150 "certtool.gaa" +#line 156 "certtool.gaa" { gaaval->bits = 2048; gaaval->pkcs8 = 0; gaaval->privkey = NULL; gaaval->ca=NULL; gaaval->ca_privkey = NULL; gaaval->debug=1; gaaval->request = NULL; gaaval->infile = NULL; gaaval->outfile = NULL; gaaval->cert = NULL; gaaval->incert_format = 0; gaaval->outcert_format = 0; gaaval->action=-1; gaaval->pass = NULL; gaaval->v1_cert = 0; gaaval->export = 0; gaaval->template = NULL; gaaval->hash=NULL; gaaval->fix_key = 0; gaaval->quick_random=1; gaaval->privkey_op = 0; gaaval->pkcs_cipher = "3des"; gaaval->crq_extensions=1; gaaval->pkcs11_provider= NULL; - gaaval->pkcs11_url = NULL; gaaval->pkcs11_type = PKCS11_TYPE_PK; ;}; + gaaval->pkcs11_url = NULL; gaaval->pkcs11_type = PKCS11_TYPE_PK; gaaval->pubkey=NULL; ;}; } inited = 1; diff --git a/src/certtool-gaa.h b/src/certtool-gaa.h index ded4286568..80b022a1bb 100644 --- a/src/certtool-gaa.h +++ b/src/certtool-gaa.h @@ -8,54 +8,56 @@ typedef struct _gaainfo gaainfo; struct _gaainfo { -#line 143 "certtool.gaa" +#line 149 "certtool.gaa" int debug; -#line 137 "certtool.gaa" +#line 142 "certtool.gaa" int pkcs11_type; -#line 134 "certtool.gaa" +#line 139 "certtool.gaa" char* pkcs11_url; -#line 131 "certtool.gaa" +#line 136 "certtool.gaa" char* pkcs11_provider; -#line 128 "certtool.gaa" +#line 133 "certtool.gaa" char *pkcs_cipher; -#line 125 "certtool.gaa" +#line 130 "certtool.gaa" char *template; -#line 122 "certtool.gaa" +#line 127 "certtool.gaa" char *infile; -#line 119 "certtool.gaa" +#line 124 "certtool.gaa" char *outfile; -#line 116 "certtool.gaa" +#line 121 "certtool.gaa" int quick_random; -#line 113 "certtool.gaa" +#line 118 "certtool.gaa" int bits; -#line 109 "certtool.gaa" +#line 114 "certtool.gaa" int outcert_format; -#line 105 "certtool.gaa" +#line 110 "certtool.gaa" int incert_format; -#line 102 "certtool.gaa" +#line 107 "certtool.gaa" int export; -#line 99 "certtool.gaa" +#line 104 "certtool.gaa" char *hash; -#line 96 "certtool.gaa" +#line 101 "certtool.gaa" int dsa; -#line 93 "certtool.gaa" +#line 98 "certtool.gaa" int pkcs8; -#line 85 "certtool.gaa" +#line 90 "certtool.gaa" int v1_cert; -#line 82 "certtool.gaa" +#line 87 "certtool.gaa" int fix_key; -#line 67 "certtool.gaa" +#line 70 "certtool.gaa" int crq_extensions; -#line 54 "certtool.gaa" +#line 57 "certtool.gaa" char *pass; -#line 51 "certtool.gaa" +#line 54 "certtool.gaa" char *ca; -#line 48 "certtool.gaa" +#line 51 "certtool.gaa" char *ca_privkey; -#line 45 "certtool.gaa" +#line 48 "certtool.gaa" char *cert; -#line 42 "certtool.gaa" +#line 45 "certtool.gaa" char *request; +#line 42 "certtool.gaa" + char *pubkey; #line 39 "certtool.gaa" char *privkey; #line 17 "certtool.gaa" diff --git a/src/certtool.c b/src/certtool.c index bdc8b0c652..075f19c840 100644 --- a/src/certtool.c +++ b/src/certtool.c @@ -26,6 +26,7 @@ #include #include #include +#include #include @@ -60,6 +61,7 @@ void generate_pkcs12 (void); void generate_pkcs8 (void); void verify_chain (void); void verify_crl (void); +void pubkey_info (void); void pgp_privkey_info (void); void pgp_ring_info (void); gnutls_x509_privkey_t load_private_key (int mand); @@ -67,6 +69,7 @@ gnutls_x509_crq_t load_request (void); gnutls_x509_privkey_t load_ca_private_key (void); gnutls_x509_crt_t load_ca_cert (void); gnutls_x509_crt_t load_cert (int mand); +gnutls_pubkey_t load_pubkey (int mand); void certificate_info (void); void pgp_certificate_info (void); void crl_info (void); @@ -133,8 +136,11 @@ static void print_dsa_pkey (gnutls_datum_t * x, gnutls_datum_t * y, gnutls_datum_t * p, gnutls_datum_t * q, gnutls_datum_t * g) { - fprintf (outfile, "private key:"); - print_hex_datum (x); + if (x) + { + fprintf (outfile, "private key:"); + print_hex_datum (x); + } fprintf (outfile, "public key:"); print_hex_datum (y); fprintf (outfile, "p:"); @@ -153,14 +159,17 @@ print_rsa_pkey (gnutls_datum_t * m, gnutls_datum_t * e, gnutls_datum_t * d, print_hex_datum (m); fprintf (outfile, "public exponent:"); print_hex_datum (e); - fprintf (outfile, "private exponent:"); - print_hex_datum (d); - fprintf (outfile, "prime1:"); - print_hex_datum (p); - fprintf (outfile, "prime2:"); - print_hex_datum (q); - fprintf (outfile, "coefficient:"); - print_hex_datum (u); + if (d) + { + fprintf (outfile, "private exponent:"); + print_hex_datum (d); + fprintf (outfile, "prime1:"); + print_hex_datum (p); + fprintf (outfile, "prime2:"); + print_hex_datum (q); + fprintf (outfile, "coefficient:"); + print_hex_datum (u); + } } static gnutls_x509_privkey_t @@ -971,6 +980,9 @@ gaa_parser (int argc, char **argv) case ACTION_PRIVKEY_INFO: privkey_info (); break; + case ACTION_PUBKEY_INFO: + pubkey_info (); + break; case ACTION_UPDATE_CERTIFICATE: update_signed_certificate (); break; @@ -1610,6 +1622,51 @@ privkey_info (void) gnutls_x509_privkey_deinit (key); } +/* Load a public key. + * @mand should be non zero if it is required to read a public key. + */ +gnutls_pubkey_t +load_pubkey (int mand) +{ + gnutls_pubkey_t key; + int ret; + gnutls_datum_t dat; + size_t size; + + if (!info.pubkey && !mand) + return NULL; + + if (info.pubkey == NULL) + error (EXIT_FAILURE, 0, "missing --load-pubkey"); + + ret = gnutls_pubkey_init (&key); + if (ret < 0) + error (EXIT_FAILURE, 0, "privkey_init: %s", gnutls_strerror (ret)); + + dat.data = read_binary_file (info.pubkey, &size); + dat.size = size; + + if (!dat.data) + error (EXIT_FAILURE, errno, "reading --load-pubkey: %s", info.pubkey); + + ret = gnutls_pubkey_import (key, &dat, info.incert_format); + + free (dat.data); + + if (ret == GNUTLS_E_BASE64_UNEXPECTED_HEADER_ERROR) + { + error (EXIT_FAILURE, 0, + "import error: could not find a valid PEM header; " + "check if your key has the PUBLIC KEY header"); + } + + if (ret < 0) + error (EXIT_FAILURE, 0, "importing --load-pubkey: %s: %s", + info.pubkey, gnutls_strerror (ret)); + + return key; +} + /* Load the private key. * @mand should be non zero if it is required to read a private key. @@ -2978,3 +3035,141 @@ certtool_version (void) version_etc (stdout, program_name, p, gnutls_check_version (NULL), "Nikos Mavrogiannopoulos", "Simon Josefsson", (char *) NULL); } + +static void print_key_usage(FILE* outfile, unsigned int usage) +{ + if (usage & GNUTLS_KEY_DIGITAL_SIGNATURE) { + fprintf(outfile, "\tDigital signature.\n"); + } + + if (usage & GNUTLS_KEY_NON_REPUDIATION) { + fprintf(outfile, "\tNon repudiation.\n"); + } + + if (usage & GNUTLS_KEY_KEY_ENCIPHERMENT) { + fprintf(outfile, "\tKey encipherment.\n"); + } + + if (usage & GNUTLS_KEY_DATA_ENCIPHERMENT) { + fprintf(outfile, "\tData encipherment.\n"); + } + + if (usage & GNUTLS_KEY_KEY_AGREEMENT) { + fprintf(outfile, "\tKey agreement.\n"); + } + + if (usage & GNUTLS_KEY_KEY_CERT_SIGN) { + fprintf(outfile, "\tCertificate signing.\n"); + } + + if (usage & GNUTLS_KEY_NON_REPUDIATION) { + fprintf(outfile, "\tCRL signing.\n"); + } + + if (usage & GNUTLS_KEY_ENCIPHER_ONLY) { + fprintf(outfile, "\tKey encipher only.\n"); + } + + if (usage & GNUTLS_KEY_DECIPHER_ONLY) { + fprintf(outfile, "\tKey decipher only.\n"); + } +} + +void pubkey_info (void) +{ + gnutls_x509_crt_t crt; + gnutls_pubkey_t pubkey; + unsigned int bits, usage; + int ret; + size_t size; + const char* cprint; + + ret = gnutls_pubkey_init(&pubkey); + if (ret < 0) { + error (EXIT_FAILURE, 0, "pubkey_init: %s", gnutls_strerror (ret)); + } + + crt = load_cert(0); + + if (crt != NULL) { + ret = gnutls_pubkey_import_x509(pubkey, crt, 0); + if (ret < 0) { + error (EXIT_FAILURE, 0, "pubkey_import_x509: %s", gnutls_strerror (ret)); + } + } else { + pubkey = load_pubkey(1); + } + + fprintf (outfile, "Public Key Info:\n\n"); + ret = gnutls_pubkey_get_pk_algorithm (pubkey, &bits); + fprintf (outfile, "Public Key Algorithm: "); + + cprint = gnutls_pk_algorithm_get_name (ret); + fprintf (outfile, "%s (%u bits)\n", cprint ? cprint : "Unknown", bits); + + + /* Print the raw public and private keys + */ + if (ret == GNUTLS_PK_RSA) + { + gnutls_datum_t m, e; + + ret = gnutls_pubkey_get_pk_rsa_raw (pubkey, &m, &e); + if (ret < 0) + fprintf (stderr, "Error in key RSA data export: %s\n", + gnutls_strerror (ret)); + else + { + print_rsa_pkey (&m, &e, NULL, NULL, NULL, NULL); + gnutls_free (m.data); + gnutls_free (e.data); + } + } + else if (ret == GNUTLS_PK_DSA) + { + gnutls_datum_t p, q, g, y; + + ret = gnutls_pubkey_get_pk_dsa_raw (pubkey, &p, &q, &g, &y); + if (ret < 0) + fprintf (stderr, "Error in key DSA data export: %s\n", + gnutls_strerror (ret)); + else + { + print_dsa_pkey (NULL, &y, &p, &q, &g); + gnutls_free (y.data); + gnutls_free (p.data); + gnutls_free (q.data); + gnutls_free (g.data); + } + } + + ret = gnutls_pubkey_get_key_usage (pubkey, &usage); + if (ret < 0) { + error (EXIT_FAILURE, 0, "pubkey_get_key_usage: %s", gnutls_strerror (ret)); + } + + fprintf (outfile, "Public Key Usage:\n"); + print_key_usage(outfile, usage); + + fprintf (outfile, "\n"); + + size = sizeof (buffer); + if ((ret = gnutls_pubkey_get_key_id (pubkey, 0, buffer, &size)) < 0) + { + fprintf (stderr, "Error in key id calculation: %s\n", + gnutls_strerror (ret)); + } + else + { + fprintf (outfile, "Public Key ID: %s\n", raw_to_string (buffer, size)); + } + + size = sizeof (buffer); + ret = gnutls_pubkey_export (pubkey, GNUTLS_X509_FMT_PEM, buffer, &size); + if (ret < 0) + error (EXIT_FAILURE, 0, "export error: %s", gnutls_strerror (ret)); + + fprintf (outfile, "\n%s\n", buffer); + + gnutls_pubkey_deinit (pubkey); +} diff --git a/src/certtool.gaa b/src/certtool.gaa index 0e9da9e0c0..f84b6dbb8d 100644 --- a/src/certtool.gaa +++ b/src/certtool.gaa @@ -39,6 +39,9 @@ option (get-dh-params) { $action=ACTION_GET_DH; } "Get the included PKCS #3 enco #char *privkey; option (load-privkey) STR "FILE" { $privkey = $1 } "Private key file to use." +#char *pubkey; +option (load-pubkey) STR "FILE" { $pubkey = $1 } "Private key file to use." + #char *request; option (load-request) STR "FILE" { $request = $1 } "Certificate request file to use." @@ -79,6 +82,8 @@ option (k, key-info) { $privkey_op=1; $action = ACTION_PRIVKEY_INFO; } "Print in option (pgp-key-info) { $privkey_op=1; $action = ACTION_PGP_PRIVKEY_INFO; } "Print information on a OpenPGP private key." +option (pubkey-info) { $action = ACTION_PUBKEY_INFO; } "Print information on a public key." + #int fix_key; option (fix-key) { $privkey_op=1; $fix_key = 1; } "Regenerate the parameters in a private key." @@ -135,8 +140,9 @@ option (pkcs11-provider) STR "Library" { $pkcs11_provider = $1 } "Specify the pk option (pkcs11-export-url) STR "URL" { $action = ACTION_PKCS11_EXPORT_URL; $pkcs11_url = $1; } "Export data specified a pkcs11 URL" #int pkcs11_type; -option (pkcs11-list) { $action = ACTION_PKCS11_LIST; $pkcs11_type=PKCS11_TYPE_PK; } "List objects specified by a PKCS#11 URL" -option (pkcs11-list-trusted) { $action = ACTION_PKCS11_LIST; $pkcs11_type=PKCS11_TYPE_TRUSTED; } "List objects marked as trusted, specified by a PKCS#11 URL" +option (pkcs11-list-certs) { $action = ACTION_PKCS11_LIST; $pkcs11_type=PKCS11_TYPE_PK; } "List certificates specified by a PKCS#11 URL" +option (pkcs11-list-trusted) { $action = ACTION_PKCS11_LIST; $pkcs11_type=PKCS11_TYPE_TRUSTED; } "List certificates marked as trusted, specified by a PKCS#11 URL" +option (pkcs11-list-all-certs) { $action = ACTION_PKCS11_LIST; $pkcs11_type=PKCS11_TYPE_CRT_ALL; } "List all certificates specified by a PKCS#11 URL" option (pkcs11-list-all) { $action = ACTION_PKCS11_LIST; $pkcs11_type=PKCS11_TYPE_ALL; } "List all objects specified by a PKCS#11 URL" option (pkcs11-list-tokens) { $action = ACTION_PKCS11_TOKENS; } "List all available tokens" @@ -152,4 +158,4 @@ init { $bits = 2048; $pkcs8 = 0; $privkey = NULL; $ca=NULL; $ca_privkey = NULL; $incert_format = 0; $outcert_format = 0; $action=-1; $pass = NULL; $v1_cert = 0; $export = 0; $template = NULL; $hash=NULL; $fix_key = 0; $quick_random=1; $privkey_op = 0; $pkcs_cipher = "3des"; $crq_extensions=1; $pkcs11_provider= NULL; - $pkcs11_url = NULL; $pkcs11_type = PKCS11_TYPE_PK; } + $pkcs11_url = NULL; $pkcs11_type = PKCS11_TYPE_PK; $pubkey=NULL; } diff --git a/src/pkcs11.c b/src/pkcs11.c index b933799378..d2b3301839 100644 --- a/src/pkcs11.c +++ b/src/pkcs11.c @@ -47,7 +47,7 @@ static void pkcs11_common(void) */ void pkcs11_list( FILE* outfile, const char* url, int type) { -gnutls_pkcs11_crt_t *crt_list; +gnutls_pkcs11_obj_t *crt_list; gnutls_x509_crt_t xcrt; unsigned int crt_list_size = 0; int ret; @@ -59,52 +59,66 @@ int i, flags; if (url == NULL) url = "pkcs11:"; - ret = gnutls_pkcs11_crt_list_import_url( NULL, &crt_list_size, url, GNUTLS_PKCS11_CRT_ATTR_ALL); + if (type == PKCS11_TYPE_TRUSTED) { + flags = GNUTLS_PKCS11_OBJ_ATTR_CRT_TRUSTED; + } else if (type == PKCS11_TYPE_PK) { + flags = GNUTLS_PKCS11_OBJ_ATTR_CRT_WITH_PRIVKEY; + } else if (type == PKCS11_TYPE_CRT_ALL) { + flags = GNUTLS_PKCS11_OBJ_ATTR_CRT_ALL; + } else { + flags = GNUTLS_PKCS11_OBJ_ATTR_ALL; + } + + /* give some initial value to avoid asking for the pkcs11 pin twice. + */ + crt_list_size = 128; + crt_list = malloc(sizeof(*crt_list)*crt_list_size); + if (crt_list == NULL) { + fprintf(stderr, "Memory error\n"); + exit(1); + } + + ret = gnutls_pkcs11_obj_list_import_url( crt_list, &crt_list_size, url, flags); if (ret < 0 && ret != GNUTLS_E_SHORT_MEMORY_BUFFER) { fprintf(stderr, "Error in crt_list_import (1): %s\n", gnutls_strerror(ret)); exit(1); } if (crt_list_size == 0) { - fprintf(stderr, "No matching certificates found\n"); + fprintf(stderr, "No matching objects found\n"); exit(0); } - crt_list = malloc(sizeof(*crt_list)*crt_list_size); - if (crt_list == NULL) { - fprintf(stderr, "Memory error\n"); - exit(1); - } - - if (type == PKCS11_TYPE_TRUSTED) { - flags = GNUTLS_PKCS11_CRT_ATTR_TRUSTED; - } else if (type == PKCS11_TYPE_PK) { - flags = GNUTLS_PKCS11_CRT_ATTR_WITH_PK; - } else { - flags = GNUTLS_PKCS11_CRT_ATTR_ALL; - } + if (ret == GNUTLS_E_SHORT_MEMORY_BUFFER) { + crt_list = realloc(crt_list, sizeof(*crt_list)*crt_list_size); + if (crt_list == NULL) { + fprintf(stderr, "Memory error\n"); + exit(1); + } - ret = gnutls_pkcs11_crt_list_import_url( crt_list, &crt_list_size, url, flags); - if (ret < 0) { - fprintf(stderr, "Error in crt_list_import: %s\n", gnutls_strerror(ret)); - exit(1); + ret = gnutls_pkcs11_obj_list_import_url( crt_list, &crt_list_size, url, flags); + if (ret < 0) { + fprintf(stderr, "Error in crt_list_import: %s\n", gnutls_strerror(ret)); + exit(1); + } } for (i=0;i