Replaced system SQLite with SQLCipher to support encrypted database

This commit is contained in:
Oleksii Zghurskyi
2025-06-07 18:11:17 +03:00
parent f4198d62a7
commit 177d74700f
534 changed files with 362771 additions and 21 deletions

View File

@@ -0,0 +1,28 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
/* SPDX-License-Identifier: Unlicense */
#include "tomcrypt_private.h"
/**
@file der_decode_sequence_ex.c
ASN.1 DER, decode a SEQUENCE, Tom St Denis
*/
#ifdef LTC_DER
/**
Decode a SEQUENCE
@param in The DER encoded input
@param inlen The size of the input
@param list The list of items to decode
@param outlen The number of items in the list
@param flags c.f. enum ltc_der_seq
@return CRYPT_OK on success
*/
int der_decode_sequence_ex(const unsigned char *in, unsigned long inlen,
ltc_asn1_list *list, unsigned long outlen, unsigned int flags)
{
return der_decode_custom_type_ex(in, inlen, NULL, list, outlen, flags);
}
#endif

View File

@@ -0,0 +1,546 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
/* SPDX-License-Identifier: Unlicense */
#include "tomcrypt_private.h"
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wconversion"
#pragma clang diagnostic ignored "-Wshorten-64-to-32"
/**
@file der_decode_sequence_flexi.c
ASN.1 DER, decode an array of ASN.1 types with a flexi parser, Tom St Denis
*/
#ifdef LTC_DER
static int s_new_element(ltc_asn1_list **l)
{
/* alloc new link */
if (*l == NULL) {
*l = XCALLOC(1, sizeof(ltc_asn1_list));
if (*l == NULL) {
return CRYPT_MEM;
}
} else {
(*l)->next = XCALLOC(1, sizeof(ltc_asn1_list));
if ((*l)->next == NULL) {
return CRYPT_MEM;
}
(*l)->next->prev = *l;
*l = (*l)->next;
}
return CRYPT_OK;
}
/**
ASN.1 DER Flexi(ble) decoder will decode arbitrary DER packets and create a linked list of the decoded elements.
@param in The input buffer
@param inlen [in/out] The length of the input buffer and on output the amount of decoded data
@param out [out] A pointer to the linked list
@param depth The depth/level of decoding recursion we've already reached
@return CRYPT_OK on success.
*/
static int s_der_decode_sequence_flexi(const unsigned char *in, unsigned long *inlen, ltc_asn1_list **out, unsigned long depth)
{
ltc_asn1_list *l;
unsigned long err, identifier, len, totlen, data_offset, id_len, len_len;
void *realloc_tmp;
LTC_ARGCHK(in != NULL);
LTC_ARGCHK(inlen != NULL);
LTC_ARGCHK(out != NULL);
l = NULL;
totlen = 0;
if (*inlen == 0) {
/* alloc new link */
if ((err = s_new_element(&l)) != CRYPT_OK) {
goto error;
}
}
/* scan the input and and get lengths and what not */
while (*inlen) {
/* alloc new link */
if ((err = s_new_element(&l)) != CRYPT_OK) {
goto error;
}
id_len = *inlen;
if ((err = der_decode_asn1_identifier(in, &id_len, l)) != CRYPT_OK) {
goto error;
}
/* read the type byte */
identifier = *in;
if (l->type != LTC_ASN1_EOL) {
/* fetch length */
len_len = *inlen - id_len;
#if defined(LTC_TEST_DBG)
data_offset = 666;
len = 0;
#endif
if ((err = der_decode_asn1_length(&in[id_len], &len_len, &len)) != CRYPT_OK) {
#if defined(LTC_TEST_DBG)
fprintf(stderr, "E1 %02lx: hl=%4lu l=%4lu - %s (%s)\n", identifier, data_offset, len, der_asn1_tag_to_string_map[l->tag], error_to_string(err));
#endif
goto error;
} else if (len > (*inlen - id_len - len_len)) {
err = CRYPT_INVALID_PACKET;
#if defined(LTC_TEST_DBG)
fprintf(stderr, "E2 %02lx: hl=%4lu l=%4lu - %s (%s)\n", identifier, data_offset, len, der_asn1_tag_to_string_map[l->tag], error_to_string(err));
#endif
goto error;
}
data_offset = id_len + len_len;
#if defined(LTC_TEST_DBG) && LTC_TEST_DBG > 1
if (l->type == LTC_ASN1_CUSTOM_TYPE && l->klass == LTC_ASN1_CL_CONTEXT_SPECIFIC) {
fprintf(stderr, "OK %02lx: hl=%4lu l=%4lu - Context Specific[%s %llu]\n", identifier, data_offset, len, der_asn1_pc_to_string_map[l->pc], l->tag);
} else {
fprintf(stderr, "OK %02lx: hl=%4lu l=%4lu - %s\n", identifier, data_offset, len, der_asn1_tag_to_string_map[l->tag]);
}
#endif
len += data_offset;
if (l->type == LTC_ASN1_CUSTOM_TYPE) {
/* Custom type, use the 'used' field to store the original identifier */
l->used = identifier;
if (l->pc == LTC_ASN1_PC_CONSTRUCTED) {
/* treat constructed elements like SEQUENCEs */
identifier = 0x20;
} else {
/* primitive elements are treated as opaque data */
identifier = 0x80;
}
}
} else {
/* Init this so gcc won't complain,
* as this case will only be hit when we
* can't decode the identifier so the
* switch-case should go to default anyway...
*/
data_offset = 0;
len = 0;
}
/* now switch on type */
switch (identifier) {
case 0x01: /* BOOLEAN */
if (l->type != LTC_ASN1_BOOLEAN) {
err = CRYPT_PK_ASN1_ERROR;
goto error;
}
/* init field */
l->size = 1;
l->data = XCALLOC(1, sizeof(int));
if ((err = der_decode_boolean(in, *inlen, l->data)) != CRYPT_OK) {
goto error;
}
if ((err = der_length_boolean(&len)) != CRYPT_OK) {
goto error;
}
break;
case 0x02: /* INTEGER */
if (l->type != LTC_ASN1_INTEGER) {
err = CRYPT_PK_ASN1_ERROR;
goto error;
}
/* init field */
l->size = 1;
if ((err = ltc_mp_init(&l->data)) != CRYPT_OK) {
goto error;
}
/* decode field */
if ((err = der_decode_integer(in, *inlen, l->data)) != CRYPT_OK) {
goto error;
}
/* calc length of object */
if ((err = der_length_integer(l->data, &len)) != CRYPT_OK) {
goto error;
}
break;
case 0x03: /* BIT */
if (l->type != LTC_ASN1_BIT_STRING) {
err = CRYPT_PK_ASN1_ERROR;
goto error;
}
/* init field */
l->size = len * 8; /* *8 because we store decoded bits one per char and they are encoded 8 per char. */
if ((l->data = XCALLOC(1, l->size)) == NULL) {
err = CRYPT_MEM;
goto error;
}
if ((err = der_decode_bit_string(in, *inlen, l->data, &l->size)) != CRYPT_OK) {
goto error;
}
if ((err = der_length_bit_string(l->size, &len)) != CRYPT_OK) {
goto error;
}
break;
case 0x04: /* OCTET */
if (l->type != LTC_ASN1_OCTET_STRING) {
err = CRYPT_PK_ASN1_ERROR;
goto error;
}
/* init field */
l->size = len;
if ((l->data = XCALLOC(1, l->size)) == NULL) {
err = CRYPT_MEM;
goto error;
}
if ((err = der_decode_octet_string(in, *inlen, l->data, &l->size)) != CRYPT_OK) {
goto error;
}
if ((err = der_length_octet_string(l->size, &len)) != CRYPT_OK) {
goto error;
}
break;
case 0x05: /* NULL */
if (l->type != LTC_ASN1_NULL) {
err = CRYPT_PK_ASN1_ERROR;
goto error;
}
/* valid NULL is 0x05 0x00 */
if (in[0] != 0x05 || in[1] != 0x00) {
err = CRYPT_INVALID_PACKET;
goto error;
}
/* simple to store ;-) */
l->data = NULL;
l->size = 0;
len = 2;
break;
case 0x06: /* OID */
if (l->type != LTC_ASN1_OBJECT_IDENTIFIER) {
err = CRYPT_PK_ASN1_ERROR;
goto error;
}
/* init field */
l->size = len;
if ((l->data = XCALLOC(len, sizeof(unsigned long))) == NULL) {
err = CRYPT_MEM;
goto error;
}
if ((err = der_decode_object_identifier(in, *inlen, l->data, &l->size)) != CRYPT_OK) {
goto error;
}
if ((err = der_length_object_identifier(l->data, l->size, &len)) != CRYPT_OK) {
goto error;
}
/* resize it to save a bunch of mem */
if ((realloc_tmp = XREALLOC(l->data, l->size * sizeof(unsigned long))) == NULL) {
/* out of heap but this is not an error */
break;
}
l->data = realloc_tmp;
break;
case 0x0C: /* UTF8 */
/* init field */
if (l->type != LTC_ASN1_UTF8_STRING) {
err = CRYPT_PK_ASN1_ERROR;
goto error;
}
l->size = len;
if ((l->data = XCALLOC(l->size, sizeof(wchar_t))) == NULL) {
err = CRYPT_MEM;
goto error;
}
if ((err = der_decode_utf8_string(in, *inlen, l->data, &l->size)) != CRYPT_OK) {
goto error;
}
if ((err = der_length_utf8_string(l->data, l->size, &len)) != CRYPT_OK) {
goto error;
}
break;
case 0x13: /* PRINTABLE */
if (l->type != LTC_ASN1_PRINTABLE_STRING) {
err = CRYPT_PK_ASN1_ERROR;
goto error;
}
/* init field */
l->size = len;
if ((l->data = XCALLOC(1, l->size)) == NULL) {
err = CRYPT_MEM;
goto error;
}
if ((err = der_decode_printable_string(in, *inlen, l->data, &l->size)) != CRYPT_OK) {
goto error;
}
if ((err = der_length_printable_string(l->data, l->size, &len)) != CRYPT_OK) {
goto error;
}
break;
case 0x14: /* TELETEXT */
if (l->type != LTC_ASN1_TELETEX_STRING) {
err = CRYPT_PK_ASN1_ERROR;
goto error;
}
/* init field */
l->size = len;
if ((l->data = XCALLOC(1, l->size)) == NULL) {
err = CRYPT_MEM;
goto error;
}
if ((err = der_decode_teletex_string(in, *inlen, l->data, &l->size)) != CRYPT_OK) {
goto error;
}
if ((err = der_length_teletex_string(l->data, l->size, &len)) != CRYPT_OK) {
goto error;
}
break;
case 0x16: /* IA5 */
if (l->type != LTC_ASN1_IA5_STRING) {
err = CRYPT_PK_ASN1_ERROR;
goto error;
}
/* init field */
l->size = len;
if ((l->data = XCALLOC(1, l->size)) == NULL) {
err = CRYPT_MEM;
goto error;
}
if ((err = der_decode_ia5_string(in, *inlen, l->data, &l->size)) != CRYPT_OK) {
goto error;
}
if ((err = der_length_ia5_string(l->data, l->size, &len)) != CRYPT_OK) {
goto error;
}
break;
case 0x17: /* UTC TIME */
if (l->type != LTC_ASN1_UTCTIME) {
err = CRYPT_PK_ASN1_ERROR;
goto error;
}
/* init field */
l->size = 1;
if ((l->data = XCALLOC(1, sizeof(ltc_utctime))) == NULL) {
err = CRYPT_MEM;
goto error;
}
len = *inlen;
if ((err = der_decode_utctime(in, &len, l->data)) != CRYPT_OK) {
goto error;
}
if ((err = der_length_utctime(l->data, &len)) != CRYPT_OK) {
goto error;
}
break;
case 0x18:
if (l->type != LTC_ASN1_GENERALIZEDTIME) {
err = CRYPT_PK_ASN1_ERROR;
goto error;
}
/* init field */
l->size = len;
if ((l->data = XCALLOC(1, sizeof(ltc_generalizedtime))) == NULL) {
err = CRYPT_MEM;
goto error;
}
if ((err = der_decode_generalizedtime(in, &len, l->data)) != CRYPT_OK) {
goto error;
}
if ((err = der_length_generalizedtime(l->data, &len)) != CRYPT_OK) {
goto error;
}
break;
case 0x20: /* Any CONSTRUCTED element that is neither SEQUENCE nor SET */
case 0x30: /* SEQUENCE */
case 0x31: /* SET */
/* init field */
if (identifier == 0x20) {
if (l->type != LTC_ASN1_CUSTOM_TYPE) {
err = CRYPT_PK_ASN1_ERROR;
goto error;
}
}
else if (identifier == 0x30) {
if (l->type != LTC_ASN1_SEQUENCE) {
err = CRYPT_PK_ASN1_ERROR;
goto error;
}
}
else {
if (l->type != LTC_ASN1_SET) {
err = CRYPT_PK_ASN1_ERROR;
goto error;
}
}
/* check that we don't go over the recursion limit */
if (depth > LTC_DER_MAX_RECURSION) {
err = CRYPT_PK_ASN1_ERROR;
goto error;
}
if ((l->data = XMALLOC(len)) == NULL) {
err = CRYPT_MEM;
goto error;
}
XMEMCPY(l->data, in, len);
l->size = len;
/* jump to the start of the data */
in += data_offset;
*inlen -= data_offset;
len -= data_offset;
/* save the decoded ASN.1 len */
len_len = len;
/* Sequence elements go as child */
if ((err = s_der_decode_sequence_flexi(in, &len, &(l->child), depth+1)) != CRYPT_OK) {
goto error;
}
if (len_len != len) {
err = CRYPT_PK_ASN1_ERROR;
goto error;
}
/* len update */
totlen += data_offset;
/* the flexi decoder can also do nothing, so make sure a child has been allocated */
if (l->child) {
/* link them up y0 */
l->child->parent = l;
}
break;
case 0x80: /* Context-specific */
if (l->type != LTC_ASN1_CUSTOM_TYPE) {
err = CRYPT_PK_ASN1_ERROR;
goto error;
}
if ((l->data = XCALLOC(1, len - data_offset)) == NULL) {
err = CRYPT_MEM;
goto error;
}
XMEMCPY(l->data, in + data_offset, len - data_offset);
l->size = len - data_offset;
break;
default:
/* invalid byte ... this is a soft error */
/* remove link */
if (l->prev) {
l = l->prev;
XFREE(l->next);
l->next = NULL;
}
goto outside;
}
/* advance pointers */
totlen += len;
in += len;
*inlen -= len;
}
outside:
/* in case we processed anything */
if (totlen) {
/* rewind l please */
while (l->prev != NULL || l->parent != NULL) {
if (l->parent != NULL) {
l = l->parent;
} else {
l = l->prev;
}
}
}
/* return */
*out = l;
*inlen = totlen;
return CRYPT_OK;
error:
/* free list */
der_sequence_free(l);
return err;
}
/**
ASN.1 DER Flexi(ble) decoder will decode arbitrary DER packets and create a linked list of the decoded elements.
@param in The input buffer
@param inlen [in/out] The length of the input buffer and on output the amount of decoded data
@param out [out] A pointer to the linked list
@return CRYPT_OK on success.
*/
int der_decode_sequence_flexi(const unsigned char *in, unsigned long *inlen, ltc_asn1_list **out)
{
return s_der_decode_sequence_flexi(in, inlen, out, 0);
}
#endif
#pragma clang diagnostic pop

