aboutsummaryrefslogtreecommitdiffstats
path: root/src/lib/eet
diff options
context:
space:
mode:
authorCarsten Haitzler (Rasterman) <raster@rasterman.com>2014-11-28 17:54:39 +0900
committerCarsten Haitzler (Rasterman) <raster@rasterman.com>2014-11-28 17:56:27 +0900
commit8669ab8a98ac36db6c228bcc1bb4688c25d1dccc (patch)
tree72945d25d9cc69b094750107d0b1f3332619eea5 /src/lib/eet
parentEvas GL: Use strncat and strncpy for safety (diff)
downloadefl-8669ab8a98ac36db6c228bcc1bb4688c25d1dccc.tar.gz
eet - add new api to verify eet file against stored cert
this api makes it far more obvious as to how to verify an eet file via the eet identify mechanisms that use x509 certificates to sign files. this is consistent with the api used to generate the key for sigining thus you can use the same certificate file to compare against for identify. @feature
Diffstat (limited to 'src/lib/eet')
-rw-r--r--src/lib/eet/Eet.h20
-rw-r--r--src/lib/eet/eet_lib.c148
2 files changed, 168 insertions, 0 deletions
diff --git a/src/lib/eet/Eet.h b/src/lib/eet/Eet.h
index b3451fa4fa..de56b18192 100644
--- a/src/lib/eet/Eet.h
+++ b/src/lib/eet/Eet.h
@@ -2063,6 +2063,26 @@ eet_identity_print(Eet_Key *key,
FILE *out);
/**
+ * Compare the identify certificate of an eet file against a stored one
+ *
+ * @param ef The file handle to check the identify of
+ * @param certificate_file The path to the certificate file
+ * @return EINA_TRUE if the certificates match, otherwise EINA_FALSE;
+ *
+ * The @p ef file handle mus be valid, and a signed file, otherwise
+ * checking will fail. The path to the certificate file must be a valid
+ * file path to a 'pem' format file (the same used for siging with
+ * eet_identity_open() as a certificate file).
+ *
+ * @warning You need to compile signature support in EET.
+ * @since 1.13
+ * @ingroup Eet_Cipher_Group
+ */
+EAPI Eina_Bool
+eet_identity_verify(Eet_File *ef,
+ const char *certificate_file);
+
+/**
* Get the x509 der certificate associated with an Eet_File. Will return NULL
* if the file is not signed.
*
diff --git a/src/lib/eet/eet_lib.c b/src/lib/eet/eet_lib.c
index daa6d3b897..ed610f6adc 100644
--- a/src/lib/eet/eet_lib.c
+++ b/src/lib/eet/eet_lib.c
@@ -1676,6 +1676,154 @@ eet_mode_get(Eet_File *ef)
return ef->mode;
}
+static const char *_b64_table =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+static Eina_Bool
+_b64_is(char c)
+{
+ const char *p;
+
+ if (!c) return EINA_FALSE;
+ p = strchr(_b64_table, c);
+ if (p >= _b64_table) return EINA_TRUE;
+ return EINA_FALSE;
+}
+
+static unsigned char
+_b64_val(char c)
+{
+ const char *p = strchr(_b64_table, c);
+ if (p) return p - _b64_table;
+ return 0;
+}
+
+static int
+_b64_dec(unsigned char *dst, const char *src, int len)
+{
+ unsigned char *p = dst;
+ *dst = 0;
+
+ if (!*src) return 0;
+ do
+ {
+ unsigned char a = _b64_val(src[0]);
+ unsigned char b = _b64_val(src[1]);
+ unsigned char c = _b64_val(src[2]);
+ unsigned char d = _b64_val(src[3]);
+
+ *p++ = (a << 2) | (b >> 4);
+ *p++ = (b << 4) | (c >> 2);
+ *p++ = (c << 6) | d;
+
+ if (!_b64_is(src[1]))
+ {
+ p -= 2;
+ break;
+ }
+ else if (!_b64_is(src[2]))
+ {
+ p -= 2;
+ break;
+ }
+ else if (!_b64_is(src[3]))
+ {
+ p--;
+ break;
+ }
+ src += 4;
+ while (*src && ((*src == 13) || (*src == 10))) src++;
+ }
+ while ((len -= 4));
+ *p = 0;
+ return (int)(p - dst);
+}
+
+static unsigned char *
+_base64_dec(const char *file, int *size_ret)
+{
+ char buf[4096], *p, *end;
+ unsigned char *data = NULL;
+ Eina_Binbuf *binbuf;
+ FILE *f;
+
+ f = fopen(file, "rb");
+ if (!f) return NULL;
+ binbuf = eina_binbuf_new();
+ if (!binbuf)
+ {
+ fclose(f);
+ return NULL;
+ }
+ while (fgets(buf, sizeof(buf) - 1, f))
+ {
+ buf[sizeof(buf) - 1] = 0;
+ // check where first invalid char in a line is
+ for (p = buf; *p; p++)
+ {
+ // this is the first invalid char
+ if ((*p != '=') && (!_b64_is(*p))) break;
+ }
+ end = p;
+ // go from line start to (but not including) first invalid char
+ if (((end - buf) > 0) && (((end - buf) % 4) == 0))
+ {
+ unsigned char *tmp = malloc((end - buf + 4) * 2);
+
+ if (tmp)
+ {
+ int len = _b64_dec(tmp, buf, end - buf);
+ char *str = malloc(end - buf + 1);
+ strncpy(str, buf, end - buf);
+ str[end - buf] = 0;
+ free(str);
+ eina_binbuf_append_length(binbuf, tmp, len);
+ free(tmp);
+ }
+ }
+ }
+ fclose(f);
+ // as long as data is less than a mb - we have a cert that is possibly ok
+ if (eina_binbuf_length_get(binbuf) < (1 * 1024 * 1024))
+ {
+ *size_ret = eina_binbuf_length_get(binbuf);
+ data = eina_binbuf_string_steal(binbuf);
+ }
+ eina_binbuf_free(binbuf);
+ return data;
+}
+
+EAPI Eina_Bool
+eet_identity_verify(Eet_File *ef,
+ const char *certificate_file)
+{
+ unsigned char *cert;
+ int cert_len;
+
+ if (eet_check_pointer(ef))
+ return EINA_FALSE;
+
+ if (!ef->x509_der)
+ return EINA_FALSE;
+
+ cert = _base64_dec(certificate_file, &cert_len);
+ if (!cert)
+ return EINA_FALSE;
+
+ if (cert_len != ef->x509_length)
+ {
+ free(cert);
+ return EINA_FALSE;
+ }
+ if (memcmp(ef->x509_der, cert, cert_len))
+ {
+ free(cert);
+ return EINA_FALSE;
+ }
+ free(cert);
+ return EINA_TRUE;
+}
+
EAPI const void *
eet_identity_x509(Eet_File *ef,
int *der_length)