summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikos Mavrogiannopoulos <nmav@gnutls.org>2002-02-01 11:14:47 +0000
committerNikos Mavrogiannopoulos <nmav@gnutls.org>2002-02-01 11:14:47 +0000
commit4eb7eee2eebdf38466a955b73e122933422491bf (patch)
tree9719b14062087936fd518b56b7afbe64d382f969
parent0a048d3c44bb23f6856587779c5ae0435d54f388 (diff)
downloadgnutls-4eb7eee2eebdf38466a955b73e122933422491bf.tar.gz
Several changes in certificate and key handling.
* gnutls_certificate_allocate_sc() does not require the ncerts argument
-rw-r--r--configure.in4
-rw-r--r--doc/protocol/draft-ietf-tls-openpgp-keys-01.txt3
-rw-r--r--doc/tex/ex1.tex4
-rw-r--r--doc/tex/ex2.tex4
-rw-r--r--doc/tex/ex3.tex2
-rw-r--r--doc/tex/serv1.tex6
-rw-r--r--lib/Makefile.am2
-rw-r--r--lib/auth_cert.c6
-rw-r--r--lib/auth_cert.h3
-rw-r--r--lib/gnutls.h.in.in18
-rw-r--r--lib/gnutls_cert.c1212
-rw-r--r--lib/gnutls_cert.h9
-rw-r--r--lib/gnutls_int_compat.c47
-rw-r--r--lib/gnutls_session_pack.c20
-rw-r--r--lib/gnutls_ui.h2
-rw-r--r--lib/gnutls_x509.c1187
-rw-r--r--lib/x509_extensions.c2
-rw-r--r--src/cli.c10
-rw-r--r--src/common.h2
-rw-r--r--src/serv.c8
20 files changed, 1275 insertions, 1276 deletions
diff --git a/configure.in b/configure.in
index 950c145a8f..07ae174d71 100644
--- a/configure.in
+++ b/configure.in
@@ -11,8 +11,8 @@ AC_DEFINE_UNQUOTED(T_OS, "$target_os")
dnl Gnutls Version
GNUTLS_MAJOR_VERSION=0
-GNUTLS_MINOR_VERSION=3
-GNUTLS_MICRO_VERSION=90
+GNUTLS_MINOR_VERSION=4
+GNUTLS_MICRO_VERSION=0
GNUTLS_VERSION=$GNUTLS_MAJOR_VERSION.$GNUTLS_MINOR_VERSION.$GNUTLS_MICRO_VERSION
AC_DEFINE_UNQUOTED(GNUTLS_VERSION, "$GNUTLS_VERSION")
diff --git a/doc/protocol/draft-ietf-tls-openpgp-keys-01.txt b/doc/protocol/draft-ietf-tls-openpgp-keys-01.txt
index a52b1679a9..c17061d631 100644
--- a/doc/protocol/draft-ietf-tls-openpgp-keys-01.txt
+++ b/doc/protocol/draft-ietf-tls-openpgp-keys-01.txt
@@ -64,7 +64,8 @@ Internet-Draft Using OpenPGP keys for TLS Authentication January 2002
At the time of writing, TLS [TLS] uses the X.509 protocols, to
provide certificate services. However these protocols, are limited
to hierarchical key management. This leads to a problem when
- de-centralized application protocols are to be supported.
+ applications, which do not have the concept of a central authority,
+ are to be supported.
OpenPGP keys (sometimes called OpenPGP certificates), provide
security services for electronic communications. They are widely
diff --git a/doc/tex/ex1.tex b/doc/tex/ex1.tex
index ffe7540250..6f1ab1d8a8 100644
--- a/doc/tex/ex1.tex
+++ b/doc/tex/ex1.tex
@@ -46,11 +46,11 @@ int main()
exit(1);
}
/* X509 stuff */
- if (gnutls_certificate_allocate_client_sc(&xcred, 0) < 0) { /* no client private key */
+ if (gnutls_certificate_allocate_client_sc(&xcred) < 0) {
fprintf(stderr, "memory error\n");
exit(1);
}
- gnutls_x509pki_set_client_trust_file(xcred, CAFILE, CRLFILE);
+ gnutls_certificate_set_x509_trust_file(xcred, CAFILE, CRLFILE);
for (t = 0; t < 2; t++) { /* connect 2 times to the server */
diff --git a/doc/tex/ex2.tex b/doc/tex/ex2.tex
index ca9d9158af..bb79f43821 100644
--- a/doc/tex/ex2.tex
+++ b/doc/tex/ex2.tex
@@ -36,13 +36,13 @@ int main()
exit(1);
}
/* X509 stuff */
- if (gnutls_certificate_allocate_client_sc(&xcred, 0) < 0) { /* no client private key */
+ if (gnutls_certificate_allocate_client_sc(&xcred) < 0) {
fprintf(stderr, "memory error\n");
exit(1);
}
/* set's the trusted cas file
*/
- gnutls_x509pki_set_client_trust_file(xcred, CAFILE, CRLFILE);
+ gnutls_certificate_set_x509_trust_file(xcred, CAFILE, CRLFILE);
/* connects to server
*/
diff --git a/doc/tex/ex3.tex b/doc/tex/ex3.tex
index 81c72a52da..86693ff784 100644
--- a/doc/tex/ex3.tex
+++ b/doc/tex/ex3.tex
@@ -39,7 +39,7 @@ int print_info(GNUTLS_STATE state)
/* in case of X509 PKI
*/
cert_list = gnutls_certificate_get_peers(state, &cert_list_size);
- status = gnutls_x509pki_client_get_peer_certificate_status(state);
+ status = gnutls_certificate_verify_peers(state);
switch (status) {
case GNUTLS_CERT_NOT_TRUSTED:
diff --git a/doc/tex/serv1.tex b/doc/tex/serv1.tex
index 6d2315be7c..e2ac90fc30 100644
--- a/doc/tex/serv1.tex
+++ b/doc/tex/serv1.tex
@@ -129,15 +129,15 @@ int main()
fprintf(stderr, "global state initialization error\n");
exit(1);
}
- if (gnutls_certificate_allocate_server_sc(&x509_cred, 1) < 0) {
+ if (gnutls_certificate_allocate_server_sc(&x509_cred) < 0) {
fprintf(stderr, "memory error\n");
exit(1);
}
- if (gnutls_x509pki_set_server_trust_file(x509_cred, CAFILE, CRLFILE) < 0) {
+ if (gnutls_certificate_set_x509_trust_file(x509_cred, CAFILE, CRLFILE) < 0) {
fprintf(stderr, "X509 PARSE ERROR\nDid you have ca.pem?\n");
exit(1);
}
- if (gnutls_x509pki_set_server_key_file(x509_cred, CERTFILE, KEYFILE) < 0) {
+ if (gnutls_certifcate_set_x509_key_file(x509_cred, CERTFILE, KEYFILE) < 0) {
fprintf(stderr, "X509 PARSE ERROR\nDid you have key.pem and cert.pem?\n");
exit(1);
}
diff --git a/lib/Makefile.am b/lib/Makefile.am
index 28189c8c7b..12d3ddde02 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -18,7 +18,7 @@ EXTRA_DIST = debug.h gnutls_compress.h defines.h gnutls.asn pkix.asn \
gnutls_privkey.h gnutls_constate.h gnutls_global.h x509_verify.h \
gnutls_sig.h gnutls_mem.h x509_extensions.h gnutls_ui.h \
gnutls-api.tex io_debug.h ext_max_record.h gnutls_session_pack.h \
- gnutls_alert.h asn1-api.tex gnutls_str.h gnutls_state.h
+ gnutls_alert.h asn1-api.tex gnutls_str.h gnutls_state.h gnutls_x509.h
lib_LTLIBRARIES = libgnutls.la
diff --git a/lib/auth_cert.c b/lib/auth_cert.c
index aa537941c8..595579804c 100644
--- a/lib/auth_cert.c
+++ b/lib/auth_cert.c
@@ -38,11 +38,13 @@
#include <x509_extensions.h>
#include <gnutls_state.h>
#include <gnutls_pk.h>
+#include <gnutls_x509.h>
/* Copies data from a internal certificate struct (gnutls_cert) to
* exported certificate struct (CERTIFICATE_AUTH_INFO)
*/
-int _gnutls_copy_x509_auth_info(CERTIFICATE_AUTH_INFO info, gnutls_cert * cert,
+static
+int _gnutls_copy_certificate_auth_info(CERTIFICATE_AUTH_INFO info, gnutls_cert * cert,
int ncerts)
{
/* Copy peer's information to AUTH_INFO
@@ -595,7 +597,7 @@ int _gnutls_proc_x509_server_certificate(GNUTLS_STATE state, opaque * data,
peer_certificate_list[0].subject_pk_algorithm;
if ((ret =
- _gnutls_copy_x509_auth_info(info, peer_certificate_list,
+ _gnutls_copy_certificate_auth_info(info, peer_certificate_list,
peer_certificate_list_size)) <
0) {
gnutls_assert();
diff --git a/lib/auth_cert.h b/lib/auth_cert.h
index 9a9a25c34d..7c17ebc7b6 100644
--- a/lib/auth_cert.h
+++ b/lib/auth_cert.h
@@ -19,6 +19,7 @@ typedef struct {
* row (should be 1 for OpenPGP keys).
*/
int ncerts; /* contains the number of columns in cert_list.
+ * This is the same with the number of pkeys.
*/
gnutls_private_key * pkey;
@@ -57,8 +58,6 @@ typedef struct CERTIFICATE_AUTH_INFO_INT {
typedef struct CERTIFICATE_AUTH_INFO_INT CERTIFICATE_AUTH_INFO_INT;
-int _gnutls_copy_x509_client_auth_info( CERTIFICATE_AUTH_INFO info, gnutls_cert* cert, CertificateStatus verify);
-
/* AUTH X509 functions */
int _gnutls_gen_x509_server_certificate(GNUTLS_STATE, opaque **);
int _gnutls_gen_x509_client_certificate(GNUTLS_STATE, opaque **);
diff --git a/lib/gnutls.h.in.in b/lib/gnutls.h.in.in
index cfd169f6c2..1e3721452f 100644
--- a/lib/gnutls.h.in.in
+++ b/lib/gnutls.h.in.in
@@ -201,23 +201,23 @@ int gnutls_anon_set_client_cred( GNUTLS_ANON_SERVER_CREDENTIALS res, int dh_bits
* KEYFILE is a pkcs-1 private key in PEM form (for RSA keys).
*/
void gnutls_certificate_free_sc( GNUTLS_CERTIFICATE_CREDENTIALS sc);
-int gnutls_certificate_allocate_sc( GNUTLS_CERTIFICATE_CREDENTIALS *sc, int ncerts);
+int gnutls_certificate_allocate_sc( GNUTLS_CERTIFICATE_CREDENTIALS *sc);
-int gnutls_x509pki_set_trust_file( GNUTLS_CERTIFICATE_CREDENTIALS res, char* CAFILE, char* CRLFILE);
-int gnutls_x509pki_set_trust_mem(GNUTLS_CERTIFICATE_CREDENTIALS res, const gnutls_datum *CA, const gnutls_datum *CRL);
+int gnutls_certificate_set_x509_trust_file( GNUTLS_CERTIFICATE_CREDENTIALS res, char* CAFILE, char* CRLFILE);
+int gnutls_certificate_set_x509_trust_mem(GNUTLS_CERTIFICATE_CREDENTIALS res, const gnutls_datum *CA, const gnutls_datum *CRL);
-int gnutls_x509pki_set_key_file( GNUTLS_CERTIFICATE_CREDENTIALS res, char *CERTFILE, char* KEYFILE);
-int gnutls_x509pki_set_key_mem(GNUTLS_CERTIFICATE_CREDENTIALS res, const gnutls_datum* CERT, const gnutls_datum* KEY);
+int gnutls_certificate_set_x509_key_file( GNUTLS_CERTIFICATE_CREDENTIALS res, char *CERTFILE, char* KEYFILE);
+int gnutls_certificate_set_x509_key_mem(GNUTLS_CERTIFICATE_CREDENTIALS res, const gnutls_datum* CERT, const gnutls_datum* KEY);
#define gnutls_certificate_free_server_sc gnutls_certificate_free_sc
#define gnutls_certificate_allocate_server_sc gnutls_certificate_allocate_sc
-#define gnutls_certificate_set_server_key_file gnutls_certificate_set_key_file
-#define gnutls_certificate_set_server_trust_file gnutls_certificate_set_trust_file
+#define gnutls_certificate_set_server_x509_key_file gnutls_certificate_set_x509_key_file
+#define gnutls_certificate_set_server_x509_trust_file gnutls_certificate_set_x509_trust_file
#define gnutls_certificate_free_client_sc gnutls_certificate_free_sc
#define gnutls_certificate_allocate_client_sc gnutls_certificate_allocate_sc
-#define gnutls_certificate_set_client_key_file gnutls_certificate_set_key_file
-#define gnutls_certificate_set_client_trust_file gnutls_certificate_set_trust_file
+#define gnutls_certificate_set_client_x509_key_file gnutls_certificate_set_x509_key_file
+#define gnutls_certificate_set_client_x509_trust_file gnutls_certificate_set_x509_trust_file
/* global state functions
diff --git a/lib/gnutls_cert.c b/lib/gnutls_cert.c
index 4475f102bb..717b9d1a72 100644
--- a/lib/gnutls_cert.c
+++ b/lib/gnutls_cert.c
@@ -20,20 +20,22 @@
#include <gnutls_int.h>
#include <gnutls_errors.h>
-#include <x509_b64.h>
#include <auth_cert.h>
#include <gnutls_cert.h>
#include <x509_asn1.h>
#include <x509_der.h>
#include <gnutls_datum.h>
#include <gnutls_gcry.h>
-#include <gnutls_privkey.h>
#include <gnutls_global.h>
#include <x509_verify.h>
+#include <gnutls_privkey.h>
#include <x509_extensions.h>
#include <gnutls_algorithms.h>
#include <gnutls_dh.h>
#include <gnutls_str.h>
+#include <gnutls_state.h>
+#include <gnutls_auth_int.h>
+#include <gnutls_x509.h>
/* KX mappings to PK algorithms */
typedef struct {
@@ -135,1184 +137,25 @@ void gnutls_certificate_free_sc(GNUTLS_CERTIFICATE_CREDENTIALS sc)
gnutls_free(sc);
}
-#define MAX_FILE_SIZE 100*1024
-#define CERT_SEP "-----BEGIN"
-
-/* Reads a base64 encoded certificate from memory
- */
-static int read_cert_mem(GNUTLS_CERTIFICATE_CREDENTIALS res, const char *cert, int cert_size)
-{
- int siz, i, siz2;
- opaque *b64;
- const char *ptr;
- gnutls_datum tmp;
- int ret;
-
- ptr = cert;
- siz = cert_size;
- i = 1;
-
- res->cert_list[res->ncerts] = NULL;
-
- do {
- siz2 = _gnutls_fbase64_decode(ptr, siz, &b64);
- siz -= siz2; /* FIXME: this is not enough
- */
-
- if (siz2 < 0) {
- gnutls_assert();
- gnutls_free(b64);
- return GNUTLS_E_PARSING_ERROR;
- }
-
-
- res->cert_list[res->ncerts] =
- (gnutls_cert *) gnutls_realloc(res->
- cert_list[res->ncerts],
- i *
- sizeof(gnutls_cert));
-
- if (res->cert_list[res->ncerts] == NULL) {
- gnutls_assert();
- gnutls_free(b64);
- return GNUTLS_E_MEMORY_ERROR;
- }
- /* set defaults to zero
- */
- memset(&res->cert_list[res->ncerts][i - 1], 0,
- sizeof(gnutls_cert));
-
- tmp.data = b64;
- tmp.size = siz2;
-
- if ((ret =
- _gnutls_x509_cert2gnutls_cert(&res->
- cert_list[res->ncerts][i - 1],
- tmp)) < 0) {
- gnutls_free(b64);
- gnutls_assert();
- return ret;
- }
- gnutls_free(b64);
-
- /* now we move ptr after the pem header */
- ptr = strstr(ptr, CERT_SEP);
- if (ptr!=NULL)
- ptr++;
-
- i++;
- } while ((ptr = strstr(ptr, CERT_SEP)) != NULL);
-
- res->cert_list_length[res->ncerts] = i - 1;
-
- /* WE DO NOT CATCH OVERRUNS in gnutls_x509pki_set_key().
- * This function should be called as many times as specified
- * in certificate_allocate_sc().
- */
- res->ncerts++;
-
- return 0;
-}
-
-/* Reads a base64 encoded CA list from memory
- * This is to be called once.
- */
-static int read_ca_mem(GNUTLS_CERTIFICATE_CREDENTIALS res, const char *ca, int ca_size)
-{
- int siz, siz2, i;
- opaque *b64;
- const char *ptr;
- int ret;
- gnutls_datum tmp;
-
- siz = ca_size;
-
- ptr = ca;
-
- i = res->x509_ncas + 1;
-
- do {
- siz2 = _gnutls_fbase64_decode(ptr, siz, &b64);
- siz -= siz2; /* FIXME: this is not enough
- */
-
- if (siz2 < 0) {
- gnutls_assert();
- gnutls_free(b64);
- return GNUTLS_E_PARSING_ERROR;
- }
-
- res->x509_ca_list =
- (gnutls_cert *) gnutls_realloc(res->x509_ca_list,
- i *
- sizeof(gnutls_cert));
- if (res->x509_ca_list == NULL) {
- gnutls_assert();
- gnutls_free(b64);
- return GNUTLS_E_MEMORY_ERROR;
- }
- memset(&res->x509_ca_list[i - 1], 0, sizeof(gnutls_cert));
-
- tmp.data = b64;
- tmp.size = siz2;
-
- if ((ret =
- _gnutls_x509_cert2gnutls_cert(&res->x509_ca_list[i - 1],
- tmp)) < 0) {
- gnutls_assert();
- gnutls_free(b64);
- return ret;
- }
- gnutls_free(b64);
-
- /* now we move ptr after the pem header */
- ptr = strstr(ptr, CERT_SEP);
- if (ptr!=NULL)
- ptr++;
-
- i++;
- } while ((ptr = strstr(ptr, CERT_SEP)) != NULL);
-
- res->x509_ncas = i - 1;
-
-
-
- return 0;
-}
-
-
-/* Reads a PEM encoded PKCS-1 RSA private key from memory
- * 2002-01-26: Added ability to read DSA keys.
- */
-static int read_key_mem(GNUTLS_CERTIFICATE_CREDENTIALS res, const char *key, int key_size)
-{
- int siz, ret;
- opaque *b64;
- gnutls_datum tmp;
- PKAlgorithm pk;
-
- /* read PKCS-1 private key */
- siz = key_size;
-
-
- /* If we find the "DSA PRIVATE" string in the
- * pem encoded certificate then it's a DSA key.
- */
- if (strstr( key, "DSA PRIVATE")!=NULL)
- pk = GNUTLS_PK_DSA;
- else
- pk = GNUTLS_PK_RSA;
-
- siz = _gnutls_fbase64_decode(key, siz, &b64);
-
- if (siz < 0) {
- gnutls_assert();
- gnutls_free(b64);
- return GNUTLS_E_PARSING_ERROR;
- }
-
- tmp.data = b64;
- tmp.size = siz;
-
- switch (pk) { /* decode the key */
- case GNUTLS_PK_RSA:
- if ((ret =
- _gnutls_PKCS1key2gnutlsKey(&res->pkey[res->ncerts],
- tmp)) < 0) {
- gnutls_assert();
- gnutls_free(b64);
- return ret;
- }
- break;
- case GNUTLS_PK_DSA:
- if ((ret =
- _gnutls_DSAkey2gnutlsKey(&res->pkey[res->ncerts],
- tmp)) < 0) {
- gnutls_assert();
- gnutls_free(b64);
- return ret;
- }
- break;
- }
- gnutls_free(b64);
-
- return 0;
-}
-
-/* Reads a base64 encoded certificate file
- */
-static int read_cert_file(GNUTLS_CERTIFICATE_CREDENTIALS res, char *certfile)
-{
- int siz;
- char x[MAX_FILE_SIZE];
- FILE *fd1;
-
- fd1 = fopen(certfile, "r");
- if (fd1 == NULL)
- return GNUTLS_E_UNKNOWN_ERROR;
-
- siz = fread(x, 1, sizeof(x), fd1);
- fclose(fd1);
-
- x[siz-1] = 0;
-
- return read_cert_mem( res, x, siz);
-
-}
-
-/* Reads a base64 encoded CA file (file contains multiple certificate
- * authorities). This is to be called once.
- */
-static int read_ca_file(GNUTLS_CERTIFICATE_CREDENTIALS res, char *cafile)
-{
- int siz;
- char x[MAX_FILE_SIZE];
- FILE *fd1;
-
- fd1 = fopen(cafile, "r");
- if (fd1 == NULL) {
- gnutls_assert();
- return GNUTLS_E_UNKNOWN_ERROR;
- }
-
- siz = fread(x, 1, sizeof(x), fd1);
- fclose(fd1);
-
- x[siz-1] = 0;
-
- return read_ca_mem( res, x, siz);
-}
-
-
-/* Reads a PEM encoded PKCS-1 RSA private key file
- */
-static int read_key_file(GNUTLS_CERTIFICATE_CREDENTIALS res, char *keyfile)
-{
- int siz;
- char x[MAX_FILE_SIZE];
- FILE *fd2;
-
- fd2 = fopen(keyfile, "r");
- if (fd2 == NULL)
- return GNUTLS_E_UNKNOWN_ERROR;
-
- siz = fread(x, 1, sizeof(x), fd2);
- fclose(fd2);
-
- x[siz-1] = 0;
-
- return read_key_mem( res, x, siz);
-}
/**
* gnutls_certificate_allocate_sc - Used to allocate an x509 SERVER CREDENTIALS structure
* @res: is a pointer to an &GNUTLS_CERTIFICATE_CREDENTIALS structure.
- * @ncerts: this is the number of certificate/private key pair you're going to use.
- * This should be 1 in common sites.
*
* This structure is complex enough to manipulate directly thus
* this helper function is provided in order to allocate
* the structure.
**/
-int gnutls_certificate_allocate_sc(GNUTLS_CERTIFICATE_CREDENTIALS * res, int ncerts)
+int gnutls_certificate_allocate_sc(GNUTLS_CERTIFICATE_CREDENTIALS * res)
{
-#warning FIX NCERTS
*res = gnutls_calloc(1, sizeof(CERTIFICATE_CREDENTIALS_INT));
if (*res == NULL)
return GNUTLS_E_MEMORY_ERROR;
-
- (*res)->ncerts = 0; /* this is right - set_key() increments it */
-
- if (ncerts > 0) {
- (*res)->cert_list =
- (gnutls_cert **) gnutls_malloc(ncerts *
- sizeof(gnutls_cert *));
-
- if ((*res)->cert_list == NULL) {
- gnutls_free(*res);
- return GNUTLS_E_MEMORY_ERROR;
- }
-
- (*res)->cert_list_length =
- (int *) gnutls_malloc(ncerts * sizeof(int *));
- if ((*res)->cert_list_length == NULL) {
- gnutls_free(*res);
- gnutls_free((*res)->cert_list);
- return GNUTLS_E_MEMORY_ERROR;
- }
-
- (*res)->pkey =
- gnutls_malloc(ncerts * sizeof(gnutls_private_key));
- if ((*res)->pkey == NULL) {
- gnutls_free(*res);
- gnutls_free((*res)->cert_list);
- gnutls_free((*res)->cert_list_length);
- return GNUTLS_E_MEMORY_ERROR;
- }
-
- }
-
return 0;
}
-/* returns error if the certificate has different algorithm than
- * the given key parameters.
- */
-static int _gnutls_check_key_cert_match( GNUTLS_CERTIFICATE_CREDENTIALS res) {
- if (res->pkey->pk_algorithm != res->cert_list[0]->subject_pk_algorithm) {
- gnutls_assert();
- return GNUTLS_E_CERTIFICATE_KEY_MISMATCH;
- }
- return 0;
-}
-
-
-/**
- * gnutls_x509pki_set_key_file - Used to set keys in a GNUTLS_CERTIFICATE_CREDENTIALS structure
- * @res: is an &GNUTLS_CERTIFICATE_CREDENTIALS structure.
- * @CERTFILE: is a PEM encoded file containing the certificate list (path) for
- * the specified private key
- * @KEYFILE: is a PEM encoded file containing a private key
- *
- * This function sets a certificate/private key pair in the
- * GNUTLS_CERTIFICATE_CREDENTIALS structure. This function may be called
- * more than once (in case multiple keys/certificates exist for the
- * server).
- *
- * Currently only PKCS-1 PEM encoded RSA and DSA private keys are accepted by
- * this function.
- *
- **/
-int gnutls_x509pki_set_key_file(GNUTLS_CERTIFICATE_CREDENTIALS res, char *CERTFILE,
- char *KEYFILE)
-{
- int ret;
-
- /* this should be first
- */
- if ((ret = read_key_file(res, KEYFILE)) < 0)
- return ret;
-
- if ((ret = read_cert_file(res, CERTFILE)) < 0)
- return ret;
-
- if ((ret=_gnutls_check_key_cert_match( res)) < 0) {
- gnutls_assert();
- return ret;
- }
-
- return 0;
-}
-
-static int generate_rdn_seq( GNUTLS_CERTIFICATE_CREDENTIALS res) {
-gnutls_datum tmp;
-int ret, size, i;
-opaque *pdata;
-
- /* Generate the RDN sequence
- * This will be sent to clients when a certificate
- * request message is sent.
- */
-
- /* FIXME: in case of a client it is not needed
- * to do that. This would save time and memory.
- * However we don't have that information available
- * here.
- */
-
- size = 0;
- for (i = 0; i < res->x509_ncas; i++) {
- if ((ret = _gnutls_find_dn(&tmp, &res->x509_ca_list[i])) < 0) {
- gnutls_assert();
- return ret;
- }
- size += (2 + tmp.size);
- }
-
- if (res->x509_rdn_sequence.data != NULL)
- gnutls_free( res->x509_rdn_sequence.data);
-
- res->x509_rdn_sequence.data = gnutls_malloc(size);
- if (res->x509_rdn_sequence.data == NULL) {
- gnutls_assert();
- return GNUTLS_E_MEMORY_ERROR;
- }
- res->x509_rdn_sequence.size = size;
-
- pdata = res->x509_rdn_sequence.data;
-
- for (i = 0; i < res->x509_ncas; i++) {
- if ((ret = _gnutls_find_dn(&tmp, &res->x509_ca_list[i])) < 0) {
- gnutls_free(res->x509_rdn_sequence.data);
- res->x509_rdn_sequence.size = 0;
- res->x509_rdn_sequence.data = NULL;
- gnutls_assert();
- return ret;
- }
- WRITEdatum16(pdata, tmp);
- pdata += (2 + tmp.size);
- }
-
- return 0;
-}
-
-/**
- * gnutls_x509pki_set_trust_mem - Used to add trusted CAs in a GNUTLS_CERTIFICATE_CREDENTIALS structure
- * @res: is an &GNUTLS_CERTIFICATE_CREDENTIALS structure.
- * @CA: is a PEM encoded list of trusted CAs
- * @CRL: is a PEM encoded list of CRLs (ignored for now)
- *
- * This function adds the trusted CAs in order to verify client
- * certificates. This function may be called multiple times.
- *
- **/
-int gnutls_x509pki_set_trust_mem(GNUTLS_CERTIFICATE_CREDENTIALS res, const gnutls_datum *CA,
- const gnutls_datum *CRL)
-{
- int ret;
-
- if ((ret = read_ca_mem(res, CA->data, CA->size)) < 0)
- return ret;
-
- if ((ret = generate_rdn_seq(res)) < 0)
- return ret;
-
- return 0;
-}
-
-/**
- * gnutls_x509pki_set_trust_file - Used to add trusted CAs in a GNUTLS_CERTIFICATE_CREDENTIALS structure
- * @res: is an &GNUTLS_CERTIFICATE_CREDENTIALS structure.
- * @CAFILE: is a PEM encoded file containing trusted CAs
- * @CRLFILE: is a PEM encoded file containing CRLs (ignored for now)
- *
- * This function sets the trusted CAs in order to verify client
- * certificates. This function may be called multiple times.
- *
- **/
-int gnutls_x509pki_set_trust_file(GNUTLS_CERTIFICATE_CREDENTIALS res, char *CAFILE,
- char *CRLFILE)
-{
- int ret;
-
- if ((ret = read_ca_file(res, CAFILE)) < 0)
- return ret;
-
- if ((ret = generate_rdn_seq(res)) < 0)
- return ret;
-
- return 0;
-}
-
-
-/**
- * gnutls_x509pki_set_key_mem - Used to set keys in a GNUTLS_CERTIFICATE_CREDENTIALS structure
- * @res: is an &GNUTLS_CERTIFICATE_CREDENTIALS structure.
- * @CERT: contains a PEM encoded certificate list (path) for
- * the specified private key
- * @KEY: is a PEM encoded private key
- *
- * This function sets a certificate/private key pair in the
- * GNUTLS_CERTIFICATE_CREDENTIALS structure. This function may be called
- * more than once (in case multiple keys/certificates exist for the
- * server).
- *
- * Currently only PKCS-1 PEM encoded RSA private keys are accepted by
- * this function.
- *
- **/
-int gnutls_x509pki_set_key_mem(GNUTLS_CERTIFICATE_CREDENTIALS res, const gnutls_datum* CERT,
- const gnutls_datum* KEY)
-{
- int ret;
-
- /* this should be first
- */
- if ((ret = read_key_mem( res, KEY->data, KEY->size)) < 0)
- return ret;
-
- if ((ret = read_cert_mem( res, CERT->data, CERT->size)) < 0)
- return ret;
-
- if ((ret=_gnutls_check_key_cert_match( res)) < 0) {
- gnutls_assert();
- return ret;
- }
-
- return 0;
-}
-
-
-static int _read_rsa_params(opaque * der, int dersize, MPI * params)
-{
- opaque str[MAX_PARAMETER_SIZE];
- int result;
- node_asn *spk;
-
- if (asn1_create_structure
- (_gnutls_get_gnutls_asn(), "GNUTLS.RSAPublicKey", &spk,
- "rsa_public_key") != ASN_OK) {
- gnutls_assert();
- return GNUTLS_E_ASN1_ERROR;
- }
-
- result = asn1_get_der(spk, der, dersize);
-
- if (result != ASN_OK) {
- gnutls_assert();
- asn1_delete_structure(spk);
- return GNUTLS_E_ASN1_PARSING_ERROR;
- }
-
-
- if ( (result=_gnutls_x509_read_int( spk, "rsa_public_key.modulus",
- str, sizeof(str)-1, &params[0])) < 0) {
- gnutls_assert();
- asn1_delete_structure(spk);
- return GNUTLS_E_ASN1_PARSING_ERROR;
- }
-
- if ( (result=_gnutls_x509_read_int( spk, "rsa_public_key.publicExponent",
- str, sizeof(str)-1, &params[1])) < 0) {
- gnutls_assert();
- _gnutls_mpi_release(&params[0]);
- asn1_delete_structure(spk);
- return GNUTLS_E_ASN1_PARSING_ERROR;
- }
-
- asn1_delete_structure(spk);
-
- return 0;
-
-}
-
-
-/* reads p,q and g
- * from the certificate
- * params[0-2]
- */
-static int _read_dsa_params(opaque * der, int dersize, MPI * params)
-{
- opaque str[MAX_PARAMETER_SIZE];
- int result;
- node_asn *spk;
-
- if (asn1_create_structure
- (_gnutls_get_pkix(), "PKIX1Implicit88.Dss-Parms", &spk,
- "dsa_parms") != ASN_OK) {
- gnutls_assert();
- return GNUTLS_E_ASN1_ERROR;
- }
-
- result = asn1_get_der(spk, der, dersize);
-
- if (result != ASN_OK) {
- gnutls_assert();
- asn1_delete_structure(spk);
- return GNUTLS_E_ASN1_PARSING_ERROR;
- }
-
- /* FIXME: If the parameters are not included in the certificate
- * then the issuer's parameters should be used.
- */
-
- /* Read p */
-
- if ( (result=_gnutls_x509_read_int( spk, "dsa_parms.p", str, sizeof(str)-1, &params[0])) < 0) {
- gnutls_assert();
- asn1_delete_structure(spk);
- return GNUTLS_E_ASN1_PARSING_ERROR;
- }
-
- /* Read q */
-
- if ( (result=_gnutls_x509_read_int( spk, "dsa_parms.q", str, sizeof(str)-1, &params[1])) < 0) {
- gnutls_assert();
- asn1_delete_structure(spk);
- _gnutls_mpi_release(&params[0]);
- return GNUTLS_E_ASN1_PARSING_ERROR;
- }
-
- /* Read g */
-
- if ( (result=_gnutls_x509_read_int( spk, "dsa_parms.g", str, sizeof(str)-1, &params[2])) < 0) {
- gnutls_assert();
- asn1_delete_structure(spk);
- _gnutls_mpi_release(&params[0]);
- _gnutls_mpi_release(&params[1]);
- return GNUTLS_E_ASN1_PARSING_ERROR;
- }
-
- asn1_delete_structure(spk);
-
- return 0;
-
-}
-
-/* reads DSA's Y
- * from the certificate
- * params[3]
- */
-static int _read_dsa_pubkey(opaque * der, int dersize, MPI * params)
-{
- opaque str[MAX_PARAMETER_SIZE];
- int result;
- node_asn *spk;
-
- if ( (result=asn1_create_structure
- (_gnutls_get_gnutls_asn(), "GNUTLS.DSAPublicKey", &spk,
- "dsa_public_key")) != ASN_OK) {
- gnutls_assert();
- return GNUTLS_E_ASN1_ERROR;
- }
-
- result = asn1_get_der(spk, der, dersize);
-
- if (result != ASN_OK) {
- gnutls_assert();
- asn1_delete_structure(spk);
- return GNUTLS_E_ASN1_PARSING_ERROR;
- }
-
- /* Read p */
-
- if ( (result=_gnutls_x509_read_int( spk, "dsa_public_key", str, sizeof(str)-1, &params[3])) < 0) {
- gnutls_assert();
- asn1_delete_structure(spk);
- return GNUTLS_E_ASN1_PARSING_ERROR;
- }
-
- asn1_delete_structure(spk);
-
- return 0;
-
-}
-
-
-#define _READ(a, aa, b, c, d, e, res, f) \
- result = _IREAD(a, aa, sizeof(aa), b, c, d, e, res, sizeof(res)-1, f); \
- if (result<0) return result; \
- if (result==1) continue
-
-
-int _IREAD(node_asn * rasn, char *name3, int name3_size, char *rstr, char *OID,
- char *ANAME, char *TYPE, char *res, int res_size, int CHOICE)
-{
- char name2[256];
- int result, len;
- char str[1024];
- node_asn *tmpasn;
-
- if (strcmp(rstr, OID) == 0) {
-
- _gnutls_str_cpy(str, sizeof(str), "PKIX1Implicit88.");
- _gnutls_str_cat(str, sizeof(str), ANAME);
- _gnutls_str_cpy(name2, sizeof(name2), "temp-structure-");
- _gnutls_str_cat(name2, sizeof(name2), TYPE);
-
- if ((result =
- asn1_create_structure(_gnutls_get_pkix(), str,
- &tmpasn, name2)) != ASN_OK) {
- gnutls_assert();
- return GNUTLS_E_ASN1_ERROR;
- }
-
- len = sizeof(str) -1;
- if ((result =
- asn1_read_value(rasn, name3, str, &len)) != ASN_OK) {
- asn1_delete_structure(tmpasn);
- return 1;
- }
-
- if ((result = asn1_get_der(tmpasn, str, len)) != ASN_OK) {
- asn1_delete_structure(tmpasn);
- return 1;
- }
- _gnutls_str_cpy(name3, name3_size, name2);
-
- len = sizeof(str) - 1;
- if ((result = asn1_read_value(tmpasn, name3, str, &len)) != ASN_OK) { /* CHOICE */
- asn1_delete_structure(tmpasn);
- return 1;
- }
-
- if (CHOICE == 0) {
- str[len] = 0;
- /* strlen(str) < res_size, checked above */
- _gnutls_str_cpy(res, res_size, str);
-
- } else { /* CHOICE */
- str[len] = 0;
- _gnutls_str_cat(name3, name3_size, ".");
- _gnutls_str_cat(name3, name3_size, str);
- len = sizeof(str) - 1;
-
- if ((result =
- asn1_read_value(tmpasn, name3, str,
- &len)) != ASN_OK) {
- asn1_delete_structure(tmpasn);
- return 1;
- }
- str[len] = 0;
- if ( len < res_size)
- _gnutls_str_cpy(res, res_size, str);
- }
- asn1_delete_structure(tmpasn);
-
- }
- return 0;
-}
-
-/* this function will convert up to 3 digit
- * numbers to characters.
- */
-void _gnutls_int2str(int k, char *data)
-{
- if (k > 999)
- data[0] = 0;
- else
- sprintf(data, "%d", k);
-}
-
-/* This function will attempt to read a Name
- * ASN.1 structure. (Taken from Fabio's samples!)
- *
- * FIXME: These functions need carefull auditing
- * (they're complex enough)
- * --nmav
- */
-int _gnutls_get_name_type(node_asn * rasn, char *root, gnutls_DN * dn)
-{
- int k, k2, result, len;
- char name[128], str[1024], name2[128], counter[MAX_INT_DIGITS],
- name3[128];
-
- k = 0;
- do {
- k++;
-
- _gnutls_str_cpy(name, sizeof(name), root);
- _gnutls_str_cat(name, sizeof(name), ".rdnSequence.?");
- _gnutls_int2str(k, counter);
- _gnutls_str_cat(name, sizeof(name), counter);
-
- len = sizeof(str) - 1;
-
- result = asn1_read_value(rasn, name, str, &len);
-
- /* move to next
- */
- if (result == ASN_ELEMENT_NOT_FOUND)
- break;
- if (result != ASN_VALUE_NOT_FOUND) {
- gnutls_assert();
- return GNUTLS_E_ASN1_PARSING_ERROR;
- }
-
- k2 = 0;
- do {
- k2++;
-
- _gnutls_str_cpy(name2, sizeof(name2), name);
- _gnutls_str_cat(name2, sizeof(name2), ".?");
- _gnutls_int2str(k2, counter);
- _gnutls_str_cat(name2, sizeof(name2), counter);
-
- len = sizeof(str) - 1;
- result = asn1_read_value(rasn, name2, str, &len);
-
- if (result == ASN_ELEMENT_NOT_FOUND)
- break;
- if (result != ASN_VALUE_NOT_FOUND) {
- gnutls_assert();
- return GNUTLS_E_ASN1_PARSING_ERROR;
- }
-
- _gnutls_str_cpy(name3, sizeof(name3), name2);
- _gnutls_str_cat(name3, sizeof(name3), ".type");
-
- len = sizeof(str) - 1;
- result = asn1_read_value(rasn, name3, str, &len);
-
- if (result == ASN_ELEMENT_NOT_FOUND)
- break;
- else if (result != ASN_OK) {
- gnutls_assert();
- return GNUTLS_E_ASN1_PARSING_ERROR;
- }
-
- _gnutls_str_cpy(name3, sizeof(name3), name2);
- _gnutls_str_cat(name3, sizeof(name3), ".value");
-
- if (result == ASN_OK) {
-#ifdef DEBUG
-# warning " FIX COUNTRY HERE"
-#endif
- _READ(rasn, name3, str, "2 5 4 6",
- "X520OrganizationName",
- "countryName", dn->country, 1);
- _READ(rasn, name3, str, "2 5 4 10",
- "X520OrganizationName",
- "OrganizationName", dn->organization,
- 1);
- _READ(rasn, name3, str, "2 5 4 11",
- "X520OrganizationalUnitName",
- "OrganizationalUnitName",
- dn->organizational_unit_name, 1);
- _READ(rasn, name3, str, "2 5 4 3",
- "X520CommonName", "CommonName",
- dn->common_name, 1);
- _READ(rasn, name3, str, "2 5 4 7",
- "X520LocalityName", "LocalityName",
- dn->locality_name, 1);
- _READ(rasn, name3, str, "2 5 4 8",
- "X520StateOrProvinceName",
- "StateOrProvinceName",
- dn->state_or_province_name, 1);
- _READ(rasn, name3, str,
- "1 2 840 113549 1 9 1", "Pkcs9email",
- "emailAddress", dn->email, 0);
- }
- } while (1);
- } while (1);
-
- if (result == ASN_ELEMENT_NOT_FOUND)
- return 0;
- else
- return GNUTLS_E_ASN1_PARSING_ERROR;
-}
-
-
-
-#define MAX_TIME 1024
-time_t _gnutls_get_time(node_asn * c2, char *root, char *when)
-{
- opaque ttime[MAX_TIME];
- char name[1024];
- time_t ctime;
- int len, result;
-
- _gnutls_str_cpy(name, sizeof(name), root);
- _gnutls_str_cat(name, sizeof(name), ".tbsCertificate.validity.");
- _gnutls_str_cat(name, sizeof(name), when);
-
- len = sizeof(ttime) - 1;
- if ((result = asn1_read_value(c2, name, ttime, &len)) < 0) {
- gnutls_assert();
- return (time_t) (-1);
- }
-
- /* CHOICE */
- _gnutls_str_cpy(name, sizeof(name), root);
-
- if (strcmp(ttime, "GeneralizedTime") == 0) {
-
- _gnutls_str_cat(name, sizeof(name), ".tbsCertificate.validity.");
- _gnutls_str_cat(name, sizeof(name), when);
- _gnutls_str_cat(name, sizeof(name), ".generalTime");
- len = sizeof(ttime) - 1;
- result = asn1_read_value(c2, name, ttime, &len);
- if (result == ASN_OK)
- ctime = _gnutls_generalTime2gtime(ttime);
- } else { /* UTCTIME */
-
- _gnutls_str_cat(name, sizeof(name), ".tbsCertificate.validity.");
- _gnutls_str_cat(name, sizeof(name), when);
- _gnutls_str_cat(name, sizeof(name), ".utcTime");
- len = sizeof(ttime) - 1;
- result = asn1_read_value(c2, name, ttime, &len);
- if (result == ASN_OK)
- ctime = _gnutls_utcTime2gtime(ttime);
- }
-
- if (result != ASN_OK) {
- gnutls_assert();
- return (time_t) (-1);
- }
- return ctime;
-}
-
-int _gnutls_get_version(node_asn * c2, char *root)
-{
- opaque gversion[5];
- char name[1024];
- int len, result;
-
- _gnutls_str_cpy(name, sizeof(name), root);
- _gnutls_str_cat(name, sizeof(name), ".tbsCertificate.version");
-
- len = sizeof(gversion) - 1;
- if ((result = asn1_read_value(c2, name, gversion, &len)) < 0) {
- gnutls_assert();
- return (-1);
- }
- return (int) gversion[0] + 1;
-}
-
-
-/* Extracts DSA and RSA parameters from a certificate.
- */
-static
-int _gnutls_extract_cert_mpi_params( const char* ALGO_OID, gnutls_cert * gCert,
- node_asn* c2, char* tmpstr, int tmpstr_size) {
-int len, result;
-
- if (strcmp( ALGO_OID, "1 2 840 113549 1 1 1") == 0) { /* pkix-1 1 - RSA */
- /* params[0] is the modulus,
- * params[1] is the exponent
- */
- gCert->subject_pk_algorithm = GNUTLS_PK_RSA;
-
- len = tmpstr_size - 1;
- result =
- asn1_read_value
- (c2, "certificate2.tbsCertificate.subjectPublicKeyInfo.subjectPublicKey",
- tmpstr, &len);
-
- if (result != ASN_OK) {
- gnutls_assert();
- return GNUTLS_E_ASN1_PARSING_ERROR;
- }
-
- if ((sizeof(gCert->params) / sizeof(MPI)) < RSA_PARAMS) {
- gnutls_assert();
- /* internal error. Increase the MPIs in params */
- return GNUTLS_E_INTERNAL;
- }
-
- if ((result =
- _read_rsa_params(tmpstr, len / 8, gCert->params)) < 0) {
- gnutls_assert();
- return result;
- }
-
- return 0;
- }
-
- if (strcmp( ALGO_OID, "1 2 840 10040 4 1") == 0) { /* pkix-1 1 - DSA */
- /* params[0] is p,
- * params[1] is q,
- * params[2] is q,
- * params[3] is pub.
- */
- gCert->subject_pk_algorithm = GNUTLS_PK_DSA;
-
- len = tmpstr_size - 1;
- result =
- asn1_read_value
- (c2, "certificate2.tbsCertificate.subjectPublicKeyInfo.subjectPublicKey",
- tmpstr, &len);
-
- if (result != ASN_OK) {
- gnutls_assert();
- return GNUTLS_E_ASN1_PARSING_ERROR;
- }
-
- if ((sizeof(gCert->params) / sizeof(MPI)) < DSA_PARAMS) {
- gnutls_assert();
- /* internal error. Increase the MPIs in params */
- return GNUTLS_E_INTERNAL;
- }
-
- if ((result =
- _read_dsa_pubkey(tmpstr, len / 8, gCert->params)) < 0) {
- gnutls_assert();
- return result;
- }
-
- /* Now read the parameters
- */
- len = tmpstr_size - 1;
- result =
- asn1_read_value
- (c2, "certificate2.tbsCertificate.subjectPublicKeyInfo.algorithm.parameters",
- tmpstr, &len);
-
- if (result != ASN_OK) {
- gnutls_assert();
- return GNUTLS_E_ASN1_PARSING_ERROR;
- }
-
- if ((result =
- _read_dsa_params(tmpstr, len, gCert->params)) < 0) {
- gnutls_assert();
- return result;
- }
-
- return 0;
- }
-
-
-
- /* other types like DH
- * currently not supported
- */
- gnutls_assert();
-
- _gnutls_log("CERT: ALGORITHM: %s\n", ALGO_OID);
-
- gCert->subject_pk_algorithm = GNUTLS_PK_UNKNOWN;
-
- return GNUTLS_E_INVALID_PARAMETERS;
-}
-
-
-#define X509_SIG_SIZE 1024
-
-/* This function will convert a der certificate, to a format
- * (structure) that gnutls can understand and use. Actually the
- * important thing on this function is that it extracts the
- * certificate's (public key) parameters.
- */
-int _gnutls_x509_cert2gnutls_cert(gnutls_cert * gCert, gnutls_datum derCert)
-{
- int result;
- node_asn *c2;
- opaque str[MAX_X509_CERT_SIZE];
- int len = sizeof(str);
-
- memset(gCert, 0, sizeof(gnutls_cert));
-
- gCert->valid = 1;
- gCert->cert_type = GNUTLS_CRT_X509;
-
- if (gnutls_set_datum(&gCert->raw, derCert.data, derCert.size) < 0) {
- gnutls_assert();
- return GNUTLS_E_MEMORY_ERROR;
- }
-
- if (asn1_create_structure
- (_gnutls_get_pkix(), "PKIX1Implicit88.Certificate", &c2,
- "certificate2")
- != ASN_OK) {
- gnutls_assert();
- gnutls_free_datum( &gCert->raw);
- return GNUTLS_E_ASN1_ERROR;
- }
-
- result = asn1_get_der(c2, derCert.data, derCert.size);
- if (result != ASN_OK) {
- /* couldn't decode DER */
-
- _gnutls_log("CERT: Decoding error %d\n", result);
-
- gnutls_assert();
- asn1_delete_structure(c2);
- gnutls_free_datum( &gCert->raw);
- return GNUTLS_E_ASN1_PARSING_ERROR;
- }
-
- len = sizeof(str) - 1;
- result =
- asn1_read_value
- (c2,
- "certificate2.tbsCertificate.subjectPublicKeyInfo.algorithm.algorithm",
- str, &len);
-
- if (result != ASN_OK) {
- gnutls_assert();
- asn1_delete_structure(c2);
- gnutls_free_datum( &gCert->raw);
- return GNUTLS_E_ASN1_PARSING_ERROR;
- }
-
- if ( (result=_gnutls_extract_cert_mpi_params( str, gCert, c2, str, sizeof(str))) < 0) {
- gnutls_assert();
- asn1_delete_structure(c2);
- gnutls_free_datum( &gCert->raw);
- return result;
- }
-
- len = gCert->signature.size = X509_SIG_SIZE;
- gCert->signature.data = gnutls_malloc( gCert->signature.size);
- if (gCert->signature.data==NULL) {
- gnutls_assert();
- return GNUTLS_E_MEMORY_ERROR;
- }
-
- result =
- asn1_read_value
- (c2, "certificate2.signature", gCert->signature.data, &len);
-
- if ((len % 8) != 0) {
- gnutls_assert();
- asn1_delete_structure(c2);
- gnutls_free_datum( &gCert->raw);
- gnutls_free_datum( &gCert->signature);
- return GNUTLS_E_UNIMPLEMENTED_FEATURE;
- }
-
- len /= 8; /* convert to bytes */
- gCert->signature.size = len; /* put the actual sig size */
-
-
- gCert->expiration_time =
- _gnutls_get_time(c2, "certificate2", "notAfter");
- gCert->activation_time =
- _gnutls_get_time(c2, "certificate2", "notBefore");
- gCert->version = _gnutls_get_version(c2, "certificate2");
-
- if ((result =
- _gnutls_get_ext_type(c2,
- "certificate2.tbsCertificate.extensions",
- gCert)) < 0) {
- gnutls_assert();
- asn1_delete_structure(c2);
- gnutls_free_datum( &gCert->raw);
- return result;
- }
-
- asn1_delete_structure(c2);
-
-
- gCert->valid = 0; /* if we got until here
- * the certificate is valid.
- */
-
- return 0;
-
-}
-
-/* Returns 0 if it's ok to use the KXAlgorithm with this cert
- * (using KeyUsage field).
- */
-int _gnutls_check_x509_key_usage(const gnutls_cert * cert,
- KXAlgorithm alg)
-{
- if (_gnutls_map_kx_get_cred(alg) == GNUTLS_CRD_CERTIFICATE) {
- switch (alg) {
- case GNUTLS_KX_RSA:
- if (cert->keyUsage != 0) {
- if (!
- (cert->
- keyUsage & GNUTLS_X509KEY_KEY_ENCIPHERMENT))
- return
- GNUTLS_E_X509_KEY_USAGE_VIOLATION;
- else
- return 0;
- }
- return 0;
- case GNUTLS_KX_DHE_RSA:
- case GNUTLS_KX_DHE_DSS:
- if (cert->keyUsage != 0) {
- if (!
- (cert->
- keyUsage & GNUTLS_X509KEY_DIGITAL_SIGNATURE))
- return
- GNUTLS_E_X509_KEY_USAGE_VIOLATION;
- else
- return 0;
- }
- return 0;
- default:
- gnutls_assert();
- return GNUTLS_E_X509_KEY_USAGE_VIOLATION;
- }
- }
- return 0;
-}
/* returns the KX algorithms that are supported by a
* certificate. (Eg a certificate with RSA params, supports
@@ -1332,7 +175,16 @@ int _gnutls_cert_supported_kx(const gnutls_cert * cert, KXAlgorithm ** alg,
for (kx = 0; kx < MAX_KX_ALGOS; kx++) {
pk = _gnutls_map_pk_get_pk(kx);
if (pk == cert->subject_pk_algorithm) {
- if (_gnutls_check_x509_key_usage(cert, kx) == 0) {
+ if (cert->cert_type==GNUTLS_CRT_X509) {
+ /* then check key usage */
+ if (_gnutls_check_x509_key_usage(cert, kx) == 0) {
+ kxlist[i] = kx;
+ i++;
+ }
+ } else if ( cert->cert_type==GNUTLS_CRT_OPENPGP) {
+ /* FIXME: something like key usage
+ * should be added
+ */
kxlist[i] = kx;
i++;
}
@@ -1453,3 +305,37 @@ void gnutls_certificate_server_set_select_func(GNUTLS_STATE state,
{
state->gnutls_internals.server_cert_callback = func;
}
+
+/**
+ * gnutls_certificate_verify_peers - This function returns the peer's certificate verification status
+ * @state: is a gnutls state
+ *
+ * This function will try to verify the peer's certificate and return it's status (TRUSTED, EXPIRED etc.).
+ * The return value (status) should be one of the CertificateStatus enumerated elements.
+ * However you must also check the peer's name in order to check if the verified certificate belongs to the
+ * actual peer. Returns a negative error code in case of an error, or GNUTLS_CERT_NONE if no certificate was sent.
+ *
+ **/
+int gnutls_certificate_verify_peers(GNUTLS_STATE state)
+{
+ CERTIFICATE_AUTH_INFO info;
+
+ CHECK_AUTH(GNUTLS_CRD_CERTIFICATE, GNUTLS_E_INVALID_REQUEST);
+
+ info = _gnutls_get_auth_info(state);
+ if (info == NULL)
+ return GNUTLS_E_INVALID_REQUEST;
+
+ if (info->raw_certificate_list == NULL || info->ncerts == 0)
+ return GNUTLS_CERT_NONE;
+
+ switch( gnutls_cert_type_get( state)) {
+ case GNUTLS_CRT_X509:
+ return _gnutls_x509_cert_verify_peers( state);
+ case GNUTLS_CRT_OPENPGP:
+ /* FIX THIS */
+/* return _gnutls_openpgp_cert_verify_peers( state); */
+ default:
+ return GNUTLS_E_INVALID_REQUEST;
+ }
+}
diff --git a/lib/gnutls_cert.h b/lib/gnutls_cert.h
index ad08db483a..54e04103d7 100644
--- a/lib/gnutls_cert.h
+++ b/lib/gnutls_cert.h
@@ -34,7 +34,7 @@ typedef struct gnutls_cert {
gnutls_datum signature;
- opaque fingerprint[20];
+ opaque fingerprint[20];
time_t expiration_time;
time_t activation_time;
@@ -82,14 +82,7 @@ struct GNUTLS_STATE_INT; /* because GNUTLS_STATE is not defined when this file i
int _gnutls_cert_supported_kx( const gnutls_cert* cert, KXAlgorithm **alg, int *alg_size);
PKAlgorithm _gnutls_map_pk_get_pk(KXAlgorithm kx_algorithm);
-int _gnutls_x509_cert2gnutls_cert(gnutls_cert * gCert, gnutls_datum derCert);
-#define MAX_INT_DIGITS 4
-void _gnutls_int2str(int k, char* data);
-int _gnutls_get_name_type( node_asn *rasn, char *root, gnutls_dn * dn);
void gnutls_free_cert(gnutls_cert cert);
-int _gnutls_check_x509_key_usage( const gnutls_cert * cert, KXAlgorithm alg);
-int _gnutls_get_version(node_asn * c2, char *root);
-time_t _gnutls_get_time(node_asn * c2, char *root, char *when);
#endif
diff --git a/lib/gnutls_int_compat.c b/lib/gnutls_int_compat.c
index f402b66095..5da43995b1 100644
--- a/lib/gnutls_int_compat.c
+++ b/lib/gnutls_int_compat.c
@@ -8,51 +8,6 @@
#ifdef GNUTLS_BACKWARDS_COMPATIBLE
-/* used in 0.3.x */
-int gnutls_anon_set_server_cred( GNUTLS_ANON_SERVER_CREDENTIALS res, int dh_bits) {
- return 0;
-}
-
-/* used in 0.3.x */
-int gnutls_check_pending( GNUTLS_STATE state) {
- return gnutls_record_check_pending( state);
-}
-
-/* used in 0.3.x */
-void gnutls_x509pki_set_dh_bits(GNUTLS_STATE state, int bits) {
- gnutls_dh_set_bits( state, bits);
-}
-
-/* used in 0.3.x */
-int gnutls_anon_server_get_dh_bits(GNUTLS_STATE state)
-{
- return gnutls_dh_get_bits( state);
-}
-
-/* used in 0.3.x */
-int gnutls_anon_client_get_dh_bits(GNUTLS_STATE state)
-{
- return gnutls_dh_get_bits( state);
-}
-
-/* used in 0.3.x */
-int gnutls_set_max_handshake_data_buffer_size( GNUTLS_STATE state) {
- return 0;
-}
-
-GNUTLS_BulkCipherAlgorithm gnutls_cipher_get_algo( GNUTLS_STATE state) {
- return gnutls_cipher_get( state);
-}
-GNUTLS_KXAlgorithm gnutls_kx_get_algo( GNUTLS_STATE state) {
- return gnutls_kx_get( state);
-}
-
-GNUTLS_MACAlgorithm gnutls_mac_get_algo( GNUTLS_STATE state) {
- return gnutls_mac_get( state);
-}
-
-GNUTLS_CompressionMethod gnutls_compression_get_algo( GNUTLS_STATE state) {
- return gnutls_compression_get( state);
-}
+/* nothing here */
#endif /* GNUTLS_BACKWARDS_COMPATIBLE */
diff --git a/lib/gnutls_session_pack.c b/lib/gnutls_session_pack.c
index 6c723f4688..a76bce3393 100644
--- a/lib/gnutls_session_pack.c
+++ b/lib/gnutls_session_pack.c
@@ -28,11 +28,11 @@
#include <gnutls_num.h>
#define PACK_HEADER_SIZE 1
-int _gnutls_pack_x509pki_auth_info( CERTIFICATE_AUTH_INFO info,
+int _gnutls_pack_certificate_auth_info( CERTIFICATE_AUTH_INFO info,
gnutls_datum * packed_session);
-int _gnutls_unpack_x509pki_auth_info(CERTIFICATE_AUTH_INFO info,
+int _gnutls_unpack_certificate_auth_info(CERTIFICATE_AUTH_INFO info,
const gnutls_datum * packed_session);
-static int _gnutls_pack_x509pki_auth_info_size( CERTIFICATE_AUTH_INFO info);
+static int _gnutls_pack_certificate_auth_info_size( CERTIFICATE_AUTH_INFO info);
/* Since auth_info structures contain malloced data, this function
@@ -106,7 +106,7 @@ int _gnutls_session_pack(GNUTLS_STATE state, gnutls_datum * packed_session)
return GNUTLS_E_INVALID_PARAMETERS;
ret =
- _gnutls_pack_x509pki_auth_info(info,
+ _gnutls_pack_certificate_auth_info(info,
packed_session);
if (ret < 0) {
gnutls_assert();
@@ -152,7 +152,7 @@ int _gnutls_session_size( GNUTLS_STATE state)
if (info == NULL)
return GNUTLS_E_INVALID_PARAMETERS;
- pack_size += _gnutls_pack_x509pki_auth_info_size( info);
+ pack_size += _gnutls_pack_certificate_auth_info_size( info);
}
break;
}
@@ -260,7 +260,7 @@ int _gnutls_session_unpack(GNUTLS_STATE state,
sizeof(CERTIFICATE_AUTH_INFO_INT);
ret =
- _gnutls_unpack_x509pki_auth_info(state->
+ _gnutls_unpack_certificate_auth_info(state->
gnutls_key->
auth_info,
packed_session);
@@ -308,11 +308,11 @@ int _gnutls_session_unpack(GNUTLS_STATE state,
return 0;
}
-int _gnutls_pack_x509pki_auth_info( CERTIFICATE_AUTH_INFO info,
+int _gnutls_pack_certificate_auth_info( CERTIFICATE_AUTH_INFO info,
gnutls_datum * packed_session)
{
uint32 pos, i;
- packed_session->size = _gnutls_pack_x509pki_auth_info_size( info);
+ packed_session->size = _gnutls_pack_certificate_auth_info_size( info);
packed_session->data[0] = GNUTLS_CRD_CERTIFICATE;
WRITEuint32( packed_session->size-PACK_HEADER_SIZE-sizeof(uint32), &packed_session->data[PACK_HEADER_SIZE]);
@@ -335,7 +335,7 @@ int _gnutls_pack_x509pki_auth_info( CERTIFICATE_AUTH_INFO info,
return 0;
}
-static int _gnutls_pack_x509pki_auth_info_size( CERTIFICATE_AUTH_INFO info)
+static int _gnutls_pack_certificate_auth_info_size( CERTIFICATE_AUTH_INFO info)
{
uint32 pack_size = sizeof(CERTIFICATE_AUTH_INFO_INT);
int i;
@@ -351,7 +351,7 @@ static int _gnutls_pack_x509pki_auth_info_size( CERTIFICATE_AUTH_INFO info)
}
-int _gnutls_unpack_x509pki_auth_info(CERTIFICATE_AUTH_INFO info,
+int _gnutls_unpack_certificate_auth_info(CERTIFICATE_AUTH_INFO info,
const gnutls_datum * packed_session)
{
int ret, i, pos, j;
diff --git a/lib/gnutls_ui.h b/lib/gnutls_ui.h
index 78ec695402..6a5e97eb5a 100644
--- a/lib/gnutls_ui.h
+++ b/lib/gnutls_ui.h
@@ -81,7 +81,7 @@ const gnutls_datum *gnutls_certificate_get_ours(GNUTLS_STATE state);
int gnutls_certificate_get_ours_index(GNUTLS_STATE state);
int gnutls_certificate_client_get_request_status( GNUTLS_STATE);
-int gnutls_x509pki_verify_peers( GNUTLS_STATE);
+int gnutls_certificate_verify_peers( GNUTLS_STATE);
int gnutls_b64_encode_fmt( const char* msg, const gnutls_datum *data, char* result, int* result_size);
int gnutls_b64_decode_fmt( const gnutls_datum *b64_data, char* result, int* result_size);
diff --git a/lib/gnutls_x509.c b/lib/gnutls_x509.c
index 472f01c9a6..59dac2d218 100644
--- a/lib/gnutls_x509.c
+++ b/lib/gnutls_x509.c
@@ -38,7 +38,279 @@
#include <x509_extensions.h>
#include <gnutls_state.h>
#include <gnutls_pk.h>
+#include <gnutls_str.h>
#include <debug.h>
+#include <x509_b64.h>
+#include <gnutls_privkey.h>
+#include <gnutls_x509.h>
+
+/*
+ * some x509 certificate parsing functions.
+ */
+
+#define _READ(a, aa, b, c, d, e, res, f) \
+ result = _IREAD(a, aa, sizeof(aa), b, c, d, e, res, sizeof(res)-1, f); \
+ if (result<0) return result; \
+ if (result==1) continue
+
+
+static int _IREAD(node_asn * rasn, char *name3, int name3_size, char *rstr, char *OID,
+ char *ANAME, char *TYPE, char *res, int res_size, int CHOICE)
+{
+ char name2[256];
+ int result, len;
+ char str[1024];
+ node_asn *tmpasn;
+
+ if (strcmp(rstr, OID) == 0) {
+
+ _gnutls_str_cpy(str, sizeof(str), "PKIX1Implicit88.");
+ _gnutls_str_cat(str, sizeof(str), ANAME);
+ _gnutls_str_cpy(name2, sizeof(name2), "temp-structure-");
+ _gnutls_str_cat(name2, sizeof(name2), TYPE);
+
+ if ((result =
+ asn1_create_structure(_gnutls_get_pkix(), str,
+ &tmpasn, name2)) != ASN_OK) {
+ gnutls_assert();
+ return GNUTLS_E_ASN1_ERROR;
+ }
+
+ len = sizeof(str) -1;
+ if ((result =
+ asn1_read_value(rasn, name3, str, &len)) != ASN_OK) {
+ asn1_delete_structure(tmpasn);
+ return 1;
+ }
+
+ if ((result = asn1_get_der(tmpasn, str, len)) != ASN_OK) {
+ asn1_delete_structure(tmpasn);
+ return 1;
+ }
+ _gnutls_str_cpy(name3, name3_size, name2);
+
+ len = sizeof(str) - 1;
+ if ((result = asn1_read_value(tmpasn, name3, str, &len)) != ASN_OK) { /* CHOICE */
+ asn1_delete_structure(tmpasn);
+ return 1;
+ }
+
+ if (CHOICE == 0) {
+ str[len] = 0;
+ /* strlen(str) < res_size, checked above */
+ _gnutls_str_cpy(res, res_size, str);
+
+ } else { /* CHOICE */
+ str[len] = 0;
+ _gnutls_str_cat(name3, name3_size, ".");
+ _gnutls_str_cat(name3, name3_size, str);
+ len = sizeof(str) - 1;
+
+ if ((result =
+ asn1_read_value(tmpasn, name3, str,
+ &len)) != ASN_OK) {
+ asn1_delete_structure(tmpasn);
+ return 1;
+ }
+ str[len] = 0;
+ if ( len < res_size)
+ _gnutls_str_cpy(res, res_size, str);
+ }
+ asn1_delete_structure(tmpasn);
+
+ }
+ return 0;
+}
+
+/* this function will convert up to 3 digit
+ * numbers to characters.
+ */
+void _gnutls_int2str(int k, char *data)
+{
+ if (k > 999)
+ data[0] = 0;
+ else
+ sprintf(data, "%d", k);
+}
+
+/* This function will attempt to read a Name
+ * ASN.1 structure. (Taken from Fabio's samples!)
+ *
+ * FIXME: These functions need carefull auditing
+ * (they're complex enough)
+ * --nmav
+ */
+int _gnutls_x509_get_name_type(node_asn * rasn, char *root, gnutls_DN * dn)
+{
+ int k, k2, result, len;
+ char name[128], str[1024], name2[128], counter[MAX_INT_DIGITS],
+ name3[128];
+
+ k = 0;
+ do {
+ k++;
+
+ _gnutls_str_cpy(name, sizeof(name), root);
+ _gnutls_str_cat(name, sizeof(name), ".rdnSequence.?");
+ _gnutls_int2str(k, counter);
+ _gnutls_str_cat(name, sizeof(name), counter);
+
+ len = sizeof(str) - 1;
+
+ result = asn1_read_value(rasn, name, str, &len);
+
+ /* move to next
+ */
+ if (result == ASN_ELEMENT_NOT_FOUND)
+ break;
+ if (result != ASN_VALUE_NOT_FOUND) {
+ gnutls_assert();
+ return GNUTLS_E_ASN1_PARSING_ERROR;
+ }
+
+ k2 = 0;
+ do {
+ k2++;
+
+ _gnutls_str_cpy(name2, sizeof(name2), name);
+ _gnutls_str_cat(name2, sizeof(name2), ".?");
+ _gnutls_int2str(k2, counter);
+ _gnutls_str_cat(name2, sizeof(name2), counter);
+
+ len = sizeof(str) - 1;
+ result = asn1_read_value(rasn, name2, str, &len);
+
+ if (result == ASN_ELEMENT_NOT_FOUND)
+ break;
+ if (result != ASN_VALUE_NOT_FOUND) {
+ gnutls_assert();
+ return GNUTLS_E_ASN1_PARSING_ERROR;
+ }
+
+ _gnutls_str_cpy(name3, sizeof(name3), name2);
+ _gnutls_str_cat(name3, sizeof(name3), ".type");
+
+ len = sizeof(str) - 1;
+ result = asn1_read_value(rasn, name3, str, &len);
+
+ if (result == ASN_ELEMENT_NOT_FOUND)
+ break;
+ else if (result != ASN_OK) {
+ gnutls_assert();
+ return GNUTLS_E_ASN1_PARSING_ERROR;
+ }
+
+ _gnutls_str_cpy(name3, sizeof(name3), name2);
+ _gnutls_str_cat(name3, sizeof(name3), ".value");
+
+ if (result == ASN_OK) {
+#ifdef DEBUG
+# warning " FIX COUNTRY HERE"
+#endif
+ _READ(rasn, name3, str, "2 5 4 6",
+ "X520OrganizationName",
+ "countryName", dn->country, 1);
+ _READ(rasn, name3, str, "2 5 4 10",
+ "X520OrganizationName",
+ "OrganizationName", dn->organization,
+ 1);
+ _READ(rasn, name3, str, "2 5 4 11",
+ "X520OrganizationalUnitName",
+ "OrganizationalUnitName",
+ dn->organizational_unit_name, 1);
+ _READ(rasn, name3, str, "2 5 4 3",
+ "X520CommonName", "CommonName",
+ dn->common_name, 1);
+ _READ(rasn, name3, str, "2 5 4 7",
+ "X520LocalityName", "LocalityName",
+ dn->locality_name, 1);
+ _READ(rasn, name3, str, "2 5 4 8",
+ "X520StateOrProvinceName",
+ "StateOrProvinceName",
+ dn->state_or_province_name, 1);
+ _READ(rasn, name3, str,
+ "1 2 840 113549 1 9 1", "Pkcs9email",
+ "emailAddress", dn->email, 0);
+ }
+ } while (1);
+ } while (1);
+
+ if (result == ASN_ELEMENT_NOT_FOUND)
+ return 0;
+ else
+ return GNUTLS_E_ASN1_PARSING_ERROR;
+}
+
+
+
+#define MAX_TIME 1024
+time_t _gnutls_x509_get_time(node_asn * c2, char *root, char *when)
+{
+ opaque ttime[MAX_TIME];
+ char name[1024];
+ time_t ctime;
+ int len, result;
+
+ _gnutls_str_cpy(name, sizeof(name), root);
+ _gnutls_str_cat(name, sizeof(name), ".tbsCertificate.validity.");
+ _gnutls_str_cat(name, sizeof(name), when);
+
+ len = sizeof(ttime) - 1;
+ if ((result = asn1_read_value(c2, name, ttime, &len)) < 0) {
+ gnutls_assert();
+ return (time_t) (-1);
+ }
+
+ /* CHOICE */
+ _gnutls_str_cpy(name, sizeof(name), root);
+
+ if (strcmp(ttime, "GeneralizedTime") == 0) {
+
+ _gnutls_str_cat(name, sizeof(name), ".tbsCertificate.validity.");
+ _gnutls_str_cat(name, sizeof(name), when);
+ _gnutls_str_cat(name, sizeof(name), ".generalTime");
+ len = sizeof(ttime) - 1;
+ result = asn1_read_value(c2, name, ttime, &len);
+ if (result == ASN_OK)
+ ctime = _gnutls_generalTime2gtime(ttime);
+ } else { /* UTCTIME */
+
+ _gnutls_str_cat(name, sizeof(name), ".tbsCertificate.validity.");
+ _gnutls_str_cat(name, sizeof(name), when);
+ _gnutls_str_cat(name, sizeof(name), ".utcTime");
+ len = sizeof(ttime) - 1;
+ result = asn1_read_value(c2, name, ttime, &len);
+ if (result == ASN_OK)
+ ctime = _gnutls_utcTime2gtime(ttime);
+ }
+
+ if (result != ASN_OK) {
+ gnutls_assert();
+ return (time_t) (-1);
+ }
+ return ctime;
+}
+
+int _gnutls_x509_get_version(node_asn * c2, char *root)
+{
+ opaque gversion[5];
+ char name[1024];
+ int len, result;
+
+ _gnutls_str_cpy(name, sizeof(name), root);
+ _gnutls_str_cat(name, sizeof(name), ".tbsCertificate.version");
+
+ len = sizeof(gversion) - 1;
+ if ((result = asn1_read_value(c2, name, gversion, &len)) < 0) {
+ gnutls_assert();
+ return (-1);
+ }
+ return (int) gversion[0] + 1;
+}
+
+
+
+
/**
* gnutls_x509_extract_dn - This function parses an RDN sequence
@@ -71,7 +343,7 @@ int gnutls_x509_extract_dn(const gnutls_datum * idn, gnutls_dn * rdn)
return GNUTLS_E_ASN1_PARSING_ERROR;
}
- result = _gnutls_get_name_type(dn, "dn", rdn);
+ result = _gnutls_x509_get_name_type(dn, "dn", rdn);
asn1_delete_structure(dn);
if (result < 0) {
@@ -122,7 +394,7 @@ int gnutls_x509_extract_certificate_dn(const gnutls_datum * cert,
return GNUTLS_E_ASN1_PARSING_ERROR;
}
if ((result =
- _gnutls_get_name_type(c2,
+ _gnutls_x509_get_name_type(c2,
"certificate2.tbsCertificate.subject",
ret)) < 0) {
gnutls_assert();
@@ -173,7 +445,7 @@ int gnutls_x509_extract_certificate_issuer_dn(const gnutls_datum * cert,
return GNUTLS_E_ASN1_PARSING_ERROR;
}
if ((result =
- _gnutls_get_name_type(c2,
+ _gnutls_x509_get_name_type(c2,
"certificate2.tbsCertificate.issuer",
ret)) < 0) {
gnutls_assert();
@@ -269,7 +541,7 @@ time_t gnutls_x509_extract_certificate_activation_time(const
return -1;
}
- ret = _gnutls_get_time(c2, "certificate2", "notBefore");
+ ret = _gnutls_x509_get_time(c2, "certificate2", "notBefore");
asn1_delete_structure(c2);
@@ -311,7 +583,7 @@ time_t gnutls_x509_extract_certificate_expiration_time(const
return -1;
}
- ret = _gnutls_get_time(c2, "certificate2", "notAfter");
+ ret = _gnutls_x509_get_time(c2, "certificate2", "notAfter");
asn1_delete_structure(c2);
@@ -349,7 +621,7 @@ int gnutls_x509_extract_certificate_version(const gnutls_datum * cert)
return GNUTLS_E_ASN1_PARSING_ERROR;
}
- result = _gnutls_get_version(c2, "certificate2");
+ result = _gnutls_x509_get_version(c2, "certificate2");
asn1_delete_structure(c2);
@@ -359,8 +631,8 @@ int gnutls_x509_extract_certificate_version(const gnutls_datum * cert)
#define CLEAR_CERTS for(x=0;x<peer_certificate_list_size;x++) gnutls_free_cert(peer_certificate_list[x])
-/**
- * gnutls_x509pki_verify_peers - This function returns the peer's certificate status
+/*-
+ * _gnutls_x509_cert_verify_peers - This function returns the peer's certificate status
* @state: is a gnutls state
*
* This function will try to verify the peer's certificate and return it's status (TRUSTED, EXPIRED etc.).
@@ -368,8 +640,8 @@ int gnutls_x509_extract_certificate_version(const gnutls_datum * cert)
* However you must also check the peer's name in order to check if the verified certificate belongs to the
* actual peer. Returns a negative error code in case of an error, or GNUTLS_CERT_NONE if no certificate was sent.
*
- **/
-int gnutls_x509pki_verify_peers(GNUTLS_STATE state)
+ -*/
+int _gnutls_x509_cert_verify_peers(GNUTLS_STATE state)
{
CERTIFICATE_AUTH_INFO info;
const GNUTLS_CERTIFICATE_CREDENTIALS cred;
@@ -440,7 +712,7 @@ int gnutls_x509pki_verify_peers(GNUTLS_STATE state)
#define CLEAR_CERTS_CA for(x=0;x<peer_certificate_list_size;x++) gnutls_free_cert(peer_certificate_list[x]); \
for(x=0;x<ca_certificate_list_size;x++) gnutls_free_cert(ca_certificate_list[x])
/**
- * gnutls_x509pki_verify_certificate - This function verifies given certificate list
+ * gnutls_x509_verify_certificate - This function verifies given certificate list
* @cert_list: is the certificate list to be verified
* @cert_list_length: holds the number of certificate in cert_list
* @CA_list: is the CA list which will be used in verification
@@ -454,7 +726,7 @@ int gnutls_x509pki_verify_peers(GNUTLS_STATE state)
* actual peer. Returns a negative error code in case of an error.
*
**/
-int gnutls_x509pki_verify_certificate( const gnutls_datum* cert_list, int cert_list_length, const gnutls_datum * CA_list, int CA_list_length, const gnutls_datum* CRL_list, int CRL_list_length)
+int gnutls_x509_verify_certificate( const gnutls_datum* cert_list, int cert_list_length, const gnutls_datum * CA_list, int CA_list_length, const gnutls_datum* CRL_list, int CRL_list_length)
{
CertificateStatus verify;
gnutls_cert *peer_certificate_list;
@@ -583,3 +855,894 @@ int gnutls_x509_extract_certificate_serial(const gnutls_datum * cert, char* resu
return 0;
}
+
+
+/*
+ * Read certificates and private keys, from files, memory etc.
+ */
+
+/* returns error if the certificate has different algorithm than
+ * the given key parameters.
+ */
+static int _gnutls_check_key_cert_match( GNUTLS_CERTIFICATE_CREDENTIALS res) {
+ if (res->pkey->pk_algorithm != res->cert_list[0]->subject_pk_algorithm) {
+ gnutls_assert();
+ return GNUTLS_E_CERTIFICATE_KEY_MISMATCH;
+ }
+ return 0;
+}
+
+#define MAX_FILE_SIZE 100*1024
+#define CERT_SEP "-----BEGIN"
+
+/* Reads a base64 encoded certificate from memory
+ */
+static int read_cert_mem(GNUTLS_CERTIFICATE_CREDENTIALS res, const char *cert, int cert_size)
+{
+ int siz, i, siz2;
+ opaque *b64;
+ const char *ptr;
+ gnutls_datum tmp;
+ int ret;
+
+ /* allocate space for the certificate to add
+ */
+ res->cert_list = gnutls_realloc( res->cert_list, (1+res->ncerts)*sizeof(gnutls_cert*));
+ if (res->cert_list==NULL) {
+ gnutls_assert();
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+
+ res->cert_list_length = gnutls_realloc( res->cert_list_length,
+ (1+res->ncerts)*sizeof(int));
+ if (res->cert_list_length==NULL) {
+ gnutls_assert();
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+
+
+ ptr = cert;
+ siz = cert_size;
+ i = 1;
+
+ res->cert_list[res->ncerts] = NULL;
+
+ do {
+ siz2 = _gnutls_fbase64_decode(ptr, siz, &b64);
+ siz -= siz2; /* FIXME: this is not enough
+ */
+
+ if (siz2 < 0) {
+ gnutls_assert();
+ gnutls_free(b64);
+ return GNUTLS_E_PARSING_ERROR;
+ }
+
+
+ res->cert_list[res->ncerts] =
+ (gnutls_cert *) gnutls_realloc(res->
+ cert_list[res->ncerts],
+ i *
+ sizeof(gnutls_cert));
+
+ if (res->cert_list[res->ncerts] == NULL) {
+ gnutls_assert();
+ gnutls_free(b64);
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+ /* set defaults to zero
+ */
+ memset(&res->cert_list[res->ncerts][i - 1], 0,
+ sizeof(gnutls_cert));
+
+ tmp.data = b64;
+ tmp.size = siz2;
+
+ if ((ret =
+ _gnutls_x509_cert2gnutls_cert(&res->
+ cert_list[res->ncerts][i - 1],
+ tmp)) < 0) {
+ gnutls_free(b64);
+ gnutls_assert();
+ return ret;
+ }
+ gnutls_free(b64);
+
+ /* now we move ptr after the pem header */
+ ptr = strstr(ptr, CERT_SEP);
+ if (ptr!=NULL)
+ ptr++;
+
+ i++;
+ } while ((ptr = strstr(ptr, CERT_SEP)) != NULL);
+
+ res->cert_list_length[res->ncerts] = i - 1;
+
+ res->ncerts++;
+
+ return 0;
+}
+
+/* Reads a base64 encoded CA list from memory
+ * This is to be called once.
+ */
+static int read_ca_mem(GNUTLS_CERTIFICATE_CREDENTIALS res, const char *ca, int ca_size)
+{
+ int siz, siz2, i;
+ opaque *b64;
+ const char *ptr;
+ int ret;
+ gnutls_datum tmp;
+
+ siz = ca_size;
+
+ ptr = ca;
+
+ i = res->x509_ncas + 1;
+
+ do {
+ siz2 = _gnutls_fbase64_decode(ptr, siz, &b64);
+ siz -= siz2; /* FIXME: this is not enough
+ */
+
+ if (siz2 < 0) {
+ gnutls_assert();
+ gnutls_free(b64);
+ return GNUTLS_E_PARSING_ERROR;
+ }
+
+ res->x509_ca_list =
+ (gnutls_cert *) gnutls_realloc(res->x509_ca_list,
+ i *
+ sizeof(gnutls_cert));
+ if (res->x509_ca_list == NULL) {
+ gnutls_assert();
+ gnutls_free(b64);
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+ memset(&res->x509_ca_list[i - 1], 0, sizeof(gnutls_cert));
+
+ tmp.data = b64;
+ tmp.size = siz2;
+
+ if ((ret =
+ _gnutls_x509_cert2gnutls_cert(&res->x509_ca_list[i - 1],
+ tmp)) < 0) {
+ gnutls_assert();
+ gnutls_free(b64);
+ return ret;
+ }
+ gnutls_free(b64);
+
+ /* now we move ptr after the pem header */
+ ptr = strstr(ptr, CERT_SEP);
+ if (ptr!=NULL)
+ ptr++;
+
+ i++;
+ } while ((ptr = strstr(ptr, CERT_SEP)) != NULL);
+
+ res->x509_ncas = i - 1;
+
+
+
+ return 0;
+}
+
+
+/* Reads a PEM encoded PKCS-1 RSA private key from memory
+ * 2002-01-26: Added ability to read DSA keys.
+ */
+static int read_key_mem(GNUTLS_CERTIFICATE_CREDENTIALS res, const char *key, int key_size)
+{
+ int siz, ret;
+ opaque *b64;
+ gnutls_datum tmp;
+ PKAlgorithm pk;
+
+ /* allocate space for the pkey list
+ */
+ res->pkey = gnutls_realloc( res->pkey, (res->ncerts+1)*sizeof(gnutls_private_key));
+ if (res->pkey==NULL) {
+ gnutls_assert();
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+
+ /* read PKCS-1 private key */
+ siz = key_size;
+
+ /* If we find the "DSA PRIVATE" string in the
+ * pem encoded certificate then it's a DSA key.
+ */
+ if (strstr( key, "DSA PRIVATE")!=NULL)
+ pk = GNUTLS_PK_DSA;
+ else
+ pk = GNUTLS_PK_RSA;
+
+ siz = _gnutls_fbase64_decode(key, siz, &b64);
+
+ if (siz < 0) {
+ gnutls_assert();
+ gnutls_free(b64);
+ return GNUTLS_E_PARSING_ERROR;
+ }
+
+ tmp.data = b64;
+ tmp.size = siz;
+
+ switch (pk) { /* decode the key */
+ case GNUTLS_PK_RSA:
+ if ((ret =
+ _gnutls_PKCS1key2gnutlsKey(&res->pkey[res->ncerts],
+ tmp)) < 0) {
+ gnutls_assert();
+ gnutls_free(b64);
+ return ret;
+ }
+ break;
+ case GNUTLS_PK_DSA:
+ if ((ret =
+ _gnutls_DSAkey2gnutlsKey(&res->pkey[res->ncerts],
+ tmp)) < 0) {
+ gnutls_assert();
+ gnutls_free(b64);
+ return ret;
+ }
+ break;
+ }
+ gnutls_free(b64);
+
+ return 0;
+}
+
+
+/* Reads a base64 encoded certificate file
+ */
+static int read_cert_file(GNUTLS_CERTIFICATE_CREDENTIALS res, char *certfile)
+{
+ int siz;
+ char x[MAX_FILE_SIZE];
+ FILE *fd1;
+
+ fd1 = fopen(certfile, "r");
+ if (fd1 == NULL)
+ return GNUTLS_E_UNKNOWN_ERROR;
+
+ siz = fread(x, 1, sizeof(x), fd1);
+ fclose(fd1);
+
+ x[siz-1] = 0;
+
+ return read_cert_mem( res, x, siz);
+
+}
+
+/* Reads a base64 encoded CA file (file contains multiple certificate
+ * authorities). This is to be called once.
+ */
+static int read_ca_file(GNUTLS_CERTIFICATE_CREDENTIALS res, char *cafile)
+{
+ int siz;
+ char x[MAX_FILE_SIZE];
+ FILE *fd1;
+
+ fd1 = fopen(cafile, "r");
+ if (fd1 == NULL) {
+ gnutls_assert();
+ return GNUTLS_E_UNKNOWN_ERROR;
+ }
+
+ siz = fread(x, 1, sizeof(x), fd1);
+ fclose(fd1);
+
+ x[siz-1] = 0;
+
+ return read_ca_mem( res, x, siz);
+}
+
+
+/* Reads a PEM encoded PKCS-1 RSA private key file
+ */
+static int read_key_file(GNUTLS_CERTIFICATE_CREDENTIALS res, char *keyfile)
+{
+ int siz;
+ char x[MAX_FILE_SIZE];
+ FILE *fd2;
+
+ fd2 = fopen(keyfile, "r");
+ if (fd2 == NULL)
+ return GNUTLS_E_UNKNOWN_ERROR;
+
+ siz = fread(x, 1, sizeof(x), fd2);
+ fclose(fd2);
+
+ x[siz-1] = 0;
+
+ return read_key_mem( res, x, siz);
+}
+
+
+/**
+ * gnutls_certificate_set_x509_key_file - Used to set keys in a GNUTLS_CERTIFICATE_CREDENTIALS structure
+ * @res: is an &GNUTLS_CERTIFICATE_CREDENTIALS structure.
+ * @CERTFILE: is a PEM encoded file containing the certificate list (path) for
+ * the specified private key
+ * @KEYFILE: is a PEM encoded file containing a private key
+ *
+ * This function sets a certificate/private key pair in the
+ * GNUTLS_CERTIFICATE_CREDENTIALS structure. This function may be called
+ * more than once (in case multiple keys/certificates exist for the
+ * server).
+ *
+ * Currently only PKCS-1 PEM encoded RSA and DSA private keys are accepted by
+ * this function.
+ *
+ **/
+int gnutls_certificate_set_x509_key_file(GNUTLS_CERTIFICATE_CREDENTIALS res, char *CERTFILE,
+ char *KEYFILE)
+{
+ int ret;
+
+ /* this should be first
+ */
+ if ((ret = read_key_file(res, KEYFILE)) < 0)
+ return ret;
+
+ if ((ret = read_cert_file(res, CERTFILE)) < 0)
+ return ret;
+
+ if ((ret=_gnutls_check_key_cert_match( res)) < 0) {
+ gnutls_assert();
+ return ret;
+ }
+
+ return 0;
+}
+
+static int generate_rdn_seq( GNUTLS_CERTIFICATE_CREDENTIALS res) {
+gnutls_datum tmp;
+int ret, size, i;
+opaque *pdata;
+
+ /* Generate the RDN sequence
+ * This will be sent to clients when a certificate
+ * request message is sent.
+ */
+
+ /* FIXME: in case of a client it is not needed
+ * to do that. This would save time and memory.
+ * However we don't have that information available
+ * here.
+ */
+
+ size = 0;
+ for (i = 0; i < res->x509_ncas; i++) {
+ if ((ret = _gnutls_find_dn(&tmp, &res->x509_ca_list[i])) < 0) {
+ gnutls_assert();
+ return ret;
+ }
+ size += (2 + tmp.size);
+ }
+
+ if (res->x509_rdn_sequence.data != NULL)
+ gnutls_free( res->x509_rdn_sequence.data);
+
+ res->x509_rdn_sequence.data = gnutls_malloc(size);
+ if (res->x509_rdn_sequence.data == NULL) {
+ gnutls_assert();
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+ res->x509_rdn_sequence.size = size;
+
+ pdata = res->x509_rdn_sequence.data;
+
+ for (i = 0; i < res->x509_ncas; i++) {
+ if ((ret = _gnutls_find_dn(&tmp, &res->x509_ca_list[i])) < 0) {
+ gnutls_free(res->x509_rdn_sequence.data);
+ res->x509_rdn_sequence.size = 0;
+ res->x509_rdn_sequence.data = NULL;
+ gnutls_assert();
+ return ret;
+ }
+ WRITEdatum16(pdata, tmp);
+ pdata += (2 + tmp.size);
+ }
+
+ return 0;
+}
+
+/**
+ * gnutls_certificate_set_x509_trust_mem - Used to add trusted CAs in a GNUTLS_CERTIFICATE_CREDENTIALS structure
+ * @res: is an &GNUTLS_CERTIFICATE_CREDENTIALS structure.
+ * @CA: is a PEM encoded list of trusted CAs
+ * @CRL: is a PEM encoded list of CRLs (ignored for now)
+ *
+ * This function adds the trusted CAs in order to verify client
+ * certificates. This function may be called multiple times.
+ *
+ **/
+int gnutls_certificate_set_x509_trust_mem(GNUTLS_CERTIFICATE_CREDENTIALS res, const gnutls_datum *CA,
+ const gnutls_datum *CRL)
+{
+ int ret;
+
+ if ((ret = read_ca_mem(res, CA->data, CA->size)) < 0)
+ return ret;
+
+ if ((ret = generate_rdn_seq(res)) < 0)
+ return ret;
+
+ return 0;
+}
+
+/**
+ * gnutls_certificate_set_x509_trust_file - Used to add trusted CAs in a GNUTLS_CERTIFICATE_CREDENTIALS structure
+ * @res: is an &GNUTLS_CERTIFICATE_CREDENTIALS structure.
+ * @CAFILE: is a PEM encoded file containing trusted CAs
+ * @CRLFILE: is a PEM encoded file containing CRLs (ignored for now)
+ *
+ * This function sets the trusted CAs in order to verify client
+ * certificates. This function may be called multiple times.
+ *
+ **/
+int gnutls_certificate_set_x509_trust_file(GNUTLS_CERTIFICATE_CREDENTIALS res, char *CAFILE,
+ char *CRLFILE)
+{
+ int ret;
+
+ if ((ret = read_ca_file(res, CAFILE)) < 0)
+ return ret;
+
+ if ((ret = generate_rdn_seq(res)) < 0)
+ return ret;
+
+ return 0;
+}
+
+
+/**
+ * gnutls_certificate_set_x509_key_mem - Used to set keys in a GNUTLS_CERTIFICATE_CREDENTIALS structure
+ * @res: is an &GNUTLS_CERTIFICATE_CREDENTIALS structure.
+ * @CERT: contains a PEM encoded certificate list (path) for
+ * the specified private key
+ * @KEY: is a PEM encoded private key
+ *
+ * This function sets a certificate/private key pair in the
+ * GNUTLS_CERTIFICATE_CREDENTIALS structure. This function may be called
+ * more than once (in case multiple keys/certificates exist for the
+ * server).
+ *
+ * Currently are supported: RSA PKCS-1 PEM encoded private keys,
+ * pem encoded DSA private keys.
+ *
+ **/
+int gnutls_certificate_set_x509_key_mem(GNUTLS_CERTIFICATE_CREDENTIALS res, const gnutls_datum* CERT,
+ const gnutls_datum* KEY)
+{
+ int ret;
+
+ /* this should be first
+ */
+ if ((ret = read_key_mem( res, KEY->data, KEY->size)) < 0)
+ return ret;
+
+ if ((ret = read_cert_mem( res, CERT->data, CERT->size)) < 0)
+ return ret;
+
+ if ((ret=_gnutls_check_key_cert_match( res)) < 0) {
+ gnutls_assert();
+ return ret;
+ }
+
+ return 0;
+}
+
+
+static int _read_rsa_params(opaque * der, int dersize, MPI * params)
+{
+ opaque str[MAX_PARAMETER_SIZE];
+ int result;
+ node_asn *spk;
+
+ if (asn1_create_structure
+ (_gnutls_get_gnutls_asn(), "GNUTLS.RSAPublicKey", &spk,
+ "rsa_public_key") != ASN_OK) {
+ gnutls_assert();
+ return GNUTLS_E_ASN1_ERROR;
+ }
+
+ result = asn1_get_der(spk, der, dersize);
+
+ if (result != ASN_OK) {
+ gnutls_assert();
+ asn1_delete_structure(spk);
+ return GNUTLS_E_ASN1_PARSING_ERROR;
+ }
+
+
+ if ( (result=_gnutls_x509_read_int( spk, "rsa_public_key.modulus",
+ str, sizeof(str)-1, &params[0])) < 0) {
+ gnutls_assert();
+ asn1_delete_structure(spk);
+ return GNUTLS_E_ASN1_PARSING_ERROR;
+ }
+
+ if ( (result=_gnutls_x509_read_int( spk, "rsa_public_key.publicExponent",
+ str, sizeof(str)-1, &params[1])) < 0) {
+ gnutls_assert();
+ _gnutls_mpi_release(&params[0]);
+ asn1_delete_structure(spk);
+ return GNUTLS_E_ASN1_PARSING_ERROR;
+ }
+
+ asn1_delete_structure(spk);
+
+ return 0;
+
+}
+
+
+/* reads p,q and g
+ * from the certificate
+ * params[0-2]
+ */
+static int _read_dsa_params(opaque * der, int dersize, MPI * params)
+{
+ opaque str[MAX_PARAMETER_SIZE];
+ int result;
+ node_asn *spk;
+
+ if (asn1_create_structure
+ (_gnutls_get_pkix(), "PKIX1Implicit88.Dss-Parms", &spk,
+ "dsa_parms") != ASN_OK) {
+ gnutls_assert();
+ return GNUTLS_E_ASN1_ERROR;
+ }
+
+ result = asn1_get_der(spk, der, dersize);
+
+ if (result != ASN_OK) {
+ gnutls_assert();
+ asn1_delete_structure(spk);
+ return GNUTLS_E_ASN1_PARSING_ERROR;
+ }
+
+ /* FIXME: If the parameters are not included in the certificate
+ * then the issuer's parameters should be used.
+ */
+
+ /* Read p */
+
+ if ( (result=_gnutls_x509_read_int( spk, "dsa_parms.p", str, sizeof(str)-1, &params[0])) < 0) {
+ gnutls_assert();
+ asn1_delete_structure(spk);
+ return GNUTLS_E_ASN1_PARSING_ERROR;
+ }
+
+ /* Read q */
+
+ if ( (result=_gnutls_x509_read_int( spk, "dsa_parms.q", str, sizeof(str)-1, &params[1])) < 0) {
+ gnutls_assert();
+ asn1_delete_structure(spk);
+ _gnutls_mpi_release(&params[0]);
+ return GNUTLS_E_ASN1_PARSING_ERROR;
+ }
+
+ /* Read g */
+
+ if ( (result=_gnutls_x509_read_int( spk, "dsa_parms.g", str, sizeof(str)-1, &params[2])) < 0) {
+ gnutls_assert();
+ asn1_delete_structure(spk);
+ _gnutls_mpi_release(&params[0]);
+ _gnutls_mpi_release(&params[1]);
+ return GNUTLS_E_ASN1_PARSING_ERROR;
+ }
+
+ asn1_delete_structure(spk);
+
+ return 0;
+
+}
+
+/* reads DSA's Y
+ * from the certificate
+ * params[3]
+ */
+static int _read_dsa_pubkey(opaque * der, int dersize, MPI * params)
+{
+ opaque str[MAX_PARAMETER_SIZE];
+ int result;
+ node_asn *spk;
+
+ if ( (result=asn1_create_structure
+ (_gnutls_get_gnutls_asn(), "GNUTLS.DSAPublicKey", &spk,
+ "dsa_public_key")) != ASN_OK) {
+ gnutls_assert();
+ return GNUTLS_E_ASN1_ERROR;
+ }
+
+ result = asn1_get_der(spk, der, dersize);
+
+ if (result != ASN_OK) {
+ gnutls_assert();
+ asn1_delete_structure(spk);
+ return GNUTLS_E_ASN1_PARSING_ERROR;
+ }
+
+ /* Read p */
+
+ if ( (result=_gnutls_x509_read_int( spk, "dsa_public_key", str, sizeof(str)-1, &params[3])) < 0) {
+ gnutls_assert();
+ asn1_delete_structure(spk);
+ return GNUTLS_E_ASN1_PARSING_ERROR;
+ }
+
+ asn1_delete_structure(spk);
+
+ return 0;
+
+}
+
+
+/* Extracts DSA and RSA parameters from a certificate.
+ */
+static
+int _gnutls_extract_x509_cert_mpi_params( const char* ALGO_OID, gnutls_cert * gCert,
+ node_asn* c2, char* tmpstr, int tmpstr_size) {
+int len, result;
+
+ if (strcmp( ALGO_OID, "1 2 840 113549 1 1 1") == 0) { /* pkix-1 1 - RSA */
+ /* params[0] is the modulus,
+ * params[1] is the exponent
+ */
+ gCert->subject_pk_algorithm = GNUTLS_PK_RSA;
+
+ len = tmpstr_size - 1;
+ result =
+ asn1_read_value
+ (c2, "certificate2.tbsCertificate.subjectPublicKeyInfo.subjectPublicKey",
+ tmpstr, &len);
+
+ if (result != ASN_OK) {
+ gnutls_assert();
+ return GNUTLS_E_ASN1_PARSING_ERROR;
+ }
+
+ if ((sizeof(gCert->params) / sizeof(MPI)) < RSA_PARAMS) {
+ gnutls_assert();
+ /* internal error. Increase the MPIs in params */
+ return GNUTLS_E_INTERNAL;
+ }
+
+ if ((result =
+ _read_rsa_params(tmpstr, len / 8, gCert->params)) < 0) {
+ gnutls_assert();
+ return result;
+ }
+
+ return 0;
+ }
+
+ if (strcmp( ALGO_OID, "1 2 840 10040 4 1") == 0) { /* pkix-1 1 - DSA */
+ /* params[0] is p,
+ * params[1] is q,
+ * params[2] is q,
+ * params[3] is pub.
+ */
+ gCert->subject_pk_algorithm = GNUTLS_PK_DSA;
+
+ len = tmpstr_size - 1;
+ result =
+ asn1_read_value
+ (c2, "certificate2.tbsCertificate.subjectPublicKeyInfo.subjectPublicKey",
+ tmpstr, &len);
+
+ if (result != ASN_OK) {
+ gnutls_assert();
+ return GNUTLS_E_ASN1_PARSING_ERROR;
+ }
+
+ if ((sizeof(gCert->params) / sizeof(MPI)) < DSA_PARAMS) {
+ gnutls_assert();
+ /* internal error. Increase the MPIs in params */
+ return GNUTLS_E_INTERNAL;
+ }
+
+ if ((result =
+ _read_dsa_pubkey(tmpstr, len / 8, gCert->params)) < 0) {
+ gnutls_assert();
+ return result;
+ }
+
+ /* Now read the parameters
+ */
+ len = tmpstr_size - 1;
+ result =
+ asn1_read_value
+ (c2, "certificate2.tbsCertificate.subjectPublicKeyInfo.algorithm.parameters",
+ tmpstr, &len);
+
+ if (result != ASN_OK) {
+ gnutls_assert();
+ return GNUTLS_E_ASN1_PARSING_ERROR;
+ }
+
+ if ((result =
+ _read_dsa_params(tmpstr, len, gCert->params)) < 0) {
+ gnutls_assert();
+ return result;
+ }
+
+ return 0;
+ }
+
+
+
+ /* other types like DH
+ * currently not supported
+ */
+ gnutls_assert();
+
+ _gnutls_log("CERT: ALGORITHM: %s\n", ALGO_OID);
+
+ gCert->subject_pk_algorithm = GNUTLS_PK_UNKNOWN;
+
+ return GNUTLS_E_INVALID_PARAMETERS;
+}
+
+
+
+#define X509_SIG_SIZE 1024
+
+/* This function will convert a der certificate, to a format
+ * (structure) that gnutls can understand and use. Actually the
+ * important thing on this function is that it extracts the
+ * certificate's (public key) parameters.
+ */
+int _gnutls_x509_cert2gnutls_cert(gnutls_cert * gCert, gnutls_datum derCert)
+{
+ int result;
+ node_asn *c2;
+ opaque str[MAX_X509_CERT_SIZE];
+ int len = sizeof(str);
+
+ memset(gCert, 0, sizeof(gnutls_cert));
+
+ gCert->valid = 1;
+ gCert->cert_type = GNUTLS_CRT_X509;
+
+ if (gnutls_set_datum(&gCert->raw, derCert.data, derCert.size) < 0) {
+ gnutls_assert();
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+
+ if (asn1_create_structure
+ (_gnutls_get_pkix(), "PKIX1Implicit88.Certificate", &c2,
+ "certificate2")
+ != ASN_OK) {
+ gnutls_assert();
+ gnutls_free_datum( &gCert->raw);
+ return GNUTLS_E_ASN1_ERROR;
+ }
+
+ result = asn1_get_der(c2, derCert.data, derCert.size);
+ if (result != ASN_OK) {
+ /* couldn't decode DER */
+
+ _gnutls_log("CERT: Decoding error %d\n", result);
+
+ gnutls_assert();
+ asn1_delete_structure(c2);
+ gnutls_free_datum( &gCert->raw);
+ return GNUTLS_E_ASN1_PARSING_ERROR;
+ }
+
+ len = sizeof(str) - 1;
+ result =
+ asn1_read_value
+ (c2,
+ "certificate2.tbsCertificate.subjectPublicKeyInfo.algorithm.algorithm",
+ str, &len);
+
+ if (result != ASN_OK) {
+ gnutls_assert();
+ asn1_delete_structure(c2);
+ gnutls_free_datum( &gCert->raw);
+ return GNUTLS_E_ASN1_PARSING_ERROR;
+ }
+
+ if ( (result=_gnutls_extract_x509_cert_mpi_params( str, gCert, c2, str, sizeof(str))) < 0) {
+ gnutls_assert();
+ asn1_delete_structure(c2);
+ gnutls_free_datum( &gCert->raw);
+ return result;
+ }
+
+ len = gCert->signature.size = X509_SIG_SIZE;
+ gCert->signature.data = gnutls_malloc( gCert->signature.size);
+ if (gCert->signature.data==NULL) {
+ gnutls_assert();
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+
+ result =
+ asn1_read_value
+ (c2, "certificate2.signature", gCert->signature.data, &len);
+
+ if ((len % 8) != 0) {
+ gnutls_assert();
+ asn1_delete_structure(c2);
+ gnutls_free_datum( &gCert->raw);
+ gnutls_free_datum( &gCert->signature);
+ return GNUTLS_E_UNIMPLEMENTED_FEATURE;
+ }
+
+ len /= 8; /* convert to bytes */
+ gCert->signature.size = len; /* put the actual sig size */
+
+
+ gCert->expiration_time =
+ _gnutls_x509_get_time(c2, "certificate2", "notAfter");
+ gCert->activation_time =
+ _gnutls_x509_get_time(c2, "certificate2", "notBefore");
+ gCert->version = _gnutls_x509_get_version(c2, "certificate2");
+
+ if ((result =
+ _gnutls_get_ext_type(c2,
+ "certificate2.tbsCertificate.extensions",
+ gCert)) < 0) {
+ gnutls_assert();
+ asn1_delete_structure(c2);
+ gnutls_free_datum( &gCert->raw);
+ return result;
+ }
+
+ asn1_delete_structure(c2);
+
+
+ gCert->valid = 0; /* if we got until here
+ * the certificate is valid.
+ */
+
+ return 0;
+
+}
+
+/* Returns 0 if it's ok to use the KXAlgorithm with this cert
+ * (using KeyUsage field).
+ */
+int _gnutls_check_x509_key_usage(const gnutls_cert * cert,
+ KXAlgorithm alg)
+{
+ if (_gnutls_map_kx_get_cred(alg) == GNUTLS_CRD_CERTIFICATE) {
+ switch (alg) {
+ case GNUTLS_KX_RSA:
+ if (cert->keyUsage != 0) {
+ if (!
+ (cert->
+ keyUsage & GNUTLS_X509KEY_KEY_ENCIPHERMENT))
+ return
+ GNUTLS_E_X509_KEY_USAGE_VIOLATION;
+ else
+ return 0;
+ }
+ return 0;
+ case GNUTLS_KX_DHE_RSA:
+ case GNUTLS_KX_DHE_DSS:
+ if (cert->keyUsage != 0) {
+ if (!
+ (cert->
+ keyUsage & GNUTLS_X509KEY_DIGITAL_SIGNATURE))
+ return
+ GNUTLS_E_X509_KEY_USAGE_VIOLATION;
+ else
+ return 0;
+ }
+ return 0;
+ default:
+ gnutls_assert();
+ return GNUTLS_E_X509_KEY_USAGE_VIOLATION;
+ }
+ }
+ return 0;
+}
diff --git a/lib/x509_extensions.c b/lib/x509_extensions.c
index e411c52f9e..68bf6aba65 100644
--- a/lib/x509_extensions.c
+++ b/lib/x509_extensions.c
@@ -27,7 +27,7 @@
#include <gnutls_global.h>
#include "debug.h"
#include <gnutls_str.h>
-
+#include <gnutls_x509.h>
/* Here we only extract the KeyUsage field
*/
diff --git a/src/cli.c b/src/cli.c
index 9027bdc7ff..1c688bb807 100644
--- a/src/cli.c
+++ b/src/cli.c
@@ -133,14 +133,14 @@ int main(int argc, char** argv)
}
/* X509 stuff */
- if (gnutls_certificate_allocate_client_sc( &xcred, 2) < 0) { /* space for 2 certificates */
+ if (gnutls_certificate_allocate_client_sc( &xcred) < 0) { /* space for 2 certificates */
fprintf(stderr, "memory error\n");
exit(1);
}
- gnutls_x509pki_set_trust_file( xcred, CAFILE, CRLFILE);
- gnutls_x509pki_set_key_file( xcred, CLICERTFILE1, CLIKEYFILE1);
- gnutls_x509pki_set_key_file( xcred, CLICERTFILE2, CLIKEYFILE2);
-/* gnutls_certificate_client_callback_callback( xcred, cert_callback); */
+ gnutls_certificate_set_x509_trust_file( xcred, CAFILE, CRLFILE);
+ gnutls_certificate_set_x509_key_file( xcred, CLICERTFILE1, CLIKEYFILE1);
+ gnutls_certificate_set_x509_key_file( xcred, CLICERTFILE2, CLIKEYFILE2);
+/* gnutls_certificate_client_callback_func( xcred, cert_callback); */
/* SRP stuff */
if (gnutls_srp_allocate_client_sc( &cred)<0) {
diff --git a/src/common.h b/src/common.h
index ebed84572c..28605c0187 100644
--- a/src/common.h
+++ b/src/common.h
@@ -44,7 +44,7 @@ GNUTLS_KXAlgorithm kx;
/* in case of X509 PKI
*/
cert_list = gnutls_certificate_get_peers( state, &cert_list_size);
- status = gnutls_x509pki_verify_peers( state);
+ status = gnutls_certificate_verify_peers( state);
switch( status) {
case GNUTLS_CERT_NOT_TRUSTED:
diff --git a/src/serv.c b/src/serv.c
index 3bbe205546..bfdb19b7ce 100644
--- a/src/serv.c
+++ b/src/serv.c
@@ -256,22 +256,22 @@ int main(int argc, char **argv)
exit(1);
}
- if (gnutls_certificate_allocate_server_sc(&x509_cred, 2) < 0) {
+ if (gnutls_certificate_allocate_server_sc(&x509_cred) < 0) {
fprintf(stderr, "memory error\n");
exit(1);
}
- if (gnutls_x509pki_set_trust_file( x509_cred, CAFILE, CRLFILE) < 0) {
+ if (gnutls_certificate_set_x509_trust_file( x509_cred, CAFILE, CRLFILE) < 0) {
fprintf(stderr, "X509 PARSE ERROR\nDid you have ca.pem?\n");
exit(1);
}
- if (gnutls_x509pki_set_key_file( x509_cred, CERTFILE1, KEYFILE1) < 0) {
+ if (gnutls_certificate_set_x509_key_file( x509_cred, CERTFILE1, KEYFILE1) < 0) {
fprintf(stderr, "X509 PARSE ERROR\nDid you have key.pem and cert.pem?\n");
exit(1);
}
- if (gnutls_x509pki_set_key_file( x509_cred, CERTFILE2, KEYFILE2) < 0) {
+ if (gnutls_certificate_set_x509_key_file( x509_cred, CERTFILE2, KEYFILE2) < 0) {
fprintf(stderr, "X509 PARSE ERROR\nDid you have key.pem and cert.pem?\n");
exit(1);
}