View File

@@ -0,0 +1,184 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
/* SPDX-License-Identifier: Unlicense */
#include "tomcrypt_private.h"
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wconversion"
#pragma clang diagnostic ignored "-Wshorten-64-to-32"
/**
@file der_decode_sequence_multi.c
ASN.1 DER, decode a SEQUENCE, Tom St Denis
*/
#ifdef LTC_DER
/**
Decode a SEQUENCE type using a VA list
@param in Input buffer
@param inlen Length of input in octets
@param a1 Initialized argument list #1
@param a2 Initialized argument list #2 (copy of #1)
@param flags c.f. enum ltc_der_seq
@return CRYPT_OK on success
*/
static int s_der_decode_sequence_va(const unsigned char *in, unsigned long inlen, va_list a1, va_list a2, unsigned int flags)
{
int err;
ltc_asn1_type type;
unsigned long size, x;
void *data;
ltc_asn1_list *list;
LTC_ARGCHK(in != NULL);
/* get size of output that will be required */
x = 0;
for (;;) {
type = (ltc_asn1_type)va_arg(a1, int);
if (type == LTC_ASN1_EOL) {
break;
}
size = va_arg(a1, unsigned long);
data = va_arg(a1, void*);
LTC_UNUSED_PARAM(size);
LTC_UNUSED_PARAM(data);
switch (type) {
case LTC_ASN1_BOOLEAN:
case LTC_ASN1_INTEGER:
case LTC_ASN1_SHORT_INTEGER:
case LTC_ASN1_BIT_STRING:
case LTC_ASN1_OCTET_STRING:
case LTC_ASN1_NULL:
case LTC_ASN1_OBJECT_IDENTIFIER:
case LTC_ASN1_IA5_STRING:
case LTC_ASN1_PRINTABLE_STRING:
case LTC_ASN1_UTF8_STRING:
case LTC_ASN1_UTCTIME:
case LTC_ASN1_SET:
case LTC_ASN1_SETOF:
case LTC_ASN1_SEQUENCE:
case LTC_ASN1_CHOICE:
case LTC_ASN1_RAW_BIT_STRING:
case LTC_ASN1_TELETEX_STRING:
case LTC_ASN1_GENERALIZEDTIME:
++x;
break;
case LTC_ASN1_EOL:
case LTC_ASN1_CUSTOM_TYPE:
return CRYPT_INVALID_ARG;
}
}
/* allocate structure for x elements */
if (x == 0) {
return CRYPT_NOP;
}
list = XCALLOC(x, sizeof(*list));
if (list == NULL) {
return CRYPT_MEM;
}
/* fill in the structure */
x = 0;
for (;;) {
type = (ltc_asn1_type)va_arg(a2, int);
size = va_arg(a2, unsigned long);
data = va_arg(a2, void*);
if (type == LTC_ASN1_EOL) {
break;
}
switch (type) {
case LTC_ASN1_BOOLEAN:
case LTC_ASN1_INTEGER:
case LTC_ASN1_SHORT_INTEGER:
case LTC_ASN1_BIT_STRING:
case LTC_ASN1_OCTET_STRING:
case LTC_ASN1_NULL:
case LTC_ASN1_OBJECT_IDENTIFIER:
case LTC_ASN1_IA5_STRING:
case LTC_ASN1_PRINTABLE_STRING:
case LTC_ASN1_UTF8_STRING:
case LTC_ASN1_UTCTIME:
case LTC_ASN1_SEQUENCE:
case LTC_ASN1_SET:
case LTC_ASN1_SETOF:
case LTC_ASN1_CHOICE:
case LTC_ASN1_RAW_BIT_STRING:
case LTC_ASN1_TELETEX_STRING:
case LTC_ASN1_GENERALIZEDTIME:
LTC_SET_ASN1(list, x++, type, data, size);
break;
/* coverity[dead_error_line] */
case LTC_ASN1_EOL:
case LTC_ASN1_CUSTOM_TYPE:
break;
}
}
err = der_decode_sequence_ex(in, inlen, list, x, flags);
XFREE(list);
return err;
}
/**
Decode a SEQUENCE type using a VA list
@param in Input buffer
@param inlen Length of input in octets
@remark <...> is of the form <type, size, data> (int, unsigned long, void*)
@return CRYPT_OK on success
*/
int der_decode_sequence_multi(const unsigned char *in, unsigned long inlen, ...)
{
va_list a1, a2;
int err;
LTC_ARGCHK(in != NULL);
va_start(a1, inlen);
va_start(a2, inlen);
err = s_der_decode_sequence_va(in, inlen, a1, a2, LTC_DER_SEQ_SEQUENCE | LTC_DER_SEQ_RELAXED);
va_end(a2);
va_end(a1);
return err;
}
/**
Decode a SEQUENCE type using a VA list
@param in Input buffer
@param inlen Length of input in octets
@param flags c.f. enum ltc_der_seq
@remark <...> is of the form <type, size, data> (int, unsigned long, void*)
@return CRYPT_OK on success
*/
int der_decode_sequence_multi_ex(const unsigned char *in, unsigned long inlen, unsigned int flags, ...)
{
va_list a1, a2;
int err;
LTC_ARGCHK(in != NULL);
va_start(a1, flags);
va_start(a2, flags);
err = s_der_decode_sequence_va(in, inlen, a1, a2, flags);
va_end(a2);
va_end(a1);
return err;
}
#endif
#pragma clang diagnostic pop

