Hi guys,
So here is a little patch that signature support to eet. It append
at the end of a classic eet file a signature and the public x509
certificate in der format. This change doesn't break file
compatibility as the signature is automatically detected based on the
file content against it's size. But this means, that eet_open first
make an attempt to load the file structure (directory and dictionnary)
before checking the signature. It use openssl library and the test
provided in eet_suite.c work well with openssl version 0.9.8e.
Before I start adding crypto support every where in eet, plese
review this patch and give me your feedback. Have fun !
--
Cedric BAIL
diff --git a/configure.in b/configure.in
index ebf301e..e2eba51 100644
--- a/configure.in
+++ b/configure.in
@@ -117,6 +117,22 @@ int main (int argc, char **argv) {
], AC_MSG_WARN([Cannot check when cross-compiling -- assuming null is okay])
)
+dnl Disable support for old eet file format.
+old_eet_file_format="yes"
+AC_ARG_ENABLE(old-eet-file-format,
+ AC_HELP_STRING(
+ [--disable-old-eet-file-format],
+ [disable old eet file format support. [[default=enabled]]]
+ ),
+ [ old_eet_file_format=$enableval ]
+)
+AM_CONDITIONAL(EET_OLD_EET_FILE_FORMAT, test "x$old_eet_file_format" = "xyes")
+if test "x$old_eet_file_format" = "xyes"; then
+ AC_DEFINE(EET_OLD_EET_FILE_FORMAT, 1, [support old eet file format])
+else
+ AC_DEFINE(EET_OLD_EET_FILE_FORMAT, 0, [support old eet file format])
+fi
+
dnl Unit Tests
AC_ARG_ENABLE(tests,
@@ -143,6 +159,54 @@ fi
AM_CONDITIONAL(EET_ENABLE_TESTS, test "x${enable_tests}" = "xyes")
+dnl Openssl support
+want_openssl="auto"
+have_openssl="no"
+AC_ARG_ENABLE(openssl,
+ [AC_HELP_STRING([--disable-openssl], [disable openssl eet support])],
+ [ want_openssl=$enableval ]
+)
+if test "x$want_openssl" = "xyes" -o "x$want_openssl" = "xauto"; then
+ PKG_CHECK_MODULES(OPENSSL, openssl,
+ [
+ have_openssl="yes"
+ AC_DEFINE(HAVE_OPENSSL, 1, [Have Openssl support])
+ ],
+ [
+ if test "x$use_strict" = "xyes"; then
+ AC_MSG_ERROR([Openssl not found (strict dependencies checking)])
+ fi
+ ])
+fi
+
+dnl Crypto option
+want_cypher="yes"
+have_cypher="yes"
+want_signature="yes"
+have_signature="yes"
+
+AC_MSG_CHECKING(whether to activate cypher support in eet)
+AC_ARG_ENABLE(cypher,
+ [AC_HELP_STRING([--disable-cypher], [disable cypher support for eet API])],
+ [ want_cypher=$enableval ]
+)
+if test "x$have_openssl" = "xyes" -a "x$want_cypher" = "xyes"; then
+ have_cypher="yes"
+ AC_DEFINE(HAVE_CYPHER, 1, [Have cypher support built in eet])
+fi
+AC_MSG_RESULT($have_cypher)
+
+AC_MSG_CHECKING(whether to activate signature support in eet)
+AC_ARG_ENABLE(signature,
+ [AC_HELP_STRING([--disable-signature], [disable signature file support for eet])],
+ [ want_signature=$enableval ]
+)
+if test "x$have_signature" = "xyes" -a "x$want_signature" = "xyes"; then
+ have_signature="yes"
+ AC_DEFINE(HAVE_SIGNATURE, 1, [Have signature support for eet file])
+fi
+AC_MSG_RESULT($have_signature)
+
dnl Coverage
AC_ARG_ENABLE(coverage,
@@ -241,6 +305,12 @@ echo "------------------------------------------------------------------------"
echo
echo "Configuration Options Summary:"
echo
+echo " Openssl..............: ${have_openssl}"
+echo " Cypher support.....: ${have_cypher}"
+echo " Signature..........: ${have_signature}"
+
+echo " Old eet file format..: ${old_eet_file_format}"
+echo
echo " Tests................: ${enable_tests}"
echo " Coverage.............: ${enable_coverage}"
echo
diff --git a/src/lib/Eet.h b/src/lib/Eet.h
index dc7a383..35ad69b 100644
--- a/src/lib/Eet.h
+++ b/src/lib/Eet.h
@@ -86,12 +86,19 @@ extern "C" {
EET_ERROR_WRITE_ERROR_FILE_TOO_BIG,
EET_ERROR_WRITE_ERROR_IO_ERROR,
EET_ERROR_WRITE_ERROR_OUT_OF_SPACE,
- EET_ERROR_WRITE_ERROR_FILE_CLOSED
+ EET_ERROR_WRITE_ERROR_FILE_CLOSED,
+ EET_ERROR_MMAP_FAILED,
+ EET_ERROR_X509_ENCODING_FAILED,
+ EET_ERROR_SIGNATURE_FAILED,
+ EET_ERROR_INVALID_SIGNATURE,
+ EET_ERROR_NOT_SIGNED,
+ EET_ERROR_NOT_IMPLEMENTED
} Eet_Error;
typedef struct _Eet_File Eet_File;
typedef struct _Eet_Dictionary Eet_Dictionary;
typedef struct _Eet_Data_Descriptor Eet_Data_Descriptor;
+ typedef struct _Eet_Key Eet_Key;
typedef struct _Eet_Data_Descriptor_Class Eet_Data_Descriptor_Class;
@@ -237,6 +244,39 @@ extern "C" {
*/
EAPI Eet_Error eet_close(Eet_File *ef);
+ /**
+ * Create an Eet_Key needed for signing an eet file.
+ *
+ * The certificate should provide the public that match the private key.
+ * No verification is done to ensure that.
+ *
+ * @since 2.0.0
+ */
+ EAPI Eet_Key* eet_identity_open(const char *certificate_file, const char *private_key_file);
+
+ /**
+ * Close and release all ressource used by an Eet_Key.
+ * An reference counter prevent it from being freed until all file using it are
+ * also closed.
+ *
+ * @since 2.0.0
+ */
+ EAPI void eet_identity_close(Eet_Key *key);
+
+ /**
+ * Set a key to sign a file
+ *
+ * @since 2.0.0
+ */
+ EAPI Eet_Error eet_identity_set(Eet_File *ef, Eet_Key *key);
+
+ /**
+ * Get the x509 der certificate associated with an Eet_File. Will return NULL
+ * if the file is not signed.
+ *
+ * @since 2.0.0
+ */
+ EAPI const void *eet_identity_x509(Eet_File *ef, int *der_length);
/**
* Return a handle to the shared string dictionary of the Eet file
diff --git a/src/lib/Eet_private.h b/src/lib/Eet_private.h
index 4af3e2b..85a1df4 100644
--- a/src/lib/Eet_private.h
+++ b/src/lib/Eet_private.h
@@ -12,6 +12,14 @@
# endif
#endif
+#include "config.h"
+
+#ifdef HAVE_OPENSSL
+#include <openssl/evp.h>
+#include <openssl/x509.h>
+#include <openssl/pem.h>
+#endif
+
typedef struct _Eet_String Eet_String;
struct _Eet_String
@@ -53,6 +61,15 @@ struct _Eet_Dictionary
const char *end;
};
+struct _Eet_Key
+{
+ int references;
+#ifdef HAVE_SIGNATURE
+ X509 *certificate;
+ EVP_PKEY *private_key;
+#endif
+};
+
Eet_Dictionary *eet_dictionary_add(void);
void eet_dictionary_free(Eet_Dictionary *ed);
int eet_dictionary_string_add(Eet_Dictionary *ed, const char *string);
@@ -71,6 +88,15 @@ int _eet_hash_gen(const char *key, int hash_size);
int _eet_string_to_double_convert(const char *src, long long *m, long *e);
void _eet_double_to_string_convert(char des[128], double d);
+const void* eet_identity_check(const void *data_base, unsigned int data_length,
+ const void *signature_base, unsigned int signature_length,
+ int *x509_length);
+Eet_Error eet_cypher(void *data, unsigned int size, const char *key, unsigned int length);
+Eet_Error eet_decypher(void *data, unsigned int size, const char *key, unsigned int length);
+Eet_Error eet_identity_sign(FILE *fp, Eet_Key *key);
+void eet_identity_unref(Eet_Key *key);
+void eet_identity_ref(Eet_Key *key);
+
#ifndef PATH_MAX
#define PATH_MAX 4096
#endif
diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am
index 4141f7a..0a5b87a 100644
--- a/src/lib/Makefile.am
+++ b/src/lib/Makefile.am
@@ -8,7 +8,8 @@ AM_CPPFLAGS = \
-DPACKAGE_LIB_DIR=\"$(libdir)\" \
-DPACKAGE_DATA_DIR=\"$(datadir)/$(PACKAGE)\" \
@EVIL_CFLAGS@ \
[EMAIL PROTECTED]@
[EMAIL PROTECTED]@ \
[EMAIL PROTECTED]@
include_HEADERS = Eet.h
@@ -18,12 +19,13 @@ libeet_la_SOURCES = \
eet_lib.c \
eet_data.c \
eet_image.c \
+eet_cypher.c \
eet_memfile.c \
eet_dictionary.c \
eet_utils.c
libeet_la_CFLAGS = @WIN32_CFLAGS@
-libeet_la_LIBADD = @COVERAGE_LIBS@ @EVIL_LIBS@ @WIN32_LIBS@ -lz -ljpeg @fnmatch_libs@ -lm
+libeet_la_LIBADD = @OPENSSL_LIBS@ @COVERAGE_LIBS@ @EVIL_LIBS@ @WIN32_LIBS@ -lz -ljpeg @fnmatch_libs@ -lm
libeet_la_LDFLAGS = @lt_no_undefined@ @lt_enable_auto_import@ -version-info @version_info@
libeet_la_DEPENDENCIES = $(top_builddir)/config.h
diff --git a/src/lib/eet_cypher.c b/src/lib/eet_cypher.c
new file mode 100644
index 0000000..8e1a819
--- /dev/null
+++ b/src/lib/eet_cypher.c
@@ -0,0 +1,254 @@
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <openssl/rsa.h>
+#include <openssl/objects.h>
+#include <openssl/err.h>
+#include <openssl/ssl.h>
+#include <sys/mman.h>
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "Eet.h"
+#include "Eet_private.h"
+
+#define EET_MAGIC_SIGN 0x1ee74271
+
+EAPI Eet_Key*
+eet_identity_open(const char *certificate_file, const char *private_key_file)
+{
+#ifdef HAVE_SIGNATURE
+ EVP_PKEY *pkey = NULL;
+ X509 *cert = NULL;
+ Eet_Key *key;
+ FILE *fp;
+
+ /* Load the X509 certificate in memory. */
+ fp = fopen(certificate_file, "r");
+ if (!fp) return NULL;
+ cert = PEM_read_X509(fp, NULL, NULL, NULL);
+ fclose(fp);
+ if (!cert) return NULL;
+
+ /* Check the presence of the public key. Just in case. */
+ pkey = X509_get_pubkey(cert);
+ if (!pkey) goto on_error;
+
+ /* Load the private key in memory. */
+ fp = fopen(private_key_file, "r");
+ if (!fp) goto on_error;
+ pkey = PEM_read_PrivateKey(fp, NULL, NULL, NULL);
+ fclose(fp);
+ if (!pkey) goto on_error;
+
+ key = malloc(sizeof(Eet_Key));
+ if (!key) goto on_error;
+
+ key->references = 1;
+ key->certificate = cert;
+ key->private_key = pkey;
+
+ return key;
+
+ on_error:
+ if (cert) X509_free(cert);
+ if (pkey) EVP_PKEY_free(pkey);
+#endif
+ return NULL;
+}
+
+EAPI void
+eet_identity_close(Eet_Key *key)
+{
+#ifdef HAVE_SIGNATURE
+ if (key->references > 0) return ;
+
+ X509_free(key->certificate);
+ EVP_PKEY_free(key->private_key);
+ free(key);
+#endif
+}
+
+void
+eet_identity_ref(Eet_Key *key)
+{
+ if (key == NULL) return ;
+ key->references++;
+}
+
+void
+eet_identity_unref(Eet_Key *key)
+{
+ if (key == NULL) return ;
+ key->references--;
+ eet_identity_close(key);
+}
+
+Eet_Error
+eet_identity_sign(FILE *fp, Eet_Key *key)
+{
+#ifdef HAVE_SIGNATURE
+ unsigned char *x509_der = NULL;
+ void *sign = NULL;
+ void *data;
+ int head[3];
+ EVP_MD_CTX md_ctx;
+ struct stat st_buf;
+ Eet_Error err = EET_ERROR_NONE;
+ int sign_length;
+ int x509_length;
+ int fd;
+
+ /* A few check and flush pending write. */
+ if (!fp
+ || !key
+ || !key->certificate
+ || !key->private_key)
+ return EET_ERROR_BAD_OBJECT;
+
+ /* Get the file size. */
+ fd = fileno(fp);
+ if (fd < 0) return EET_ERROR_BAD_OBJECT;
+ if (fstat(fd, &st_buf) < 0) return EET_ERROR_MMAP_FAILED;
+
+ /* Map the file in memory. */
+ data = mmap(NULL, st_buf.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
+ if (data == MAP_FAILED) return EET_ERROR_MMAP_FAILED;
+
+ sign_length = EVP_PKEY_size(key->private_key);
+ sign = malloc(sign_length);
+ if (sign == NULL)
+ {
+ err = EET_ERROR_OUT_OF_MEMORY;
+ goto on_error;
+ }
+
+ /* Do the signature. */
+ EVP_SignInit(&md_ctx, EVP_sha1());
+ EVP_SignUpdate (&md_ctx, data, st_buf.st_size);
+ err = EVP_SignFinal (&md_ctx, sign, &sign_length, key->private_key);
+ if (err != 1)
+ {
+ ERR_print_errors_fp(stdout);
+ err = EET_ERROR_SIGNATURE_FAILED;
+ goto on_error;
+ }
+
+ /* Give me the der (binary form for X509). */
+ x509_length = i2d_X509(key->certificate, &x509_der);
+ if (x509_length < 0)
+ {
+ ERR_print_errors_fp(stdout);
+ err = EET_ERROR_X509_ENCODING_FAILED;
+ goto on_error;
+ }
+
+ /* Append the signature at the end of the file. */
+ head[0] = (int) htonl ((unsigned int) EET_MAGIC_SIGN);
+ head[1] = (int) htonl ((unsigned int) sign_length);
+ head[2] = (int) htonl ((unsigned int) x509_length);
+
+ if (fwrite(head, sizeof(head), 1, fp) != 1)
+ {
+ err = EET_ERROR_WRITE_ERROR;
+ goto on_error;
+ }
+ if (fwrite(sign, sign_length, 1, fp) != 1)
+ {
+ err = EET_ERROR_WRITE_ERROR;
+ goto on_error;
+ }
+ if (fwrite(x509_der, x509_length, 1, fp) != 1)
+ {
+ err = EET_ERROR_WRITE_ERROR;
+ goto on_error;
+ }
+
+ on_error:
+ if (x509_der) OPENSSL_free(x509_der);
+ if (sign != NULL) free(sign);
+ munmap(data, st_buf.st_size);
+ return err;
+#else
+ return EET_ERROR_NOT_IMPLEMENTED;
+#endif
+}
+
+const void*
+eet_identity_check(const void *data_base, unsigned int data_length,
+ const void *signature_base, unsigned int signature_length,
+ int *x509_length)
+{
+#ifdef HAVE_SIGNATURE
+ const int *header = signature_base;
+ const unsigned char *sign;
+ const unsigned char *cert_der;
+ EVP_PKEY *pkey;
+ X509 *x509;
+ EVP_MD_CTX md_ctx;
+ int sign_length;
+ int cert_length;
+ int magic;
+ int err;
+
+ if (signature_length < sizeof(int) * 3) return NULL;
+
+ magic = ntohl(header[0]);
+ sign_length = ntohl(header[1]);
+ cert_length = ntohl(header[2]);
+
+ if (magic != EET_MAGIC_SIGN) return NULL;
+ if (sign_length + cert_length + sizeof(int) * 3 > signature_length) return NULL;
+
+ sign = signature_base + sizeof(int) * 3;
+ cert_der = sign + sign_length;
+
+ x509 = d2i_X509(NULL, &cert_der, cert_length);
+ if (x509 == NULL) return NULL;
+
+ /* Get public key - eay */
+ pkey=X509_get_pubkey(x509);
+ if (pkey == NULL)
+ {
+ X509_free(x509);
+ return NULL;
+ }
+
+ /* Verify the signature */
+ EVP_VerifyInit(&md_ctx, EVP_sha1());
+ EVP_VerifyUpdate(&md_ctx, data_base, data_length);
+ err = EVP_VerifyFinal(&md_ctx, sign, sign_length, pkey);
+
+ X509_free(x509);
+ EVP_PKEY_free(pkey);
+
+ if (err != 1)
+ return NULL;
+
+ if (x509_length) *x509_length = cert_length;
+ return cert_der;
+#else
+ return NULL;
+#endif
+}
+
+Eet_Error
+eet_cypher(void *data, unsigned int size, const char *key, unsigned int length)
+{
+#ifdef HAVE_CYPHER
+#else
+ return EET_ERROR_NOT_IMPLEMENTED;
+#endif
+}
+
+Eet_Error
+eet_decypher(void *data, unsigned int size, const char *key, unsigned int length)
+{
+#ifdef HAVE_CYPHER
+#else
+ return EET_ERROR_NOT_IMPLEMENTED;
+#endif
+}
diff --git a/src/lib/eet_lib.c b/src/lib/eet_lib.c
index 23449d3..af89099 100644
--- a/src/lib/eet_lib.c
+++ b/src/lib/eet_lib.c
@@ -69,14 +69,17 @@ struct _Eet_File
FILE *fp;
FILE *readfp;
Eet_File_Header *header;
- const unsigned char *data;
Eet_Dictionary *ed;
+ Eet_Key *key;
+ const unsigned char *data;
+ const void *x509_der;
int magic;
int references;
Eet_File_Mode mode;
int data_size;
+ int x509_length;
time_t mtime;
unsigned char writes_pending : 1;
@@ -158,6 +161,11 @@ struct
} dictionary[num_dictionary_entries];
/* now start the string stream. */
/* and right after them the data stream. */
+int magic_sign; /* Optional, only if the eet file is signed. */
+int signature_length; /* Signature length. */
+int x509_length; /* Public certificate that signed the file. */
+char signature[signature_length]; /* The signature. */
+char x509[x509_length]; /* The public certificate. */
#endif
#define EET_FILE2_HEADER_COUNT 3
@@ -509,6 +517,17 @@ eet_flush2(Eet_File *ef)
}
}
+ /* flush all write to the file. */
+ fflush(ef->fp);
+
+ /* append signature if required */
+ if (ef->key)
+ {
+ error = eet_identity_sign(ef->fp, ef->key);
+ if (error != EET_ERROR_NONE)
+ goto sign_error;
+ }
+
/* no more writes pending */
ef->writes_pending = 0;
@@ -523,6 +542,7 @@ eet_flush2(Eet_File *ef)
case EPIPE: error = EET_ERROR_WRITE_ERROR_FILE_CLOSED; break;
default: error = EET_ERROR_WRITE_ERROR; break;
}
+ sign_error:
fclose(ef->fp);
ef->fp = NULL;
return error;
@@ -653,6 +673,19 @@ eet_flush(Eet_File *ef)
EAPI int
eet_init(void)
{
+#ifdef HAVE_OPENSSL
+ /* Just load the crypto library error strings,
+ * SSL_load_error_strings() loads the crypto AND the SSL ones */
+ /* SSL_load_error_strings();*/
+ static int call_once = 0;
+
+ if (call_once == 0)
+ {
+ call_once = 1;
+ ERR_load_crypto_strings();
+ }
+
+#endif
return ++eet_initcount;
}
@@ -732,6 +765,7 @@ eet_internal_read2(Eet_File *ef)
int bytes_directory_entries;
int num_dictionary_entries;
int bytes_dictionary_entries;
+ int signature_base_offset;
int i;
index += sizeof(int);
@@ -781,6 +815,8 @@ eet_internal_read2(Eet_File *ef)
if (eet_test_close(!ef->header->directory->nodes, ef))
return NULL;
+ signature_base_offset = 0;
+
/* actually read the directory block - all of it, into ram */
for (i = 0; i < num_directory_entries; ++i)
{
@@ -844,6 +880,10 @@ eet_internal_read2(Eet_File *ef)
if (efn->data)
memcpy(efn->data, ef->data + efn->offset, efn->size);
}
+
+ /* compute the possible position of a signature */
+ if (signature_base_offset < efn->offset + efn->size)
+ signature_base_offset = efn->offset + efn->size;
}
ef->ed = NULL;
@@ -900,9 +940,35 @@ eet_internal_read2(Eet_File *ef)
ef->ed->all[j].hash = hash;
if (ef->ed->all[j].prev == -1)
ef->ed->hash[hash] = j;
+
+ /* compute the possible position of a signature */
+ if (signature_base_offset < offset + ef->ed->all[j].len)
+ signature_base_offset = offset + ef->ed->all[j].len;
}
}
+ /* Check if the file is signed */
+ ef->x509_der = NULL;
+ ef->x509_length = 0;
+ if (signature_base_offset < ef->data_size)
+ {
+#ifdef HAVE_SIGNATURE
+ const unsigned char *buffer = ((const unsigned char*) ef->data) + signature_base_offset;
+ ef->x509_der = eet_identity_check(ef->data, signature_base_offset,
+ buffer, ef->data_size - signature_base_offset,
+ &ef->x509_length);
+
+ if (ef->x509_der == NULL)
+ {
+ ef->delete_me_now = 1;
+ eet_close(ef);
+ return NULL;
+ }
+#else
+ fprintf(stderr, "This file could be signed but you didn't compile the necessary code to check the signature.\n");
+#endif
+ }
+
return ef;
}
@@ -1115,6 +1181,7 @@ eet_memopen_read(const void *data, size_t size)
ef->ed = NULL;
ef->path = NULL;
+ ef->key = NULL;
ef->magic = EET_MAGIC_FILE;
ef->references = 1;
ef->mode = EET_FILE_MODE_READ;
@@ -1191,11 +1258,15 @@ eet_open(const char *file, Eet_File_Mode mode)
}
else
{
+ int fd;
+
if (mode != EET_FILE_MODE_WRITE) return NULL;
memset(&file_stat, 0, sizeof(file_stat));
/* opening for write - delete old copy of file right away */
unlink(file);
- fp = fopen(file, "wb");
+ fd = open(file, O_CREAT | O_TRUNC | O_RDWR, S_IRUSR | S_IWUSR);
+ fp = fdopen(fd, "wb");
+ if (!fp) return NULL;
}
/* We found one */
@@ -1224,6 +1295,7 @@ eet_open(const char *file, Eet_File_Mode mode)
/* fill some of the members */
ef->fp = fp;
+ ef->key = NULL;
ef->readfp = NULL;
ef->path = ((char *)ef) + sizeof(Eet_File);
memcpy(ef->path, file, file_len);
@@ -1265,9 +1337,12 @@ eet_open(const char *file, Eet_File_Mode mode)
/* we need to delete the original file in read-write mode and re-open for writing */
if (ef->mode == EET_FILE_MODE_READ_WRITE)
{
+ int fd;
+
ef->readfp = ef->fp;
unlink(ef->path);
- ef->fp = fopen(ef->path, "wb");
+ fd = open(ef->path, O_CREAT | O_TRUNC | O_RDWR, S_IRUSR | S_IWUSR);
+ ef->fp = fdopen(fd, "wb");
if (eet_test_close(!ef->fp, ef))
return NULL;
fcntl(fileno(ef->fp), F_SETFD, FD_CLOEXEC);
@@ -1296,6 +1371,29 @@ eet_mode_get(Eet_File *ef)
return ef->mode;
}
+EAPI const void *
+eet_identity_x509(Eet_File *ef, int *der_length)
+{
+ if (!ef->x509_der) return NULL;
+
+ if (der_length) *der_length = ef->x509_length;
+ return ef->x509_der;
+}
+
+EAPI Eet_Error
+eet_identity_set(Eet_File *ef, Eet_Key *key)
+{
+ Eet_Key *tmp = ef->key;
+
+ if (!ef) return EET_ERROR_BAD_OBJECT;
+
+ ef->key = key;
+ eet_identity_ref(ef->key);
+ eet_identity_unref(tmp);
+
+ return EET_ERROR_NONE;
+}
+
EAPI Eet_Error
eet_close(Eet_File *ef)
{
@@ -1311,6 +1409,9 @@ eet_close(Eet_File *ef)
/* flush any writes */
err = eet_flush2(ef);
+ eet_identity_unref(ef->key);
+ ef->key = NULL;
+
/* if not urgent to delete it - dont free it - leave it in cache */
if ((!ef->delete_me_now) && (ef->mode == EET_FILE_MODE_READ))
return EET_ERROR_NONE;
diff --git a/src/tests/cert.pem b/src/tests/cert.pem
new file mode 100644
index 0000000..3265462
--- /dev/null
+++ b/src/tests/cert.pem
@@ -0,0 +1,22 @@
+-----BEGIN CERTIFICATE-----
+MIIDmTCCAwKgAwIBAgIJAIKWPcLUT5FAMA0GCSqGSIb3DQEBBQUAMIGQMQswCQYD
+VQQGEwJGUjEWMBQGA1UECBMNSWxlLURlLUZyYW5jZTEOMAwGA1UEBxMFUGFyaXMx
+FjAUBgNVBAoTDUVubGlnaHRlbm1lbnQxDjAMBgNVBAsTBVRlc3RzMQ0wCwYDVQQD
+EwRCQUlMMSIwIAYJKoZIhvcNAQkBFhNjZWRyaWMuYmFpbEBmcmVlLmZyMB4XDTA4
+MDczMDEzNDU1OVoXDTA5MDczMDEzNDU1OVowgZAxCzAJBgNVBAYTAkZSMRYwFAYD
+VQQIEw1JbGUtRGUtRnJhbmNlMQ4wDAYDVQQHEwVQYXJpczEWMBQGA1UEChMNRW5s
+aWdodGVubWVudDEOMAwGA1UECxMFVGVzdHMxDTALBgNVBAMTBEJBSUwxIjAgBgkq
+hkiG9w0BCQEWE2NlZHJpYy5iYWlsQGZyZWUuZnIwgZ8wDQYJKoZIhvcNAQEBBQAD
+gY0AMIGJAoGBAMiE486eROKePG0/639D4XTTDR9XSRWp1xqZzq7P+jjWRFbZ/MWV
+IVzkc4MRm83UOolbPj76LjM10cseaVAhK7G9CHp2dur4alWvdCXPH5Q+LPOFS9gM
+x0Jz9EZeHHOHZKLyJdKSmot+zluwJTLe081RRUwzNKct6JrVVG/7SmITAgMBAAGj
+gfgwgfUwHQYDVR0OBBYEFEFar6doT5ImL2rf0rJX7EYQqtYQMIHFBgNVHSMEgb0w
+gbqAFEFar6doT5ImL2rf0rJX7EYQqtYQoYGWpIGTMIGQMQswCQYDVQQGEwJGUjEW
+MBQGA1UECBMNSWxlLURlLUZyYW5jZTEOMAwGA1UEBxMFUGFyaXMxFjAUBgNVBAoT
+DUVubGlnaHRlbm1lbnQxDjAMBgNVBAsTBVRlc3RzMQ0wCwYDVQQDEwRCQUlMMSIw
+IAYJKoZIhvcNAQkBFhNjZWRyaWMuYmFpbEBmcmVlLmZyggkAgpY9wtRPkUAwDAYD
+VR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQCpZJhk8BgQh0foiMkOwOMKvObq
+GxAzqjbr7iU9tEvJgwukCBv59ndBM0B5l5ybQdIYWQJOfZE1HTvB60swZMwqap9X
+5QXgewymuXiVk+roVh34wg8Pg8F588G2BtLIoujY/gN3WJQR7YPD34iTPc4koV+A
+4vs6nmL6wtW21+hsaw==
+-----END CERTIFICATE-----
diff --git a/src/tests/eet_suite.c b/src/tests/eet_suite.c
index 0c7aaa0..dde5386 100644
--- a/src/tests/eet_suite.c
+++ b/src/tests/eet_suite.c
@@ -1,10 +1,17 @@
+#include <sys/types.h>
+#include <sys/stat.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <stdio.h>
+#include <fcntl.h>
#include <check.h>
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
#include "eet_suite.h"
START_TEST(eet_test_init)
@@ -1146,6 +1169,77 @@ START_TEST(eet_small_image)
}
END_TEST
+START_TEST(eet_identity_simple)
+{
+ const char *buffer = "Here is a string of data to save !";
+ const void *tmp;
+ Eet_File *ef;
+ Eet_Key *k;
+ char *test;
+ char *file = strdup("/tmp/eet_suite_testXXXXXX");
+ int size;
+ int fd;
+
+ eet_init();
+
+ mktemp(file);
+ chdir("src/tests");
+
+ /* Sign an eet file. */
+ ef = eet_open(file, EET_FILE_MODE_WRITE);
+ fail_if(!ef);
+
+ fail_if(!eet_write(ef, "keys/tests", buffer, strlen(buffer) + 1, 0));
+
+ k = eet_identity_open("cert.pem", "key.pem");
+ fail_if(!k);
+
+ fail_if(eet_identity_set(ef, k) != EET_ERROR_NONE);
+
+ eet_close(ef);
+
+ /* Open a signed file. */
+ ef = eet_open(file, EET_FILE_MODE_READ);
+ fail_if(!ef);
+
+ test = eet_read(ef, "keys/tests", &size);
+ fail_if(!test);
+ fail_if(size != strlen(buffer) + 1);
+
+ fail_if(memcmp(test, buffer, strlen(buffer) + 1) != 0);
+
+ tmp = eet_identity_x509(ef, &size);
+ fail_if(tmp == NULL);
+
+ eet_close(ef);
+
+ /* As we are changing file contain in less than 1s, this could get unnoticed
+ by eet cache system. */
+ eet_clearcache();
+
+ /* Corrupting the file. */
+ fd = open(file, O_WRONLY);
+ fail_if(fd < 0);
+
+ fail_if(lseek(fd, 200, SEEK_SET) != 200);
+ fail_if(write(fd, "42", 2) != 2);
+ fail_if(lseek(fd, 50, SEEK_SET) != 50);
+ fail_if(write(fd, "42", 2) != 2);
+ fail_if(lseek(fd, 88, SEEK_SET) != 88);
+ fail_if(write(fd, "42", 2) != 2);
+
+ close(fd);
+
+ /* Attempt to open a modified file. */
+ ef = eet_open(file, EET_FILE_MODE_READ);
+ fail_if(ef);
+
+/* fail_if(unlink(file) != 0); */
+
+ eet_shutdown();
+}
+END_TEST
+
Suite *
eet_suite(void)
{
@@ -1175,6 +1269,12 @@ eet_suite(void)
tcase_add_test(tc, eet_small_image);
suite_add_tcase(s, tc);
+#ifdef HAVE_SIGNATURE
+ tc = tcase_create("Eet Identity");
+ tcase_add_test(tc, eet_identity_simple);
+ suite_add_tcase(s, tc);
+#endif
+
return s;
}
diff --git a/src/tests/key.pem b/src/tests/key.pem
new file mode 100644
index 0000000..74763ca
--- /dev/null
+++ b/src/tests/key.pem
@@ -0,0 +1,15 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIICXAIBAAKBgQDIhOPOnkTinjxtP+t/Q+F00w0fV0kVqdcamc6uz/o41kRW2fzF
+lSFc5HODEZvN1DqJWz4++i4zNdHLHmlQISuxvQh6dnbq+GpVr3Qlzx+UPizzhUvY
+DMdCc/RGXhxzh2Si8iXSkpqLfs5bsCUy3tPNUUVMMzSnLeia1VRv+0piEwIDAQAB
+AoGAfLLHyNJ8HEIzae16UmawaqplWrw5YxOABbbo5aXJAledoDVoEKexW8dmXngw
+4Eu/K3RmvVtwJ8CsexiqfX5jYMU+YKRbww6Vqr/punIUhiEHVarHMFKG9yo14qSa
+z2xPgXvC5p7/Rhci+rAUp36S5kIHch5sLhEEcJayymyzDyECQQD/5B3JdpcovrSI
++nyZ8Iub2+I3f3uox6m1DKxHead26ICoIr7VCnPV5J1gLIB2MofVCbKhmy4PNi5a
+0QdvazJfAkEAyJq9Y+9SQ4sCOVDrFklJxhXuZE4WbnR32XsBdnQ9dauo0E2vDVkv
+6mHnzMWroTjLv4hH5nufE5NvMo8PNGB0zQJAFOKkf737JmsyRv/Szamxa14t/4Ob
+LzJkqo9HPGo0feMKJS74zmCVBb8sDR50ubD0HzI0bzZAMyOj8uuepLxmFwJAH+RR
+5bhfeLN52AjgRvvBycckzjeH42mKwD2I/v794l43CV7ATLv4HSgRhQGMBqaT5dBR
+tffDU4Zl8EDEJwyKpQJBAJ2NNacURTyavU699QJOIdGAsA4KXici8H3PuuWMtHLR
+RKdPFeaCRn+9p7Tglf0rH9hUGOpUXHYD3+ECt6gnVDc=
+-----END RSA PRIVATE KEY-----
-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/
_______________________________________________
enlightenment-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/enlightenment-devel