add required ASN.1 custom-types functions
This commit is contained in:
parent
1b3a757345
commit
0d02137a8e
@ -617,6 +617,18 @@ int der_decode_sequence_ex(const unsigned char *in, unsigned long inlen,
|
||||
int der_length_sequence(ltc_asn1_list *list, unsigned long inlen,
|
||||
unsigned long *outlen);
|
||||
|
||||
|
||||
/* Custom-types */
|
||||
int der_encode_custom_type(const ltc_asn1_list *root,
|
||||
unsigned char *out, unsigned long *outlen);
|
||||
|
||||
int der_decode_custom_type(const unsigned char *in, unsigned long inlen,
|
||||
ltc_asn1_list *root);
|
||||
|
||||
int der_length_custom_type(const ltc_asn1_list *root,
|
||||
unsigned long *outlen,
|
||||
unsigned long *payloadlen);
|
||||
|
||||
#ifdef LTC_SOURCE
|
||||
/* internal helper functions */
|
||||
int der_encode_asn1_identifier(const ltc_asn1_list *id, unsigned char *out, unsigned long *outlen);
|
||||
|
339
src/pk/asn1/der/custom_type/der_decode_custom_type.c
Normal file
339
src/pk/asn1/der/custom_type/der_decode_custom_type.c
Normal file
@ -0,0 +1,339 @@
|
||||
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
|
||||
*
|
||||
* LibTomCrypt is a library that provides various cryptographic
|
||||
* algorithms in a highly modular and flexible manner.
|
||||
*
|
||||
* The library is free for all purposes without any express
|
||||
* guarantee it works.
|
||||
*/
|
||||
#include "tomcrypt.h"
|
||||
|
||||
|
||||
/**
|
||||
@file der_decode_custom_type.c
|
||||
ASN.1 DER, decode a Custom type, Steffen Jaeckel
|
||||
*/
|
||||
|
||||
#ifdef LTC_DER
|
||||
|
||||
/**
|
||||
Decode a Custom type
|
||||
@param in The DER encoded input
|
||||
@param inlen The size of the input
|
||||
@param root The item that defines the custom type to decode
|
||||
@return CRYPT_OK on success
|
||||
*/
|
||||
int der_decode_custom_type(const unsigned char *in, unsigned long inlen,
|
||||
ltc_asn1_list *root)
|
||||
{
|
||||
int err, i;
|
||||
ltc_asn1_type type;
|
||||
ltc_asn1_list ident, *list;
|
||||
unsigned long size, x, y, z, blksize, outlen;
|
||||
unsigned char* in_new = NULL;
|
||||
void *data;
|
||||
|
||||
LTC_ARGCHK(in != NULL);
|
||||
LTC_ARGCHK(root != NULL);
|
||||
|
||||
if (root->type != LTC_ASN1_CUSTOM_TYPE) {
|
||||
return CRYPT_INVALID_PACKET;
|
||||
}
|
||||
/* get blk size */
|
||||
if (inlen < 2) {
|
||||
return CRYPT_INVALID_PACKET;
|
||||
}
|
||||
|
||||
/* Alloc a copy of the data for primitive handling. */
|
||||
if (root->pc == LTC_ASN1_PC_PRIMITIVE) {
|
||||
in_new = XMALLOC(inlen);
|
||||
if (in_new == NULL) {
|
||||
return CRYPT_MEM;
|
||||
}
|
||||
XMEMCPY(in_new, in, inlen);
|
||||
in = in_new;
|
||||
}
|
||||
|
||||
x = 0;
|
||||
y = inlen;
|
||||
if ((err = der_decode_asn1_identifier(in, &y, &ident)) != CRYPT_OK) {
|
||||
goto LBL_ERR;
|
||||
}
|
||||
if ((ident.type != root->type) ||
|
||||
(ident.class != root->class) ||
|
||||
(ident.pc != root->pc) ||
|
||||
(ident.tag != root->tag)) {
|
||||
err = CRYPT_INVALID_PACKET;
|
||||
goto LBL_ERR;
|
||||
}
|
||||
x += y;
|
||||
|
||||
list = root->data;
|
||||
outlen = root->size;
|
||||
|
||||
if (root->pc == LTC_ASN1_PC_PRIMITIVE) {
|
||||
if (der_asn1_type_to_identifier_map[list[0].type] == -1) {
|
||||
err = CRYPT_INVALID_PACKET;
|
||||
goto LBL_ERR;
|
||||
}
|
||||
x -= 1;
|
||||
in_new[x] = (unsigned char)der_asn1_type_to_identifier_map[list[0].type];
|
||||
blksize = inlen - x;
|
||||
} else {
|
||||
y = inlen - x;
|
||||
if ((err = der_decode_asn1_length(&in[x], &y, &blksize)) != CRYPT_OK) {
|
||||
goto LBL_ERR;
|
||||
}
|
||||
x += y;
|
||||
}
|
||||
|
||||
/* would this blksize overflow? */
|
||||
if (x + blksize > inlen) {
|
||||
err = CRYPT_INVALID_PACKET;
|
||||
goto LBL_ERR;
|
||||
}
|
||||
|
||||
/* mark all as unused */
|
||||
for (i = 0; i < (int)outlen; i++) {
|
||||
list[i].used = 0;
|
||||
}
|
||||
|
||||
/* ok read data */
|
||||
inlen = blksize;
|
||||
for (i = 0; i < (int)outlen; i++) {
|
||||
z = 0;
|
||||
type = list[i].type;
|
||||
size = list[i].size;
|
||||
data = list[i].data;
|
||||
|
||||
if (type == LTC_ASN1_EOL) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (root->pc == LTC_ASN1_PC_PRIMITIVE && i != 0) {
|
||||
err = CRYPT_PK_ASN1_ERROR;
|
||||
goto LBL_ERR;
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case LTC_ASN1_BOOLEAN:
|
||||
z = inlen;
|
||||
if ((err = der_decode_boolean(in + x, z, ((int *)data))) != CRYPT_OK) {
|
||||
goto LBL_ERR;
|
||||
}
|
||||
if ((err = der_length_boolean(&z)) != CRYPT_OK) {
|
||||
goto LBL_ERR;
|
||||
}
|
||||
break;
|
||||
|
||||
case LTC_ASN1_INTEGER:
|
||||
z = inlen;
|
||||
if ((err = der_decode_integer(in + x, z, data)) != CRYPT_OK) {
|
||||
goto LBL_ERR;
|
||||
}
|
||||
if ((err = der_length_integer(data, &z)) != CRYPT_OK) {
|
||||
goto LBL_ERR;
|
||||
}
|
||||
break;
|
||||
|
||||
case LTC_ASN1_SHORT_INTEGER:
|
||||
z = inlen;
|
||||
if ((err = der_decode_short_integer(in + x, z, data)) != CRYPT_OK) {
|
||||
goto LBL_ERR;
|
||||
}
|
||||
if ((err = der_length_short_integer(((unsigned long*)data)[0], &z)) != CRYPT_OK) {
|
||||
goto LBL_ERR;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case LTC_ASN1_BIT_STRING:
|
||||
z = inlen;
|
||||
if ((err = der_decode_bit_string(in + x, z, data, &size)) != CRYPT_OK) {
|
||||
goto LBL_ERR;
|
||||
}
|
||||
list[i].size = size;
|
||||
if ((err = der_length_bit_string(size, &z)) != CRYPT_OK) {
|
||||
goto LBL_ERR;
|
||||
}
|
||||
break;
|
||||
|
||||
case LTC_ASN1_RAW_BIT_STRING:
|
||||
z = inlen;
|
||||
if ((err = der_decode_raw_bit_string(in + x, z, data, &size)) != CRYPT_OK) {
|
||||
goto LBL_ERR;
|
||||
}
|
||||
list[i].size = size;
|
||||
if ((err = der_length_bit_string(size, &z)) != CRYPT_OK) {
|
||||
goto LBL_ERR;
|
||||
}
|
||||
break;
|
||||
|
||||
case LTC_ASN1_OCTET_STRING:
|
||||
z = inlen;
|
||||
if ((err = der_decode_octet_string(in + x, z, data, &size)) != CRYPT_OK) {
|
||||
goto LBL_ERR;
|
||||
}
|
||||
list[i].size = size;
|
||||
if ((err = der_length_octet_string(size, &z)) != CRYPT_OK) {
|
||||
goto LBL_ERR;
|
||||
}
|
||||
break;
|
||||
|
||||
case LTC_ASN1_NULL:
|
||||
if (inlen < 2 || in[x] != 0x05 || in[x+1] != 0x00) {
|
||||
err = CRYPT_INVALID_PACKET;
|
||||
goto LBL_ERR;
|
||||
}
|
||||
z = 2;
|
||||
break;
|
||||
|
||||
case LTC_ASN1_OBJECT_IDENTIFIER:
|
||||
z = inlen;
|
||||
if ((err = der_decode_object_identifier(in + x, z, data, &size)) != CRYPT_OK) {
|
||||
goto LBL_ERR;
|
||||
}
|
||||
list[i].size = size;
|
||||
if ((err = der_length_object_identifier(data, size, &z)) != CRYPT_OK) {
|
||||
goto LBL_ERR;
|
||||
}
|
||||
break;
|
||||
|
||||
case LTC_ASN1_TELETEX_STRING:
|
||||
z = inlen;
|
||||
if ((err = der_decode_teletex_string(in + x, z, data, &size)) != CRYPT_OK) {
|
||||
goto LBL_ERR;
|
||||
}
|
||||
list[i].size = size;
|
||||
if ((err = der_length_teletex_string(data, size, &z)) != CRYPT_OK) {
|
||||
goto LBL_ERR;
|
||||
}
|
||||
break;
|
||||
|
||||
case LTC_ASN1_IA5_STRING:
|
||||
z = inlen;
|
||||
if ((err = der_decode_ia5_string(in + x, z, data, &size)) != CRYPT_OK) {
|
||||
goto LBL_ERR;
|
||||
}
|
||||
list[i].size = size;
|
||||
if ((err = der_length_ia5_string(data, size, &z)) != CRYPT_OK) {
|
||||
goto LBL_ERR;
|
||||
}
|
||||
break;
|
||||
|
||||
case LTC_ASN1_PRINTABLE_STRING:
|
||||
z = inlen;
|
||||
if ((err = der_decode_printable_string(in + x, z, data, &size)) != CRYPT_OK) {
|
||||
goto LBL_ERR;
|
||||
}
|
||||
list[i].size = size;
|
||||
if ((err = der_length_printable_string(data, size, &z)) != CRYPT_OK) {
|
||||
goto LBL_ERR;
|
||||
}
|
||||
break;
|
||||
|
||||
case LTC_ASN1_UTF8_STRING:
|
||||
z = inlen;
|
||||
if ((err = der_decode_utf8_string(in + x, z, data, &size)) != CRYPT_OK) {
|
||||
goto LBL_ERR;
|
||||
}
|
||||
list[i].size = size;
|
||||
if ((err = der_length_utf8_string(data, size, &z)) != CRYPT_OK) {
|
||||
goto LBL_ERR;
|
||||
}
|
||||
break;
|
||||
|
||||
case LTC_ASN1_UTCTIME:
|
||||
z = inlen;
|
||||
if ((err = der_decode_utctime(in + x, &z, data)) != CRYPT_OK) {
|
||||
goto LBL_ERR;
|
||||
}
|
||||
break;
|
||||
|
||||
case LTC_ASN1_GENERALIZEDTIME:
|
||||
z = inlen;
|
||||
if ((err = der_decode_generalizedtime(in + x, &z, data)) != CRYPT_OK) {
|
||||
goto LBL_ERR;
|
||||
}
|
||||
break;
|
||||
|
||||
case LTC_ASN1_SET:
|
||||
z = inlen;
|
||||
if ((err = der_decode_set(in + x, z, data, size)) != CRYPT_OK) {
|
||||
goto LBL_ERR;
|
||||
}
|
||||
if ((err = der_length_sequence(data, size, &z)) != CRYPT_OK) {
|
||||
goto LBL_ERR;
|
||||
}
|
||||
break;
|
||||
|
||||
case LTC_ASN1_SETOF:
|
||||
case LTC_ASN1_SEQUENCE:
|
||||
/* detect if we have the right type */
|
||||
if ((type == LTC_ASN1_SETOF && (in[x] & 0x3F) != 0x31) || (type == LTC_ASN1_SEQUENCE && (in[x] & 0x3F) != 0x30)) {
|
||||
err = CRYPT_INVALID_PACKET;
|
||||
goto LBL_ERR;
|
||||
}
|
||||
|
||||
z = inlen;
|
||||
if ((err = der_decode_sequence(in + x, z, data, size)) != CRYPT_OK) {
|
||||
goto LBL_ERR;
|
||||
}
|
||||
if ((err = der_length_sequence(data, size, &z)) != CRYPT_OK) {
|
||||
goto LBL_ERR;
|
||||
}
|
||||
break;
|
||||
|
||||
case LTC_ASN1_CUSTOM_TYPE:
|
||||
z = inlen;
|
||||
if ((err = der_decode_custom_type(in + x, z, &list[i])) != CRYPT_OK) {
|
||||
goto LBL_ERR;
|
||||
}
|
||||
if ((err = der_length_custom_type(&list[i], &z, NULL)) != CRYPT_OK) {
|
||||
goto LBL_ERR;
|
||||
}
|
||||
break;
|
||||
|
||||
case LTC_ASN1_CHOICE:
|
||||
z = inlen;
|
||||
if ((err = der_decode_choice(in + x, &z, data, size)) != CRYPT_OK) {
|
||||
goto LBL_ERR;
|
||||
}
|
||||
break;
|
||||
|
||||
case LTC_ASN1_CONSTRUCTED:
|
||||
case LTC_ASN1_CONTEXT_SPECIFIC:
|
||||
case LTC_ASN1_EOL:
|
||||
err = CRYPT_INVALID_ARG;
|
||||
goto LBL_ERR;
|
||||
}
|
||||
x += z;
|
||||
inlen -= z;
|
||||
list[i].used = 1;
|
||||
}
|
||||
|
||||
for (i = 0; i < (int)outlen; i++) {
|
||||
if (list[i].used == 0 && list[i].optional == 0) {
|
||||
err = CRYPT_INVALID_PACKET;
|
||||
goto LBL_ERR;
|
||||
}
|
||||
}
|
||||
|
||||
if (inlen == 0) {
|
||||
err = CRYPT_OK;
|
||||
} else {
|
||||
err = CRYPT_INPUT_TOO_LONG;
|
||||
}
|
||||
|
||||
LBL_ERR:
|
||||
if (in_new != NULL) {
|
||||
XFREE(in_new);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* ref: $Format:%D$ */
|
||||
/* git commit: $Format:%H$ */
|
||||
/* commit time: $Format:%ai$ */
|
234
src/pk/asn1/der/custom_type/der_encode_custom_type.c
Normal file
234
src/pk/asn1/der/custom_type/der_encode_custom_type.c
Normal file
@ -0,0 +1,234 @@
|
||||
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
|
||||
*
|
||||
* LibTomCrypt is a library that provides various cryptographic
|
||||
* algorithms in a highly modular and flexible manner.
|
||||
*
|
||||
* The library is free for all purposes without any express
|
||||
* guarantee it works.
|
||||
*/
|
||||
#include "tomcrypt.h"
|
||||
|
||||
|
||||
/**
|
||||
@file der_encode_custom_type.c
|
||||
ASN.1 DER, encode a Custom Type, Steffen Jaeckel
|
||||
*/
|
||||
|
||||
#ifdef LTC_DER
|
||||
|
||||
/**
|
||||
Encode a Custom Type
|
||||
|
||||
This function is a bit special compared to the others, as it requires the
|
||||
root-ltc_asn1_list where the type is defined.
|
||||
|
||||
@param root The root of the list of items to encode
|
||||
@param out [out] The destination
|
||||
@param outlen [in/out] The size of the output
|
||||
@return CRYPT_OK on success
|
||||
*/
|
||||
int der_encode_custom_type(const ltc_asn1_list *root,
|
||||
unsigned char *out, unsigned long *outlen)
|
||||
{
|
||||
int err;
|
||||
ltc_asn1_type type;
|
||||
ltc_asn1_list *list;
|
||||
unsigned long size, x, y, z, i, inlen, id_len;
|
||||
void *data;
|
||||
|
||||
LTC_ARGCHK(root != NULL);
|
||||
LTC_ARGCHK(out != NULL);
|
||||
LTC_ARGCHK(outlen != NULL);
|
||||
|
||||
/* get size of output that will be required */
|
||||
y = 0; z = 0;
|
||||
if ((err = der_length_custom_type(root, &y, &z)) != CRYPT_OK) return CRYPT_INVALID_ARG;
|
||||
|
||||
/* too big ? */
|
||||
if (*outlen < y) {
|
||||
*outlen = y;
|
||||
err = CRYPT_BUFFER_OVERFLOW;
|
||||
goto LBL_ERR;
|
||||
}
|
||||
|
||||
/* get length of the identifier, so we know the offset where to start writing */
|
||||
if ((err = der_length_asn1_identifier(root, &id_len)) != CRYPT_OK) return CRYPT_INVALID_ARG;
|
||||
x = id_len;
|
||||
|
||||
|
||||
if (root->pc == LTC_ASN1_PC_PRIMITIVE) {
|
||||
/* In case it's a PRIMITIVE type we encode directly to the output
|
||||
* but leave space for a potentially longer identifier as it will
|
||||
* simply be replaced afterwards.
|
||||
*/
|
||||
x -= 1;
|
||||
} else {
|
||||
/* store length, identifier will be added later */
|
||||
y = *outlen - x;
|
||||
if ((err = der_encode_asn1_length(z, &out[x], &y)) != CRYPT_OK) {
|
||||
goto LBL_ERR;
|
||||
}
|
||||
x += y;
|
||||
}
|
||||
|
||||
list = root->data;
|
||||
inlen = root->size;
|
||||
/* 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_CONSTRUCTED:
|
||||
case LTC_ASN1_CONTEXT_SPECIFIC:
|
||||
case LTC_ASN1_EOL:
|
||||
case LTC_ASN1_TELETEX_STRING:
|
||||
err = CRYPT_INVALID_ARG;
|
||||
goto LBL_ERR;
|
||||
}
|
||||
|
||||
|
||||
x += z;
|
||||
*outlen -= z;
|
||||
}
|
||||
|
||||
if ((err = der_encode_asn1_identifier(root, out, &id_len)) != CRYPT_OK) {
|
||||
goto LBL_ERR;
|
||||
}
|
||||
*outlen = x;
|
||||
err = CRYPT_OK;
|
||||
|
||||
LBL_ERR:
|
||||
return err;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* ref: $Format:%D$ */
|
||||
/* git commit: $Format:%H$ */
|
||||
/* commit time: $Format:%ai$ */
|
213
src/pk/asn1/der/custom_type/der_length_custom_type.c
Normal file
213
src/pk/asn1/der/custom_type/der_length_custom_type.c
Normal file
@ -0,0 +1,213 @@
|
||||
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
|
||||
*
|
||||
* LibTomCrypt is a library that provides various cryptographic
|
||||
* algorithms in a highly modular and flexible manner.
|
||||
*
|
||||
* The library is free for all purposes without any express
|
||||
* guarantee it works.
|
||||
*/
|
||||
#include "tomcrypt.h"
|
||||
|
||||
/**
|
||||
@file der_length_custom_type.c
|
||||
ASN.1 DER, length of a custom type, Steffen Jaeckel
|
||||
*/
|
||||
|
||||
#ifdef LTC_DER
|
||||
|
||||
/**
|
||||
Get the length of a DER custom type
|
||||
|
||||
This function is a bit special compared to the others, as it requires the
|
||||
root-ltc_asn1_list where the type is defined.
|
||||
|
||||
@param root The root of the struct to encode
|
||||
@param outlen [out] The length required in octets to store it
|
||||
@param payloadlen [out] The length of the payload in octets
|
||||
@return CRYPT_OK on success
|
||||
*/
|
||||
int der_length_custom_type(const ltc_asn1_list *root, unsigned long *outlen, unsigned long *payloadlen)
|
||||
{
|
||||
int err;
|
||||
ltc_asn1_list *list;
|
||||
ltc_asn1_type type;
|
||||
unsigned long size, x, y, i, inlen, id_len;
|
||||
void *data;
|
||||
|
||||
LTC_ARGCHK(root != NULL);
|
||||
LTC_ARGCHK(outlen != NULL);
|
||||
|
||||
if ((root->pc == LTC_ASN1_PC_PRIMITIVE) && (root->size != 1)) {
|
||||
/* In case it's a PRIMITIVE element there has to be
|
||||
* exactly one element following.
|
||||
*/
|
||||
return CRYPT_INVALID_PACKET;
|
||||
}
|
||||
|
||||
/* get size of output that will be required */
|
||||
if ((err = der_length_asn1_identifier(root, &id_len)) != CRYPT_OK) {
|
||||
return err;
|
||||
}
|
||||
y = id_len;
|
||||
|
||||
inlen = root->size;
|
||||
list = root->data;
|
||||
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_CONSTRUCTED:
|
||||
case LTC_ASN1_CONTEXT_SPECIFIC:
|
||||
case LTC_ASN1_EOL:
|
||||
err = CRYPT_INVALID_ARG;
|
||||
goto LBL_ERR;
|
||||
}
|
||||
}
|
||||
|
||||
if (root->pc == LTC_ASN1_PC_PRIMITIVE) {
|
||||
/* In case it's a PRIMITIVE element we're going
|
||||
* to only replace the identifier of the one element
|
||||
* by the custom identifier.
|
||||
*/
|
||||
y -= 1;
|
||||
if (payloadlen != NULL) {
|
||||
*payloadlen = y - id_len;
|
||||
}
|
||||
} else {
|
||||
/* calc length of length */
|
||||
if ((err = der_length_asn1_length(y, &x)) != CRYPT_OK) {
|
||||
goto LBL_ERR;
|
||||
}
|
||||
if (payloadlen != NULL) {
|
||||
*payloadlen = y - id_len;
|
||||
}
|
||||
y += x;
|
||||
}
|
||||
|
||||
/* store size */
|
||||
*outlen = y;
|
||||
|
||||
LBL_ERR:
|
||||
return err;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* ref: $Format:%D$ */
|
||||
/* git commit: $Format:%H$ */
|
||||
/* commit time: $Format:%ai$ */
|
Loading…
Reference in New Issue
Block a user