summaryrefslogtreecommitdiff
path: root/libextra/gnutls_openssl.c
diff options
context:
space:
mode:
authorAndrew McDonald <admcd@gnutls.org>2002-06-19 20:41:59 +0000
committerAndrew McDonald <admcd@gnutls.org>2002-06-19 20:41:59 +0000
commitb7a33637d38f7b70e8c970c3c2fdad2a426ab3de (patch)
tree9a40848093c68d2e2098c26653870efb6ae593c7 /libextra/gnutls_openssl.c
parentc22a6eca4d5d78d1d94a48a0ec881470ac924ea0 (diff)
downloadgnutls-b7a33637d38f7b70e8c970c3c2fdad2a426ab3de.tar.gz
Implemented some more functions.
Basic TLS/SSL operations tested with: slrn, wget, lynx
Diffstat (limited to 'libextra/gnutls_openssl.c')
-rw-r--r--libextra/gnutls_openssl.c502
1 files changed, 414 insertions, 88 deletions
diff --git a/libextra/gnutls_openssl.c b/libextra/gnutls_openssl.c
index fbff4e7825..6cf8ae01b1 100644
--- a/libextra/gnutls_openssl.c
+++ b/libextra/gnutls_openssl.c
@@ -18,10 +18,39 @@
#include <gnutls.h>
#include <gcrypt.h>
+#include <stdio.h>
+#include <stdlib.h>
#include "gnutls-openssl.h"
static int last_error = 0;
+
+/* Library initialisation functions */
+
+int SSL_library_init(void)
+{
+ return 1;
+}
+
+void OpenSSL_add_all_algorithms(void)
+{
+ return;
+}
+
+
+/* SSL_CTX structure handling */
+
+SSL_CTX *SSL_CTX_new(SSL_METHOD *method)
+{
+ SSL_CTX *ctx;
+ gnutls_global_init();
+
+ ctx = (SSL_CTX *)calloc(1, sizeof(SSL_CTX));
+ ctx->method = method;
+
+ return ctx;
+}
+
void SSL_CTX_free(SSL_CTX *ctx)
{
free(ctx->method->protocol_priority);
@@ -35,128 +64,255 @@ void SSL_CTX_free(SSL_CTX *ctx)
gnutls_global_deinit();
}
+int SSL_CTX_set_default_verify_paths(SSL_CTX *ctx)
+{
+ return 0;
+}
-unsigned long ERR_get_error(void)
+int SSL_CTX_use_certificate_file(SSL_CTX *ctx, const char *certfile, int type)
{
- unsigned long ret;
+ ctx->certfile = (char *)calloc(1, strlen(certfile)+1);
+ if (!ctx->certfile)
+ return -1;
+ memcpy(ctx->certfile, certfile, strlen(certfile));
- ret = -1 * last_error;
- last_error = 0;
+ ctx->certfile_type = type;
- return ret;
+ return 1;
}
-int SSL_get_error(SSL *ssl, int ret)
+int SSL_CTX_use_PrivateKey_file(SSL_CTX *ctx, const char *keyfile, int type)
{
- if (ret > 0)
- return SSL_ERROR_NONE;
+ ctx->keyfile = (char *)calloc(1, strlen(keyfile)+1);
+ if (!ctx->keyfile)
+ return -1;
+ memcpy(ctx->keyfile, keyfile, strlen(keyfile));
+
+ ctx->keyfile_type = type;
+
+ return 1;
- return SSL_ERROR_ZERO_RETURN;
}
-char *ERR_error_string(unsigned long e, char *buf)
+void SSL_CTX_set_verify(SSL_CTX *ctx, int verify_mode,
+ int (*verify_callback)(int, X509_STORE_CTX *))
{
- return gnutls_strerror(-1 * e);
+ ctx->verify_mode = verify_mode;
+ ctx->verify_callback = verify_callback;
+}
+
+unsigned long SSL_CTX_set_options(SSL_CTX *ctx, unsigned long options)
+{
+ return (ctx->options |= options);
}
-int RAND_status(void)
+/* SSL structure handling */
+
+SSL *SSL_new(SSL_CTX *ctx)
{
- return 1;
+ SSL *ssl;
+ int err;
+
+ ssl = (SSL *)calloc(1, sizeof(SSL));
+ if (!ssl)
+ return NULL;
+
+ err = gnutls_certificate_allocate_sc(&ssl->gnutls_cred);
+ if (err < 0)
+ {
+ last_error = err;
+ free(ssl);
+ return NULL;
+ }
+
+ gnutls_init(&ssl->gnutls_state, GNUTLS_CLIENT);
+
+ gnutls_protocol_set_priority (ssl->gnutls_state, ctx->method->protocol_priority);
+ gnutls_cipher_set_priority (ssl->gnutls_state, ctx->method->cipher_priority);
+ gnutls_compression_set_priority (ssl->gnutls_state, ctx->method->comp_priority);
+ gnutls_kx_set_priority (ssl->gnutls_state, ctx->method->kx_priority);
+ gnutls_mac_set_priority (ssl->gnutls_state, ctx->method->mac_priority);
+
+ gnutls_cred_set (ssl->gnutls_state, GNUTLS_CRD_CERTIFICATE, ssl->gnutls_cred);
+ if (ctx->certfile)
+ gnutls_certificate_set_x509_trust_file(ssl->gnutls_cred, ctx->certfile,
+ ctx->certfile_type);
+ if (ctx->keyfile)
+ gnutls_certificate_set_x509_key_file(ssl->gnutls_cred, ctx->certfile,
+ ctx->keyfile, ctx->keyfile_type);
+
+ ssl->verify_mode = ctx->verify_mode;
+ ssl->verify_callback = ctx->verify_callback;
+
+ ssl->options = ctx->options;
+
+ return ssl;
}
-void RAND_seed(const void *buf, int num)
+void SSL_free(SSL *ssl)
{
+ gnutls_certificate_free_sc(ssl->gnutls_cred);
+ gnutls_deinit(ssl->gnutls_state);
+ free(ssl);
return;
}
-int RAND_bytes(unsigned char *buf, int num)
+void SSL_load_error_strings(void)
{
- gcry_randomize(buf, num, GCRY_STRONG_RANDOM);
- return 1;
+ return;
}
-int SSL_library_init(void)
+int SSL_get_error(SSL *ssl, int ret)
{
- gnutls_global_init();
+ if (ret > 0)
+ return SSL_ERROR_NONE;
+
+ return SSL_ERROR_ZERO_RETURN;
+}
+
+int SSL_set_fd(SSL *ssl, int fd)
+{
+ gnutls_transport_set_ptr (ssl->gnutls_state, fd);
return 1;
}
-void SSL_load_error_strings(void)
+
+void SSL_set_connect_state(SSL *ssl)
{
return;
}
-SSL_CTX *SSL_CTX_new(SSL_METHOD *method)
+int SSL_pending(SSL *ssl)
{
- SSL_CTX *ctx;
- gnutls_global_init();
-
- ctx = (SSL_CTX *)calloc(sizeof(SSL_CTX), 1);
- ctx->method = method;
+ return gnutls_record_check_pending(ssl->gnutls_state);
}
-SSL *SSL_new(SSL_CTX *ctx)
+void SSL_set_verify(SSL *ssl, int verify_mode,
+ int (*verify_callback)(int, X509_STORE_CTX *))
{
- SSL *ssl;
+ ssl->verify_mode = verify_mode;
+ ssl->verify_callback = verify_callback;
+}
+
+
+/* SSL connection open/close/read/write functions */
+
+int SSL_connect(SSL *ssl)
+{
+ X509_STORE_CTX *store;
+ int cert_list_size = 0;
int err;
- ssl = (SSL *)calloc(sizeof(SSL), 1);
- if (!ssl)
- return NULL;
+ err = gnutls_handshake(ssl->gnutls_state);
+ ssl->last_error = err;
- err = gnutls_certificate_allocate_sc(&ssl->cred);
if (err < 0)
{
- last_error = err;
- free(ssl);
- return NULL;
+ last_error = err;
+ return 0;
}
- gnutls_init(&ssl->state, GNUTLS_CLIENT);
+ store = (X509_STORE_CTX *)calloc(1, sizeof(X509_STORE_CTX));
+ store->ssl = ssl;
+ store->cert_list = gnutls_certificate_get_peers(ssl->gnutls_state,
+ &cert_list_size);
- gnutls_protocol_set_priority (ssl->state, ctx->method->protocol_priority);
- gnutls_cipher_set_priority (ssl->state, ctx->method->cipher_priority);
- gnutls_compression_set_priority (ssl->state, ctx->method->comp_priority);
- gnutls_kx_set_priority (ssl->state, ctx->method->kx_priority);
- gnutls_mac_set_priority (ssl->state, ctx->method->mac_priority);
+ if (ssl->verify_callback)
+ {
+ ssl->verify_callback(1 /*FIXME*/, store);
+ }
+ ssl->state = SSL_ST_OK;
- gnutls_cred_set (ssl->state, GNUTLS_CRD_CERTIFICATE, ssl->cred);
+ err = store->error;
+ free(store);
- return ssl;
+ return 1;
+}
+
+int SSL_shutdown(SSL *ssl)
+{
+ if (!ssl->shutdown)
+ {
+ gnutls_bye(ssl->gnutls_state, GNUTLS_SHUT_WR);
+ ssl->shutdown++;
+ }
+ else
+ {
+ gnutls_bye(ssl->gnutls_state, GNUTLS_SHUT_RDWR);
+ ssl->shutdown++;
+ }
+
+ /* FIXME */
+ return 1;
+}
+
+int SSL_read(SSL *ssl, const void *buf, int len)
+{
+ int ret;
+
+ ret = gnutls_record_recv(ssl->gnutls_state, buf, len);
+ ssl->last_error = ret;
+
+ if (ret < 0)
+ {
+ last_error = ret;
+ return 0;
+ }
+
+ return ret;
+}
+
+int SSL_write(SSL *ssl, const void *buf, int len)
+{
+ int ret;
+
+ ret = gnutls_record_send(ssl->gnutls_state, buf, len);
+ ssl->last_error = ret;
+
+ if (ret < 0)
+ {
+ last_error = ret;
+ return 0;
+ }
+
+ return ret;
}
+
+/* SSL_METHOD functions */
+
SSL_METHOD *SSLv23_client_method(void)
{
SSL_METHOD *m;
- m = (SSL_METHOD *)calloc(sizeof(SSL_METHOD), 1);
+ m = (SSL_METHOD *)calloc(1, sizeof(SSL_METHOD));
if (!m)
- return;
+ return NULL;
- m->protocol_priority = (int *)calloc(sizeof(int), 3);
+ m->protocol_priority = (int *)calloc(3, sizeof(int));
m->protocol_priority[0] = GNUTLS_TLS1;
m->protocol_priority[1] = GNUTLS_SSL3;
m->protocol_priority[2] = 0;
- m->cipher_priority = (int *)calloc(sizeof(int), 5);
+ m->cipher_priority = (int *)calloc(5, sizeof(int));
m->cipher_priority[0] = GNUTLS_CIPHER_RIJNDAEL_128_CBC;
m->cipher_priority[1] = GNUTLS_CIPHER_3DES_CBC;
m->cipher_priority[2] = GNUTLS_CIPHER_RIJNDAEL_256_CBC;
m->cipher_priority[3] = GNUTLS_CIPHER_ARCFOUR;
m->cipher_priority[4] = 0;
- m->comp_priority = (int *)calloc(sizeof(int), 3);
+ m->comp_priority = (int *)calloc(3, sizeof(int));
m->comp_priority[0] = GNUTLS_COMP_ZLIB;
m->comp_priority[1] = GNUTLS_COMP_NULL;
m->comp_priority[2] = 0;
- m->kx_priority = (int *)calloc(sizeof(int), 4);
+ m->kx_priority = (int *)calloc(4, sizeof(int));
m->kx_priority[0] = GNUTLS_KX_DHE_RSA;
m->kx_priority[1] = GNUTLS_KX_RSA;
m->kx_priority[2] = GNUTLS_KX_DHE_DSS;
m->kx_priority[3] = 0;
- m->mac_priority = (int *)calloc(sizeof(int), 3);
+ m->mac_priority = (int *)calloc(3, sizeof(int));
m->mac_priority[0] = GNUTLS_MAC_SHA;
m->mac_priority[1] = GNUTLS_MAC_MD5;
m->mac_priority[2] = 0;
@@ -164,74 +320,244 @@ SSL_METHOD *SSLv23_client_method(void)
return m;
}
-void SSL_free(SSL *ssl)
-{
- gnutls_certificate_free_sc(ssl->cred);
- gnutls_deinit(ssl->state);
- free(ssl);
- return;
-}
+/* SSL_CIPHER functions */
-int SSL_set_fd(SSL *ssl, int fd)
+SSL_CIPHER *SSL_get_current_cipher(SSL *ssl)
{
- gnutls_transport_set_ptr (ssl->state, fd);
- return 1;
+ SSL_CIPHER *sslc;
+
+ sslc = (SSL_CIPHER *)calloc(1, sizeof(SSL_CIPHER));
+ if (!sslc)
+ return NULL;
+
+ sslc->version = gnutls_protocol_get_version(ssl->gnutls_state);
+ sslc->cipher = gnutls_cipher_get(ssl->gnutls_state);
+ sslc->kx = gnutls_kx_get(ssl->gnutls_state);
+ sslc->mac = gnutls_mac_get(ssl->gnutls_state);
+ sslc->compression = gnutls_compression_get(ssl->gnutls_state);
+ sslc->cert = gnutls_cert_type_get(ssl->gnutls_state);
+
+ return sslc;
}
+const char *SSL_CIPHER_get_name(SSL_CIPHER *cipher)
+{
+ if (!cipher)
+ return ("NONE");
-int SSL_connect(SSL *ssl)
+ /* FIXME */
+ return gnutls_cipher_get_name(cipher->cipher);
+}
+
+int SSL_CIPHER_get_bits(SSL_CIPHER *cipher, int *bits)
{
- int err;
+ int bit_result;
- err = gnutls_handshake(ssl->state);
- ssl->last_error = err;
+ if (!cipher)
+ return 0;
- if (err < 0)
+ /* FIXME: ought to do this by parsing data returned by cipher_get_name */
+ switch(cipher->cipher)
{
- last_error = err;
- return 0;
+ case GNUTLS_CIPHER_ARCFOUR:
+ case GNUTLS_CIPHER_RIJNDAEL_128_CBC:
+ case GNUTLS_CIPHER_TWOFISH_128_CBC:
+ bit_result = 128;
+ break;
+ case GNUTLS_CIPHER_3DES_CBC:
+ bit_result = 168;
+ break;
+ case GNUTLS_CIPHER_RIJNDAEL_256_CBC:
+ bit_result = 256;
+ break;
+ default:
+ bit_result = 0;
+ break;
}
- return 1;
-}
+ if (bits)
+ *bits = bit_result;
+ return bit_result;
+}
-int SSL_write(SSL *ssl, const void *buf, int num)
+const char *SSL_CIPHER_get_version(SSL_CIPHER *cipher)
{
- int ret;
+ if (!cipher)
+ return ("(NONE)");
- ret = gnutls_record_send(ssl->state, buf, num);
- ssl->last_error = ret;
+ if (cipher->version == GNUTLS_TLS1)
+ return ("TLSv1");
+ else if (cipher->version == GNUTLS_SSL3)
+ return ("SSLv3");
- if (ret < 0)
+ return ("unknown");
+}
+
+
+/* X509 functions */
+
+X509_NAME *X509_get_subject_name(X509 *cert)
+{
+ gnutls_x509_dn *dn;
+ dn = (gnutls_x509_dn *)calloc(1, sizeof(gnutls_x509_dn));
+ if (gnutls_x509_extract_certificate_dn(cert, dn) < 0)
{
- last_error = ret;
- return 0;
+ free(dn);
+ return NULL;
}
+ return dn;
+}
- return ret;
+char *X509_NAME_oneline(gnutls_x509_dn *name, char *buf, int len)
+{
+ memset(buf, 0, len);
+ if (!buf)
+ return NULL;
+
+ snprintf(buf, len-1, "C=%s, ST=%s, L=%s, O=%s, OU=%s, CN=%s/Email=%s",
+ name->country, name->state_or_province_name,
+ name->locality_name, name->organization,
+ name->organizational_unit_name,
+ name->common_name, name->email);
+ return buf;
}
-int SSL_read(SSL *ssl, const void *buf, int num)
+/* BIO functions */
+
+void BIO_get_fd(GNUTLS_STATE gnutls_state, int *fd)
{
- int ret;
+ *fd = gnutls_transport_get_ptr(gnutls_state);
+}
- ret = gnutls_record_recv(ssl->state, buf, num);
- ssl->last_error = ret;
- if (ret < 0)
- {
- last_error = ret;
- return 0;
- }
+/* error handling */
+
+unsigned long ERR_get_error(void)
+{
+ unsigned long ret;
+
+ ret = -1 * last_error;
+ last_error = 0;
return ret;
}
+char *ERR_error_string(unsigned long e, char *buf)
+{
+ return gnutls_strerror(-1 * e);
+}
-int SSL_pending(SSL *ssl)
+
+/* RAND functions */
+
+int RAND_status(void)
+{
+ return 1;
+}
+
+void RAND_seed(const void *buf, int num)
{
- return gnutls_record_check_pending(ssl->state);
+ return;
+}
+
+int RAND_bytes(unsigned char *buf, int num)
+{
+ gcry_randomize(buf, num, GCRY_STRONG_RANDOM);
+ return 1;
+}
+
+const char *RAND_file_name(char *buf, size_t len)
+{
+ return "";
+}
+
+int RAND_load_file(const char *name, long maxbytes)
+{
+ return maxbytes;
+}
+
+int RAND_write_file(const char *name)
+{
+ return 0;
+}
+
+
+/* message digest functions */
+
+void MD5_Init(MD5_CTX *ctx)
+{
+ ctx->handle = gcry_md_open(GCRY_MD_MD5, 0);
+}
+
+void MD5_Update(MD5_CTX *ctx, const void *buf, int len)
+{
+ gcry_md_write(ctx->handle, buf, len);
+}
+
+void MD5_Final(unsigned char *md, MD5_CTX *ctx)
+{
+ unsigned char *local_md;
+
+ gcry_md_final(ctx->handle);
+ local_md = gcry_md_read(ctx->handle, 0);
+ if (md)
+ memcpy(md, local_md, gcry_md_get_algo_dlen(GCRY_MD_MD5));
+ gcry_md_close(ctx->handle);
+}
+
+unsigned char *MD5(const unsigned char *buf, unsigned long len,
+ unsigned char *md)
+{
+ unsigned char *local_md;
+
+ if (!md)
+ return NULL;
+
+ local_md = alloca(gcry_md_get_algo_dlen(GCRY_MD_MD5));
+
+ gcry_md_hash_buffer(GCRY_MD_MD5, local_md, buf, len);
+
+ memcpy(md, local_md, gcry_md_get_algo_dlen(GCRY_MD_MD5));
+
+ return md;
+}
+
+void RIPEMD160_Init(RIPEMD160_CTX *ctx)
+{
+ ctx->handle = gcry_md_open(GCRY_MD_RMD160, 0);
+}
+
+void RIPEMD160_Update(RIPEMD160_CTX *ctx, const void *buf, int len)
+{
+ gcry_md_write(ctx->handle, buf, len);
+}
+
+void RIPEMD160_Final(unsigned char *md, RIPEMD160_CTX *ctx)
+{
+ unsigned char *local_md;
+ gcry_md_final(ctx->handle);
+ local_md = gcry_md_read(ctx->handle, 0);
+ if (md)
+ memcpy(md, local_md, gcry_md_get_algo_dlen(GCRY_MD_RMD160));
+ gcry_md_close(ctx->handle);
+}
+
+unsigned char *RIPEMD160(const unsigned char *buf, unsigned long len,
+ unsigned char *md)
+{
+ unsigned char *local_md;
+
+ if (!md)
+ return NULL;
+
+ local_md = alloca(gcry_md_get_algo_dlen(GCRY_MD_RMD160));
+
+ gcry_md_hash_buffer(GCRY_MD_RMD160, local_md, buf, len);
+
+ memcpy(md, local_md, gcry_md_get_algo_dlen(GCRY_MD_RMD160));
+
+ return md;
}