View File

@@ -0,0 +1,202 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
/* SPDX-License-Identifier: Unlicense */
#include "tomcrypt_private.h"
/**
@file der_encode_sequence_ex.c
ASN.1 DER, encode a SEQUENCE, Tom St Denis
*/
#ifdef LTC_DER
/**
Encode a SEQUENCE
@param list The list of items to encode
@param inlen The number of items in the list
@param out [out] The destination
@param outlen [in/out] The size of the output
@param type_of LTC_ASN1_SEQUENCE or LTC_ASN1_SET/LTC_ASN1_SETOF
@return CRYPT_OK on success
*/
int der_encode_sequence_ex(const ltc_asn1_list *list, unsigned long inlen,
unsigned char *out, unsigned long *outlen, int type_of)
{
int err;
ltc_asn1_type type;
unsigned long size, x, y, z, i;
void *data;
LTC_ARGCHK(list != NULL);
LTC_ARGCHK(out != NULL);
LTC_ARGCHK(outlen != NULL);
/* get size of output that will be required */
y = 0; z = 0;
if (der_length_sequence_ex(list, inlen, &y, &z) != CRYPT_OK) return CRYPT_INVALID_ARG;
/* too big ? */
if (*outlen < y) {
*outlen = y;
err = CRYPT_BUFFER_OVERFLOW;
goto LBL_ERR;
}
/* store header */
x = 0;
out[x++] = (type_of == LTC_ASN1_SEQUENCE) ? 0x30 : 0x31;
y = *outlen - x;
if ((err = der_encode_asn1_length(z, &out[x], &y)) != CRYPT_OK) {
goto LBL_ERR;
}
x += y;
/* store data */
*outlen -= x;
for (i = 0; i < inlen; i++) {
type = list[i].type;
size = list[i].size;
data = list[i].data;
if (type == LTC_ASN1_EOL) {
break;
}
switch (type) {
case LTC_ASN1_BOOLEAN:
z = *outlen;
if ((err = der_encode_boolean(*((int *)data), out + x, &z)) != CRYPT_OK) {
goto LBL_ERR;
}
break;
case LTC_ASN1_INTEGER:
z = *outlen;
if ((err = der_encode_integer(data, out + x, &z)) != CRYPT_OK) {
goto LBL_ERR;
}
break;
case LTC_ASN1_SHORT_INTEGER:
z = *outlen;
if ((err = der_encode_short_integer(*((unsigned long*)data), out + x, &z)) != CRYPT_OK) {
goto LBL_ERR;
}
break;
case LTC_ASN1_BIT_STRING:
z = *outlen;
if ((err = der_encode_bit_string(data, size, out + x, &z)) != CRYPT_OK) {
goto LBL_ERR;
}
break;
case LTC_ASN1_RAW_BIT_STRING:
z = *outlen;
if ((err = der_encode_raw_bit_string(data, size, out + x, &z)) != CRYPT_OK) {
goto LBL_ERR;
}
break;
case LTC_ASN1_OCTET_STRING:
z = *outlen;
if ((err = der_encode_octet_string(data, size, out + x, &z)) != CRYPT_OK) {
goto LBL_ERR;
}
break;
case LTC_ASN1_NULL:
out[x] = 0x05;
out[x+1] = 0x00;
z = 2;
break;
case LTC_ASN1_OBJECT_IDENTIFIER:
z = *outlen;
if ((err = der_encode_object_identifier(data, size, out + x, &z)) != CRYPT_OK) {
goto LBL_ERR;
}
break;
case LTC_ASN1_IA5_STRING:
z = *outlen;
if ((err = der_encode_ia5_string(data, size, out + x, &z)) != CRYPT_OK) {
goto LBL_ERR;
}
break;
case LTC_ASN1_PRINTABLE_STRING:
z = *outlen;
if ((err = der_encode_printable_string(data, size, out + x, &z)) != CRYPT_OK) {
goto LBL_ERR;
}
break;
case LTC_ASN1_UTF8_STRING:
z = *outlen;
if ((err = der_encode_utf8_string(data, size, out + x, &z)) != CRYPT_OK) {
goto LBL_ERR;
}
break;
case LTC_ASN1_UTCTIME:
z = *outlen;
if ((err = der_encode_utctime(data, out + x, &z)) != CRYPT_OK) {
goto LBL_ERR;
}
break;
case LTC_ASN1_GENERALIZEDTIME:
z = *outlen;
if ((err = der_encode_generalizedtime(data, out + x, &z)) != CRYPT_OK) {
goto LBL_ERR;
}
break;
case LTC_ASN1_SET:
z = *outlen;
if ((err = der_encode_set(data, size, out + x, &z)) != CRYPT_OK) {
goto LBL_ERR;
}
break;
case LTC_ASN1_SETOF:
z = *outlen;
if ((err = der_encode_setof(data, size, out + x, &z)) != CRYPT_OK) {
goto LBL_ERR;
}
break;
case LTC_ASN1_SEQUENCE:
z = *outlen;
if ((err = der_encode_sequence_ex(data, size, out + x, &z, type)) != CRYPT_OK) {
goto LBL_ERR;
}
break;
case LTC_ASN1_CUSTOM_TYPE:
z = *outlen;
if ((err = der_encode_custom_type(&list[i], out + x, &z)) != CRYPT_OK) {
goto LBL_ERR;
}
break;
case LTC_ASN1_CHOICE:
case LTC_ASN1_EOL:
case LTC_ASN1_TELETEX_STRING:
err = CRYPT_INVALID_ARG;
goto LBL_ERR;
}
x += z;
*outlen -= z;
}
*outlen = x;
err = CRYPT_OK;
LBL_ERR:
return err;
}
#endif

View File

@@ -0,0 +1,142 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
/* SPDX-License-Identifier: Unlicense */
#include "tomcrypt_private.h"
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wconversion"
#pragma clang diagnostic ignored "-Wshorten-64-to-32"
/**
@file der_encode_sequence_multi.c
ASN.1 DER, encode a SEQUENCE, Tom St Denis
*/
#ifdef LTC_DER
/**
Encode a SEQUENCE type using a VA list
@param out [out] Destination for data
@param outlen [in/out] Length of buffer and resulting length of output
@remark <...> is of the form <type, size, data> (int, unsigned long, void*)
@return CRYPT_OK on success
*/
int der_encode_sequence_multi(unsigned char *out, unsigned long *outlen, ...)
{
int err;
ltc_asn1_type type;
unsigned long size, x;
void *data;
va_list args;
ltc_asn1_list *list;
LTC_ARGCHK(out != NULL);
LTC_ARGCHK(outlen != NULL);
/* get size of output that will be required */
va_start(args, outlen);
x = 0;
for (;;) {
type = (ltc_asn1_type)va_arg(args, int);
if (type == LTC_ASN1_EOL) {
break;
}
size = va_arg(args, unsigned long);
data = va_arg(args, void*);
LTC_UNUSED_PARAM(size);
LTC_UNUSED_PARAM(data);
switch (type) {
case LTC_ASN1_BOOLEAN:
case LTC_ASN1_INTEGER:
case LTC_ASN1_SHORT_INTEGER:
case LTC_ASN1_BIT_STRING:
case LTC_ASN1_OCTET_STRING:
case LTC_ASN1_NULL:
case LTC_ASN1_OBJECT_IDENTIFIER:
case LTC_ASN1_IA5_STRING:
case LTC_ASN1_PRINTABLE_STRING:
case LTC_ASN1_UTF8_STRING:
case LTC_ASN1_UTCTIME:
case LTC_ASN1_SEQUENCE:
case LTC_ASN1_SET:
case LTC_ASN1_SETOF:
case LTC_ASN1_RAW_BIT_STRING:
case LTC_ASN1_GENERALIZEDTIME:
++x;
break;
case LTC_ASN1_CHOICE:
case LTC_ASN1_CUSTOM_TYPE:
case LTC_ASN1_EOL:
case LTC_ASN1_TELETEX_STRING:
va_end(args);
return CRYPT_INVALID_ARG;
}
}
va_end(args);
/* allocate structure for x elements */
if (x == 0) {
return CRYPT_NOP;
}
list = XCALLOC(x, sizeof(*list));
if (list == NULL) {
return CRYPT_MEM;
}
/* fill in the structure */
va_start(args, outlen);
x = 0;
for (;;) {
type = (ltc_asn1_type)va_arg(args, int);
if (type == LTC_ASN1_EOL) {
break;
}
size = va_arg(args, unsigned long);
data = va_arg(args, void*);
switch (type) {
case LTC_ASN1_BOOLEAN:
case LTC_ASN1_INTEGER:
case LTC_ASN1_SHORT_INTEGER:
case LTC_ASN1_BIT_STRING:
case LTC_ASN1_OCTET_STRING:
case LTC_ASN1_NULL:
case LTC_ASN1_OBJECT_IDENTIFIER:
case LTC_ASN1_IA5_STRING:
case LTC_ASN1_PRINTABLE_STRING:
case LTC_ASN1_UTF8_STRING:
case LTC_ASN1_UTCTIME:
case LTC_ASN1_SEQUENCE:
case LTC_ASN1_SET:
case LTC_ASN1_SETOF:
case LTC_ASN1_RAW_BIT_STRING:
case LTC_ASN1_GENERALIZEDTIME:
LTC_SET_ASN1(list, x++, type, data, size);
break;
case LTC_ASN1_CHOICE:
case LTC_ASN1_CUSTOM_TYPE:
case LTC_ASN1_EOL:
case LTC_ASN1_TELETEX_STRING:
va_end(args);
err = CRYPT_INVALID_ARG;
goto LBL_ERR;
}
}
va_end(args);
err = der_encode_sequence(list, x, out, outlen);
LBL_ERR:
XFREE(list);
return err;
}
#endif
#pragma clang diagnostic pop

View File

@@ -0,0 +1,38 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
/* SPDX-License-Identifier: Unlicense */
#include "tomcrypt_private.h"
/**
@file der_length_sequence.c
ASN.1 DER, length a SEQUENCE, Tom St Denis
*/
#ifdef LTC_DER
/**
Get the length of a DER sequence
@param list The sequences of items in the SEQUENCE
@param inlen The number of items
@param outlen [out] The length required in octets to store it
@return CRYPT_OK on success
*/
int der_flexi_sequence_cmp(const ltc_asn1_list *flexi, der_flexi_check *check)
{
ltc_asn1_list *cur;
if (flexi->type != LTC_ASN1_SEQUENCE) {
return CRYPT_INVALID_PACKET;
}
cur = flexi->child;
while(check->t != LTC_ASN1_EOL) {
if (!LTC_ASN1_IS_TYPE(cur, check->t)) {
return CRYPT_INVALID_PACKET;
}
if (check->pp != NULL) *check->pp = cur;
cur = cur->next;
check++;
}
return CRYPT_OK;
}
#endif

View File

@@ -0,0 +1,179 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
/* SPDX-License-Identifier: Unlicense */
#include "tomcrypt_private.h"
/**
@file der_length_sequence.c
ASN.1 DER, length a SEQUENCE, Tom St Denis
*/
#ifdef LTC_DER
/**
Get the length of a DER sequence
@param list The sequences of items in the SEQUENCE
@param inlen The number of items
@param outlen [out] The length required in octets to store it
@return CRYPT_OK on success
*/
int der_length_sequence(const ltc_asn1_list *list, unsigned long inlen,
unsigned long *outlen)
{
return der_length_sequence_ex(list, inlen, outlen, NULL);
}
int der_length_sequence_ex(const ltc_asn1_list *list, unsigned long inlen,
unsigned long *outlen, unsigned long *payloadlen)
{
int err;
ltc_asn1_type type;
unsigned long size, x, y, i;
void *data;
LTC_ARGCHK(list != NULL);
LTC_ARGCHK(outlen != NULL);
/* get size of output that will be required */
y = 0;
for (i = 0; i < inlen; i++) {
type = list[i].type;
size = list[i].size;
data = list[i].data;
if (type == LTC_ASN1_EOL) {
break;
}
/* some items may be optional during import */
if (!list[i].used && list[i].optional) continue;
switch (type) {
case LTC_ASN1_BOOLEAN:
if ((err = der_length_boolean(&x)) != CRYPT_OK) {
goto LBL_ERR;
}
y += x;
break;
case LTC_ASN1_INTEGER:
if ((err = der_length_integer(data, &x)) != CRYPT_OK) {
goto LBL_ERR;
}
y += x;
break;
case LTC_ASN1_SHORT_INTEGER:
if ((err = der_length_short_integer(*((unsigned long *)data), &x)) != CRYPT_OK) {
goto LBL_ERR;
}
y += x;
break;
case LTC_ASN1_BIT_STRING:
case LTC_ASN1_RAW_BIT_STRING:
if ((err = der_length_bit_string(size, &x)) != CRYPT_OK) {
goto LBL_ERR;
}
y += x;
break;
case LTC_ASN1_OCTET_STRING:
if ((err = der_length_octet_string(size, &x)) != CRYPT_OK) {
goto LBL_ERR;
}
y += x;
break;
case LTC_ASN1_NULL:
y += 2;
break;
case LTC_ASN1_OBJECT_IDENTIFIER:
if ((err = der_length_object_identifier(data, size, &x)) != CRYPT_OK) {
goto LBL_ERR;
}
y += x;
break;
case LTC_ASN1_IA5_STRING:
if ((err = der_length_ia5_string(data, size, &x)) != CRYPT_OK) {
goto LBL_ERR;
}
y += x;
break;
case LTC_ASN1_TELETEX_STRING:
if ((err = der_length_teletex_string(data, size, &x)) != CRYPT_OK) {
goto LBL_ERR;
}
y += x;
break;
case LTC_ASN1_PRINTABLE_STRING:
if ((err = der_length_printable_string(data, size, &x)) != CRYPT_OK) {
goto LBL_ERR;
}
y += x;
break;
case LTC_ASN1_UTCTIME:
if ((err = der_length_utctime(data, &x)) != CRYPT_OK) {
goto LBL_ERR;
}
y += x;
break;
case LTC_ASN1_GENERALIZEDTIME:
if ((err = der_length_generalizedtime(data, &x)) != CRYPT_OK) {
goto LBL_ERR;
}
y += x;
break;
case LTC_ASN1_UTF8_STRING:
if ((err = der_length_utf8_string(data, size, &x)) != CRYPT_OK) {
goto LBL_ERR;
}
y += x;
break;
case LTC_ASN1_CUSTOM_TYPE:
if ((err = der_length_custom_type(&list[i], &x, NULL)) != CRYPT_OK) {
goto LBL_ERR;
}
y += x;
break;
case LTC_ASN1_SET:
case LTC_ASN1_SETOF:
case LTC_ASN1_SEQUENCE:
if ((err = der_length_sequence(data, size, &x)) != CRYPT_OK) {
goto LBL_ERR;
}
y += x;
break;
case LTC_ASN1_CHOICE:
case LTC_ASN1_EOL:
err = CRYPT_INVALID_ARG;
goto LBL_ERR;
}
}
if ((err = der_length_asn1_length(y, &x)) != CRYPT_OK) {
goto LBL_ERR;
}
if (payloadlen != NULL) {
*payloadlen = y;
}
/* store size */
*outlen = y + x + 1;
err = CRYPT_OK;
LBL_ERR:
return err;
}
#endif

View File

@@ -0,0 +1,53 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
/* SPDX-License-Identifier: Unlicense */
#include "tomcrypt_private.h"
/**
@file der_sequence_free.c
ASN.1 DER, free's a structure allocated by der_decode_sequence_flexi(), Tom St Denis
*/
#ifdef LTC_DER
/**
Free memory allocated by der_decode_sequence_flexi()
@param in The list to free
*/
void der_sequence_free(ltc_asn1_list *in)
{
ltc_asn1_list *l;
if (!in) return;
/* walk to the start of the chain */
while (in->prev != NULL || in->parent != NULL) {
if (in->parent != NULL) {
in = in->parent;
} else {
in = in->prev;
}
}
/* now walk the list and free stuff */
while (in != NULL) {
/* is there a child? */
if (in->child) {
/* disconnect */
in->child->parent = NULL;
der_sequence_free(in->child);
}
switch (in->type) {
case LTC_ASN1_SETOF: break;
case LTC_ASN1_INTEGER : if (in->data != NULL) { ltc_mp_clear(in->data); } break;
default : if (in->data != NULL) { XFREE(in->data); }
}
/* move to next and free current */
l = in->next;
XFREE(in);
in = l;
}
}
#endif

View File

@@ -0,0 +1,40 @@
/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
/* SPDX-License-Identifier: Unlicense */
#include "tomcrypt_private.h"
/**
@file der_sequence_shrink.c
Free memory allocated for CONSTRUCTED, SET or SEQUENCE elements by der_decode_sequence_flexi(), Steffen Jaeckel
*/
#ifdef LTC_DER
/**
Free memory allocated for CONSTRUCTED,
SET or SEQUENCE elements by der_decode_sequence_flexi()
@param in The list to shrink
*/
void der_sequence_shrink(ltc_asn1_list *in)
{
if (!in) return;
/* now walk the list and free stuff */
while (in != NULL) {
/* is there a child? */
if (in->child) {
der_sequence_shrink(in->child);
}
switch (in->type) {
case LTC_ASN1_CUSTOM_TYPE:
case LTC_ASN1_SET:
case LTC_ASN1_SEQUENCE : if (in->data != NULL) { XFREE(in->data); in->data = NULL; } break;
default: break;
}
/* move to next and free current */
in = in->next;
}
}
#endif