diff options
author | Andrew McDonald <admcd@gnutls.org> | 2002-06-19 20:41:59 +0000 |
---|---|---|
committer | Andrew McDonald <admcd@gnutls.org> | 2002-06-19 20:41:59 +0000 |
commit | b7a33637d38f7b70e8c970c3c2fdad2a426ab3de (patch) | |
tree | 9a40848093c68d2e2098c26653870efb6ae593c7 /libextra/gnutls_openssl.c | |
parent | c22a6eca4d5d78d1d94a48a0ec881470ac924ea0 (diff) | |
download | gnutls-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.c | 502 |
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; } |