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:
parent
151eeacec8
commit
8669ab8a98
|
@ -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.
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue