summaryrefslogtreecommitdiff
path: root/legacy
diff options
context:
space:
mode:
authorCedric BAIL <cedric.bail@free.fr>2008-09-08 09:19:57 +0000
committerCedric BAIL <cedric.bail@free.fr>2008-09-08 09:19:57 +0000
commit46b7796946d58e83cd24dbed2b9de670d7cf4937 (patch)
tree2534bd2cf3e9613fe7a0ad88e35c32adc3040d88 /legacy
parentaa2fded0fc262199480338243a024c835e43c1b0 (diff)
Add signature support in eet.
You can use eet -s to sign a eet file and eet -c to check its signature. The current code doesn't check any certificate trust path, only if the signature match the certificate and that the certificate could be loaded. If that's not the case, eet_open will fail. If the file is not signed, eet_open will just continue to succeed. SVN revision: 35882
Diffstat (limited to 'legacy')
-rw-r--r--legacy/eet/configure.in52
-rw-r--r--legacy/eet/src/bin/eet_main.c58
-rw-r--r--legacy/eet/src/lib/Eet.h64
-rw-r--r--legacy/eet/src/lib/Eet_private.h26
-rw-r--r--legacy/eet/src/lib/Makefile.am4
-rw-r--r--legacy/eet/src/lib/eet_cypher.c335
-rw-r--r--legacy/eet/src/lib/eet_lib.c104
-rw-r--r--legacy/eet/src/tests/cert.pem22
-rw-r--r--legacy/eet/src/tests/eet_suite.c84
-rw-r--r--legacy/eet/src/tests/key.pem15
10 files changed, 760 insertions, 4 deletions
diff --git a/legacy/eet/configure.in b/legacy/eet/configure.in
index ebf301e28b..21026ee0be 100644
--- a/legacy/eet/configure.in
+++ b/legacy/eet/configure.in
@@ -143,6 +143,54 @@ fi
143 143
144AM_CONDITIONAL(EET_ENABLE_TESTS, test "x${enable_tests}" = "xyes") 144AM_CONDITIONAL(EET_ENABLE_TESTS, test "x${enable_tests}" = "xyes")
145 145
146dnl Openssl support
147want_openssl="auto"
148have_openssl="no"
149AC_ARG_ENABLE(openssl,
150 [AC_HELP_STRING([--disable-openssl], [disable openssl eet support])],
151 [ want_openssl=$enableval ]
152)
153if test "x$want_openssl" = "xyes" -o "x$want_openssl" = "xauto"; then
154 PKG_CHECK_MODULES(OPENSSL, openssl,
155 [
156 have_openssl="yes"
157 AC_DEFINE(HAVE_OPENSSL, 1, [Have Openssl support])
158 ],
159 [
160 if test "x$use_strict" = "xyes"; then
161 AC_MSG_ERROR([Openssl not found (strict dependencies checking)])
162 fi
163 ])
164fi
165
166dnl Crypto option
167want_cypher="yes"
168have_cypher="no"
169want_signature="yes"
170have_signature="no"
171
172AC_MSG_CHECKING(whether to activate cypher support in eet)
173AC_ARG_ENABLE(cypher,
174 [AC_HELP_STRING([--disable-cypher], [disable cypher support for eet API])],
175 [ want_cypher=$enableval ]
176)
177if test "x$have_openssl" = "xyes" -a "x$want_cypher" = "xyes"; then
178 have_cypher="yes"
179 AC_DEFINE(HAVE_CYPHER, 1, [Have cypher support built in eet])
180fi
181AC_MSG_RESULT($have_cypher)
182
183AC_MSG_CHECKING(whether to activate signature support in eet)
184AC_ARG_ENABLE(signature,
185 [AC_HELP_STRING([--disable-signature], [disable signature file support for eet])],
186 [ want_signature=$enableval ]
187)
188if test "x$have_openssl" = "xyes" -a "x$want_signature" = "xyes"; then
189 have_signature="yes"
190 AC_DEFINE(HAVE_SIGNATURE, 1, [Have signature support for eet file])
191fi
192AC_MSG_RESULT($have_signature)
193
146dnl Coverage 194dnl Coverage
147 195
148AC_ARG_ENABLE(coverage, 196AC_ARG_ENABLE(coverage,
@@ -241,6 +289,10 @@ echo "------------------------------------------------------------------------"
241echo 289echo
242echo "Configuration Options Summary:" 290echo "Configuration Options Summary:"
243echo 291echo
292echo " Openssl..............: ${have_openssl}"
293echo " Cypher support.....: ${have_cypher}"
294echo " Signature..........: ${have_signature}"
295
244echo " Tests................: ${enable_tests}" 296echo " Tests................: ${enable_tests}"
245echo " Coverage.............: ${enable_coverage}" 297echo " Coverage.............: ${enable_coverage}"
246echo 298echo
diff --git a/legacy/eet/src/bin/eet_main.c b/legacy/eet/src/bin/eet_main.c
index 539cec8854..0db402641a 100644
--- a/legacy/eet/src/bin/eet_main.c
+++ b/legacy/eet/src/bin/eet_main.c
@@ -200,6 +200,50 @@ do_eet_remove(const char *file, const char *key)
200 eet_close(ef); 200 eet_close(ef);
201} 201}
202 202
203static void
204do_eet_check(const char *file)
205{
206 Eet_File *ef;
207 const void *der;
208 int der_length;
209
210 ef = eet_open(file, EET_FILE_MODE_READ);
211 if (!ef)
212 {
213 fprintf(stdout, "checking signature of `%s` failed\n", file);
214 exit(-1);
215 }
216
217 der = eet_identity_x509(ef, &der_length);
218
219 eet_identity_certificate_print(der, der_length, stdout);
220
221 eet_close(ef);
222}
223
224static void
225do_eet_sign(const char *file, const char *private_key, const char *public_key)
226{
227 Eet_File *ef;
228 Eet_Key *key;
229
230 ef = eet_open(file, EET_FILE_MODE_READ_WRITE);
231 if (!ef)
232 {
233 fprintf(stdout, "cannot open for read+write: %s.\n", file);
234 exit(-1);
235 }
236
237 key = eet_identity_open(public_key, private_key, NULL);
238
239 fprintf(stdout, "Using the following key to sign `%s`.\n", file);
240 eet_identity_print(key, stdout);
241
242 eet_identity_set(ef, key);
243
244 eet_close(ef);
245}
246
203int 247int
204main(int argc, char **argv) 248main(int argc, char **argv)
205{ 249{
@@ -214,6 +258,8 @@ main(int argc, char **argv)
214 " eet -i FILE.EET KEY IN-FILE COMPRESS insert data to KEY in FILE.EET from IN-FILE and if COMPRESS is 1, compress it\n" 258 " eet -i FILE.EET KEY IN-FILE COMPRESS insert data to KEY in FILE.EET from IN-FILE and if COMPRESS is 1, compress it\n"
215 " eet -e FILE.EET KEY IN-FILE COMPRESS insert and encode to KEY in FILE.EET from IN-FILE and if COMPRESS is 1, compress it\n" 259 " eet -e FILE.EET KEY IN-FILE COMPRESS insert and encode to KEY in FILE.EET from IN-FILE and if COMPRESS is 1, compress it\n"
216 " eet -r FILE.EET KEY remove KEY in FILE.EET\n" 260 " eet -r FILE.EET KEY remove KEY in FILE.EET\n"
261 " eet -c FILE.EET report and check the signature information of an eet file\n"
262 " eet -s FILE.EET PRIVATE_KEY PUBLIC_KEY sign FILE.EET with PRIVATE_KEY and attach PUBLIC_KEY as it's certificate\n"
217 ); 263 );
218 eet_shutdown(); 264 eet_shutdown();
219 return -1; 265 return -1;
@@ -250,6 +296,18 @@ main(int argc, char **argv)
250 { 296 {
251 goto help; 297 goto help;
252 } 298 }
299 else if ((!strcmp(argv[1], "-c")) && (argc > 2))
300 {
301 do_eet_check(argv[2]);
302 }
303 else if ((!strcmp(argv[1], "-s")) && (argc > 4))
304 {
305 do_eet_sign(argv[2], argv[3], argv[4]);
306 }
307 else
308 {
309 goto help;
310 }
253 eet_shutdown(); 311 eet_shutdown();
254 return 0; 312 return 0;
255} 313}
diff --git a/legacy/eet/src/lib/Eet.h b/legacy/eet/src/lib/Eet.h
index 2f52aab8b6..c528bc2e8e 100644
--- a/legacy/eet/src/lib/Eet.h
+++ b/legacy/eet/src/lib/Eet.h
@@ -2,6 +2,7 @@
2#define _EET_H 2#define _EET_H
3 3
4#include <stdlib.h> 4#include <stdlib.h>
5#include <stdio.h>
5 6
6#ifdef EAPI 7#ifdef EAPI
7# undef EAPI 8# undef EAPI
@@ -86,12 +87,19 @@ extern "C" {
86 EET_ERROR_WRITE_ERROR_FILE_TOO_BIG, 87 EET_ERROR_WRITE_ERROR_FILE_TOO_BIG,
87 EET_ERROR_WRITE_ERROR_IO_ERROR, 88 EET_ERROR_WRITE_ERROR_IO_ERROR,
88 EET_ERROR_WRITE_ERROR_OUT_OF_SPACE, 89 EET_ERROR_WRITE_ERROR_OUT_OF_SPACE,
89 EET_ERROR_WRITE_ERROR_FILE_CLOSED 90 EET_ERROR_WRITE_ERROR_FILE_CLOSED,
91 EET_ERROR_MMAP_FAILED,
92 EET_ERROR_X509_ENCODING_FAILED,
93 EET_ERROR_SIGNATURE_FAILED,
94 EET_ERROR_INVALID_SIGNATURE,
95 EET_ERROR_NOT_SIGNED,
96 EET_ERROR_NOT_IMPLEMENTED
90 } Eet_Error; 97 } Eet_Error;
91 98
92 typedef struct _Eet_File Eet_File; 99 typedef struct _Eet_File Eet_File;
93 typedef struct _Eet_Dictionary Eet_Dictionary; 100 typedef struct _Eet_Dictionary Eet_Dictionary;
94 typedef struct _Eet_Data_Descriptor Eet_Data_Descriptor; 101 typedef struct _Eet_Data_Descriptor Eet_Data_Descriptor;
102 typedef struct _Eet_Key Eet_Key;
95 103
96 typedef struct _Eet_Data_Descriptor_Class Eet_Data_Descriptor_Class; 104 typedef struct _Eet_Data_Descriptor_Class Eet_Data_Descriptor_Class;
97 105
@@ -247,6 +255,60 @@ extern "C" {
247 */ 255 */
248 EAPI Eet_Error eet_close(Eet_File *ef); 256 EAPI Eet_Error eet_close(Eet_File *ef);
249 257
258 /**
259 * Callback used to request if needed the password of a private key.
260 *
261 * @since 2.0.0
262 */
263 typedef int (*Eet_Key_Password_Callback)(char *buffer, int size, int rwflag, void *data);
264
265 /**
266 * Create an Eet_Key needed for signing an eet file.
267 *
268 * The certificate should provide the public that match the private key.
269 * No verification is done to ensure that.
270 *
271 * @since 2.0.0
272 */
273 EAPI Eet_Key* eet_identity_open(const char *certificate_file, const char *private_key_file, Eet_Key_Password_Callback cb);
274
275 /**
276 * Close and release all ressource used by an Eet_Key.
277 * An reference counter prevent it from being freed until all file using it are
278 * also closed.
279 *
280 * @since 2.0.0
281 */
282 EAPI void eet_identity_close(Eet_Key *key);
283
284 /**
285 * Set a key to sign a file
286 *
287 * @since 2.0.0
288 */
289 EAPI Eet_Error eet_identity_set(Eet_File *ef, Eet_Key *key);
290
291 /**
292 * Display both private and public key of an Eet_Key.
293 *
294 * @since 2.0.0
295 */
296 EAPI void eet_identity_print(Eet_Key *key, FILE *out);
297
298 /**
299 * Get the x509 der certificate associated with an Eet_File. Will return NULL
300 * if the file is not signed.
301 *
302 * @since 2.0.0
303 */
304 EAPI const void *eet_identity_x509(Eet_File *ef, int *der_length);
305
306 /**
307 * Display the x509 der certificate to out.
308 *
309 * @since 2.0.0
310 */
311 EAPI void eet_identity_certificate_print(const unsigned char *certificate, int der_length, FILE *out);
250 312
251 /** 313 /**
252 * Return a handle to the shared string dictionary of the Eet file 314 * Return a handle to the shared string dictionary of the Eet file
diff --git a/legacy/eet/src/lib/Eet_private.h b/legacy/eet/src/lib/Eet_private.h
index 7160783e98..57da2a4744 100644
--- a/legacy/eet/src/lib/Eet_private.h
+++ b/legacy/eet/src/lib/Eet_private.h
@@ -12,6 +12,14 @@
12# endif 12# endif
13#endif 13#endif
14 14
15#include "config.h"
16
17#ifdef HAVE_OPENSSL
18#include <openssl/evp.h>
19#include <openssl/x509.h>
20#include <openssl/pem.h>
21#endif
22
15typedef struct _Eet_String Eet_String; 23typedef struct _Eet_String Eet_String;
16 24
17struct _Eet_String 25struct _Eet_String
@@ -53,6 +61,15 @@ struct _Eet_Dictionary
53 const char *end; 61 const char *end;
54}; 62};
55 63
64struct _Eet_Key
65{
66 int references;
67#ifdef HAVE_SIGNATURE
68 X509 *certificate;
69 EVP_PKEY *private_key;
70#endif
71};
72
56Eet_Dictionary *eet_dictionary_add(void); 73Eet_Dictionary *eet_dictionary_add(void);
57void eet_dictionary_free(Eet_Dictionary *ed); 74void eet_dictionary_free(Eet_Dictionary *ed);
58int eet_dictionary_string_add(Eet_Dictionary *ed, const char *string); 75int eet_dictionary_string_add(Eet_Dictionary *ed, const char *string);
@@ -66,6 +83,15 @@ int _eet_hash_gen(const char *key, int hash_size);
66int _eet_string_to_double_convert(const char *src, long long *m, long *e); 83int _eet_string_to_double_convert(const char *src, long long *m, long *e);
67void _eet_double_to_string_convert(char des[128], double d); 84void _eet_double_to_string_convert(char des[128], double d);
68 85
86const void* eet_identity_check(const void *data_base, unsigned int data_length,
87 const void *signature_base, unsigned int signature_length,
88 int *x509_length);
89Eet_Error eet_cypher(void *data, unsigned int size, const char *key, unsigned int length);
90Eet_Error eet_decypher(void *data, unsigned int size, const char *key, unsigned int length);
91Eet_Error eet_identity_sign(FILE *fp, Eet_Key *key);
92void eet_identity_unref(Eet_Key *key);
93void eet_identity_ref(Eet_Key *key);
94
69#ifndef PATH_MAX 95#ifndef PATH_MAX
70#define PATH_MAX 4096 96#define PATH_MAX 4096
71#endif 97#endif
diff --git a/legacy/eet/src/lib/Makefile.am b/legacy/eet/src/lib/Makefile.am
index 0214fa3e77..7055ffd7a2 100644
--- a/legacy/eet/src/lib/Makefile.am
+++ b/legacy/eet/src/lib/Makefile.am
@@ -8,7 +8,8 @@ AM_CPPFLAGS = \
8-DPACKAGE_LIB_DIR=\"$(libdir)\" \ 8-DPACKAGE_LIB_DIR=\"$(libdir)\" \
9-DPACKAGE_DATA_DIR=\"$(datadir)/$(PACKAGE)\" \ 9-DPACKAGE_DATA_DIR=\"$(datadir)/$(PACKAGE)\" \
10@EVIL_CFLAGS@ \ 10@EVIL_CFLAGS@ \
11@COVERAGE_CFLAGS@ 11@COVERAGE_CFLAGS@ \
12@OPENSSL_CFLAGS@
12 13
13include_HEADERS = Eet.h 14include_HEADERS = Eet.h
14 15
@@ -18,6 +19,7 @@ libeet_la_SOURCES = \
18eet_lib.c \ 19eet_lib.c \
19eet_data.c \ 20eet_data.c \
20eet_image.c \ 21eet_image.c \
22eet_cypher.c \
21eet_dictionary.c \ 23eet_dictionary.c \
22eet_utils.c 24eet_utils.c
23 25
diff --git a/legacy/eet/src/lib/eet_cypher.c b/legacy/eet/src/lib/eet_cypher.c
new file mode 100644
index 0000000000..dcaab55357
--- /dev/null
+++ b/legacy/eet/src/lib/eet_cypher.c
@@ -0,0 +1,335 @@
1#ifdef HAVE_CONFIG_H
2# include <config.h>
3#endif
4
5#include <stdio.h>
6#include <sys/types.h>
7#include <sys/stat.h>
8#include <unistd.h>
9#include <sys/mman.h>
10
11#ifdef HAVE_SIGNATURE
12# include <openssl/rsa.h>
13# include <openssl/objects.h>
14# include <openssl/err.h>
15# include <openssl/ssl.h>
16# include <openssl/dh.h>
17# include <openssl/dsa.h>
18#endif
19
20#include "Eet.h"
21#include "Eet_private.h"
22
23#define EET_MAGIC_SIGN 0x1ee74271
24
25EAPI Eet_Key*
26eet_identity_open(const char *certificate_file, const char *private_key_file, Eet_Key_Password_Callback cb)
27{
28#ifdef HAVE_SIGNATURE
29 EVP_PKEY *pkey = NULL;
30 X509 *cert = NULL;
31 Eet_Key *key;
32 FILE *fp;
33
34 /* Load the X509 certificate in memory. */
35 fp = fopen(certificate_file, "r");
36 if (!fp) return NULL;
37 cert = PEM_read_X509(fp, NULL, NULL, NULL);
38 fclose(fp);
39 if (!cert) return NULL;
40
41 /* Check the presence of the public key. Just in case. */
42 pkey = X509_get_pubkey(cert);
43 if (!pkey) goto on_error;
44
45 /* Load the private key in memory. */
46 fp = fopen(private_key_file, "r");
47 if (!fp) goto on_error;
48 pkey = PEM_read_PrivateKey(fp, NULL, cb, NULL);
49 fclose(fp);
50 if (!pkey) goto on_error;
51
52 key = malloc(sizeof(Eet_Key));
53 if (!key) goto on_error;
54
55 key->references = 1;
56 key->certificate = cert;
57 key->private_key = pkey;
58
59 return key;
60
61 on_error:
62 if (cert) X509_free(cert);
63 if (pkey) EVP_PKEY_free(pkey);
64#endif
65 return NULL;
66}
67
68EAPI void
69eet_identity_print(Eet_Key *key, FILE *out)
70{
71#ifdef HAVE_SIGNATURE
72 RSA *rsa;
73 DSA *dsa;
74 DH *dh;
75
76 if (!key) return ;
77
78 rsa = EVP_PKEY_get1_RSA(key->private_key);
79 if (rsa)
80 {
81 fprintf(out, "Private key (RSA) :\n");
82 RSA_print_fp(out, rsa, 0);
83 }
84
85 dsa = EVP_PKEY_get1_DSA(key->private_key);
86 if (dsa)
87 {
88 fprintf(out, "Private key (DSA) :\n");
89 DSA_print_fp(out, dsa, 0);
90 }
91
92 dh = EVP_PKEY_get1_DH(key->private_key);
93 if (dh)
94 {
95 fprintf(out, "Private key (DH) :\n");
96 DHparams_print_fp(out, dh);
97 }
98
99 fprintf(out, "Public certificate :\n");
100 X509_print_fp(out, key->certificate);
101#else
102 fprintf(out, "You need to compile signature support in EET.\n");
103#endif
104}
105
106EAPI void
107eet_identity_close(Eet_Key *key)
108{
109#ifdef HAVE_SIGNATURE
110 if (key->references > 0) return ;
111
112 X509_free(key->certificate);
113 EVP_PKEY_free(key->private_key);
114 free(key);
115#endif
116}
117
118void
119eet_identity_ref(Eet_Key *key)
120{
121 if (key == NULL) return ;
122 key->references++;
123}
124
125void
126eet_identity_unref(Eet_Key *key)
127{
128 if (key == NULL) return ;
129 key->references--;
130 eet_identity_close(key);
131}
132
133Eet_Error
134eet_identity_sign(FILE *fp, Eet_Key *key)
135{
136#ifdef HAVE_SIGNATURE
137 unsigned char *x509_der = NULL;
138 void *sign = NULL;
139 void *data;
140 int head[3];
141 EVP_MD_CTX md_ctx;
142 struct stat st_buf;
143 Eet_Error err = EET_ERROR_NONE;
144 int sign_length;
145 int x509_length;
146 int fd;
147
148 /* A few check and flush pending write. */
149 if (!fp
150 || !key
151 || !key->certificate
152 || !key->private_key)
153 return EET_ERROR_BAD_OBJECT;
154
155 /* Get the file size. */
156 fd = fileno(fp);
157 if (fd < 0) return EET_ERROR_BAD_OBJECT;
158 if (fstat(fd, &st_buf) < 0) return EET_ERROR_MMAP_FAILED;
159
160 /* Map the file in memory. */
161 data = mmap(NULL, st_buf.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
162 if (data == MAP_FAILED) return EET_ERROR_MMAP_FAILED;
163
164 sign_length = EVP_PKEY_size(key->private_key);
165 sign = malloc(sign_length);
166 if (sign == NULL)
167 {
168 err = EET_ERROR_OUT_OF_MEMORY;
169 goto on_error;
170 }
171
172 /* Do the signature. */
173 EVP_SignInit(&md_ctx, EVP_sha1());
174 EVP_SignUpdate (&md_ctx, data, st_buf.st_size);
175 err = EVP_SignFinal (&md_ctx, sign, &sign_length, key->private_key);
176 if (err != 1)
177 {
178 ERR_print_errors_fp(stdout);
179 err = EET_ERROR_SIGNATURE_FAILED;
180 goto on_error;
181 }
182
183 /* Give me the der (binary form for X509). */
184 x509_length = i2d_X509(key->certificate, &x509_der);
185 if (x509_length < 0)
186 {
187 ERR_print_errors_fp(stdout);
188 err = EET_ERROR_X509_ENCODING_FAILED;
189 goto on_error;
190 }
191
192 /* Append the signature at the end of the file. */
193 head[0] = (int) htonl ((unsigned int) EET_MAGIC_SIGN);
194 head[1] = (int) htonl ((unsigned int) sign_length);
195 head[2] = (int) htonl ((unsigned int) x509_length);
196
197 if (fwrite(head, sizeof(head), 1, fp) != 1)
198 {
199 err = EET_ERROR_WRITE_ERROR;
200 goto on_error;
201 }
202 if (fwrite(sign, sign_length, 1, fp) != 1)
203 {
204 err = EET_ERROR_WRITE_ERROR;
205 goto on_error;
206 }
207 if (fwrite(x509_der, x509_length, 1, fp) != 1)
208 {
209 err = EET_ERROR_WRITE_ERROR;
210 goto on_error;
211 }
212
213 on_error:
214 if (x509_der) OPENSSL_free(x509_der);
215 if (sign != NULL) free(sign);
216 munmap(data, st_buf.st_size);
217 return err;
218#else
219 return EET_ERROR_NOT_IMPLEMENTED;
220#endif
221}
222
223const void*
224eet_identity_check(const void *data_base, unsigned int data_length,
225 const void *signature_base, unsigned int signature_length,
226 int *x509_length)
227{
228#ifdef HAVE_SIGNATURE
229 const int *header = signature_base;
230 const unsigned char *sign;
231 const unsigned char *cert_der;
232 const unsigned char *tmp;
233 EVP_PKEY *pkey;
234 X509 *x509;
235 EVP_MD_CTX md_ctx;
236 int sign_length;
237 int cert_length;
238 int magic;
239 int err;
240
241 if (signature_length < sizeof(int) * 3) return NULL;
242
243 magic = ntohl(header[0]);
244 sign_length = ntohl(header[1]);
245 cert_length = ntohl(header[2]);
246
247 if (magic != EET_MAGIC_SIGN) return NULL;
248 if (sign_length + cert_length + sizeof(int) * 3 > signature_length) return NULL;
249
250 sign = signature_base + sizeof(int) * 3;
251 cert_der = sign + sign_length;
252
253 /* Strange but d2i_X509 seems to put 0 all over the place. */
254 tmp = alloca(cert_length);
255 memcpy((char*) tmp, cert_der, cert_length);
256 x509 = d2i_X509(NULL, &tmp, cert_length);
257 if (x509 == NULL) return NULL;
258
259 /* Get public key - eay */
260 pkey=X509_get_pubkey(x509);
261 if (pkey == NULL)
262 {
263 X509_free(x509);
264 return NULL;
265 }
266
267 /* Verify the signature */
268 EVP_VerifyInit(&md_ctx, EVP_sha1());
269 EVP_VerifyUpdate(&md_ctx, data_base, data_length);
270 err = EVP_VerifyFinal(&md_ctx, sign, sign_length, pkey);
271
272 X509_free(x509);
273 EVP_PKEY_free(pkey);
274
275 if (err != 1)
276 return NULL;
277
278 if (x509_length) *x509_length = cert_length;
279 return cert_der;
280#else
281 return NULL;
282#endif
283}
284
285EAPI void
286eet_identity_certificate_print(const unsigned char *certificate, int der_length, FILE *out)
287{
288#ifdef HAVE_SIGNATURE
289 const unsigned char *tmp;
290 X509 *x509;
291
292 if (certificate == NULL
293 || out == NULL
294 || der_length <= 0)
295 {
296 fprintf(out, "No certificate provided.\n");
297 return ;
298 }
299
300 /* Strange but d2i_X509 seems to put 0 all over the place. */
301 tmp = alloca(der_length);
302 memcpy((char*) tmp, certificate, der_length);
303 x509 = d2i_X509(NULL, &tmp, der_length);
304 if (x509 == NULL)
305 {
306 fprintf(out, "Not a valid certificate.\n");
307 return ;
308 }
309
310 fprintf(out, "Public certificate :\n");
311 X509_print_fp(out, x509);
312
313 X509_free(x509);
314#else
315 fprintf(out, "You need to compile signature support in EET.\n");
316#endif
317}
318
319Eet_Error
320eet_cypher(void *data, unsigned int size, const char *key, unsigned int length)
321{
322#ifdef HAVE_CYPHER
323#else
324 return EET_ERROR_NOT_IMPLEMENTED;
325#endif
326}
327
328Eet_Error
329eet_decypher(void *data, unsigned int size, const char *key, unsigned int length)
330{
331#ifdef HAVE_CYPHER
332#else
333 return EET_ERROR_NOT_IMPLEMENTED;
334#endif
335}
diff --git a/legacy/eet/src/lib/eet_lib.c b/legacy/eet/src/lib/eet_lib.c
index 9d0be1ce38..76e60dfce1 100644
--- a/legacy/eet/src/lib/eet_lib.c
+++ b/legacy/eet/src/lib/eet_lib.c
@@ -69,14 +69,17 @@ struct _Eet_File
69 FILE *fp; 69 FILE *fp;
70 FILE *readfp; 70 FILE *readfp;
71 Eet_File_Header *header; 71 Eet_File_Header *header;
72 const unsigned char *data;
73 Eet_Dictionary *ed; 72 Eet_Dictionary *ed;
73 Eet_Key *key;
74 const unsigned char *data;
75 const void *x509_der;
74 76
75 int magic; 77 int magic;
76 int references; 78 int references;
77 79
78 Eet_File_Mode mode; 80 Eet_File_Mode mode;
79 int data_size; 81 int data_size;
82 int x509_length;
80 time_t mtime; 83 time_t mtime;
81 84
82 unsigned char writes_pending : 1; 85 unsigned char writes_pending : 1;
@@ -158,6 +161,11 @@ struct
158} dictionary[num_dictionary_entries]; 161} dictionary[num_dictionary_entries];
159/* now start the string stream. */ 162/* now start the string stream. */
160/* and right after them the data stream. */ 163/* and right after them the data stream. */
164int magic_sign; /* Optional, only if the eet file is signed. */
165int signature_length; /* Signature length. */
166int x509_length; /* Public certificate that signed the file. */
167char signature[signature_length]; /* The signature. */
168char x509[x509_length]; /* The public certificate. */
161#endif 169#endif
162 170
163#define EET_FILE2_HEADER_COUNT 3 171#define EET_FILE2_HEADER_COUNT 3
@@ -379,8 +387,11 @@ eet_flush2(Eet_File *ef)
379 return EET_ERROR_NONE; 387 return EET_ERROR_NONE;
380 if (ef->mode == EET_FILE_MODE_READ_WRITE && ef->fp == NULL) 388 if (ef->mode == EET_FILE_MODE_READ_WRITE && ef->fp == NULL)
381 { 389 {
390 int fd;
391
382 unlink(ef->path); 392 unlink(ef->path);
383 ef->fp = fopen(ef->path, "wb"); 393 fd = open(file, O_CREAT | O_TRUNC | O_RDWR, S_IRUSR | S_IWUSR);
394 ef->fp = fdopen(fd, "wb");
384 if (!ef->fp) return EET_ERROR_NOT_WRITABLE; 395 if (!ef->fp) return EET_ERROR_NOT_WRITABLE;
385 fcntl(fileno(ef->fp), F_SETFD, FD_CLOEXEC); 396 fcntl(fileno(ef->fp), F_SETFD, FD_CLOEXEC);
386 } 397 }
@@ -516,6 +527,17 @@ eet_flush2(Eet_File *ef)
516 } 527 }
517 } 528 }
518 529
530 /* flush all write to the file. */
531 fflush(ef->fp);
532
533 /* append signature if required */
534 if (ef->key)
535 {
536 error = eet_identity_sign(ef->fp, ef->key);
537 if (error != EET_ERROR_NONE)
538 goto sign_error;
539 }
540
519 /* no more writes pending */ 541 /* no more writes pending */
520 ef->writes_pending = 0; 542 ef->writes_pending = 0;
521 543
@@ -651,6 +673,7 @@ eet_flush(Eet_File *ef)
651 ef->fp = NULL; 673 ef->fp = NULL;
652 return EET_ERROR_WRITE_ERROR; 674 return EET_ERROR_WRITE_ERROR;
653 } 675 }
676 sign_error:
654 fclose(ef->fp); 677 fclose(ef->fp);
655 ef->fp = NULL; 678 ef->fp = NULL;
656 return EET_ERROR_WRITE_ERROR; 679 return EET_ERROR_WRITE_ERROR;
@@ -660,6 +683,19 @@ eet_flush(Eet_File *ef)
660EAPI int 683EAPI int
661eet_init(void) 684eet_init(void)
662{ 685{
686#ifdef HAVE_OPENSSL
687 /* Just load the crypto library error strings,
688 * SSL_load_error_strings() loads the crypto AND the SSL ones */
689 /* SSL_load_error_strings();*/
690 static int call_once = 0;
691
692 if (call_once == 0)
693 {
694 call_once = 1;
695 ERR_load_crypto_strings();
696 }
697
698#endif
663 return ++eet_initcount; 699 return ++eet_initcount;
664} 700}
665 701
@@ -738,6 +774,7 @@ eet_internal_read2(Eet_File *ef)
738 int bytes_directory_entries; 774 int bytes_directory_entries;
739 int num_dictionary_entries; 775 int num_dictionary_entries;
740 int bytes_dictionary_entries; 776 int bytes_dictionary_entries;
777 int signature_base_offset;
741 int i; 778 int i;
742 779
743 index += sizeof(int); 780 index += sizeof(int);
@@ -787,6 +824,8 @@ eet_internal_read2(Eet_File *ef)
787 if (eet_test_close(!ef->header->directory->nodes, ef)) 824 if (eet_test_close(!ef->header->directory->nodes, ef))
788 return NULL; 825 return NULL;
789 826
827 signature_base_offset = 0;
828
790 /* actually read the directory block - all of it, into ram */ 829 /* actually read the directory block - all of it, into ram */
791 for (i = 0; i < num_directory_entries; ++i) 830 for (i = 0; i < num_directory_entries; ++i)
792 { 831 {
@@ -850,6 +889,10 @@ eet_internal_read2(Eet_File *ef)
850 if (efn->data) 889 if (efn->data)
851 memcpy(efn->data, ef->data + efn->offset, efn->size); 890 memcpy(efn->data, ef->data + efn->offset, efn->size);
852 } 891 }
892
893 /* compute the possible position of a signature */
894 if (signature_base_offset < efn->offset + efn->size)
895 signature_base_offset = efn->offset + efn->size;
853 } 896 }
854 897
855 ef->ed = NULL; 898 ef->ed = NULL;
@@ -906,9 +949,35 @@ eet_internal_read2(Eet_File *ef)
906 ef->ed->all[j].hash = hash; 949 ef->ed->all[j].hash = hash;
907 if (ef->ed->all[j].prev == -1) 950 if (ef->ed->all[j].prev == -1)
908 ef->ed->hash[hash] = j; 951 ef->ed->hash[hash] = j;
952
953 /* compute the possible position of a signature */
954 if (signature_base_offset < offset + ef->ed->all[j].len)
955 signature_base_offset = offset + ef->ed->all[j].len;
909 } 956 }
910 } 957 }
911 958
959 /* Check if the file is signed */
960 ef->x509_der = NULL;
961 ef->x509_length = 0;
962 if (signature_base_offset < ef->data_size)
963 {
964#ifdef HAVE_SIGNATURE
965 const unsigned char *buffer = ((const unsigned char*) ef->data) + signature_base_offset;
966 ef->x509_der = eet_identity_check(ef->data, signature_base_offset,
967 buffer, ef->data_size - signature_base_offset,
968 &ef->x509_length);
969
970 if (ef->x509_der == NULL)
971 {
972 ef->delete_me_now = 1;
973 eet_close(ef);
974 return NULL;
975 }
976#else
977 fprintf(stderr, "This file could be signed but you didn't compile the necessary code to check the signature.\n");
978#endif
979 }
980
912 return ef; 981 return ef;
913} 982}
914 983
@@ -1120,6 +1189,7 @@ eet_memopen_read(const void *data, size_t size)
1120 1189
1121 ef->ed = NULL; 1190 ef->ed = NULL;
1122 ef->path = NULL; 1191 ef->path = NULL;
1192 ef->key = NULL;
1123 ef->magic = EET_MAGIC_FILE; 1193 ef->magic = EET_MAGIC_FILE;
1124 ef->references = 1; 1194 ef->references = 1;
1125 ef->mode = EET_FILE_MODE_READ; 1195 ef->mode = EET_FILE_MODE_READ;
@@ -1229,6 +1299,7 @@ eet_open(const char *file, Eet_File_Mode mode)
1229 1299
1230 /* fill some of the members */ 1300 /* fill some of the members */
1231 ef->fp = fp; 1301 ef->fp = fp;
1302 ef->key = NULL;
1232 ef->readfp = NULL; 1303 ef->readfp = NULL;
1233 ef->path = ((char *)ef) + sizeof(Eet_File); 1304 ef->path = ((char *)ef) + sizeof(Eet_File);
1234 memcpy(ef->path, file, file_len); 1305 memcpy(ef->path, file, file_len);
@@ -1297,6 +1368,32 @@ eet_mode_get(Eet_File *ef)
1297 return ef->mode; 1368 return ef->mode;
1298} 1369}
1299 1370
1371EAPI const void *
1372eet_identity_x509(Eet_File *ef, int *der_length)
1373{
1374 if (!ef->x509_der) return NULL;
1375
1376 if (der_length) *der_length = ef->x509_length;
1377 return ef->x509_der;
1378}
1379
1380EAPI Eet_Error
1381eet_identity_set(Eet_File *ef, Eet_Key *key)
1382{
1383 Eet_Key *tmp = ef->key;
1384
1385 if (!ef) return EET_ERROR_BAD_OBJECT;
1386
1387 ef->key = key;
1388 eet_identity_ref(ef->key);
1389 eet_identity_unref(tmp);
1390
1391 /* flags that writes are pending */
1392 ef->writes_pending = 1;
1393
1394 return EET_ERROR_NONE;
1395}
1396
1300EAPI Eet_Error 1397EAPI Eet_Error
1301eet_close(Eet_File *ef) 1398eet_close(Eet_File *ef)
1302{ 1399{
@@ -1312,6 +1409,9 @@ eet_close(Eet_File *ef)
1312 /* flush any writes */ 1409 /* flush any writes */
1313 err = eet_flush2(ef); 1410 err = eet_flush2(ef);
1314 1411
1412 eet_identity_unref(ef->key);
1413 ef->key = NULL;
1414
1315 /* if not urgent to delete it - dont free it - leave it in cache */ 1415 /* if not urgent to delete it - dont free it - leave it in cache */
1316 if ((!ef->delete_me_now) && (ef->mode == EET_FILE_MODE_READ)) 1416 if ((!ef->delete_me_now) && (ef->mode == EET_FILE_MODE_READ))
1317 return EET_ERROR_NONE; 1417 return EET_ERROR_NONE;
diff --git a/legacy/eet/src/tests/cert.pem b/legacy/eet/src/tests/cert.pem
new file mode 100644
index 0000000000..3265462d7b
--- /dev/null
+++ b/legacy/eet/src/tests/cert.pem
@@ -0,0 +1,22 @@
1-----BEGIN CERTIFICATE-----
2MIIDmTCCAwKgAwIBAgIJAIKWPcLUT5FAMA0GCSqGSIb3DQEBBQUAMIGQMQswCQYD
3VQQGEwJGUjEWMBQGA1UECBMNSWxlLURlLUZyYW5jZTEOMAwGA1UEBxMFUGFyaXMx
4FjAUBgNVBAoTDUVubGlnaHRlbm1lbnQxDjAMBgNVBAsTBVRlc3RzMQ0wCwYDVQQD
5EwRCQUlMMSIwIAYJKoZIhvcNAQkBFhNjZWRyaWMuYmFpbEBmcmVlLmZyMB4XDTA4
6MDczMDEzNDU1OVoXDTA5MDczMDEzNDU1OVowgZAxCzAJBgNVBAYTAkZSMRYwFAYD
7VQQIEw1JbGUtRGUtRnJhbmNlMQ4wDAYDVQQHEwVQYXJpczEWMBQGA1UEChMNRW5s
8aWdodGVubWVudDEOMAwGA1UECxMFVGVzdHMxDTALBgNVBAMTBEJBSUwxIjAgBgkq
9hkiG9w0BCQEWE2NlZHJpYy5iYWlsQGZyZWUuZnIwgZ8wDQYJKoZIhvcNAQEBBQAD
10gY0AMIGJAoGBAMiE486eROKePG0/639D4XTTDR9XSRWp1xqZzq7P+jjWRFbZ/MWV
11IVzkc4MRm83UOolbPj76LjM10cseaVAhK7G9CHp2dur4alWvdCXPH5Q+LPOFS9gM
12x0Jz9EZeHHOHZKLyJdKSmot+zluwJTLe081RRUwzNKct6JrVVG/7SmITAgMBAAGj
13gfgwgfUwHQYDVR0OBBYEFEFar6doT5ImL2rf0rJX7EYQqtYQMIHFBgNVHSMEgb0w
14gbqAFEFar6doT5ImL2rf0rJX7EYQqtYQoYGWpIGTMIGQMQswCQYDVQQGEwJGUjEW
15MBQGA1UECBMNSWxlLURlLUZyYW5jZTEOMAwGA1UEBxMFUGFyaXMxFjAUBgNVBAoT
16DUVubGlnaHRlbm1lbnQxDjAMBgNVBAsTBVRlc3RzMQ0wCwYDVQQDEwRCQUlMMSIw
17IAYJKoZIhvcNAQkBFhNjZWRyaWMuYmFpbEBmcmVlLmZyggkAgpY9wtRPkUAwDAYD
18VR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQCpZJhk8BgQh0foiMkOwOMKvObq
19GxAzqjbr7iU9tEvJgwukCBv59ndBM0B5l5ybQdIYWQJOfZE1HTvB60swZMwqap9X
205QXgewymuXiVk+roVh34wg8Pg8F588G2BtLIoujY/gN3WJQR7YPD34iTPc4koV+A
214vs6nmL6wtW21+hsaw==
22-----END CERTIFICATE-----
diff --git a/legacy/eet/src/tests/eet_suite.c b/legacy/eet/src/tests/eet_suite.c
index 003dfa5c75..c52b15c950 100644
--- a/legacy/eet/src/tests/eet_suite.c
+++ b/legacy/eet/src/tests/eet_suite.c
@@ -1,10 +1,17 @@
1#include <sys/types.h>
2#include <sys/stat.h>
1#include <stdlib.h> 3#include <stdlib.h>
2#include <string.h> 4#include <string.h>
3#include <strings.h> 5#include <strings.h>
4#include <stdio.h> 6#include <stdio.h>
7#include <fcntl.h>
5 8
6#include <check.h> 9#include <check.h>
7 10
11#ifdef HAVE_CONFIG_H
12# include <config.h>
13#endif
14
8#include "eet_suite.h" 15#include "eet_suite.h"
9 16
10START_TEST(eet_test_init) 17START_TEST(eet_test_init)
@@ -1146,6 +1153,77 @@ START_TEST(eet_small_image)
1146} 1153}
1147END_TEST 1154END_TEST
1148 1155
1156START_TEST(eet_identity_simple)
1157{
1158 const char *buffer = "Here is a string of data to save !";
1159 const void *tmp;
1160 Eet_File *ef;
1161 Eet_Key *k;
1162 char *test;
1163 char *file = strdup("/tmp/eet_suite_testXXXXXX");
1164 int size;
1165 int fd;
1166
1167 eet_init();
1168
1169 mktemp(file);
1170 chdir("src/tests");
1171
1172 /* Sign an eet file. */
1173 ef = eet_open(file, EET_FILE_MODE_WRITE);
1174 fail_if(!ef);
1175
1176 fail_if(!eet_write(ef, "keys/tests", buffer, strlen(buffer) + 1, 0));
1177
1178 k = eet_identity_open("cert.pem", "key.pem", NULL);
1179 fail_if(!k);
1180
1181 fail_if(eet_identity_set(ef, k) != EET_ERROR_NONE);
1182
1183 eet_close(ef);
1184
1185 /* Open a signed file. */
1186 ef = eet_open(file, EET_FILE_MODE_READ);
1187 fail_if(!ef);
1188
1189 test = eet_read(ef, "keys/tests", &size);
1190 fail_if(!test);
1191 fail_if(size != strlen(buffer) + 1);
1192
1193 fail_if(memcmp(test, buffer, strlen(buffer) + 1) != 0);
1194
1195 tmp = eet_identity_x509(ef, &size);
1196 fail_if(tmp == NULL);
1197
1198 eet_close(ef);
1199
1200 /* As we are changing file contain in less than 1s, this could get unnoticed
1201 by eet cache system. */
1202 eet_clearcache();
1203
1204 /* Corrupting the file. */
1205 fd = open(file, O_WRONLY);
1206 fail_if(fd < 0);
1207
1208 fail_if(lseek(fd, 200, SEEK_SET) != 200);
1209 fail_if(write(fd, "42", 2) != 2);
1210 fail_if(lseek(fd, 50, SEEK_SET) != 50);
1211 fail_if(write(fd, "42", 2) != 2);
1212 fail_if(lseek(fd, 88, SEEK_SET) != 88);
1213 fail_if(write(fd, "42", 2) != 2);
1214
1215 close(fd);
1216
1217 /* Attempt to open a modified file. */
1218 ef = eet_open(file, EET_FILE_MODE_READ);
1219 fail_if(ef);
1220
1221 fail_if(unlink(file) != 0);
1222
1223 eet_shutdown();
1224}
1225END_TEST
1226
1149Suite * 1227Suite *
1150eet_suite(void) 1228eet_suite(void)
1151{ 1229{
@@ -1175,6 +1253,12 @@ eet_suite(void)
1175 tcase_add_test(tc, eet_small_image); 1253 tcase_add_test(tc, eet_small_image);
1176 suite_add_tcase(s, tc); 1254 suite_add_tcase(s, tc);
1177 1255
1256#ifdef HAVE_SIGNATURE
1257 tc = tcase_create("Eet Identity");
1258 tcase_add_test(tc, eet_identity_simple);
1259 suite_add_tcase(s, tc);
1260#endif
1261
1178 return s; 1262 return s;
1179} 1263}
1180 1264
diff --git a/legacy/eet/src/tests/key.pem b/legacy/eet/src/tests/key.pem
new file mode 100644
index 0000000000..74763ca8c8
--- /dev/null
+++ b/legacy/eet/src/tests/key.pem
@@ -0,0 +1,15 @@
1-----BEGIN RSA PRIVATE KEY-----
2MIICXAIBAAKBgQDIhOPOnkTinjxtP+t/Q+F00w0fV0kVqdcamc6uz/o41kRW2fzF
3lSFc5HODEZvN1DqJWz4++i4zNdHLHmlQISuxvQh6dnbq+GpVr3Qlzx+UPizzhUvY
4DMdCc/RGXhxzh2Si8iXSkpqLfs5bsCUy3tPNUUVMMzSnLeia1VRv+0piEwIDAQAB
5AoGAfLLHyNJ8HEIzae16UmawaqplWrw5YxOABbbo5aXJAledoDVoEKexW8dmXngw
64Eu/K3RmvVtwJ8CsexiqfX5jYMU+YKRbww6Vqr/punIUhiEHVarHMFKG9yo14qSa
7z2xPgXvC5p7/Rhci+rAUp36S5kIHch5sLhEEcJayymyzDyECQQD/5B3JdpcovrSI
8+nyZ8Iub2+I3f3uox6m1DKxHead26ICoIr7VCnPV5J1gLIB2MofVCbKhmy4PNi5a
90QdvazJfAkEAyJq9Y+9SQ4sCOVDrFklJxhXuZE4WbnR32XsBdnQ9dauo0E2vDVkv
106mHnzMWroTjLv4hH5nufE5NvMo8PNGB0zQJAFOKkf737JmsyRv/Szamxa14t/4Ob
11LzJkqo9HPGo0feMKJS74zmCVBb8sDR50ubD0HzI0bzZAMyOj8uuepLxmFwJAH+RR
125bhfeLN52AjgRvvBycckzjeH42mKwD2I/v794l43CV7ATLv4HSgRhQGMBqaT5dBR
13tffDU4Zl8EDEJwyKpQJBAJ2NNacURTyavU699QJOIdGAsA4KXici8H3PuuWMtHLR
14RKdPFeaCRn+9p7Tglf0rH9hUGOpUXHYD3+ECt6gnVDc=
15-----END RSA PRIVATE KEY-----