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
This commit is contained in:
Carsten Haitzler 2014-11-28 17:54:39 +09:00
parent 151eeacec8
commit 8669ab8a98
3 changed files with 171 additions and 0 deletions

View File

@ -2062,6 +2062,26 @@ EAPI void
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.

View File

@ -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)

View File

@ -1752,6 +1752,9 @@ START_TEST(eet_identity_simple)
ef = eet_open(file, EET_FILE_MODE_READ);
fail_if(!ef);
/* check that the certificates match */
fail_if(!eet_identity_verify(ef, _cert_pem));
test = eet_read(ef, "keys/tests", &size);
fail_if(!test);
fail_if(size != (int)strlen(buffer) + 1);