summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/Makefile.am3
-rw-r--r--lib/gnutls.h.in.in5
-rw-r--r--lib/gnutls_cipher.c6
-rw-r--r--lib/gnutls_errors.c1
-rw-r--r--lib/gnutls_errors_int.h1
-rw-r--r--lib/gnutls_hash_int.c2
-rw-r--r--lib/gnutls_int.h5
-rw-r--r--lib/gnutls_mpi.h1
-rw-r--r--lib/gnutls_rsa_export.c4
-rw-r--r--lib/gnutls_rsa_export.h2
-rw-r--r--lib/gnutls_ui.h17
-rw-r--r--lib/rsa_compat.c4
-rw-r--r--lib/x509/Makefile.am4
-rw-r--r--lib/x509/common.c171
-rw-r--r--lib/x509/common.h15
-rw-r--r--lib/x509/crl.c16
-rw-r--r--lib/x509/crl_write.c259
-rw-r--r--lib/x509/crq.c49
-rw-r--r--lib/x509/dn.c11
-rw-r--r--lib/x509/extensions.c215
-rw-r--r--lib/x509/extensions.h4
-rw-r--r--lib/x509/mpi.c117
-rw-r--r--lib/x509/mpi.h6
-rw-r--r--lib/x509/pkcs12.c6
-rw-r--r--lib/x509/pkcs12_bag.c1
-rw-r--r--lib/x509/pkcs12_encr.c5
-rw-r--r--lib/x509/pkcs5.c1
-rw-r--r--lib/x509/pkcs7.c2
-rw-r--r--lib/x509/privkey.c362
-rw-r--r--lib/x509/privkey_pkcs8.c5
-rw-r--r--lib/x509/rc2.c1
-rw-r--r--lib/x509/rfc2818_hostname.c86
-rw-r--r--lib/x509/sign.c116
-rw-r--r--lib/x509/sign.h2
-rw-r--r--lib/x509/verify.c31
-rw-r--r--lib/x509/x509.c347
-rw-r--r--lib/x509/x509.h12
-rw-r--r--lib/x509/x509_write.c309
-rw-r--r--lib/x509/xml.c3
39 files changed, 1783 insertions, 424 deletions
diff --git a/lib/Makefile.am b/lib/Makefile.am
index c5ff61952f..39aa7f0115 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -56,7 +56,8 @@ libgnutls_la_LIBADD = $(MINITASN1_OBJECTS) x509/dn.lo x509/crl.lo x509/common.lo
x509/x509.lo x509/extensions.lo x509/compat.lo x509/verify.lo \
x509/mpi.lo x509/privkey.lo x509/pkcs7.lo x509/crq.lo x509/xml.lo x509/sign.lo \
x509/pkcs5.lo x509/privkey_pkcs8.lo x509/pkcs12.lo x509/pkcs12_bag.lo \
- x509/pkcs12_encr.lo x509/rfc2818_hostname.lo x509/rc2.lo x509/x509_write.lo
+ x509/pkcs12_encr.lo x509/rfc2818_hostname.lo x509/rc2.lo x509/x509_write.lo \
+ x509/crl_write.lo x509/dsa.lo
libgnutls_la_LDFLAGS = $(LIBASN1_LINK) $(LIBGCRYPT_LIBS) \
$(libgnutls_version_script_cmd) \
diff --git a/lib/gnutls.h.in.in b/lib/gnutls.h.in.in
index 1d89595bd1..b39d7bcc16 100644
--- a/lib/gnutls.h.in.in
+++ b/lib/gnutls.h.in.in
@@ -157,6 +157,11 @@ typedef enum gnutls_pk_algorithm { GNUTLS_PK_RSA = 1, GNUTLS_PK_DSA,
GNUTLS_PK_UNKNOWN = 0xff
} gnutls_pk_algorithm;
+typedef enum gnutls_sign_algorithm { GNUTLS_SIGN_RSA_SHA = 1, GNUTLS_SIGN_DSA_SHA,
+ GNUTLS_SIGN_RSA_MD5, GNUTLS_SIGN_RSA_MD2,
+ GNUTLS_SIGN_UNKNOWN = 0xff
+} gnutls_sign_algorithm;
+
/* If you want to change this, then also change the
* define in gnutls_int.h, and recompile.
*/
diff --git a/lib/gnutls_cipher.c b/lib/gnutls_cipher.c
index cca6a8fed4..cf32bcd435 100644
--- a/lib/gnutls_cipher.c
+++ b/lib/gnutls_cipher.c
@@ -157,7 +157,8 @@ int _gnutls_decrypt(gnutls_session session, opaque *ciphertext,
}
inline
-static GNUTLS_MAC_HANDLE mac_init( gnutls_mac_algorithm mac, opaque* secret, int secret_size, int ver) {
+static GNUTLS_MAC_HANDLE mac_init( gnutls_mac_algorithm mac, opaque* secret, int secret_size, int ver)
+{
GNUTLS_MAC_HANDLE td;
if ( ver == GNUTLS_SSL3) { /* SSL 3.0 */
@@ -173,7 +174,8 @@ GNUTLS_MAC_HANDLE td;
}
inline
-static void mac_deinit( GNUTLS_MAC_HANDLE td, opaque* res, int ver) {
+static void mac_deinit( GNUTLS_MAC_HANDLE td, opaque* res, int ver)
+{
if ( ver == GNUTLS_SSL3) { /* SSL 3.0 */
_gnutls_mac_deinit_ssl3(td, res);
} else {
diff --git a/lib/gnutls_errors.c b/lib/gnutls_errors.c
index 0ea3581416..23670e13bf 100644
--- a/lib/gnutls_errors.c
+++ b/lib/gnutls_errors.c
@@ -54,6 +54,7 @@ static gnutls_error_entry error_algorithms[] = {
ERROR_ENTRY("The Diffie Hellman prime sent by the server is not acceptable (not long enough).", GNUTLS_E_DH_PRIME_UNACCEPTABLE, 1 ),
ERROR_ENTRY("A TLS packet with unexpected length was received.", GNUTLS_E_UNEXPECTED_PACKET_LENGTH, 1 ),
ERROR_ENTRY("The specified session has been invalidated for some reason.", GNUTLS_E_INVALID_SESSION, 1 ),
+ ERROR_ENTRY("The specified name does not match the name in the certificate.", GNUTLS_E_NAME_DOES_NOT_MATCH, 1 ),
ERROR_ENTRY("GnuTLS internal error.", GNUTLS_E_INTERNAL_ERROR, 1 ),
ERROR_ENTRY("An illegal TLS extension was received.", GNUTLS_E_RECEIVED_ILLEGAL_EXTENSION, 1 ),
diff --git a/lib/gnutls_errors_int.h b/lib/gnutls_errors_int.h
index 3f64c626d7..e5d181e01f 100644
--- a/lib/gnutls_errors_int.h
+++ b/lib/gnutls_errors_int.h
@@ -122,6 +122,7 @@
#define GNUTLS_E_OPENPGP_KEYRING_ERROR -204
#define GNUTLS_E_X509_UNSUPPORTED_OID -205
+#define GNUTLS_E_NAME_DOES_NOT_MATCH -206
#define GNUTLS_E_UNIMPLEMENTED_FEATURE -1250
diff --git a/lib/gnutls_hash_int.c b/lib/gnutls_hash_int.c
index 1746f963dc..cea75de4d0 100644
--- a/lib/gnutls_hash_int.c
+++ b/lib/gnutls_hash_int.c
@@ -78,7 +78,7 @@ int _gnutls_hash_get_algo_len(gnutls_mac_algorithm algorithm)
ret = gcry_md_get_algo_dlen(GCRY_MD_MD5);
break;
case GNUTLS_MAC_RMD160:
- ret = gcry_md_get_algo_dlen(GCRY_MD_MD5);
+ ret = gcry_md_get_algo_dlen(GCRY_MD_RMD160);
break;
default:
ret = 0; break;
diff --git a/lib/gnutls_int.h b/lib/gnutls_int.h
index ef95fee29c..00868356f8 100644
--- a/lib/gnutls_int.h
+++ b/lib/gnutls_int.h
@@ -212,6 +212,11 @@ typedef enum gnutls_pk_algorithm { GNUTLS_PK_RSA = 1, GNUTLS_PK_DSA,
GNUTLS_PK_UNKNOWN = 0xff
} gnutls_pk_algorithm;
+typedef enum gnutls_sign_algorithm { GNUTLS_SIGN_RSA_SHA = 1, GNUTLS_SIGN_DSA_SHA,
+ GNUTLS_SIGN_RSA_MD5, GNUTLS_SIGN_RSA_MD2,
+ GNUTLS_SIGN_UNKNOWN = 0xff
+} gnutls_sign_algorithm;
+
/* STATE (stop) */
typedef void (*LOG_FUNC)( int, const char*);
diff --git a/lib/gnutls_mpi.h b/lib/gnutls_mpi.h
index 2ac9eae663..357cc0a7bd 100644
--- a/lib/gnutls_mpi.h
+++ b/lib/gnutls_mpi.h
@@ -26,6 +26,7 @@
#define _gnutls_mpi_mul_ui gcry_mpi_mul_ui
# define _gnutls_mpi_alloc_like(x) _gnutls_mpi_new(_gnutls_mpi_get_nbits(x))
+# define _gnutls_mpi_salloc_like(x) _gnutls_mpi_snew(_gnutls_mpi_get_nbits(x))
void _gnutls_mpi_release( GNUTLS_MPI* x);
diff --git a/lib/gnutls_rsa_export.c b/lib/gnutls_rsa_export.c
index bc7104fb92..b772a2312c 100644
--- a/lib/gnutls_rsa_export.c
+++ b/lib/gnutls_rsa_export.c
@@ -54,7 +54,7 @@ const GNUTLS_MPI* _gnutls_get_rsa_params(gnutls_rsa_params rsa_params)
/* resarr will contain: modulus(0), public exponent(1), private exponent(2),
* prime1 - p (3), prime2 - q(4), u (5).
*/
-int _gnutls_rsa_generate_params(GNUTLS_MPI* resarr, int bits)
+int _gnutls_rsa_generate_params(GNUTLS_MPI* resarr, int* resarr_len, int bits)
{
int ret;
@@ -145,6 +145,8 @@ int _gnutls_rsa_generate_params(GNUTLS_MPI* resarr, int bits)
_gnutls_dump_mpi( "p: ", resarr[3]);
_gnutls_dump_mpi( "q: ", resarr[4]);
_gnutls_dump_mpi( "u: ", resarr[5]);
+
+ *resarr_len = 6;
return 0;
diff --git a/lib/gnutls_rsa_export.h b/lib/gnutls_rsa_export.h
index 49fec266b9..57897d32bb 100644
--- a/lib/gnutls_rsa_export.h
+++ b/lib/gnutls_rsa_export.h
@@ -20,5 +20,5 @@
const GNUTLS_MPI* _gnutls_get_rsa_params(gnutls_rsa_params);
int _gnutls_peers_cert_less_512( gnutls_session session);
-int _gnutls_rsa_generate_params(GNUTLS_MPI* resarr, int bits);
+int _gnutls_rsa_generate_params(GNUTLS_MPI* resarr, int* resarr_len, int bits);
diff --git a/lib/gnutls_ui.h b/lib/gnutls_ui.h
index ef050f9aba..007690182c 100644
--- a/lib/gnutls_ui.h
+++ b/lib/gnutls_ui.h
@@ -72,6 +72,23 @@ int gnutls_pem_base64_encode_alloc( const char* header, const gnutls_datum *data
int gnutls_pem_base64_decode_alloc( const char* header, const gnutls_datum *b64_data,
gnutls_datum* result);
+/* key_usage will be an OR of the following values:
+ */
+#define GNUTLS_KEY_DIGITAL_SIGNATURE 128 /* when the key is to be
+ * used for signing.
+ */
+#define GNUTLS_KEY_NON_REPUDIATION 64
+#define GNUTLS_KEY_KEY_ENCIPHERMENT 32 /* when the key is to be
+ * used for encryption.
+ */
+#define GNUTLS_KEY_DATA_ENCIPHERMENT 16
+#define GNUTLS_KEY_KEY_AGREEMENT 8
+#define GNUTLS_KEY_KEY_CERT_SIGN 4
+#define GNUTLS_KEY_CRL_SIGN 2
+#define GNUTLS_KEY_ENCIPHER_ONLY 1
+#define GNUTLS_KEY_DECIPHER_ONLY 32768
+
+
# endif /* LIBGNUTLS_VERSION */
#endif /* GNUTLS_UI_H */
diff --git a/lib/rsa_compat.c b/lib/rsa_compat.c
index 67e4d10141..18a33a2a3f 100644
--- a/lib/rsa_compat.c
+++ b/lib/rsa_compat.c
@@ -162,14 +162,14 @@ int gnutls_rsa_params_generate(gnutls_datum * m, gnutls_datum *e,
GNUTLS_MPI rsa_params[RSA_PRIVATE_PARAMS];
size_t siz;
uint i;
- int ret;
+ int ret, params_len;
if (check_bits(bits) < 0) {
gnutls_assert();
return GNUTLS_E_INVALID_REQUEST;
}
- ret = _gnutls_rsa_generate_params( rsa_params, bits);
+ ret = _gnutls_rsa_generate_params( rsa_params, &params_len, bits);
if (ret < 0) {
gnutls_assert();
return ret;
diff --git a/lib/x509/Makefile.am b/lib/x509/Makefile.am
index 206617b223..de9bc28e11 100644
--- a/lib/x509/Makefile.am
+++ b/lib/x509/Makefile.am
@@ -1,7 +1,7 @@
INCLUDES = -I../ -I../minitasn1/ -I../../includes/
EXTRA_DIST = dn.h common.h x509.h extensions.h pkcs7.h \
x509-api.tex compat.h verify.h mpi.h crq.h sign.h pkcs5.h \
- privkey.h pkcs12.h rc2.h rfc2818.h
+ privkey.h pkcs12.h rc2.h rfc2818.h dsa.h
noinst_LTLIBRARIES = libx509.la
#lib_LTLIBRARIES = libgnutls-x509.la
@@ -9,7 +9,7 @@ noinst_LTLIBRARIES = libx509.la
COBJECTS = crl.c dn.c common.c x509.c extensions.c \
rfc2818_hostname.c verify.c mpi.c privkey.c pkcs7.c \
crq.c xml.c sign.c pkcs5.c privkey_pkcs8.c pkcs12.c \
- pkcs12_bag.c pkcs12_encr.c rc2.c x509_write.c
+ pkcs12_bag.c pkcs12_encr.c rc2.c x509_write.c crl_write.c dsa.c
COMPAT_OBJECTS = compat.c
diff --git a/lib/x509/common.c b/lib/x509/common.c
index 7af2a068f0..b466ce192c 100644
--- a/lib/x509/common.c
+++ b/lib/x509/common.c
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2003 Nikos Mavroyanopoulos
+ * Copyright (C) 2004 Free Software Foundation
*
* This file is part of GNUTLS.
*
@@ -35,7 +36,7 @@
typedef struct _oid2string {
const char * oid;
const char * ldap_desc;
- int choice;
+ int choice; /* of type DirectoryString */
int printable;
} oid2string;
@@ -43,18 +44,34 @@ typedef struct _oid2string {
* contained in a rdnSequence and are printable.
*/
static const oid2string _oid2str[] = {
+ /* PKIX
+ */
+ {"1.3.6.1.5.5.7.9.1", "dateOfBirth", 0, 1},
+ {"1.3.6.1.5.5.7.9.2", "placeOfBirth", 0, 1},
+ {"1.3.6.1.5.5.7.9.3", "gender", 0, 1},
+ {"1.3.6.1.5.5.7.9.4", "countryOfCitizenship", 0, 1},
+ {"1.3.6.1.5.5.7.9.5", "countryOfResidence", 0, 1},
+
{"2.5.4.6", "C", 0, 1},
+ {"2.5.4.9", "STREET", 1, 1},
{"2.5.4.12", "T", 1, 1},
{"2.5.4.10", "O", 1, 1},
{"2.5.4.11", "OU", 1, 1},
{"2.5.4.3", "CN", 1, 1},
{"2.5.4.7", "L", 1, 1},
{"2.5.4.8", "ST", 1, 1},
+
{"2.5.4.5", "serialNumber", 0, 1},
{"2.5.4.20", "telephoneNumber", 0, 1},
+ {"2.5.4.4", "surName", 1, 1},
+ {"2.5.4.43", "initials", 1, 1},
+ {"2.5.4.44", "generationQualifier", 1, 1},
+ {"2.5.4.42", "givenName", 1, 1},
+ {"2.5.4.65", "pseudonym", 1, 1},
+ {"2.5.4.46", "dnQualifier", 0, 1},
{"0.9.2342.19200300.100.1.25", "DC", 0, 1},
- {"0.9.2342.19200300.100.1.1", "UID", 0, 1}, /* FIXME: CHOICE? */
+ {"0.9.2342.19200300.100.1.1", "UID", 0, 1},
{"1.2.840.113549.1.9.1", "EMAIL", 0, 1},
{"1.2.840.113549.1.9.7", NULL, 1, 1},
@@ -244,23 +261,21 @@ gnutls_pk_algorithm _gnutls_x509_oid2pk_algorithm( const char* oid)
return GNUTLS_PK_UNKNOWN;
}
-gnutls_pk_algorithm _gnutls_x509_oid2sign_algorithm( const char* oid,
- gnutls_mac_algorithm * mac)
+gnutls_sign_algorithm _gnutls_x509_oid2sign_algorithm( const char* oid)
{
if (strcmp( oid, RSA_MD5_OID) == 0) {
- if (mac) *mac = GNUTLS_MAC_MD5;
- return GNUTLS_PK_RSA;
+ return GNUTLS_SIGN_RSA_MD5;
} else if (strcmp( oid, RSA_SHA1_OID) == 0) {
- if (mac) *mac = GNUTLS_MAC_SHA;
- return GNUTLS_PK_RSA;
+ return GNUTLS_SIGN_RSA_SHA;
+ } else if (strcmp( oid, RSA_MD2_OID) == 0) {
+ return GNUTLS_SIGN_RSA_MD2;
} else if (strcmp( oid, DSA_SHA1_OID) == 0) {
- if (mac) *mac = GNUTLS_MAC_SHA;
- return GNUTLS_PK_DSA;
+ return GNUTLS_SIGN_DSA_SHA;
}
_gnutls_x509_log("Unknown SIGN OID: '%s'\n", oid);
- return GNUTLS_PK_UNKNOWN;
+ return GNUTLS_SIGN_UNKNOWN;
}
@@ -276,28 +291,41 @@ gnutls_mac_algorithm _gnutls_x509_oid2mac_algorithm( const char* oid)
return GNUTLS_MAC_UNKNOWN;
}
-const char* _gnutls_x509_mac2oid( gnutls_mac_algorithm mac)
+const char* _gnutls_x509_mac_to_oid( gnutls_mac_algorithm mac)
{
if (mac == GNUTLS_MAC_SHA) return OID_SHA1;
else if (mac == GNUTLS_MAC_MD5) return OID_MD5;
else return NULL;
}
-const char* _gnutls_x509_pk2oid( gnutls_pk_algorithm pk)
+const char* _gnutls_x509_pk_to_oid( gnutls_pk_algorithm pk)
{
if (pk == GNUTLS_PK_RSA) return PKIX1_RSA_OID;
else if (pk == GNUTLS_PK_DSA) return DSA_OID;
else return NULL;
}
-const char* _gnutls_x509_sign2oid( gnutls_pk_algorithm pk, gnutls_mac_algorithm mac)
+gnutls_sign_algorithm _gnutls_x509_pk_to_sign(
+ gnutls_pk_algorithm pk, gnutls_mac_algorithm mac)
{
if (pk == GNUTLS_PK_RSA) {
- if (mac == GNUTLS_MAC_SHA) return RSA_SHA1_OID;
- else if (mac == GNUTLS_MAC_MD5) return RSA_MD5_OID;
+ if (mac == GNUTLS_MAC_SHA) return GNUTLS_SIGN_RSA_SHA;
+ else if (mac == GNUTLS_MAC_MD5) return GNUTLS_SIGN_RSA_MD5;
} else if (pk == GNUTLS_PK_DSA) {
- if (mac == GNUTLS_MAC_SHA) return DSA_SHA1_OID;
+ if (mac == GNUTLS_MAC_SHA) return GNUTLS_SIGN_DSA_SHA;
}
+ return GNUTLS_SIGN_UNKNOWN;
+}
+
+const char* _gnutls_x509_sign_to_oid( gnutls_pk_algorithm pk, gnutls_mac_algorithm mac)
+{
+gnutls_sign_algorithm sign;
+
+ sign = _gnutls_x509_pk_to_sign( pk, mac);
+
+ if (sign == GNUTLS_SIGN_RSA_SHA) return RSA_SHA1_OID;
+ else if (sign == GNUTLS_SIGN_RSA_MD5) return RSA_MD5_OID;
+ else if (sign == GNUTLS_SIGN_DSA_SHA) return DSA_SHA1_OID;
return NULL;
}
@@ -569,7 +597,7 @@ time_t _gnutls_x509_get_time(ASN1_TYPE c2, const char *when)
*/
int _gnutls_x509_set_time(ASN1_TYPE c2, const char *where, time_t tim)
{
- opaque str_time[MAX_TIME];
+ char str_time[MAX_TIME];
char name[1024];
int result, len;
@@ -598,12 +626,13 @@ int _gnutls_x509_set_time(ASN1_TYPE c2, const char *where, time_t tim)
}
-gnutls_x509_subject_alt_name _gnutls_x509_san_find_type( char* str_type) {
+gnutls_x509_subject_alt_name _gnutls_x509_san_find_type( char* str_type)
+{
if (strcmp( str_type, "dNSName")==0) return GNUTLS_SAN_DNSNAME;
if (strcmp( str_type, "rfc822Name")==0) return GNUTLS_SAN_RFC822NAME;
if (strcmp( str_type, "uniformResourceIdentifier")==0) return GNUTLS_SAN_URI;
if (strcmp( str_type, "iPAddress")==0) return GNUTLS_SAN_IPADDRESS;
- return -1;
+ return (gnutls_x509_subject_alt_name)-1;
}
/* A generic export function. Will export the given ASN.1 encoded data
@@ -626,7 +655,6 @@ int _gnutls_x509_export_int( ASN1_TYPE asn1_data,
{
*output_data_size = len;
if (result == ASN1_MEM_ERROR) {
- gnutls_assert();
return GNUTLS_E_SHORT_MEMORY_BUFFER;
}
gnutls_assert();
@@ -949,7 +977,6 @@ gnutls_datum val;
/* Encodes and copies the private key parameters into a
* subjectPublicKeyInfo structure.
*
- * FIXME: can only support RSA parameters.
*/
int _gnutls_x509_encode_and_copy_PKI_params( ASN1_TYPE dst, const char* dst_name,
gnutls_pk_algorithm pk_algorithm, GNUTLS_MPI* params, int params_size)
@@ -959,18 +986,13 @@ gnutls_datum der = {NULL, 0};
int result;
char name[128];
- if (pk_algorithm != GNUTLS_PK_RSA) {
- gnutls_assert();
- return GNUTLS_E_UNIMPLEMENTED_FEATURE;
- }
-
- pk = _gnutls_x509_pk2oid( pk_algorithm);
+ pk = _gnutls_x509_pk_to_oid( pk_algorithm);
if (pk == NULL) {
gnutls_assert();
return GNUTLS_E_UNKNOWN_PK_ALGORITHM;
}
- /* write the RSA OID
+ /* write the OID
*/
_gnutls_str_cpy( name, sizeof(name), dst_name);
_gnutls_str_cat( name, sizeof(name), ".algorithm.algorithm");
@@ -980,34 +1002,74 @@ char name[128];
return _gnutls_asn2err(result);
}
- /* disable parameters, which are not used in RSA.
- */
- _gnutls_str_cpy( name, sizeof(name), dst_name);
- _gnutls_str_cat( name, sizeof(name), ".algorithm.parameters");
- result = asn1_write_value( dst, name, NULL, 0);
- if (result != ASN1_SUCCESS) {
- gnutls_assert();
- return _gnutls_asn2err(result);
- }
+ if (pk_algorithm == GNUTLS_PK_RSA) {
+ /* disable parameters, which are not used in RSA.
+ */
+ _gnutls_str_cpy( name, sizeof(name), dst_name);
+ _gnutls_str_cat( name, sizeof(name), ".algorithm.parameters");
+ result = asn1_write_value( dst, name, NULL, 0);
+ if (result != ASN1_SUCCESS) {
+ gnutls_assert();
+ return _gnutls_asn2err(result);
+ }
- result = _gnutls_x509_write_rsa_params( params, params_size, &der);
- if (result < 0) {
- gnutls_assert();
- return result;
- }
+ result = _gnutls_x509_write_rsa_params( params, params_size, &der);
+ if (result < 0) {
+ gnutls_assert();
+ return result;
+ }
- /* Write the DER parameters. (in bits)
- */
- _gnutls_str_cpy( name, sizeof(name), dst_name);
- _gnutls_str_cat( name, sizeof(name), ".subjectPublicKey");
- result = asn1_write_value( dst, name, der.data, der.size*8);
+ /* Write the DER parameters. (in bits)
+ */
+ _gnutls_str_cpy( name, sizeof(name), dst_name);
+ _gnutls_str_cat( name, sizeof(name), ".subjectPublicKey");
+ result = asn1_write_value( dst, name, der.data, der.size*8);
- _gnutls_free_datum(&der);
+ _gnutls_free_datum(&der);
- if (result != ASN1_SUCCESS) {
- gnutls_assert();
- return _gnutls_asn2err(result);
- }
+ if (result != ASN1_SUCCESS) {
+ gnutls_assert();
+ return _gnutls_asn2err(result);
+ }
+ } else if (pk_algorithm == GNUTLS_PK_DSA) {
+
+ result = _gnutls_x509_write_dsa_params( params, params_size, &der);
+ if (result < 0) {
+ gnutls_assert();
+ return result;
+ }
+
+ /* Write the DER parameters.
+ */
+ _gnutls_str_cpy( name, sizeof(name), dst_name);
+ _gnutls_str_cat( name, sizeof(name), ".algorithm.parameters");
+ result = asn1_write_value( dst, name, der.data, der.size);
+
+ _gnutls_free_datum(&der);
+
+ if (result != ASN1_SUCCESS) {
+ gnutls_assert();
+ return _gnutls_asn2err(result);
+ }
+
+ result = _gnutls_x509_write_dsa_public_key( params, params_size, &der);
+ if (result < 0) {
+ gnutls_assert();
+ return result;
+ }
+
+ _gnutls_str_cpy( name, sizeof(name), dst_name);
+ _gnutls_str_cat( name, sizeof(name), ".subjectPublicKey");
+ result = asn1_write_value( dst, name, der.data, der.size*8);
+
+ _gnutls_free_datum(&der);
+
+ if (result != ASN1_SUCCESS) {
+ gnutls_assert();
+ return _gnutls_asn2err(result);
+ }
+
+ } else return GNUTLS_E_UNIMPLEMENTED_FEATURE;
return 0;
}
@@ -1044,7 +1106,8 @@ char name[128];
return algo;
}
- /* Now read the parameters' bits */
+ /* Now read the parameters' bits
+ */
_gnutls_str_cpy( name, sizeof(name), src_name);
_gnutls_str_cat( name, sizeof(name), ".subjectPublicKey");
diff --git a/lib/x509/common.h b/lib/x509/common.h
index 34d07d9a23..f29a28f27b 100644
--- a/lib/x509/common.h
+++ b/lib/x509/common.h
@@ -13,8 +13,11 @@ void _gnutls_int2str(unsigned int k, char *data);
#define PKIX1_RSA_OID "1.2.840.113549.1.1.1"
#define DSA_OID "1.2.840.10040.4.1"
+/* signature OIDs
+ */
#define DSA_SHA1_OID "1.2.840.10040.4.3"
#define RSA_MD5_OID "1.2.840.113549.1.1.4"
+#define RSA_MD2_OID "1.2.840.113549.1.1.2"
#define RSA_SHA1_OID "1.2.840.113549.1.1.5"
time_t _gnutls_x509_utcTime2gtime(const char *ttime);
@@ -31,12 +34,14 @@ int _gnutls_x509_oid_data_printable( const char* OID);
gnutls_pk_algorithm _gnutls_x509_oid2pk_algorithm( const char* oid);
gnutls_mac_algorithm _gnutls_x509_oid2mac_algorithm( const char* oid);
-gnutls_pk_algorithm _gnutls_x509_oid2sign_algorithm( const char* oid,
- gnutls_mac_algorithm * mac);
+gnutls_sign_algorithm _gnutls_x509_oid2sign_algorithm( const char* oid);
-const char* _gnutls_x509_pk2oid( gnutls_pk_algorithm pk);
-const char* _gnutls_x509_sign2oid( gnutls_pk_algorithm pk, gnutls_mac_algorithm mac);
-const char* _gnutls_x509_mac2oid( gnutls_mac_algorithm mac);
+const char* _gnutls_x509_pk_to_oid( gnutls_pk_algorithm pk);
+
+gnutls_sign_algorithm _gnutls_x509_pk_to_sign(
+ gnutls_pk_algorithm pk, gnutls_mac_algorithm mac);
+const char* _gnutls_x509_sign_to_oid( gnutls_sign_algorithm, gnutls_mac_algorithm mac);
+const char* _gnutls_x509_mac_to_oid( gnutls_mac_algorithm mac);
time_t _gnutls_x509_get_time(ASN1_TYPE c2, const char *when);
diff --git a/lib/x509/crl.c b/lib/x509/crl.c
index d4e05b6cd2..3ae42dced9 100644
--- a/lib/x509/crl.c
+++ b/lib/x509/crl.c
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2003 Nikos Mavroyanopoulos
+ * Copyright (C) 2004 Free Software Foundation
*
* This file is part of GNUTLS.
*
@@ -55,6 +56,7 @@ int gnutls_x509_crl_init(gnutls_x509_crl * crl)
&(*crl)->crl);
if (result != ASN1_SUCCESS) {
gnutls_assert();
+ gnutls_free( *crl);
return _gnutls_asn2err(result);
}
return 0; /* success */
@@ -154,7 +156,7 @@ int gnutls_x509_crl_import(gnutls_x509_crl crl, const gnutls_datum * data,
* gnutls_x509_crl_get_issuer_dn - This function returns the CRL's issuer distinguished name
* @crl: should contain a gnutls_x509_crl structure
* @buf: a pointer to a structure to hold the peer's name (may be null)
- * @sizeof_buf: initialy holds the size of 'buf'
+ * @sizeof_buf: initially holds the size of @buf
*
* This function will copy the name of the CRL issuer in the provided buffer. The name
* will be in the form "C=xxxx,O=yyyy,CN=zzzz" as described in RFC2253. The output
@@ -187,7 +189,7 @@ int gnutls_x509_crl_get_issuer_dn(gnutls_x509_crl crl, char *buf,
* @indx: In case multiple same OIDs exist in the RDN, this specifies which to send. Use zero to get the first one.
* @raw_flag: If non zero returns the raw DER data of the DN part.
* @buf: a pointer to a structure to hold the peer's name (may be null)
- * @sizeof_buf: initialy holds the size of 'buf'
+ * @sizeof_buf: initially holds the size of @buf
*
* This function will extract the part of the name of the CRL issuer specified
* by the given OID. The output will be encoded as described in RFC2253. The output
@@ -224,7 +226,7 @@ int gnutls_x509_crl_get_issuer_dn_by_oid(gnutls_x509_crl crl,
* @crl: should contain a gnutls_x509_crl structure
* @indx: Specifies which DN OID to send. Use zero to get the first one.
* @oid: a pointer to a structure to hold the name (may be null)
- * @sizeof_oid: initialy holds the size of 'oid'
+ * @sizeof_oid: initially holds the size of 'oid'
*
* This function will extract the requested OID of the name of the CRL issuer, specified
* by the given index.
@@ -253,7 +255,7 @@ int gnutls_x509_crl_get_dn_oid(gnutls_x509_crl crl,
* gnutls_x509_crl_get_signature_algorithm - This function returns the CRL's signature algorithm
* @crl: should contain a gnutls_x509_crl structure
*
- * This function will return a value of the gnutls_pk_algorithm enumeration that
+ * This function will return a value of the gnutls_sign_algorithm enumeration that
* is the signature algorithm.
*
* Returns a negative value on error.
@@ -280,7 +282,7 @@ int gnutls_x509_crl_get_signature_algorithm(gnutls_x509_crl crl)
return result;
}
- result = _gnutls_x509_oid2sign_algorithm( (const char*)sa.data, NULL);
+ result = _gnutls_x509_oid2sign_algorithm( (const char*)sa.data);
_gnutls_free_datum( &sa);
@@ -393,11 +395,11 @@ int gnutls_x509_crl_get_crt_count(gnutls_x509_crl crl)
}
/**
- * gnutls_x509_crl_get_crt - This function returns the serial number of a revoked certificate
+ * gnutls_x509_crl_get_crt_serial - This function returns the serial number of a revoked certificate
* @crl: should contain a gnutls_x509_crl structure
* @index: the index of the certificate to extract (starting from 0)
* @serial: where the serial number will be copied
- * @serial_size: initialy holds the size of serial
+ * @serial_size: initially holds the size of serial
* @time: if non null, will hold the time this certificate was revoked
*
* This function will return the serial number of the specified, by the index,
diff --git a/lib/x509/crl_write.c b/lib/x509/crl_write.c
new file mode 100644
index 0000000000..7545f2c6a8
--- /dev/null
+++ b/lib/x509/crl_write.c
@@ -0,0 +1,259 @@
+/*
+ * Copyright (C) 2003 Nikos Mavroyanopoulos
+ * Copyright (C) 2004 Free Software Foundation
+ *
+ * This file is part of GNUTLS.
+ *
+ * The GNUTLS library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+/* This file contains functions to handle CRL generation.
+ */
+
+#include <gnutls_int.h>
+
+#ifdef ENABLE_PKI
+
+#include <gnutls_datum.h>
+#include <gnutls_global.h>
+#include <gnutls_errors.h>
+#include <common.h>
+#include <gnutls_x509.h>
+#include <x509_b64.h>
+#include <crq.h>
+#include <dn.h>
+#include <mpi.h>
+#include <sign.h>
+#include <extensions.h>
+#include <libtasn1.h>
+#include <gnutls_ui.h>
+
+static void disable_optional_stuff( gnutls_x509_crl crl);
+
+/**
+ * gnutls_x509_crl_set_version - This function will set the CRL version
+ * @crl: should contain a gnutls_x509_crl structure
+ * @version: holds the version number. For CRLv1 crls must be 1.
+ *
+ * This function will set the version of the CRL. This
+ * must be one for CRL version 1, and so on. The CRLs generated
+ * by gnutls should have a version number of 2.
+ *
+ * Returns 0 on success.
+ *
+ **/
+int gnutls_x509_crl_set_version(gnutls_x509_crl crl, unsigned int version)
+{
+int result;
+char null = version;
+
+ if (crl==NULL) {
+ gnutls_assert();
+ return GNUTLS_E_INVALID_REQUEST;
+ }
+
+ null -= 1;
+ if (null < 0) null = 0;
+
+ result = asn1_write_value( crl->crl, "tbsCertList.version", &null, 1);
+ if (result != ASN1_SUCCESS) {
+ gnutls_assert();
+ return _gnutls_asn2err(result);
+ }
+
+ return 0;
+}
+
+/**
+ * gnutls_x509_crl_sign - This function will sign a CRL with a key
+ * @crl: should contain a gnutls_x509_crl structure
+ * @issuer: is the certificate of the certificate issuer
+ * @issuer_key: holds the issuer's private key
+ *
+ * This function will sign the CRL with the issuer's private key, and
+ * will copy the issuer's information into the CRL.
+ *
+ * This must be the last step in a certificate CRL since all
+ * the previously set parameters are now signed.
+ *
+ * Returns 0 on success.
+ *
+ **/
+int gnutls_x509_crl_sign(gnutls_x509_crl crl, gnutls_x509_crt issuer,
+ gnutls_x509_privkey issuer_key)
+{
+int result;
+
+ if (crl==NULL || issuer == NULL) {
+ gnutls_assert();
+ return GNUTLS_E_INVALID_REQUEST;
+ }
+
+ /* disable all the unneeded OPTIONAL fields.
+ */
+ disable_optional_stuff( crl);
+
+ result = _gnutls_x509_pkix_sign( crl->crl, "tbsCertList", issuer,
+ issuer_key);
+ if (result < 0) {
+ gnutls_assert();
+ return result;
+ }
+
+ return 0;
+}
+
+/**
+ * gnutls_x509_crl_set_this_update - This function will set the CRL's issuing time
+ * @crl: should contain a gnutls_x509_crl structure
+ * @act_time: The actual time
+ *
+ * This function will set the time this CRL was issued.
+ *
+ * Returns 0 on success, or a negative value in case of an error.
+ *
+ **/
+int gnutls_x509_crl_set_this_update(gnutls_x509_crl crl, time_t act_time)
+{
+ if (crl==NULL) {
+ gnutls_assert();
+ return GNUTLS_E_INVALID_REQUEST;
+ }
+
+ return _gnutls_x509_set_time( crl->crl, "tbsCertList.thisUpdate", act_time);
+}
+
+/**
+ * gnutls_x509_crl_set_next_update - This function will set the CRL next update time
+ * @crl: should contain a gnutls_x509_crl structure
+ * @exp_time: The actual time
+ *
+ * This function will set the time this CRL will be updated.
+ *
+ * Returns 0 on success, or a negative value in case of an error.
+ *
+ **/
+int gnutls_x509_crl_set_next_update(gnutls_x509_crl crl, time_t exp_time)
+{
+ if (crl==NULL) {
+ gnutls_assert();
+ return GNUTLS_E_INVALID_REQUEST;
+ }
+ return _gnutls_x509_set_time( crl->crl, "tbsCertList.nextUpdate", exp_time);
+}
+
+/**
+ * gnutls_x509_crl_set_crt_serial - This function will set a revoked certificate's serial number
+ * @crl: should contain a gnutls_x509_crl structure
+ * @serial: The revoked certificate's serial number
+ * @serial_size: Holds the size of the serial field.
+ * @revocation_time: The time this certificate was revoked
+ *
+ * This function will set a revoked certificate's serial number to the CRL.
+ *
+ * Returns 0 on success, or a negative value in case of an error.
+ *
+ **/
+int gnutls_x509_crl_set_crt_serial(gnutls_x509_crl crl, const void* serial,
+ size_t serial_size, time_t revocation_time)
+{
+ int ret;
+
+ if (crl==NULL) {
+ gnutls_assert();
+ return GNUTLS_E_INVALID_REQUEST;
+ }
+
+ ret = asn1_write_value(crl->crl, "tbsCertList.revokedCertificates", "NEW", 1);
+ if (ret != ASN1_SUCCESS) {
+ gnutls_assert();
+ return _gnutls_asn2err(ret);
+ }
+
+ ret = asn1_write_value(crl->crl, "tbsCertList.revokedCertificates.?LAST.userCertificate", serial, serial_size);
+ if (ret != ASN1_SUCCESS) {
+ gnutls_assert();
+ return _gnutls_asn2err(ret);
+ }
+
+ ret = _gnutls_x509_set_time( crl->crl, "tbsCertList.revokedCertificates.?LAST.revocationDate",
+ revocation_time);
+ if (ret < 0) {
+ gnutls_assert();
+ return ret;
+ }
+
+ ret = asn1_write_value(crl->crl, "tbsCertList.revokedCertificates.?LAST.crlEntryExtensions", NULL, 0);
+ if (ret != ASN1_SUCCESS) {
+ gnutls_assert();
+ return _gnutls_asn2err(ret);
+ }
+
+ return 0;
+}
+
+/**
+ * gnutls_x509_crl_set_crt - This function will set a revoked certificate's serial number
+ * @crl: should contain a gnutls_x509_crl structure
+ * @crt: should contain a gnutls_x509_crt structure with the revoked certificate
+ * @revocation_time: The time this certificate was revoked
+ *
+ * This function will set a revoked certificate's serial number to the CRL.
+ *
+ * Returns 0 on success, or a negative value in case of an error.
+ *
+ **/
+int gnutls_x509_crl_set_crt(gnutls_x509_crl crl, gnutls_x509_crt crt,
+ time_t revocation_time)
+{
+ int ret;
+ opaque serial[128];
+ size_t serial_size;
+
+ if (crl==NULL || crt == NULL) {
+ gnutls_assert();
+ return GNUTLS_E_INVALID_REQUEST;
+ }
+
+ serial_size = sizeof(serial);
+ ret = gnutls_x509_crt_get_serial(crt, serial, &serial_size);
+ if (ret < 0) {
+ gnutls_assert();
+ return ret;
+ }
+
+ ret = gnutls_x509_crl_set_crt_serial( crl, serial, serial_size, revocation_time);
+ if (ret < 0) {
+ gnutls_assert();
+ return _gnutls_asn2err(ret);
+ }
+
+ return 0;
+}
+
+
+/* If OPTIONAL fields have not been initialized then
+ * disable them.
+ */
+static void disable_optional_stuff( gnutls_x509_crl crl)
+{
+
+ asn1_write_value( crl->crl, "tbsCertList.crlExtensions", NULL, 0);
+
+ return;
+}
+
+#endif /* ENABLE_PKI */
diff --git a/lib/x509/crq.c b/lib/x509/crq.c
index 07938ccab1..e6d4d1669c 100644
--- a/lib/x509/crq.c
+++ b/lib/x509/crq.c
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2003 Nikos Mavroyanopoulos
+ * Copyright (C) 2004 Free Software Foundation
*
* This file is part of GNUTLS.
*
@@ -59,6 +60,7 @@ int gnutls_x509_crq_init(gnutls_x509_crq * crq)
&((*crq)->crq));
if (result != ASN1_SUCCESS) {
gnutls_assert();
+ gnutls_free( *crq);
return _gnutls_asn2err(result);
}
return 0; /* success */
@@ -146,9 +148,7 @@ int gnutls_x509_crq_import(gnutls_x509_crq crq, const gnutls_datum * data,
goto cleanup;
}
- if (need_free) _gnutls_free_datum( &_data);
-
- return 0;
+ result = 0;
cleanup:
if (need_free) _gnutls_free_datum( &_data);
@@ -161,7 +161,7 @@ int gnutls_x509_crq_import(gnutls_x509_crq crq, const gnutls_datum * data,
* gnutls_x509_crq_get_dn - This function returns the Certificate request subject's distinguished name
* @crq: should contain a gnutls_x509_crq structure
* @buf: a pointer to a structure to hold the name (may be null)
- * @sizeof_buf: initialy holds the size of @buf
+ * @sizeof_buf: initially holds the size of @buf
*
* This function will copy the name of the Certificate request subject in the provided buffer. The name
* will be in the form "C=xxxx,O=yyyy,CN=zzzz" as described in RFC2253. The output
@@ -193,7 +193,7 @@ int gnutls_x509_crq_get_dn(gnutls_x509_crq crq, char *buf,
* @indx: In case multiple same OIDs exist in the RDN, this specifies which to send. Use zero to get the first one.
* @raw_flag: If non zero returns the raw DER data of the DN part.
* @buf: a pointer to a structure to hold the name (may be null)
- * @sizeof_buf: initialy holds the size of @buf
+ * @sizeof_buf: initially holds the size of @buf
*
* This function will extract the part of the name of the Certificate request subject, specified
* by the given OID. The output will be encoded as described in RFC2253. The output
@@ -228,7 +228,7 @@ int gnutls_x509_crq_get_dn_by_oid(gnutls_x509_crq crq, const char* oid,
* @crq: should contain a gnutls_x509_crq structure
* @indx: Specifies which DN OID to send. Use zero to get the first one.
* @oid: a pointer to a structure to hold the name (may be null)
- * @sizeof_oid: initialy holds the size of @oid
+ * @sizeof_oid: initially holds the size of @oid
*
* This function will extract the requested OID of the name of the Certificate request subject, specified
* by the given index.
@@ -395,7 +395,7 @@ static int parse_attribute(ASN1_TYPE asn1_struct,
* gnutls_x509_crq_get_challenge_password - This function will get the challenge password
* @crq: should contain a gnutls_x509_crq structure
* @pass: will hold a null terminated password
- * @sizeof_pass: Initialy holds the size of pass.
+ * @sizeof_pass: Initially holds the size of @pass.
*
* This function will return the challenge password in the
* request.
@@ -460,15 +460,14 @@ int gnutls_x509_crq_set_dn_by_oid(gnutls_x509_crq crq, const char* oid,
int gnutls_x509_crq_set_version(gnutls_x509_crq crq, unsigned int version)
{
int result;
-char null = version;
+unsigned char null = version;
if (crq==NULL) {
gnutls_assert();
return GNUTLS_E_INVALID_REQUEST;
}
- null -= 1;
- if (null < 0) null = 0;
+ if (null > 0) null--;
result = asn1_write_value( crq->crq, "certificationRequestInfo.version", &null, 1);
if (result != ASN1_SUCCESS) {
@@ -599,18 +598,12 @@ int gnutls_x509_crq_sign(gnutls_x509_crq crq, gnutls_x509_privkey key)
{
int result;
gnutls_datum signature;
-const char* pk;
if (crq==NULL) {
gnutls_assert();
return GNUTLS_E_INVALID_REQUEST;
}
- if (key->pk_algorithm != GNUTLS_PK_RSA) {
- gnutls_assert();
- return GNUTLS_E_UNIMPLEMENTED_FEATURE;
- }
-
/* Step 1. Self sign the request.
*/
result = _gnutls_x509_sign_tbs( crq->crq, "certificationRequestInfo", GNUTLS_MAC_SHA,
@@ -634,26 +627,11 @@ const char* pk;
/* Step 3. Write the signatureAlgorithm field.
*/
- pk = _gnutls_x509_sign2oid( key->pk_algorithm, GNUTLS_MAC_SHA);
- if (pk == NULL) {
- gnutls_assert();
- return GNUTLS_E_INVALID_REQUEST;
- }
-
- /* write the RSA OID
- */
- result = asn1_write_value( crq->crq, "signatureAlgorithm.algorithm", pk, 1);
- if (result != ASN1_SUCCESS) {
- gnutls_assert();
- return _gnutls_asn2err(result);
- }
-
- /* disable parameters, which are not used in RSA.
- */
- result = asn1_write_value( crq->crq, "signatureAlgorithm.parameters", NULL, 0);
- if (result != ASN1_SUCCESS) {
+ result = _gnutls_x509_write_sig_params( crq->crq, "signatureAlgorithm",
+ key->pk_algorithm, key->params, key->params_size);
+ if (result < 0) {
gnutls_assert();
- return _gnutls_asn2err(result);
+ return result;
}
return 0;
@@ -720,7 +698,6 @@ int result;
bits);
if (result < 0) {
gnutls_assert();
- return result;
}
return result;
diff --git a/lib/x509/dn.c b/lib/x509/dn.c
index 755f72ec55..ef0e6401cc 100644
--- a/lib/x509/dn.c
+++ b/lib/x509/dn.c
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2003 Nikos Mavroyanopoulos
+ * Copyright (C) 2004 Free Software Foundation
*
* This file is part of GNUTLS.
*
@@ -244,7 +245,7 @@ int _gnutls_x509_parse_dn(ASN1_TYPE asn1_struct,
ldap_desc = oid2ldap_string(oid);
printable = _gnutls_x509_oid_data_printable(oid);
- sizeof_escaped = 2*len;
+ sizeof_escaped = 2*len + 1;
escaped = gnutls_malloc( sizeof_escaped);
if (escaped == NULL) {
@@ -272,6 +273,7 @@ int _gnutls_x509_parse_dn(ASN1_TYPE asn1_struct,
len,
string,
&sizeof_string);
+
if (result < 0) {
gnutls_assert();
_gnutls_x509_log
@@ -290,10 +292,13 @@ int _gnutls_x509_parse_dn(ASN1_TYPE asn1_struct,
res =
_gnutls_bin2hex(value2, len, escaped,
sizeof_escaped);
+
+ STR_APPEND(ldap_desc);
+ STR_APPEND("=#");
if (res) {
- STR_APPEND(ldap_desc);
- STR_APPEND("=#");
STR_APPEND(res);
+ } else {
+ STR_APPEND("(null)");
}
}
diff --git a/lib/x509/extensions.c b/lib/x509/extensions.c
index c88a69c250..fc6e07a2df 100644
--- a/lib/x509/extensions.c
+++ b/lib/x509/extensions.c
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2003 Nikos Mavroyanopoulos
+ * Copyright (C) 2004 Free Software Foundation
*
* This file is part of GNUTLS.
*
@@ -28,6 +29,8 @@
#include <libtasn1.h>
#include <common.h>
#include <x509.h>
+#include <extensions.h>
+#include <gnutls_datum.h>
/* This function will attempt to return the requested extension found in
* the given X509v3 certificate. The return value is allocated and stored into
@@ -103,7 +106,7 @@ int _gnutls_x509_crt_get_extension( gnutls_x509_crt cert, const char* extension_
return _gnutls_asn2err(result);
}
- if (strcmp( str_critical, "TRUE")==0)
+ if (str_critical[0] == 'T')
critical = 1;
else critical = 0;
@@ -339,9 +342,10 @@ int _gnutls_x509_ext_extract_keyUsage(uint16 *keyUsage, opaque * extnValue,
int extnValueLen)
{
ASN1_TYPE ext = ASN1_TYPE_EMPTY;
- uint8 str[2];
int len, result;
+ uint8 str[2];
+ str[0] = str[1] = 0;
*keyUsage = 0;
if ((result=asn1_create_element
@@ -356,7 +360,7 @@ int _gnutls_x509_ext_extract_keyUsage(uint16 *keyUsage, opaque * extnValue,
if (result != ASN1_SUCCESS) {
gnutls_assert();
asn1_delete_structure(&ext);
- return 0;
+ return _gnutls_asn2err(result);
}
len = sizeof(str);
@@ -366,7 +370,7 @@ int _gnutls_x509_ext_extract_keyUsage(uint16 *keyUsage, opaque * extnValue,
asn1_delete_structure(&ext);
return 0;
}
-
+
*keyUsage = str[0] | (str[1] << 8);
asn1_delete_structure(&ext);
@@ -397,13 +401,14 @@ int _gnutls_x509_ext_extract_basicConstraints(int *CA, opaque * extnValue,
if (result != ASN1_SUCCESS) {
gnutls_assert();
asn1_delete_structure(&ext);
- return 0;
+ return _gnutls_asn2err(result);
}
len = sizeof(str) - 1;
+ /* the default value of cA is false.
+ */
result = asn1_read_value(ext, "cA", str, &len);
if (result != ASN1_SUCCESS) {
- gnutls_assert();
asn1_delete_structure(&ext);
return 0;
}
@@ -458,23 +463,51 @@ int _gnutls_x509_ext_gen_basicConstraints(int CA, gnutls_datum* der_ext)
return 0;
}
-/* generate the subject alternative name in a DER encoded extension
+/* generate the keyUsage in a DER encoded extension
+ * Use an ORed SEQUENCE of GNUTLS_KEY_* for usage.
*/
-int _gnutls_x509_ext_gen_subject_alt_name(gnutls_x509_subject_alt_name type,
- const char* data_string, gnutls_datum* der_ext)
+int _gnutls_x509_ext_gen_keyUsage(uint16 usage, gnutls_datum* der_ext)
{
ASN1_TYPE ext = ASN1_TYPE_EMPTY;
- const char *str;
- char name[128];
int result;
+ uint8 str[2];
- result = asn1_create_element(_gnutls_get_pkix(), "PKIX1.SubjectAltName", &ext);
+ result = asn1_create_element(_gnutls_get_pkix(), "PKIX1.KeyUsage", &ext);
if (result != ASN1_SUCCESS) {
gnutls_assert();
return _gnutls_asn2err(result);
}
- result = asn1_write_value( ext, "", "NEW", 1);
+ str[0] = usage & 0xff;
+ str[1] = usage >> 8;
+
+ result = asn1_write_value(ext, "", str, 9);
+ if (result != ASN1_SUCCESS) {
+ gnutls_assert();
+ asn1_delete_structure(&ext);
+ return _gnutls_asn2err(result);
+ }
+
+ result = _gnutls_x509_der_encode( ext, "", der_ext, 0);
+
+ asn1_delete_structure(&ext);
+
+ if (result < 0) {
+ gnutls_assert();
+ return result;
+ }
+
+ return 0;
+}
+
+static int write_new_general_name( ASN1_TYPE ext, const char* ext_name,
+ gnutls_x509_subject_alt_name type, const char* data_string)
+{
+const char* str;
+int result;
+char name[128];
+
+ result = asn1_write_value( ext, ext_name, "NEW", 1);
if (result != ASN1_SUCCESS) {
gnutls_assert();
return _gnutls_asn2err(result);
@@ -498,13 +531,20 @@ int _gnutls_x509_ext_gen_subject_alt_name(gnutls_x509_subject_alt_name type,
return GNUTLS_E_INTERNAL_ERROR;
}
- result = asn1_write_value( ext, "?LAST", str, 1);
+ if (ext_name[0] == 0) { /* no dot */
+ _gnutls_str_cpy( name, sizeof(name), "?LAST");
+ } else {
+ _gnutls_str_cpy( name, sizeof(name), ext_name);
+ _gnutls_str_cat( name, sizeof(name), ".?LAST");
+ }
+
+ result = asn1_write_value( ext, name, str, 1);
if (result != ASN1_SUCCESS) {
gnutls_assert();
return _gnutls_asn2err(result);
}
- _gnutls_str_cpy( name, sizeof(name), "?LAST.");
+ _gnutls_str_cat( name, sizeof(name), ".");
_gnutls_str_cat( name, sizeof(name), str);
result = asn1_write_value(ext, name, data_string, strlen(data_string));
@@ -514,6 +554,31 @@ int _gnutls_x509_ext_gen_subject_alt_name(gnutls_x509_subject_alt_name type,
return _gnutls_asn2err(result);
}
+ return 0;
+}
+
+/* Convert the given name to GeneralNames in a DER encoded extension.
+ * This is the same as subject alternative name.
+ */
+int _gnutls_x509_ext_gen_subject_alt_name(gnutls_x509_subject_alt_name type,
+ const char* data_string, gnutls_datum* der_ext)
+{
+ ASN1_TYPE ext = ASN1_TYPE_EMPTY;
+ int result;
+
+ result = asn1_create_element(_gnutls_get_pkix(), "PKIX1.GeneralNames", &ext);
+ if (result != ASN1_SUCCESS) {
+ gnutls_assert();
+ return _gnutls_asn2err(result);
+ }
+
+ result = write_new_general_name(ext, "", type, data_string);
+ if (result < 0) {
+ gnutls_assert();
+ asn1_delete_structure(&ext);
+ return result;
+ }
+
result = _gnutls_x509_der_encode( ext, "", der_ext, 0);
asn1_delete_structure(&ext);
@@ -525,3 +590,123 @@ int _gnutls_x509_ext_gen_subject_alt_name(gnutls_x509_subject_alt_name type,
return 0;
}
+
+/* generate the SubjectKeyID in a DER encoded extension
+ */
+int _gnutls_x509_ext_gen_key_id(const void* id, size_t id_size, gnutls_datum* der_ext)
+{
+ ASN1_TYPE ext = ASN1_TYPE_EMPTY;
+ int result;
+
+ result = asn1_create_element(_gnutls_get_pkix(), "PKIX1.SubjectKeyIdentifier", &ext);
+ if (result != ASN1_SUCCESS) {
+ gnutls_assert();
+ return _gnutls_asn2err(result);
+ }
+
+ result = asn1_write_value(ext, "", id, id_size);
+ if (result != ASN1_SUCCESS) {
+ gnutls_assert();
+ asn1_delete_structure(&ext);
+ return _gnutls_asn2err(result);
+ }
+
+ result = _gnutls_x509_der_encode( ext, "", der_ext, 0);
+
+ asn1_delete_structure(&ext);
+
+ if (result < 0) {
+ gnutls_assert();
+ return result;
+ }
+
+ return 0;
+}
+
+/* Creates and encodes the CRL Distribution points. data_string should be a name
+ * and type holds the type of the name.
+ * reason_flags should be an or'ed sequence of GNUTLS_CRL_REASON_*.
+ *
+ */
+int _gnutls_x509_ext_gen_crl_dist_points(gnutls_x509_subject_alt_name type,
+ const void* data_string, unsigned int reason_flags, gnutls_datum* der_ext)
+{
+ ASN1_TYPE ext = ASN1_TYPE_EMPTY;
+ gnutls_datum gnames = {NULL, 0};
+ int result;
+ uint8 reasons[2];
+
+ reasons[0] = reason_flags & 0xff;
+ reasons[1] = reason_flags >> 8;
+
+ result = asn1_create_element(_gnutls_get_pkix(), "PKIX1.CRLDistributionPoints", &ext);
+ if (result != ASN1_SUCCESS) {
+ gnutls_assert();
+ result = _gnutls_asn2err(result);
+ goto cleanup;
+ }
+
+ result = asn1_write_value( ext, "", "NEW", 1);
+ if (result != ASN1_SUCCESS) {
+ gnutls_assert();
+ result = _gnutls_asn2err(result);
+ goto cleanup;
+ }
+
+ if (reason_flags) {
+ result = asn1_write_value( ext, "?LAST.reasons", reasons, 9);
+ if (result != ASN1_SUCCESS) {
+ gnutls_assert();
+ result = _gnutls_asn2err(result);
+ goto cleanup;
+ }
+ } else {
+ result = asn1_write_value( ext, "?LAST.reasons", NULL, 0);
+ if (result != ASN1_SUCCESS) {
+ gnutls_assert();
+ result = _gnutls_asn2err(result);
+ goto cleanup;
+ }
+ }
+
+ result = asn1_write_value( ext, "?LAST.cRLIssuer", NULL, 0);
+ if (result != ASN1_SUCCESS) {
+ gnutls_assert();
+ result = _gnutls_asn2err(result);
+ goto cleanup;
+ }
+
+#if 0
+ /* When used as type CHOICE.
+ */
+ result = asn1_write_value( ext, "?LAST.distributionPoint", "fullName", 1);
+ if (result != ASN1_SUCCESS) {
+ gnutls_assert();
+ result = _gnutls_asn2err(result);
+ goto cleanup;
+ }
+#endif
+
+ asn1_write_value( ext, "?LAST.distributionPoint.nameRelativeToCRLIssuer", NULL, 0);
+
+ result = write_new_general_name(ext, "?LAST.distributionPoint.fullName", type, data_string);
+ if (result < 0) {
+ gnutls_assert();
+ goto cleanup;
+ }
+
+ result = _gnutls_x509_der_encode( ext, "", der_ext, 0);
+
+ if (result < 0) {
+ gnutls_assert();
+ goto cleanup;
+ }
+
+ result = 0;
+
+cleanup:
+ _gnutls_free_datum( &gnames);
+ asn1_delete_structure(&ext);
+
+ return result;
+}
diff --git a/lib/x509/extensions.h b/lib/x509/extensions.h
index 12f8f70c88..ce2e70a67b 100644
--- a/lib/x509/extensions.h
+++ b/lib/x509/extensions.h
@@ -10,5 +10,9 @@ int _gnutls_x509_ext_extract_basicConstraints(int *CA, opaque * extnValue,
int _gnutls_x509_crt_set_extension( gnutls_x509_crt cert, const char* extension_id,
const gnutls_datum* ext_data, unsigned int critical);
int _gnutls_x509_ext_gen_basicConstraints(int CA, gnutls_datum* der_ext);
+int _gnutls_x509_ext_gen_keyUsage(uint16 usage, gnutls_datum* der_ext);
int _gnutls_x509_ext_gen_subject_alt_name(gnutls_x509_subject_alt_name type,
const char* data_string, gnutls_datum* der_ext);
+int _gnutls_x509_ext_gen_crl_dist_points(gnutls_x509_subject_alt_name type,
+ const void* data_string, unsigned int reason_flags, gnutls_datum* der_ext);
+int _gnutls_x509_ext_gen_key_id( const void* id, size_t id_size, gnutls_datum* der_data);
diff --git a/lib/x509/mpi.c b/lib/x509/mpi.c
index 2eb76bb064..d2d260f63d 100644
--- a/lib/x509/mpi.c
+++ b/lib/x509/mpi.c
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2003 Nikos Mavroyanopoulos
+ * Copyright (C) 2004 Free Software Foundation
*
* This file is part of GNUTLS.
*
@@ -141,7 +142,7 @@ int _gnutls_x509_read_dsa_params(opaque * der, int dersize, GNUTLS_MPI * params)
/* reads DSA's Y
* from the certificate
- * params[3]
+ * only sets params[3]
*/
int _gnutls_x509_read_dsa_pubkey(opaque * der, int dersize, GNUTLS_MPI * params)
{
@@ -163,7 +164,7 @@ int _gnutls_x509_read_dsa_pubkey(opaque * der, int dersize, GNUTLS_MPI * params)
return _gnutls_asn2err(result);
}
- /* Read p */
+ /* Read Y */
if ( (result=_gnutls_x509_read_int( spk, "", &params[3])) < 0) {
gnutls_assert();
@@ -331,7 +332,69 @@ cleanup:
}
/*
- * This function writes the BIT STRING subjectPublicKey for DSS keys.
+ * This function writes and encodes the parameters for DSS or RSA keys.
+ * This is the "signatureAlgorithm" fields.
+ */
+int _gnutls_x509_write_sig_params( ASN1_TYPE dst, const char* dst_name,
+ gnutls_pk_algorithm pk_algorithm, GNUTLS_MPI * params, int params_size)
+{
+gnutls_datum der;
+int result;
+char name[128];
+const char* pk;
+
+ _gnutls_str_cpy( name, sizeof(name), dst_name);
+ _gnutls_str_cat( name, sizeof(name), ".algorithm");
+
+ pk = _gnutls_x509_sign_to_oid( pk_algorithm, GNUTLS_MAC_SHA);
+ if (pk == NULL) {
+ gnutls_assert();
+ return GNUTLS_E_INVALID_REQUEST;
+ }
+
+ /* write the OID.
+ */
+ result = asn1_write_value( dst, name, pk, 1);
+ if (result != ASN1_SUCCESS) {
+ gnutls_assert();
+ return _gnutls_asn2err(result);
+ }
+
+
+ _gnutls_str_cpy( name, sizeof(name), dst_name);
+ _gnutls_str_cat( name, sizeof(name), ".parameters");
+
+ if (pk_algorithm == GNUTLS_PK_DSA) {
+ result = _gnutls_x509_write_dsa_params( params, params_size, &der);
+ if (result < 0) {
+ gnutls_assert();
+ return result;
+ }
+
+ result = asn1_write_value( dst, name, der.data, der.size);
+ _gnutls_free_datum( &der);
+
+ if (result != ASN1_SUCCESS) {
+ gnutls_assert();
+ return _gnutls_asn2err(result);
+ }
+ } else { /* RSA */
+ result = asn1_write_value( dst, name, NULL, 0);
+
+ if (result != ASN1_SUCCESS && result != ASN1_ELEMENT_NOT_FOUND) {
+ /* Here we ignore the element not found error, since this
+ * may have been disabled before.
+ */
+ gnutls_assert();
+ return _gnutls_asn2err(result);
+ }
+ }
+
+ return 0;
+}
+
+/*
+ * This function writes the parameters for DSS keys.
* Needs 3 parameters (p,q,g).
*
* Allocates the space used to store the DER data.
@@ -390,6 +453,54 @@ cleanup:
return result;
}
+/*
+ * This function writes the public parameters for DSS keys.
+ * Needs 1 parameter (y).
+ *
+ * Allocates the space used to store the DER data.
+ */
+int _gnutls_x509_write_dsa_public_key( GNUTLS_MPI * params, int params_size,
+ gnutls_datum* der)
+{
+ int result;
+ ASN1_TYPE spk = ASN1_TYPE_EMPTY;
+
+ der->data = NULL;
+ der->size = 0;
+
+ if (params_size < 3) {
+ gnutls_assert();
+ result = GNUTLS_E_INVALID_REQUEST;
+ goto cleanup;
+ }
+
+ if ((result=asn1_create_element
+ (_gnutls_get_gnutls_asn(), "GNUTLS.DSAPublicKey", &spk))
+ != ASN1_SUCCESS) {
+ gnutls_assert();
+ return _gnutls_asn2err(result);
+ }
+
+ result = _gnutls_x509_write_int( spk, "", params[3], 0);
+ if (result < 0) {
+ gnutls_assert();
+ goto cleanup;
+ }
+
+ result = _gnutls_x509_der_encode( spk, "", der, 0);
+ if (result < 0) {
+ gnutls_assert();
+ goto cleanup;
+ }
+
+ asn1_delete_structure(&spk);
+ return 0;
+
+cleanup:
+ asn1_delete_structure(&spk);
+ return result;
+}
+
/* this function reads a (small) unsigned integer
* from asn1 structs. Combines the read and the convertion
diff --git a/lib/x509/mpi.h b/lib/x509/mpi.h
index 471a01c8de..cfa92918f7 100644
--- a/lib/x509/mpi.h
+++ b/lib/x509/mpi.h
@@ -1,3 +1,4 @@
+#include <gnutls_int.h>
#include "x509.h"
int _gnutls_x509_crt_get_mpis( gnutls_x509_crt cert,
@@ -10,6 +11,8 @@ int _gnutls_x509_write_rsa_params( GNUTLS_MPI * params, int params_size,
gnutls_datum* der);
int _gnutls_x509_write_dsa_params( GNUTLS_MPI * params, int params_size,
gnutls_datum* der);
+int _gnutls_x509_write_dsa_public_key( GNUTLS_MPI * params, int params_size,
+ gnutls_datum* der);
int _gnutls_x509_read_uint( ASN1_TYPE node, const char* value,
unsigned int* ret);
@@ -18,3 +21,6 @@ int _gnutls_x509_read_int( ASN1_TYPE node, const char* value,
GNUTLS_MPI* ret_mpi);
int _gnutls_x509_write_int( ASN1_TYPE node, const char* value, GNUTLS_MPI mpi, int lz);
int _gnutls_x509_write_uint32( ASN1_TYPE node, const char* value, uint32 num);
+
+int _gnutls_x509_write_sig_params( ASN1_TYPE dst, const char* dst_name,
+ gnutls_pk_algorithm pk_algorithm, GNUTLS_MPI * params, int params_size);
diff --git a/lib/x509/pkcs12.c b/lib/x509/pkcs12.c
index 9f61e21d0d..27bbe41218 100644
--- a/lib/x509/pkcs12.c
+++ b/lib/x509/pkcs12.c
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2003 Nikos Mavroyanopoulos
+ * Copyright (C) 2004 Free Software Foundation
*
* This file is part of GNUTLS.
*
@@ -129,6 +130,7 @@ int gnutls_pkcs12_init(gnutls_pkcs12 * pkcs12)
&(*pkcs12)->pkcs12);
if (result != ASN1_SUCCESS) {
gnutls_assert();
+ gnutls_free( *pkcs12);
return _gnutls_asn2err(result);
}
return 0; /* success */
@@ -264,7 +266,7 @@ static int oid2bag( const char* oid)
return GNUTLS_BAG_UNKNOWN;
}
-static const char* bag2oid( int bag)
+static const char* bag_to_oid( int bag)
{
switch (bag) {
case GNUTLS_BAG_PKCS8_KEY:
@@ -1050,7 +1052,7 @@ const char* oid;
for (i=0;i<bag->bag_elements;i++) {
- oid = bag2oid( bag->element[i].type);
+ oid = bag_to_oid( bag->element[i].type);
if (oid==NULL) {
gnutls_assert();
continue;
diff --git a/lib/x509/pkcs12_bag.c b/lib/x509/pkcs12_bag.c
index 6b9ab32ba1..466f4e7970 100644
--- a/lib/x509/pkcs12_bag.c
+++ b/lib/x509/pkcs12_bag.c
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2003 Nikos Mavroyanopoulos
+ * Copyright (C) 2004 Free Software Foundation
*
* This file is part of GNUTLS.
*
diff --git a/lib/x509/pkcs12_encr.c b/lib/x509/pkcs12_encr.c
index c1501e62db..921bff9b86 100644
--- a/lib/x509/pkcs12_encr.c
+++ b/lib/x509/pkcs12_encr.c
@@ -1,7 +1,4 @@
-/* This is based on minip12.
- */
-
-/* minip12.c - A minilam pkcs-12 implementation.
+/* minip12.c - A mini pkcs-12 implementation (modified for gnutls)
* Copyright (C) 2002 Free Software Foundation, Inc.
*
* This file some day was part of GnuPG.
diff --git a/lib/x509/pkcs5.c b/lib/x509/pkcs5.c
index 15ce59c05c..c1c745b71e 100644
--- a/lib/x509/pkcs5.c
+++ b/lib/x509/pkcs5.c
@@ -1,5 +1,6 @@
/* pkcs5.c Implementation of Password-Based Cryptography as per PKCS#5
* Copyright (C) 2002,2003 Simon Josefsson
+ * Copyright (C) 2004 Free Software Foundation
*
* This file is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
diff --git a/lib/x509/pkcs7.c b/lib/x509/pkcs7.c
index eb12fc1212..3b969f32fb 100644
--- a/lib/x509/pkcs7.c
+++ b/lib/x509/pkcs7.c
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2003 Nikos Mavroyanopoulos
+ * Copyright (C) 2004 Free Software Foundation
*
* This file is part of GNUTLS.
*
@@ -145,6 +146,7 @@ int gnutls_pkcs7_init(gnutls_pkcs7 * pkcs7)
&(*pkcs7)->pkcs7);
if (result != ASN1_SUCCESS) {
gnutls_assert();
+ gnutls_free( *pkcs7);
return _gnutls_asn2err(result);
}
return 0; /* success */
diff --git a/lib/x509/privkey.c b/lib/x509/privkey.c
index b1dbeec086..4798e221dd 100644
--- a/lib/x509/privkey.c
+++ b/lib/x509/privkey.c
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2003 Nikos Mavroyanopoulos
+ * Copyright (C) 2004 Free Software Foundation
*
* This file is part of GNUTLS.
*
@@ -32,9 +33,11 @@
#include <mpi.h>
#include <extensions.h>
#include <sign.h>
+#include <dsa.h>
#include <verify.h>
static int _encode_rsa( ASN1_TYPE* c2, GNUTLS_MPI* params);
+static int _encode_dsa( ASN1_TYPE* c2, GNUTLS_MPI* params);
/**
* gnutls_x509_privkey_init - This function initializes a gnutls_crl structure
@@ -356,7 +359,9 @@ int gnutls_x509_privkey_import(gnutls_x509_privkey key, const gnutls_datum * dat
return result;
}
-#define FREE_PRIVATE_PARAMS for (i=0;i<RSA_PRIVATE_PARAMS;i++) \
+#define FREE_RSA_PRIVATE_PARAMS for (i=0;i<RSA_PRIVATE_PARAMS;i++) \
+ _gnutls_mpi_release(&key->params[i])
+#define FREE_DSA_PRIVATE_PARAMS for (i=0;i<DSA_PRIVATE_PARAMS;i++) \
_gnutls_mpi_release(&key->params[i])
/**
@@ -389,49 +394,49 @@ int gnutls_x509_privkey_import_rsa_raw(gnutls_x509_privkey key,
siz = m->size;
if (_gnutls_mpi_scan(&key->params[0], m->data, &siz)) {
gnutls_assert();
- FREE_PRIVATE_PARAMS;
+ FREE_RSA_PRIVATE_PARAMS;
return GNUTLS_E_MPI_SCAN_FAILED;
}
siz = e->size;
if (_gnutls_mpi_scan(&key->params[1], e->data, &siz)) {
gnutls_assert();
- FREE_PRIVATE_PARAMS;
+ FREE_RSA_PRIVATE_PARAMS;
return GNUTLS_E_MPI_SCAN_FAILED;
}
siz = d->size;
if (_gnutls_mpi_scan(&key->params[2], d->data, &siz)) {
gnutls_assert();
- FREE_PRIVATE_PARAMS;
+ FREE_RSA_PRIVATE_PARAMS;
return GNUTLS_E_MPI_SCAN_FAILED;
}
siz = p->size;
if (_gnutls_mpi_scan(&key->params[3], p->data, &siz)) {
gnutls_assert();
- FREE_PRIVATE_PARAMS;
+ FREE_RSA_PRIVATE_PARAMS;
return GNUTLS_E_MPI_SCAN_FAILED;
}
siz = q->size;
if (_gnutls_mpi_scan(&key->params[4], q->data, &siz)) {
gnutls_assert();
- FREE_PRIVATE_PARAMS;
+ FREE_RSA_PRIVATE_PARAMS;
return GNUTLS_E_MPI_SCAN_FAILED;
}
siz = u->size;
if (_gnutls_mpi_scan(&key->params[5], u->data, &siz)) {
gnutls_assert();
- FREE_PRIVATE_PARAMS;
+ FREE_RSA_PRIVATE_PARAMS;
return GNUTLS_E_MPI_SCAN_FAILED;
}
ret = _encode_rsa( &key->key, key->params);
if (ret < 0) {
gnutls_assert();
- FREE_PRIVATE_PARAMS;
+ FREE_RSA_PRIVATE_PARAMS;
return ret;
}
@@ -442,6 +447,81 @@ int gnutls_x509_privkey_import_rsa_raw(gnutls_x509_privkey key,
}
+/**
+ * gnutls_x509_privkey_import_dsa_raw - This function will import a raw DSA key
+ * @key: The structure to store the parsed key
+ * @p: holds the p
+ * @q: holds the q
+ * @g: holds the g
+ * @y: holds the y
+ * @x: holds the x
+ *
+ * This function will convert the given DSA raw parameters
+ * to the native gnutls_x509_privkey format. The output will be stored in @key.
+ *
+ **/
+int gnutls_x509_privkey_import_dsa_raw(gnutls_x509_privkey key,
+ const gnutls_datum* p, const gnutls_datum* q,
+ const gnutls_datum* g, const gnutls_datum* y,
+ const gnutls_datum* x)
+{
+ int i = 0, ret;
+ size_t siz = 0;
+
+ if (key == NULL) {
+ gnutls_assert();
+ return GNUTLS_E_INVALID_REQUEST;
+ }
+
+ siz = p->size;
+ if (_gnutls_mpi_scan(&key->params[0], p->data, &siz)) {
+ gnutls_assert();
+ FREE_DSA_PRIVATE_PARAMS;
+ return GNUTLS_E_MPI_SCAN_FAILED;
+ }
+
+ siz = q->size;
+ if (_gnutls_mpi_scan(&key->params[1], q->data, &siz)) {
+ gnutls_assert();
+ FREE_DSA_PRIVATE_PARAMS;
+ return GNUTLS_E_MPI_SCAN_FAILED;
+ }
+
+ siz = g->size;
+ if (_gnutls_mpi_scan(&key->params[2], g->data, &siz)) {
+ gnutls_assert();
+ FREE_DSA_PRIVATE_PARAMS;
+ return GNUTLS_E_MPI_SCAN_FAILED;
+ }
+
+ siz = y->size;
+ if (_gnutls_mpi_scan(&key->params[3], y->data, &siz)) {
+ gnutls_assert();
+ FREE_DSA_PRIVATE_PARAMS;
+ return GNUTLS_E_MPI_SCAN_FAILED;
+ }
+
+ siz = x->size;
+ if (_gnutls_mpi_scan(&key->params[4], x->data, &siz)) {
+ gnutls_assert();
+ FREE_DSA_PRIVATE_PARAMS;
+ return GNUTLS_E_MPI_SCAN_FAILED;
+ }
+
+ ret = _encode_dsa( &key->key, key->params);
+ if (ret < 0) {
+ gnutls_assert();
+ FREE_DSA_PRIVATE_PARAMS;
+ return ret;
+ }
+
+ key->params_size = DSA_PRIVATE_PARAMS;
+ key->pk_algorithm = GNUTLS_PK_DSA;
+
+ return 0;
+
+}
+
/**
* gnutls_x509_privkey_get_pk_algorithm - This function returns the key's PublicKey algorithm
@@ -623,6 +703,106 @@ int gnutls_x509_privkey_export_rsa_raw(gnutls_x509_privkey key,
}
+/**
+ * gnutls_x509_privkey_export_dsa_raw - This function will export the DSA private key
+ * @params: a structure that holds the DSA parameters
+ * @p: will hold the p
+ * @q: will hold the q
+ * @g: will hold the g
+ * @y: will hold the y
+ * @x: will hold the x
+ *
+ * This function will export the DSA private 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.
+ *
+ **/
+int gnutls_x509_privkey_export_dsa_raw(gnutls_x509_privkey key,
+ gnutls_datum * p, gnutls_datum *q,
+ gnutls_datum *g, gnutls_datum *y, gnutls_datum* x)
+{
+ size_t siz;
+
+ if (key == NULL) {
+ gnutls_assert();
+ return GNUTLS_E_INVALID_REQUEST;
+ }
+
+ /* P */
+ siz = 0;
+ _gnutls_mpi_print(NULL, &siz, key->params[0]);
+
+ p->data = gnutls_malloc(siz);
+ if (p->data == NULL) {
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+
+ p->size = siz;
+ _gnutls_mpi_print( p->data, &siz, key->params[0]);
+
+ /* Q */
+ siz = 0;
+ _gnutls_mpi_print(NULL, &siz, key->params[1]);
+
+ q->data = gnutls_malloc(siz);
+ if (q->data == NULL) {
+ _gnutls_free_datum( p);
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+
+ q->size = siz;
+ _gnutls_mpi_print( q->data, &siz, key->params[1]);
+
+ /* G */
+ siz = 0;
+ _gnutls_mpi_print(NULL, &siz, key->params[2]);
+
+ g->data = gnutls_malloc(siz);
+ if (g->data == NULL) {
+ _gnutls_free_datum( q);
+ _gnutls_free_datum( p);
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+
+ g->size = siz;
+ _gnutls_mpi_print( g->data, &siz, key->params[2]);
+
+ /* Y */
+ siz = 0;
+ _gnutls_mpi_print(NULL, &siz, key->params[3]);
+
+ y->data = gnutls_malloc(siz);
+ if (y->data == NULL) {
+ _gnutls_free_datum( g);
+ _gnutls_free_datum( q);
+ _gnutls_free_datum( p);
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+
+ y->size = siz;
+ _gnutls_mpi_print(y->data, &siz, key->params[3]);
+
+ /* X */
+ siz = 0;
+ _gnutls_mpi_print(NULL, &siz, key->params[4]);
+
+ x->data = gnutls_malloc(siz);
+ if (x->data == NULL) {
+ _gnutls_free_datum( p);
+ _gnutls_free_datum( q);
+ _gnutls_free_datum( g);
+ _gnutls_free_datum( y);
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+
+ x->size = siz;
+ _gnutls_mpi_print(x->data, &siz, key->params[4]);
+
+ return 0;
+
+}
+
+
/* Encodes the RSA parameters into an ASN.1 RSA private key structure.
*/
static int _encode_rsa( ASN1_TYPE* c2, GNUTLS_MPI* params)
@@ -644,28 +824,28 @@ static int _encode_rsa( ASN1_TYPE* c2, GNUTLS_MPI* params)
/* Now generate exp1 and exp2
*/
- exp1 = _gnutls_mpi_alloc_like( params[0]); /* like modulus */
+ exp1 = _gnutls_mpi_salloc_like( params[0]); /* like modulus */
if (exp1 == NULL) {
gnutls_assert();
result = GNUTLS_E_MEMORY_ERROR;
goto cleanup;
}
- exp2 = _gnutls_mpi_alloc_like( params[0]);
+ exp2 = _gnutls_mpi_salloc_like( params[0]);
if (exp2 == NULL) {
gnutls_assert();
result = GNUTLS_E_MEMORY_ERROR;
goto cleanup;
}
- q1 = _gnutls_mpi_alloc_like( params[4]);
+ q1 = _gnutls_mpi_salloc_like( params[4]);
if (q1 == NULL) {
gnutls_assert();
result = GNUTLS_E_MEMORY_ERROR;
goto cleanup;
}
- p1 = _gnutls_mpi_alloc_like( params[3]);
+ p1 = _gnutls_mpi_salloc_like( params[3]);
if (p1 == NULL) {
gnutls_assert();
result = GNUTLS_E_MEMORY_ERROR;
@@ -689,13 +869,13 @@ static int _encode_rsa( ASN1_TYPE* c2, GNUTLS_MPI* params)
/* Encoding phase.
* allocate data enough to hold everything
*/
- all_data = gnutls_alloca( total);
+ all_data = gnutls_secure_malloc( total);
if (all_data == NULL) {
gnutls_assert();
result = GNUTLS_E_MEMORY_ERROR;
goto cleanup;
}
-
+
p = all_data;
m_data = p; p+= size[0];
pube_data = p; p+= size[1];
@@ -704,7 +884,7 @@ static int _encode_rsa( ASN1_TYPE* c2, GNUTLS_MPI* params)
p2_data = p; p+= size[4];
u_data = p; p+= size[5];
exp1_data = p; p+= size[6];
- exp2_data = p;
+ exp2_data = p;
_gnutls_mpi_print_lz( m_data, &size[0], params[0]);
_gnutls_mpi_print_lz( pube_data, &size[1], params[1]);
@@ -792,7 +972,7 @@ static int _encode_rsa( ASN1_TYPE* c2, GNUTLS_MPI* params)
goto cleanup;
}
- gnutls_afree(all_data);
+ gnutls_free(all_data);
if ((result = asn1_write_value(*c2, "otherPrimeInfos",
NULL, 0)) != ASN1_SUCCESS) {
@@ -816,7 +996,118 @@ static int _encode_rsa( ASN1_TYPE* c2, GNUTLS_MPI* params)
_gnutls_mpi_release( &q1);
_gnutls_mpi_release( &p1);
asn1_delete_structure(c2);
- gnutls_afree( all_data);
+ gnutls_free( all_data);
+
+ return result;
+}
+
+/* Encodes the DSA parameters into an ASN.1 DSAPrivateKey structure.
+ */
+static int _encode_dsa( ASN1_TYPE* c2, GNUTLS_MPI* params)
+{
+ int result, i;
+ size_t size[DSA_PRIVATE_PARAMS], total;
+ opaque* p_data, *q_data, *g_data, *x_data, *y_data;
+ opaque * all_data = NULL, *p;
+ opaque null = '\0';
+
+ /* Read all the sizes */
+ total = 0;
+ for (i=0;i<DSA_PRIVATE_PARAMS;i++) {
+ _gnutls_mpi_print_lz( NULL, &size[i], params[i]);
+ total += size[i];
+ }
+
+ /* Encoding phase.
+ * allocate data enough to hold everything
+ */
+ all_data = gnutls_secure_malloc( total);
+ if (all_data == NULL) {
+ gnutls_assert();
+ result = GNUTLS_E_MEMORY_ERROR;
+ goto cleanup;
+ }
+
+ p = all_data;
+ p_data = p; p += size[0];
+ q_data = p; p += size[1];
+ g_data = p; p += size[2];
+ y_data = p; p += size[3];
+ x_data = p;
+
+ _gnutls_mpi_print_lz( p_data, &size[0], params[0]);
+ _gnutls_mpi_print_lz( q_data, &size[1], params[1]);
+ _gnutls_mpi_print_lz( g_data, &size[2], params[2]);
+ _gnutls_mpi_print_lz( y_data, &size[3], params[3]);
+ _gnutls_mpi_print_lz( x_data, &size[4], params[4]);
+
+ /* Ok. Now we have the data. Create the asn1 structures
+ */
+
+ if ((result = asn1_create_element
+ (_gnutls_get_gnutls_asn(), "GNUTLS.DSAPrivateKey", c2))
+ != ASN1_SUCCESS) {
+ gnutls_assert();
+ result = _gnutls_asn2err(result);
+ goto cleanup;
+ }
+
+ /* Write PRIME
+ */
+ if ((result = asn1_write_value(*c2, "p",
+ p_data, size[0])) != ASN1_SUCCESS)
+ {
+ gnutls_assert();
+ result = _gnutls_asn2err(result);
+ goto cleanup;
+ }
+
+ if ((result = asn1_write_value(*c2, "q",
+ q_data, size[1])) != ASN1_SUCCESS)
+ {
+ gnutls_assert();
+ result = _gnutls_asn2err(result);
+ goto cleanup;
+ }
+
+ if ((result = asn1_write_value(*c2, "g",
+ g_data, size[2])) != ASN1_SUCCESS)
+ {
+ gnutls_assert();
+ result = _gnutls_asn2err(result);
+ goto cleanup;
+ }
+
+ if ((result = asn1_write_value(*c2, "Y",
+ y_data, size[3])) != ASN1_SUCCESS)
+ {
+ gnutls_assert();
+ result = _gnutls_asn2err(result);
+ goto cleanup;
+ }
+
+ if ((result = asn1_write_value(*c2, "priv",
+ x_data, size[4])) != ASN1_SUCCESS)
+ {
+ gnutls_assert();
+ result = _gnutls_asn2err(result);
+ goto cleanup;
+ }
+
+ gnutls_free(all_data);
+
+ if ((result = asn1_write_value(*c2, "version",
+ &null, 1)) != ASN1_SUCCESS) {
+ gnutls_assert();
+ result = _gnutls_asn2err(result);
+ goto cleanup;
+ }
+
+ return 0;
+
+ cleanup:
+ asn1_delete_structure(c2);
+ gnutls_free( all_data);
return result;
}
@@ -830,8 +1121,7 @@ static int _encode_rsa( ASN1_TYPE* c2, GNUTLS_MPI* params)
* @flags: unused for now. Must be 0.
*
* This function will generate a random private key. Note that
- * this function must be called on an empty private key. Currently only RSA
- * keys can be generated.
+ * this function must be called on an empty private key.
*
* Returns 0 on success or a negative value on error.
*
@@ -839,7 +1129,8 @@ static int _encode_rsa( ASN1_TYPE* c2, GNUTLS_MPI* params)
int gnutls_x509_privkey_generate( gnutls_x509_privkey key, gnutls_pk_algorithm algo,
unsigned int bits, unsigned int flags)
{
-int ret;
+int ret, params_len;
+int i;
if (key == NULL) {
gnutls_assert();
@@ -848,10 +1139,23 @@ int ret;
switch( algo) {
case GNUTLS_PK_DSA:
- return GNUTLS_E_UNIMPLEMENTED_FEATURE;
- case GNUTLS_PK_RSA:
- ret = _gnutls_rsa_generate_params( key->params, bits);
+ ret = _gnutls_dsa_generate_params( key->params, &params_len, bits);
+ if (ret < 0) {
+ gnutls_assert();
+ return ret;
+ }
+ ret = _encode_dsa( &key->key, key->params);
+ if (ret < 0) {
+ gnutls_assert();
+ goto cleanup;
+ }
+ key->params_size = params_len;
+ key->pk_algorithm = GNUTLS_PK_DSA;
+
+ break;
+ case GNUTLS_PK_RSA:
+ ret = _gnutls_rsa_generate_params( key->params, &params_len, bits);
if (ret < 0) {
gnutls_assert();
return ret;
@@ -862,7 +1166,7 @@ int ret;
gnutls_assert();
goto cleanup;
}
- key->params_size = 6;
+ key->params_size = params_len;
key->pk_algorithm = GNUTLS_PK_RSA;
break;
@@ -876,12 +1180,8 @@ int ret;
cleanup:
key->pk_algorithm = GNUTLS_PK_UNKNOWN;
key->params_size = 0;
- _gnutls_mpi_release(&key->params[0]);
- _gnutls_mpi_release(&key->params[1]);
- _gnutls_mpi_release(&key->params[2]);
- _gnutls_mpi_release(&key->params[3]);
- _gnutls_mpi_release(&key->params[4]);
- _gnutls_mpi_release(&key->params[5]);
+ for (i=0;i<params_len;i++)
+ _gnutls_mpi_release(&key->params[i]);
return ret;
}
@@ -930,7 +1230,7 @@ gnutls_datum der = { NULL, 0 };
goto cleanup;
}
} else if (key->pk_algorithm == GNUTLS_PK_DSA) {
- result = _gnutls_x509_write_dsa_params( key->params, key->params_size, &der);
+ result = _gnutls_x509_write_dsa_public_key( key->params, key->params_size, &der);
if (result < 0) {
gnutls_assert();
goto cleanup;
diff --git a/lib/x509/privkey_pkcs8.c b/lib/x509/privkey_pkcs8.c
index 433436fa3b..93a67d41d6 100644
--- a/lib/x509/privkey_pkcs8.c
+++ b/lib/x509/privkey_pkcs8.c
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2003 Nikos Mavroyanopoulos
+ * Copyright (C) 2004 Free Software Foundation
*
* This file is part of GNUTLS.
*
@@ -605,7 +606,7 @@ int decode_pkcs8_key(const gnutls_datum * raw_key,
gnutls_x509_privkey pkey, ASN1_TYPE* out)
{
int result, len;
- opaque enc_oid[64];
+ char enc_oid[64];
gnutls_datum tmp;
ASN1_TYPE pbes2_asn = ASN1_TYPE_EMPTY, pkcs8_asn = ASN1_TYPE_EMPTY;
ASN1_TYPE ret_asn;
@@ -1701,7 +1702,7 @@ int _gnutls_pkcs7_decrypt_data(const gnutls_datum * data,
gnutls_datum * dec)
{
int result, len;
- opaque enc_oid[64];
+ char enc_oid[64];
gnutls_datum tmp;
ASN1_TYPE pbes2_asn = ASN1_TYPE_EMPTY, pkcs7_asn = ASN1_TYPE_EMPTY;
int params_start, params_end, params_len;
diff --git a/lib/x509/rc2.c b/lib/x509/rc2.c
index b993d44793..982d556f25 100644
--- a/lib/x509/rc2.c
+++ b/lib/x509/rc2.c
@@ -1,5 +1,6 @@
/* rc2.c - The RC2 stream cipher
* Copyright (C) 2003 Nikos Mavroyanopoulos
+ * Copyright (C) 2004 Free Software Foundation
*
* This file is part of GNUTLS.
*
diff --git a/lib/x509/rfc2818_hostname.c b/lib/x509/rfc2818_hostname.c
index 7c19c228db..d07b113e9c 100644
--- a/lib/x509/rfc2818_hostname.c
+++ b/lib/x509/rfc2818_hostname.c
@@ -1,6 +1,7 @@
/*
* Copyright (C) 2002 Andrew McDonald
* Portions Copyright 2003 Nikos Mavroyanopoulos
+ * Copyright (C) 2004 Free Software Foundation
*
* This file is part of GNUTLS.
*
@@ -25,80 +26,8 @@
#include <x509.h>
#include <dn.h>
#include <common.h>
-#include <gnutls/compat8.h>
#include <rfc2818.h>
-
-/*-
- * gnutls_x509_check_certificates_hostname - This function compares the given hostname with the hostname in the certificate
- * @cert: should contain a DER encoded certificate
- * @hostname: A null terminated string that contains a DNS name
- *
- * This function will check if the given certificate's subject matches
- * the given hostname. This is a basic implementation of the matching
- * described in RFC2818 (HTTPS), which takes into account wildcards.
- *
- * Returns non zero on success, and zero on failure.
- *
- -*/
-int gnutls_x509_check_certificates_hostname(const gnutls_datum * cert,
- const char *hostname)
-{
- char dnsname[MAX_CN];
- int dnsnamesize;
- int found_dnsname = 0;
- int ret = 0;
- gnutls_x509_dn dn;
- int i = 0;
-
- /* try matching against:
- * 1) a DNS name as an alternative name (subjectAltName) extension
- * in the certificate
- * 2) the common name (CN) in the certificate
- *
- * either of these may be of the form: *.domain.tld
- *
- * only try (2) if there is no subjectAltName extension of
- * type dNSName
- */
-
- /* Check through all included subjectAltName extensions, comparing
- * against all those of type dNSName.
- */
- for (i = 0; !(ret < 0); i++) {
-
- dnsnamesize = MAX_CN;
- ret =
- gnutls_x509_extract_certificate_subject_alt_name(cert, i,
- dnsname,
- &dnsnamesize);
-
- if (ret == GNUTLS_SAN_DNSNAME) {
- found_dnsname = 1;
- if (_gnutls_hostname_compare(dnsname, hostname)) {
- return 1;
- }
- }
-
- }
-
- if (!found_dnsname) {
- /* not got the necessary extension, use CN instead
- */
- if (gnutls_x509_extract_certificate_dn(cert, &dn) != 0) {
- /* got an error, can't find a name
- */
- return 0;
- }
-
- if (_gnutls_hostname_compare(dn.common_name, hostname)) {
- return 1;
- }
- }
-
- /* not found a matching name
- */
- return 0;
-}
+#include <gnutls_errors.h>
/* compare hostname against certificate, taking account of wildcards
* return 1 on success or 0 on error
@@ -144,7 +73,8 @@ int _gnutls_hostname_compare(const char *certname, const char *hostname)
*
* This function will check if the given certificate's subject matches
* the given hostname. This is a basic implementation of the matching
- * described in RFC2818 (HTTPS), which takes into account wildcards.
+ * described in RFC2818 (HTTPS), which takes into account wildcards,
+ * and the subject alternative name PKIX extension.
*
* Returns non zero on success, and zero on failure.
*
@@ -183,7 +113,7 @@ int gnutls_x509_crt_check_hostname(gnutls_x509_crt cert,
if (ret == GNUTLS_SAN_DNSNAME) {
found_dnsname = 1;
if (_gnutls_hostname_compare(dnsname, hostname)) {
- return 1;
+ return GNUTLS_E_NAME_DOES_NOT_MATCH;
}
}
@@ -194,14 +124,14 @@ int gnutls_x509_crt_check_hostname(gnutls_x509_crt cert,
*/
dnsnamesize = sizeof(dnsname);
if (gnutls_x509_crt_get_dn_by_oid(cert, OID_X520_COMMON_NAME, 0,
- 0, dnsname, &dnsnamesize) != 0) {
+ 0, dnsname, &dnsnamesize) < 0) {
/* got an error, can't find a name
*/
- return 0;
+ return GNUTLS_E_NAME_DOES_NOT_MATCH;
}
if (_gnutls_hostname_compare(dnsname, hostname)) {
- return 1;
+ return GNUTLS_E_NAME_DOES_NOT_MATCH;
}
}
diff --git a/lib/x509/sign.c b/lib/x509/sign.c
index 3a45b0ecb1..b63724e060 100644
--- a/lib/x509/sign.c
+++ b/lib/x509/sign.c
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2003 Nikos Mavroyanopoulos <nmav@hellug.gr>
+ * Copyright (C) 2004 Free Software Foundation
*
* This file is part of GNUTLS.
*
@@ -52,7 +53,7 @@ ASN1_TYPE dinfo = ASN1_TYPE_EMPTY;
int result;
const char* algo;
- algo = _gnutls_x509_mac2oid( hash);
+ algo = _gnutls_x509_mac_to_oid( hash);
if (algo == NULL) {
gnutls_assert();
return GNUTLS_E_UNKNOWN_PK_ALGORITHM;
@@ -116,7 +117,7 @@ const char* algo;
* params[1] is public key
*/
static int
-_pkcs1_rsa_sign( gnutls_mac_algorithm hash, const gnutls_datum* text,
+pkcs1_rsa_sign( gnutls_mac_algorithm hash, const gnutls_datum* text,
GNUTLS_MPI *params, int params_len, gnutls_datum* signature)
{
int ret;
@@ -154,6 +155,35 @@ _pkcs1_rsa_sign( gnutls_mac_algorithm hash, const gnutls_datum* text,
return 0;
}
+static int
+dsa_sign( const gnutls_datum* text,
+ GNUTLS_MPI *params, int params_len, gnutls_datum* signature)
+{
+ int ret;
+ opaque _digest[MAX_HASH_SIZE];
+ GNUTLS_HASH_HANDLE hd;
+ gnutls_datum digest;
+
+ hd = _gnutls_hash_init( GNUTLS_MAC_SHA);
+ if (hd == NULL) {
+ gnutls_assert();
+ return GNUTLS_E_HASH_FAILED;
+ }
+
+ _gnutls_hash( hd, text->data, text->size);
+ _gnutls_hash_deinit( hd, _digest);
+
+ digest.data = _digest;
+ digest.size = 20;
+
+ if ( (ret=_gnutls_sign( GNUTLS_PK_DSA, params, params_len, &digest, signature)) < 0) {
+ gnutls_assert();
+ return ret;
+ }
+
+ return 0;
+}
+
/* Signs the given data using the parameters from the signer's
* private key.
*
@@ -171,7 +201,7 @@ int ret;
switch( signer->pk_algorithm)
{
case GNUTLS_PK_RSA:
- ret = _pkcs1_rsa_sign( hash, tbs, signer->params, signer->params_size,
+ ret = pkcs1_rsa_sign( hash, tbs, signer->params, signer->params_size,
signature);
if (ret < 0) {
gnutls_assert();
@@ -180,7 +210,7 @@ int ret;
return 0;
break;
case GNUTLS_PK_DSA:
- ret = _gnutls_dsa_sign( signature, tbs, signer->params, signer->params_size);
+ ret = dsa_sign( tbs, signer->params, signer->params_size, signature);
if (ret < 0) {
gnutls_assert();
return ret;
@@ -233,4 +263,82 @@ gnutls_datum tbs;
return result;
}
+/*-
+ * _gnutls_x509_pkix_sign - This function will sign a CRL or a certificate with a key
+ * @src: should contain an ASN1_TYPE
+ * @issuer: is the certificate of the certificate issuer
+ * @issuer_key: holds the issuer's private key
+ *
+ * This function will sign a CRL or a certificate with the issuer's private key, and
+ * will copy the issuer's information into the CRL or certificate.
+ *
+ * Returns 0 on success.
+ *
+ -*/
+int _gnutls_x509_pkix_sign(ASN1_TYPE src, const char* src_name,
+ gnutls_x509_crt issuer, gnutls_x509_privkey issuer_key)
+{
+int result;
+gnutls_datum signature;
+char name[128];
+
+ /* Step 1. Copy the issuer's name into the certificate.
+ */
+ _gnutls_str_cpy( name, sizeof(name), src_name);
+ _gnutls_str_cat( name, sizeof(name), ".issuer");
+
+ result = _gnutls_asn1_copy_node( &src, name,
+ issuer->cert, "tbsCertificate.subject");
+ if (result < 0) {
+ gnutls_assert();
+ return result;
+ }
+
+ /* Step 1.5. Write the signature stuff in the tbsCertificate.
+ */
+ _gnutls_str_cpy( name, sizeof(name), src_name);
+ _gnutls_str_cat( name, sizeof(name), ".signature");
+
+ result = _gnutls_x509_write_sig_params( src, name,
+ issuer_key->pk_algorithm, issuer_key->params, issuer_key->params_size);
+ if (result < 0) {
+ gnutls_assert();
+ return result;
+ }
+
+ /* Step 2. Sign the certificate.
+ */
+ result = _gnutls_x509_sign_tbs( src, src_name, GNUTLS_MAC_SHA,
+ issuer_key, &signature);
+
+ if (result < 0) {
+ gnutls_assert();
+ return result;
+ }
+
+ /* write the signature (bits)
+ */
+ result = asn1_write_value( src, "signature", signature.data, signature.size*8);
+
+ _gnutls_free_datum( &signature);
+
+ if (result != ASN1_SUCCESS) {
+ gnutls_assert();
+ return _gnutls_asn2err(result);
+ }
+
+ /* Step 3. Move up and write the AlgorithmIdentifier, which is also
+ * the same.
+ */
+
+ result = _gnutls_x509_write_sig_params( src, "signatureAlgorithm",
+ issuer_key->pk_algorithm, issuer_key->params, issuer_key->params_size);
+ if (result < 0) {
+ gnutls_assert();
+ return result;
+ }
+
+ return 0;
+}
+
#endif
diff --git a/lib/x509/sign.h b/lib/x509/sign.h
index dd6936f346..08e0475f72 100644
--- a/lib/x509/sign.h
+++ b/lib/x509/sign.h
@@ -2,3 +2,5 @@ int _gnutls_x509_sign( const gnutls_datum* tbs, gnutls_mac_algorithm hash,
gnutls_x509_privkey signer, gnutls_datum* signature);
int _gnutls_x509_sign_tbs( ASN1_TYPE cert, const char* tbs_name,
gnutls_mac_algorithm hash, gnutls_x509_privkey signer, gnutls_datum* signature);
+int _gnutls_x509_pkix_sign(ASN1_TYPE src, const char* src_name,
+ gnutls_x509_crt issuer, gnutls_x509_privkey issuer_key);
diff --git a/lib/x509/verify.c b/lib/x509/verify.c
index 24c7cdb702..9b3f658b00 100644
--- a/lib/x509/verify.c
+++ b/lib/x509/verify.c
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2003 Nikos Mavroyanopoulos <nmav@hellug.gr>
+ * Copyright (C) 2004 Free Software Foundation
*
* This file is part of GNUTLS.
*
@@ -459,6 +460,34 @@ _pkcs1_rsa_verify_sig( const gnutls_datum* text, const gnutls_datum* signature,
return 0;
}
+/* Hashes input data and verifies a DSA signature.
+ */
+static int
+dsa_verify_sig( const gnutls_datum* text, const gnutls_datum* signature,
+ GNUTLS_MPI *params, int params_len)
+{
+ int ret;
+ opaque _digest[MAX_HASH_SIZE];
+ gnutls_datum digest;
+ GNUTLS_HASH_HANDLE hd;
+
+ hd = _gnutls_hash_init( GNUTLS_MAC_SHA);
+ if (hd == NULL) {
+ gnutls_assert();
+ return GNUTLS_E_HASH_FAILED;
+ }
+
+ _gnutls_hash( hd, text->data, text->size);
+ _gnutls_hash_deinit( hd, _digest);
+
+ digest.data = _digest;
+ digest.size = 20;
+
+ ret = _gnutls_dsa_verify( &digest, signature, params, params_len);
+
+ return ret;
+}
+
/* Verifies the signature data, and returns 0 if not verified,
* or 1 otherwise.
*/
@@ -479,7 +508,7 @@ static int verify_sig( const gnutls_datum* tbs, const gnutls_datum* signature,
break;
case GNUTLS_PK_DSA:
- if (_gnutls_dsa_verify( tbs, signature, issuer_params, issuer_params_size)!=0) {
+ if (dsa_verify_sig( tbs, signature, issuer_params, issuer_params_size)!=0) {
gnutls_assert();
return 0;
}
diff --git a/lib/x509/x509.c b/lib/x509/x509.c
index d6d78592af..96096d6aaf 100644
--- a/lib/x509/x509.c
+++ b/lib/x509/x509.c
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2003 Nikos Mavroyanopoulos
+ * Copyright (C) 2004 Free Software Foundation
*
* This file is part of GNUTLS.
*
@@ -57,6 +58,7 @@ int gnutls_x509_crt_init(gnutls_x509_crt * cert)
&(*cert)->cert);
if (result != ASN1_SUCCESS) {
gnutls_assert();
+ gnutls_free( *cert);
return _gnutls_asn2err(result);
}
return 0; /* success */
@@ -214,7 +216,7 @@ int gnutls_x509_crt_import(gnutls_x509_crt cert, const gnutls_datum * data,
* gnutls_x509_crt_get_issuer_dn - This function returns the Certificate's issuer distinguished name
* @cert: should contain a gnutls_x509_crt structure
* @buf: a pointer to a structure to hold the name (may be null)
- * @sizeof_buf: initialy holds the size of 'buf'
+ * @sizeof_buf: initially holds the size of @buf
*
* This function will copy the name of the Certificate issuer in the provided buffer. The name
* will be in the form "C=xxxx,O=yyyy,CN=zzzz" as described in RFC2253. The output
@@ -246,7 +248,7 @@ int gnutls_x509_crt_get_issuer_dn(gnutls_x509_crt cert, char *buf,
* @indx: In case multiple same OIDs exist in the RDN, this specifies which to send. Use zero to get the first one.
* @raw_flag: If non zero returns the raw DER data of the DN part.
* @buf: a pointer to a structure to hold the name (may be null)
- * @sizeof_buf: initialy holds the size of @buf
+ * @sizeof_buf: initially holds the size of @buf
*
* This function will extract the part of the name of the Certificate issuer specified
* by the given OID. The output will be encoded as described in RFC2253. The output
@@ -281,7 +283,7 @@ int gnutls_x509_crt_get_issuer_dn_by_oid(gnutls_x509_crt cert, const char* oid,
* @cert: should contain a gnutls_x509_crt structure
* @indx: This specifies which OID to return. Use zero to get the first one.
* @oid: a pointer to a buffer to hold the OID (may be null)
- * @sizeof_oid: initialy holds the size of @oid
+ * @sizeof_oid: initially holds the size of @oid
*
* This function will extract the OIDs of the name of the Certificate issuer specified
* by the given index.
@@ -309,7 +311,7 @@ int gnutls_x509_crt_get_issuer_dn_oid(gnutls_x509_crt cert,
* gnutls_x509_crt_get_dn - This function returns the Certificate's distinguished name
* @cert: should contain a gnutls_x509_crt structure
* @buf: a pointer to a structure to hold the name (may be null)
- * @sizeof_buf: initialy holds the size of @buf
+ * @sizeof_buf: initially holds the size of @buf
*
* This function will copy the name of the Certificate in the provided buffer. The name
* will be in the form "C=xxxx,O=yyyy,CN=zzzz" as described in RFC2253. The output
@@ -341,7 +343,7 @@ int gnutls_x509_crt_get_dn(gnutls_x509_crt cert, char *buf,
* @indx: In case multiple same OIDs exist in the RDN, this specifies which to send. Use zero to get the first one.
* @raw_flag: If non zero returns the raw DER data of the DN part.
* @buf: a pointer to a structure to hold the name (may be null)
- * @sizeof_buf: initialy holds the size of @buf
+ * @sizeof_buf: initially holds the size of @buf
*
* This function will extract the part of the name of the Certificate subject, specified
* by the given OID. The output
@@ -376,7 +378,7 @@ int gnutls_x509_crt_get_dn_by_oid(gnutls_x509_crt cert, const char* oid,
* @cert: should contain a gnutls_x509_crt structure
* @indx: This specifies which OID to return. Use zero to get the first one.
* @oid: a pointer to a buffer to hold the OID (may be null)
- * @sizeof_oid: initialy holds the size of @oid
+ * @sizeof_oid: initially holds the size of @oid
*
* This function will extract the OIDs of the name of the Certificate subject specified
* by the given index.
@@ -404,7 +406,7 @@ int gnutls_x509_crt_get_dn_oid(gnutls_x509_crt cert,
* gnutls_x509_crt_get_signature_algorithm - This function returns the Certificate's signature algorithm
* @cert: should contain a gnutls_x509_crt structure
*
- * This function will return a value of the gnutls_pk_algorithm enumeration that
+ * This function will return a value of the gnutls_sign_algorithm enumeration that
* is the signature algorithm.
*
* Returns a negative value on error.
@@ -430,7 +432,7 @@ int gnutls_x509_crt_get_signature_algorithm(gnutls_x509_crt cert)
return result;
}
- result = _gnutls_x509_oid2sign_algorithm( sa.data, NULL);
+ result = _gnutls_x509_oid2sign_algorithm( sa.data);
_gnutls_free_datum( &sa);
@@ -537,7 +539,82 @@ int gnutls_x509_crt_get_serial(gnutls_x509_crt cert, void* result,
}
return 0;
+}
+
+/**
+ * gnutls_x509_crt_get_subject_key_id - This function returns the certificate's key identifier
+ * @cert: should contain a gnutls_x509_crt structure
+ * @result: The place where the identifier will be copied
+ * @result_size: Holds the size of the result field.
+ * @critical: will be non zero if the extension is marked as critical (may be null)
+ *
+ * This function will return the X.509v3 certificate's subject key identifier.
+ * This is obtained by the X.509 Subject Key identifier extension
+ * field (2.5.29.14).
+ *
+ * Returns 0 on success and a negative value in case of an error.
+ *
+ **/
+int gnutls_x509_crt_get_subject_key_id(gnutls_x509_crt cert, void* ret,
+ size_t* ret_size, unsigned int* critical)
+{
+ int result, len;
+ gnutls_datum id;
+ ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
+
+ if (cert==NULL) {
+ gnutls_assert();
+ return GNUTLS_E_INVALID_REQUEST;
+ }
+
+
+ if (ret) memset(ret, 0, *ret_size);
+ else *ret_size = 0;
+
+ if ((result =
+ _gnutls_x509_crt_get_extension(cert, "2.5.29.14", 0, &id, critical)) < 0) {
+ return result;
+ }
+
+ if (id.size == 0 || id.data==NULL) {
+ gnutls_assert();
+ return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
+ }
+
+ result=asn1_create_element
+ (_gnutls_get_pkix(), "PKIX1.SubjectKeyIdentifier", &c2);
+ if (result != ASN1_SUCCESS) {
+ gnutls_assert();
+ _gnutls_free_datum( &id);
+ return _gnutls_asn2err(result);
+ }
+
+ result = asn1_der_decoding(&c2, id.data, id.size, NULL);
+ _gnutls_free_datum( &id);
+
+ if (result != ASN1_SUCCESS) {
+ gnutls_assert();
+ asn1_delete_structure(&c2);
+ return _gnutls_asn2err(result);
+ }
+
+ len = *ret_size;
+ result =
+ asn1_read_value(c2, "", ret, &len);
+
+ *ret_size = len;
+ asn1_delete_structure(&c2);
+
+ if (result == ASN1_VALUE_NOT_FOUND || result == ASN1_ELEMENT_NOT_FOUND) {
+ return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
+ }
+
+ if (result != ASN1_SUCCESS) {
+ gnutls_assert();
+ return _gnutls_asn2err(result);
+ }
+ return 0;
}
/**
@@ -578,6 +655,66 @@ int gnutls_x509_crt_get_pk_algorithm( gnutls_x509_crt cert, unsigned int* bits)
}
+/* returns the type and the name.
+ */
+static int parse_general_name( ASN1_TYPE src, const char* src_name,
+ int seq, void* name, size_t *name_size)
+{
+int len;
+char num[MAX_INT_DIGITS];
+char nptr[128];
+int result;
+opaque choice_type[128];
+gnutls_x509_subject_alt_name type;
+
+ seq++; /* 0->1, 1->2 etc */
+ _gnutls_int2str( seq, num);
+
+ _gnutls_str_cpy( nptr, sizeof(nptr), src_name);
+ if (src_name[0] != 0) _gnutls_str_cat( nptr, sizeof(nptr), ".");
+
+ _gnutls_str_cat( nptr, sizeof(nptr), "?");
+ _gnutls_str_cat( nptr, sizeof(nptr), num);
+
+ len = sizeof(choice_type);
+ result =
+ asn1_read_value(src, nptr, choice_type, &len);
+
+ if (result == ASN1_VALUE_NOT_FOUND || result == ASN1_ELEMENT_NOT_FOUND) {
+ return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
+ }
+
+ if (result != ASN1_SUCCESS) {
+ gnutls_assert();
+ return _gnutls_asn2err(result);
+ }
+
+
+ type = _gnutls_x509_san_find_type( choice_type);
+ if (type == (gnutls_x509_subject_alt_name)-1) {
+ gnutls_assert();
+ return GNUTLS_E_X509_UNKNOWN_SAN;
+ }
+
+ _gnutls_str_cat( nptr, sizeof(nptr), ".");
+ _gnutls_str_cat( nptr, sizeof(nptr), choice_type);
+
+ len = *name_size;
+ result =
+ asn1_read_value(src, nptr, name, &len);
+ *name_size = len;
+
+ if (result==ASN1_MEM_ERROR)
+ return GNUTLS_E_SHORT_MEMORY_BUFFER;
+
+ if (result != ASN1_SUCCESS) {
+ gnutls_assert();
+ return _gnutls_asn2err(result);
+ }
+
+ return type;
+}
+
/**
* gnutls_x509_crt_get_subject_alt_name - This function returns the certificate's alternative name, if any
* @cert: should contain a gnutls_x509_crt structure
@@ -602,15 +739,11 @@ int gnutls_x509_crt_get_pk_algorithm( gnutls_x509_crt cert, unsigned int* bits)
*
**/
int gnutls_x509_crt_get_subject_alt_name(gnutls_x509_crt cert,
- int seq, void *ret, size_t *ret_size, unsigned int *critical)
+ unsigned int seq, void *ret, size_t *ret_size, unsigned int *critical)
{
int result;
gnutls_datum dnsname;
ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
- char nptr[128];
- char ext_data[256];
- int len;
- char num[MAX_INT_DIGITS];
gnutls_x509_subject_alt_name type;
if (cert==NULL) {
@@ -623,7 +756,6 @@ int gnutls_x509_crt_get_subject_alt_name(gnutls_x509_crt cert,
if ((result =
_gnutls_x509_crt_get_extension(cert, "2.5.29.17", 0, &dnsname, critical)) < 0) {
- gnutls_assert();
return result;
}
@@ -632,9 +764,9 @@ int gnutls_x509_crt_get_subject_alt_name(gnutls_x509_crt cert,
return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
}
- if ((result=asn1_create_element
- (_gnutls_get_pkix(), "PKIX1.SubjectAltName", &c2))
- != ASN1_SUCCESS) {
+ result=asn1_create_element
+ (_gnutls_get_pkix(), "PKIX1.SubjectAltName", &c2);
+ if (result != ASN1_SUCCESS) {
gnutls_assert();
_gnutls_free_datum( &dnsname);
return _gnutls_asn2err(result);
@@ -644,59 +776,21 @@ int gnutls_x509_crt_get_subject_alt_name(gnutls_x509_crt cert,
_gnutls_free_datum( &dnsname);
if (result != ASN1_SUCCESS) {
- /* couldn't decode DER */
-
- _gnutls_x509_log("X509 certificate: Decoding error %d\n", result);
gnutls_assert();
asn1_delete_structure(&c2);
return _gnutls_asn2err(result);
}
- seq++; /* 0->1, 1->2 etc */
- _gnutls_int2str( seq, num);
- _gnutls_str_cpy( nptr, sizeof(nptr), "?");
- _gnutls_str_cat( nptr, sizeof(nptr), num);
-
- len = sizeof(ext_data);
- result =
- asn1_read_value(c2, nptr, ext_data, &len);
+ result = parse_general_name( c2, "", seq, ret, ret_size);
- if (result == ASN1_VALUE_NOT_FOUND || result == ASN1_ELEMENT_NOT_FOUND) {
- asn1_delete_structure(&c2);
- return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
- }
-
- if (result != ASN1_SUCCESS) {
- gnutls_assert();
- asn1_delete_structure(&c2);
- return _gnutls_asn2err(result);
- }
-
-
- type = _gnutls_x509_san_find_type( ext_data);
- if (type == (gnutls_x509_subject_alt_name)-1) {
- asn1_delete_structure(&c2);
- gnutls_assert();
- return GNUTLS_E_X509_UNKNOWN_SAN;
- }
-
- _gnutls_str_cat( nptr, sizeof(nptr), ".");
- _gnutls_str_cat( nptr, sizeof(nptr), ext_data);
-
- len = *ret_size;
- result =
- asn1_read_value(c2, nptr, ret, &len);
asn1_delete_structure(&c2);
- *ret_size = len;
- if (result==ASN1_MEM_ERROR)
- return GNUTLS_E_SHORT_MEMORY_BUFFER;
-
- if (result != ASN1_SUCCESS) {
- gnutls_assert();
- return _gnutls_asn2err(result);
+ if (result < 0) {
+ return result;
}
+ type = result;
+
return type;
}
@@ -810,7 +904,7 @@ int gnutls_x509_crt_get_key_usage(gnutls_x509_crt cert, unsigned int *key_usage,
* @oid: holds an Object Identified in null terminated string
* @indx: In case multiple same OIDs exist in the extensions, this specifies which to send. Use zero to get the first one.
* @buf: a pointer to a structure to hold the name (may be null)
- * @sizeof_buf: initialy holds the size of @buf
+ * @sizeof_buf: initially holds the size of @buf
* @critical: will be non zero if the extension is marked as critical
*
* This function will return the extension specified by the OID in the certificate.
@@ -866,7 +960,7 @@ int gnutls_x509_crt_get_extension_by_oid(gnutls_x509_crt cert, const char* oid,
* @cert: should contain a gnutls_x509_crt structure
* @indx: Specifies which extension OID to send. Use zero to get the first one.
* @oid: a pointer to a structure to hold the OID (may be null)
- * @sizeof_oid: initialy holds the size of @oid
+ * @sizeof_oid: initially holds the size of @oid
*
* This function will return the requested extension OID in the certificate.
* The extension OID will be stored as a string in the provided buffer.
@@ -886,9 +980,9 @@ int gnutls_x509_crt_get_extension_oid(gnutls_x509_crt cert, int indx,
return GNUTLS_E_INVALID_REQUEST;
}
- if ((result =
- _gnutls_x509_crt_get_extension_oid(cert, indx, oid, sizeof_oid)) < 0) {
- gnutls_assert();
+ result =
+ _gnutls_x509_crt_get_extension_oid(cert, indx, oid, sizeof_oid);
+ if (result < 0) {
return result;
}
@@ -923,7 +1017,6 @@ int _gnutls_x509_crt_get_raw_dn2( gnutls_x509_crt cert,
result = asn1_der_decoding(&c2, signed_data.data, signed_data.size, NULL);
if (result != ASN1_SUCCESS) {
- /* couldn't decode DER */
gnutls_assert();
asn1_delete_structure(&c2);
result = _gnutls_asn2err(result);
@@ -992,7 +1085,7 @@ int _gnutls_x509_crt_get_raw_dn( gnutls_x509_crt cert,
* @cert: should contain a gnutls_x509_crt structure
* @algo: is a digest algorithm
* @buf: a pointer to a structure to hold the fingerprint (may be null)
- * @sizeof_buf: initialy holds the size of @buf
+ * @sizeof_buf: initially holds the size of @buf
*
* This function will calculate and copy the certificate's fingerprint
* in the provided buffer.
@@ -1136,7 +1229,7 @@ GNUTLS_HASH_HANDLE hd;
goto cleanup;
}
} else if (pk == GNUTLS_PK_DSA) {
- result = _gnutls_x509_write_dsa_params( params, params_size, &der);
+ result = _gnutls_x509_write_dsa_public_key( params, params_size, &der);
if (result < 0) {
gnutls_assert();
goto cleanup;
@@ -1305,4 +1398,122 @@ int result;
return result;
}
+/**
+ * gnutls_x509_crt_get_crl_dist_points - This function returns the CRL distribution points
+ * @cert: should contain a gnutls_x509_crt structure
+ * @seq: specifies the sequence number of the distribution point (0 for the first one, 1 for the second etc.)
+ * @ret: is the place where the distribution point will be copied to
+ * @ret_size: holds the size of ret.
+ * @reason_flags: Revocation reasons flags.
+ * @critical: will be non zero if the extension is marked as critical (may be null)
+ *
+ * This function will return the CRL distribution points (2.5.29.31), contained in the
+ * given certificate.
+ *
+ * @reason_flags should be an ORed sequence of GNUTLS_CRL_REASON_UNUSED,
+ * GNUTLS_CRL_REASON_KEY_COMPROMISE, GNUTLS_CRL_REASON_CA_COMPROMISE,
+ * GNUTLS_CRL_REASON_AFFILIATION_CHANGED, GNUTLS_CRL_REASON_SUPERSEEDED,
+ * GNUTLS_CRL_REASON_CESSATION_OF_OPERATION, GNUTLS_CRL_REASON_CERTIFICATE_HOLD,
+ * GNUTLS_CRL_REASON_PRIVILEGE_WITHDRAWN, GNUTLS_CRL_REASON_AA_COMPROMISE,
+ * or zero for all possible reasons.
+ *
+ * This is specified in X509v3 Certificate Extensions. GNUTLS will return the
+ * distribution point type, or a negative error code on error.
+ *
+ * Returns GNUTLS_E_SHORT_MEMORY_BUFFER if ret_size is not enough to hold the distribution
+ * point, or the type of the distribution point if everything was ok. The type is
+ * one of the enumerated gnutls_x509_subject_alt_name.
+ *
+ * If the certificate does not have an Alternative name with the specified
+ * sequence number then returns GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
+ *
+ **/
+int gnutls_x509_crt_get_crl_dist_points(gnutls_x509_crt cert,
+ unsigned int seq, void *ret, size_t *ret_size,
+ unsigned int* reason_flags, unsigned int *critical)
+{
+ int result;
+ gnutls_datum dist_points = {NULL, 0};
+ ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
+ char name[128];
+ int len;
+ char num[MAX_INT_DIGITS];
+ gnutls_x509_subject_alt_name type;
+ uint8 reasons[2];
+
+ if (cert==NULL) {
+ gnutls_assert();
+ return GNUTLS_E_INVALID_REQUEST;
+ }
+
+ if (ret) memset(ret, 0, *ret_size);
+ else *ret_size = 0;
+
+ if (reason_flags) *reason_flags = 0;
+
+ result =
+ _gnutls_x509_crt_get_extension(cert, "2.5.29.31", 0, &dist_points, critical);
+ if (result < 0) {
+ return result;
+ }
+
+ if (dist_points.size == 0 || dist_points.data==NULL) {
+ gnutls_assert();
+ return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
+ }
+
+ result=asn1_create_element
+ (_gnutls_get_pkix(), "PKIX1.CRLDistributionPoints", &c2);
+ if (result != ASN1_SUCCESS) {
+ gnutls_assert();
+ _gnutls_free_datum( &dist_points);
+ return _gnutls_asn2err(result);
+ }
+
+ result = asn1_der_decoding(&c2, dist_points.data, dist_points.size, NULL);
+ _gnutls_free_datum( &dist_points);
+
+ if (result != ASN1_SUCCESS) {
+ gnutls_assert();
+ asn1_delete_structure(&c2);
+ return _gnutls_asn2err(result);
+ }
+
+ /* Return the different names from the first CRLDistr. point.
+ * The whole thing is a mess.
+ */
+ _gnutls_str_cpy( name, sizeof(name), "?1.distributionPoint.fullName");
+
+ result = parse_general_name( c2, name, seq, ret, ret_size);
+ if (result < 0) {
+ asn1_delete_structure(&c2);
+ return result;
+ }
+
+ type = result;
+
+
+ /* Read the CRL reasons.
+ */
+ if (reason_flags) {
+ _gnutls_str_cpy( name, sizeof(name), "?");
+ _gnutls_str_cat( name, sizeof(name), num);
+ _gnutls_str_cat( name, sizeof(name), ".reasons");
+
+ len = sizeof(reasons);
+ result =
+ asn1_read_value(c2, name, reasons, &len);
+
+ if (result != ASN1_VALUE_NOT_FOUND && result != ASN1_SUCCESS) {
+ gnutls_assert();
+ asn1_delete_structure(&c2);
+ return _gnutls_asn2err(result);
+ }
+
+ *reason_flags = reasons[0] | (reasons[1] << 8);
+ }
+
+ return type;
+}
+
#endif
diff --git a/lib/x509/x509.h b/lib/x509/x509.h
index 72e66c21ed..ee5c949e1a 100644
--- a/lib/x509/x509.h
+++ b/lib/x509/x509.h
@@ -61,7 +61,7 @@ typedef struct gnutls_x509_privkey_int *gnutls_x509_privkey;
int gnutls_x509_crt_get_issuer_dn_by_oid(gnutls_x509_crt cert, const char* oid,
int indx, unsigned int raw_flag, void *buf, size_t *sizeof_buf);
int gnutls_x509_crt_get_subject_alt_name(gnutls_x509_crt cert,
- int seq, void *ret, size_t *ret_size, unsigned int* critical);
+ unsigned int seq, void *ret, size_t *ret_size, unsigned int* critical);
int gnutls_x509_crt_get_dn_by_oid(gnutls_x509_crt cert, const char* oid,
int indx, unsigned int raw_flag, void *buf, size_t *sizeof_buf);
int gnutls_x509_crt_get_ca_status(gnutls_x509_crt cert, unsigned int* critical);
@@ -127,4 +127,14 @@ int gnutls_x509_privkey_export_rsa_raw(gnutls_x509_privkey key,
int gnutls_x509_privkey_export( gnutls_x509_privkey key,
gnutls_x509_crt_fmt format, void* output_data, size_t* output_data_size);
+#define GNUTLS_CRL_REASON_UNUSED 128
+#define GNUTLS_CRL_REASON_KEY_COMPROMISE 64
+#define GNUTLS_CRL_REASON_CA_COMPROMISE 32
+#define GNUTLS_CRL_REASON_AFFILIATION_CHANGED 16
+#define GNUTLS_CRL_REASON_SUPERSEEDED 8
+#define GNUTLS_CRL_REASON_CESSATION_OF_OPERATION 4
+#define GNUTLS_CRL_REASON_CERTIFICATE_HOLD 2
+#define GNUTLS_CRL_REASON_PRIVILEGE_WITHDRAWN 1
+#define GNUTLS_CRL_REASON_AA_COMPROMISE 32768
+
#endif
diff --git a/lib/x509/x509_write.c b/lib/x509/x509_write.c
index 77e59d2b10..d458c252f2 100644
--- a/lib/x509/x509_write.c
+++ b/lib/x509/x509_write.c
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2003 Nikos Mavroyanopoulos
+ * Copyright (C) 2004 Free Software Foundation
*
* This file is part of GNUTLS.
*
@@ -19,7 +20,7 @@
*
*/
-/* This file contains functions to handle PKCS #10 certificate requests.
+/* This file contains functions to handle X.509 certificate generation.
*/
#include <gnutls_int.h>
@@ -122,15 +123,14 @@ int gnutls_x509_crt_set_issuer_dn_by_oid(gnutls_x509_crt crt, const char* oid,
int gnutls_x509_crt_set_version(gnutls_x509_crt crt, unsigned int version)
{
int result;
-char null = version;
+unsigned char null = version;
if (crt==NULL) {
gnutls_assert();
return GNUTLS_E_INVALID_REQUEST;
}
- null -= 1;
- if (null < 0) null = 0;
+ if (null > 0) null--;
result = asn1_write_value( crt->cert, "tbsCertificate.version", &null, 1);
if (result != ASN1_SUCCESS) {
@@ -196,11 +196,6 @@ int pk_algorithm;
pk_algorithm = gnutls_x509_crq_get_pk_algorithm( crq, NULL);
- if (pk_algorithm != GNUTLS_PK_RSA) {
- gnutls_assert();
- return GNUTLS_E_UNIMPLEMENTED_FEATURE;
- }
-
result = _gnutls_asn1_copy_node( &crt->cert, "tbsCertificate.subject",
crq->crq, "certificationRequestInfo.subject");
if (result < 0) {
@@ -222,7 +217,7 @@ int pk_algorithm;
/**
* gnutls_x509_crt_set_ca_status - This function will set the basicConstraints extension
* @crt: should contain a gnutls_x509_crt structure
- * @ca: true(1) or false(0). Depending on the Certificat authority status.
+ * @ca: true(1) or false(0). Depending on the Certificate authority status.
*
* This function will set the basicConstraints certificate extension.
*
@@ -262,6 +257,48 @@ gnutls_datum der_data;
}
/**
+ * gnutls_x509_crt_set_key_usage - This function will set the keyUsage extension
+ * @crt: should contain a gnutls_x509_crt structure
+ * @usage: an ORed sequence of the GNUTLS_KEY_* elements.
+ *
+ * This function will set the keyUsage certificate extension.
+ *
+ * Returns 0 on success.
+ *
+ **/
+int gnutls_x509_crt_set_key_usage(gnutls_x509_crt crt, unsigned int usage)
+{
+int result;
+gnutls_datum der_data;
+
+ if (crt==NULL) {
+ gnutls_assert();
+ return GNUTLS_E_INVALID_REQUEST;
+ }
+
+ /* generate the extension.
+ */
+ result = _gnutls_x509_ext_gen_keyUsage( (uint16)usage, &der_data);
+ if (result < 0) {
+ gnutls_assert();
+ return result;
+ }
+
+ result = _gnutls_x509_crt_set_extension( crt, "2.5.29.15", &der_data, 1);
+
+ _gnutls_free_datum( &der_data);
+
+ if (result < 0) {
+ gnutls_assert();
+ return result;
+ }
+
+ crt->use_extensions = 1;
+
+ return 0;
+}
+
+/**
* gnutls_x509_crt_set_subject_alt_name - This function will set the subject Alternative Name
* @crt: should contain a gnutls_x509_crt structure
* @type: is one of the gnutls_x509_subject_alt_name enumerations
@@ -336,105 +373,23 @@ int gnutls_x509_crt_sign(gnutls_x509_crt crt, gnutls_x509_crt issuer,
gnutls_x509_privkey issuer_key)
{
int result;
-gnutls_datum signature;
-const char* pk;
if (crt==NULL || issuer == NULL) {
gnutls_assert();
return GNUTLS_E_INVALID_REQUEST;
}
- if (issuer_key->pk_algorithm != GNUTLS_PK_RSA) {
- gnutls_assert();
- return GNUTLS_E_UNIMPLEMENTED_FEATURE;
- }
-
/* disable all the unneeded OPTIONAL fields.
*/
disable_optional_stuff( crt);
-
- /* Step 1. Copy the issuer's name into the certificate.
- */
- result = _gnutls_asn1_copy_node( &crt->cert, "tbsCertificate.issuer",
- issuer->cert, "tbsCertificate.subject");
- if (result < 0) {
- gnutls_assert();
- return result;
- }
-
- /* Step 1.5. Write the signature stuff in the tbsCertificate.
- */
- /* write the RSA OID
- */
- pk = _gnutls_x509_sign2oid( issuer_key->pk_algorithm, GNUTLS_MAC_SHA);
- if (pk == NULL) {
- gnutls_assert();
- return GNUTLS_E_INVALID_REQUEST;
- }
-
- result = asn1_write_value( crt->cert, "tbsCertificate.signature.algorithm", pk, 1);
- if (result != ASN1_SUCCESS) {
- gnutls_assert();
- return _gnutls_asn2err(result);
- }
-
- /* disable parameters, which are not used in RSA.
- */
- result = asn1_write_value( crt->cert, "tbsCertificate.signature.parameters", NULL, 0);
- if (result != ASN1_SUCCESS && result != ASN1_ELEMENT_NOT_FOUND) {
- /* Here we ignore the element not found error, since this
- * may have been disabled before.
- */
- gnutls_assert();
- return _gnutls_asn2err(result);
- }
-
- /* Step 2. Sign the certificate.
- */
- result = _gnutls_x509_sign_tbs( crt->cert, "tbsCertificate", GNUTLS_MAC_SHA,
- issuer_key, &signature);
-
+ result = _gnutls_x509_pkix_sign( crt->cert, "tbsCertificate", issuer,
+ issuer_key);
if (result < 0) {
gnutls_assert();
return result;
}
-
- /* write the signature (bits)
- */
- result = asn1_write_value( crt->cert, "signature", signature.data, signature.size*8);
-
- _gnutls_free_datum( &signature);
-
- if (result != ASN1_SUCCESS) {
- gnutls_assert();
- return _gnutls_asn2err(result);
- }
-
- /* Step 2. Move up and write the AlgorithmIdentifier, which is also
- * the same.
- */
-
-
- /* write the RSA OID
- */
- result = asn1_write_value( crt->cert, "signatureAlgorithm.algorithm", pk, 1);
- if (result != ASN1_SUCCESS) {
- gnutls_assert();
- return _gnutls_asn2err(result);
- }
-
- /* disable parameters, which are not used in RSA.
- */
- result = asn1_write_value( crt->cert, "signatureAlgorithm.parameters", NULL, 0);
- if (result != ASN1_SUCCESS && result != ASN1_ELEMENT_NOT_FOUND) {
- /* Here we ignore the element not found error, since this
- * may have been disabled before.
- */
- gnutls_assert();
- return _gnutls_asn2err(result);
- }
-
+
return 0;
}
@@ -481,7 +436,7 @@ int gnutls_x509_crt_set_expiration_time(gnutls_x509_crt cert, time_t exp_time)
* gnutls_x509_crt_set_serial - This function will set the certificate's serial number
* @cert: should contain a gnutls_x509_crt structure
* @serial: The serial number
- * @result_size: Holds the size of the serial field.
+ * @serial_size: Holds the size of the serial field.
*
* This function will set the X.509 certificate's serial number.
* Serial is not always a 32 or 64bit number. Some CAs use
@@ -491,7 +446,7 @@ int gnutls_x509_crt_set_expiration_time(gnutls_x509_crt cert, time_t exp_time)
* Returns 0 on success, or a negative value in case of an error.
*
**/
-int gnutls_x509_crt_set_serial(gnutls_x509_crt cert, const unsigned char* serial,
+int gnutls_x509_crt_set_serial(gnutls_x509_crt cert, const void* serial,
size_t serial_size)
{
int ret;
@@ -501,8 +456,8 @@ int gnutls_x509_crt_set_serial(gnutls_x509_crt cert, const unsigned char* serial
return GNUTLS_E_INVALID_REQUEST;
}
- if ((ret = asn1_write_value(cert->cert, "tbsCertificate.serialNumber", serial, serial_size)) < 0)
- {
+ ret = asn1_write_value(cert->cert, "tbsCertificate.serialNumber", serial, serial_size);
+ if (ret != ASN1_SUCCESS) {
gnutls_assert();
return _gnutls_asn2err(ret);
}
@@ -529,5 +484,161 @@ static void disable_optional_stuff( gnutls_x509_crt cert)
return;
}
+/**
+ * gnutls_x509_crt_set_crl_dist_points - This function will set the CRL dist points
+ * @crt: should contain a gnutls_x509_crt structure
+ * @type: is one of the gnutls_x509_subject_alt_name enumerations
+ * @data_string: The data to be set
+ * @reason_flags: revocation reasons
+ *
+ * This function will set the CRL distribution points certificate extension.
+ *
+ * Returns 0 on success.
+ *
+ **/
+int gnutls_x509_crt_set_crl_dist_points(gnutls_x509_crt crt, gnutls_x509_subject_alt_name type,
+ const void* data_string, unsigned int reason_flags)
+{
+int result;
+gnutls_datum der_data;
+gnutls_datum oldname;
+unsigned int critical;
+
+ if (crt==NULL) {
+ gnutls_assert();
+ return GNUTLS_E_INVALID_REQUEST;
+ }
+
+ /* Check if the extension already exists.
+ */
+ result = _gnutls_x509_crt_get_extension(crt, "2.5.29.31", 0, &oldname, &critical);
+
+ if (result >= 0) _gnutls_free_datum( &oldname);
+ if (result != GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
+ gnutls_assert();
+ return GNUTLS_E_INVALID_REQUEST;
+ }
+
+ /* generate the extension.
+ */
+ result = _gnutls_x509_ext_gen_crl_dist_points( type, data_string, reason_flags, &der_data);
+ if (result < 0) {
+ gnutls_assert();
+ return result;
+ }
+
+ result = _gnutls_x509_crt_set_extension( crt, "2.5.29.31", &der_data, 0);
+
+ _gnutls_free_datum( &der_data);
+
+ if (result < 0) {
+ gnutls_assert();
+ return result;
+ }
+
+ crt->use_extensions = 1;
+
+ return 0;
+}
+
+/**
+ * gnutls_x509_crt_cpy_crl_dist_points - This function will copy the CRL dist points
+ * @dst: should contain a gnutls_x509_crt structure
+ * @src: the certificate where the dist points will be copied from
+ *
+ * This function will copy the CRL distribution points certificate
+ * extension, from the source to the destination certificate.
+ * This may be useful to copy from a CA certificate to issued ones.
+ *
+ * Returns 0 on success.
+ *
+ **/
+int gnutls_x509_crt_cpy_crl_dist_points(gnutls_x509_crt dst,
+ gnutls_x509_crt src)
+{
+int result;
+gnutls_datum der_data;
+unsigned int critical;
+
+ if (dst==NULL || src == NULL) {
+ gnutls_assert();
+ return GNUTLS_E_INVALID_REQUEST;
+ }
+
+ /* Check if the extension already exists.
+ */
+ result = _gnutls_x509_crt_get_extension(src, "2.5.29.31", 0, &der_data, &critical);
+ if (result < 0) {
+ gnutls_assert();
+ return result;
+ }
+
+ result = _gnutls_x509_crt_set_extension( dst, "2.5.29.31", &der_data, critical);
+ _gnutls_free_datum( &der_data);
+
+ if (result < 0) {
+ gnutls_assert();
+ return result;
+ }
+
+ dst->use_extensions = 1;
+
+ return 0;
+}
+
+/**
+ * gnutls_x509_crt_set_subject_key_id - This function will set the certificate's subject key id
+ * @cert: should contain a gnutls_x509_crt structure
+ * @id: The key ID
+ * @id_size: Holds the size of the serial field.
+ *
+ * This function will set the X.509 certificate's subject key ID extension.
+ *
+ * Returns 0 on success, or a negative value in case of an error.
+ *
+ **/
+int gnutls_x509_crt_set_subject_key_id(gnutls_x509_crt cert, const void* id,
+ size_t id_size)
+{
+ int result;
+ gnutls_datum old_id, der_data;
+ unsigned int critical;
+
+ if (cert==NULL) {
+ gnutls_assert();
+ return GNUTLS_E_INVALID_REQUEST;
+ }
+
+ /* Check if the extension already exists.
+ */
+ result = _gnutls_x509_crt_get_extension(cert, "2.5.29.14", 0, &old_id, &critical);
+
+ if (result >= 0) _gnutls_free_datum( &old_id);
+ if (result != GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
+ gnutls_assert();
+ return GNUTLS_E_INVALID_REQUEST;
+ }
+
+ /* generate the extension.
+ */
+ result = _gnutls_x509_ext_gen_key_id( id, id_size, &der_data);
+ if (result < 0) {
+ gnutls_assert();
+ return result;
+ }
+
+ result = _gnutls_x509_crt_set_extension( cert, "2.5.29.14", &der_data, 0);
+
+ _gnutls_free_datum( &der_data);
+
+ if (result < 0) {
+ gnutls_assert();
+ return result;
+ }
+
+ cert->use_extensions = 1;
+
+ return 0;
+}
#endif /* ENABLE_PKI */
diff --git a/lib/x509/xml.c b/lib/x509/xml.c
index 5c3ec65f94..4cac03abe4 100644
--- a/lib/x509/xml.c
+++ b/lib/x509/xml.c
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2002,2003 Nikos Mavroyanopoulos
+ * Copyright (C) 2004 Free Software Foundation
*
* This file is part of GNUTLS.
*
@@ -603,7 +604,7 @@ _gnutls_asn1_get_structure_xml(ASN1_TYPE structure,
* @detail: The detail level (must be GNUTLS_XML_SHOW_ALL or GNUTLS_XML_NORMAL)
*
* This function will return the XML structures of the given X.509 certificate.
- * The XML structures are allocated internaly (with malloc) and stored into res.
+ * The XML structures are allocated internally (with malloc) and stored into res.
* Returns a negative error code in case of an error.
*
**/