add ASN.1-identifier functions
This commit is contained in:
parent
509ad5222f
commit
1b3a757345
@ -520,6 +520,18 @@ typedef enum ltc_asn1_type_ {
|
||||
LTC_ASN1_CUSTOM_TYPE,
|
||||
} ltc_asn1_type;
|
||||
|
||||
typedef enum {
|
||||
LTC_ASN1_CL_UNIVERSAL = 0x0,
|
||||
LTC_ASN1_CL_APPLICATION = 0x1,
|
||||
LTC_ASN1_CL_CONTEXT_SPECIFIC = 0x2,
|
||||
LTC_ASN1_CL_PRIVATE = 0x3,
|
||||
} ltc_asn1_class;
|
||||
|
||||
typedef enum {
|
||||
LTC_ASN1_PC_PRIMITIVE = 0x0,
|
||||
LTC_ASN1_PC_CONSTRUCTED = 0x1,
|
||||
} ltc_asn1_pc;
|
||||
|
||||
/** A LTC ASN.1 list type */
|
||||
typedef struct ltc_asn1_list_ {
|
||||
/** The LTC ASN.1 enumerated type identifier */
|
||||
@ -528,12 +540,17 @@ typedef struct ltc_asn1_list_ {
|
||||
void *data;
|
||||
/** The size of the input or resulting output */
|
||||
unsigned long size;
|
||||
/** The used flag, this is used by the CHOICE ASN.1 type to indicate which choice was made */
|
||||
/** The used flag
|
||||
* 1. This is used by the CHOICE ASN.1 type to indicate which choice was made
|
||||
* 2. This is used by the ASN.1 decoder to indicate if an element is used
|
||||
* 3. This is used by the flexi-decoder to indicate the first byte of the identifier */
|
||||
int used;
|
||||
/** Flag used to indicate optional items in ASN.1 sequences */
|
||||
int optional;
|
||||
/** Flag used to indicate context specific tags on ASN.1 sequence items */
|
||||
unsigned char tag;
|
||||
/** ASN.1 identifier */
|
||||
ltc_asn1_class class;
|
||||
ltc_asn1_pc pc;
|
||||
ulong64 tag;
|
||||
/** prev/next entry in the list */
|
||||
struct ltc_asn1_list_ *prev, *next, *child, *parent;
|
||||
} ltc_asn1_list;
|
||||
@ -546,14 +563,36 @@ typedef struct ltc_asn1_list_ {
|
||||
LTC_MACRO_list[LTC_MACRO_temp].data = (void*)(Data); \
|
||||
LTC_MACRO_list[LTC_MACRO_temp].size = (Size); \
|
||||
LTC_MACRO_list[LTC_MACRO_temp].used = 0; \
|
||||
LTC_MACRO_list[LTC_MACRO_temp].tag = 0; \
|
||||
LTC_MACRO_list[LTC_MACRO_temp].optional = 0; \
|
||||
LTC_MACRO_list[LTC_MACRO_temp].class = 0; \
|
||||
LTC_MACRO_list[LTC_MACRO_temp].pc = 0; \
|
||||
LTC_MACRO_list[LTC_MACRO_temp].tag = 0; \
|
||||
} while (0)
|
||||
|
||||
int der_encode_asn1_length(unsigned long len, unsigned char* out, unsigned long* outlen);
|
||||
int der_decode_asn1_length(const unsigned char* len, unsigned long* lenlen, unsigned long* outlen);
|
||||
int der_length_asn1_length(unsigned long len, unsigned long *outlen);
|
||||
#define __LTC_SET_ASN1_IDENTIFIER(list, index, Class, Pc, Tag) \
|
||||
do { \
|
||||
int LTC_MACRO_temp = (index); \
|
||||
ltc_asn1_list *LTC_MACRO_list = (list); \
|
||||
LTC_MACRO_list[LTC_MACRO_temp].type = LTC_ASN1_CUSTOM_TYPE; \
|
||||
LTC_MACRO_list[LTC_MACRO_temp].class = (Class); \
|
||||
LTC_MACRO_list[LTC_MACRO_temp].pc = (Pc); \
|
||||
LTC_MACRO_list[LTC_MACRO_temp].tag = (Tag); \
|
||||
} while (0)
|
||||
|
||||
#define LTC_SET_ASN1_CUSTOM_CONSTRUCTED(list, index, Class, Tag, Data) \
|
||||
do { \
|
||||
int LTC_MACRO_temp##__LINE__ = (index); \
|
||||
LTC_SET_ASN1(list, LTC_MACRO_temp##__LINE__, LTC_ASN1_CUSTOM_TYPE, Data, 1); \
|
||||
__LTC_SET_ASN1_IDENTIFIER(list, LTC_MACRO_temp##__LINE__, Class, LTC_ASN1_PC_CONSTRUCTED, Tag); \
|
||||
} while (0)
|
||||
|
||||
#define LTC_SET_ASN1_CUSTOM_PRIMITIVE(list, index, Class, Tag, Type, Data, Size) \
|
||||
do { \
|
||||
int LTC_MACRO_temp##__LINE__ = (index); \
|
||||
LTC_SET_ASN1(list, LTC_MACRO_temp##__LINE__, LTC_ASN1_CUSTOM_TYPE, Data, Size); \
|
||||
__LTC_SET_ASN1_IDENTIFIER(list, LTC_MACRO_temp##__LINE__, Class, LTC_ASN1_PC_PRIMITIVE, Tag); \
|
||||
list[LTC_MACRO_temp##__LINE__].used = (int)(Type); \
|
||||
} while (0)
|
||||
|
||||
extern const char* der_asn1_class_to_string_map[];
|
||||
extern const unsigned long der_asn1_class_to_string_map_sz;
|
||||
@ -580,6 +619,14 @@ int der_length_sequence(ltc_asn1_list *list, unsigned long inlen,
|
||||
|
||||
#ifdef LTC_SOURCE
|
||||
/* internal helper functions */
|
||||
int der_encode_asn1_identifier(const ltc_asn1_list *id, unsigned char *out, unsigned long *outlen);
|
||||
int der_decode_asn1_identifier(const unsigned char *in, unsigned long *inlen, ltc_asn1_list *id);
|
||||
int der_length_asn1_identifier(const ltc_asn1_list *id, unsigned long *idlen);
|
||||
|
||||
int der_encode_asn1_length(unsigned long len, unsigned char* out, unsigned long* outlen);
|
||||
int der_decode_asn1_length(const unsigned char* len, unsigned long* lenlen, unsigned long* outlen);
|
||||
int der_length_asn1_length(unsigned long len, unsigned long *outlen);
|
||||
|
||||
int der_length_sequence_ex(ltc_asn1_list *list, unsigned long inlen,
|
||||
unsigned long *outlen, unsigned long *payloadlen);
|
||||
|
||||
|
136
src/pk/asn1/der/general/der_decode_asn1_identifier.c
Normal file
136
src/pk/asn1/der/general/der_decode_asn1_identifier.c
Normal file
@ -0,0 +1,136 @@
|
||||
/* 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_asn1_identifier.c
|
||||
ASN.1 DER, decode the ASN.1 Identifier, Steffen Jaeckel
|
||||
*/
|
||||
|
||||
#ifdef LTC_DER
|
||||
/* c.f. X.680 & X.690, some decisions backed by X.690 ch. 10.2 */
|
||||
static const unsigned char tag_constructed_map[] =
|
||||
{
|
||||
/* 0 */
|
||||
255,
|
||||
LTC_ASN1_PC_PRIMITIVE,
|
||||
LTC_ASN1_PC_PRIMITIVE,
|
||||
LTC_ASN1_PC_PRIMITIVE,
|
||||
LTC_ASN1_PC_PRIMITIVE,
|
||||
/* 5 */
|
||||
LTC_ASN1_PC_PRIMITIVE,
|
||||
LTC_ASN1_PC_PRIMITIVE,
|
||||
LTC_ASN1_PC_PRIMITIVE,
|
||||
LTC_ASN1_PC_PRIMITIVE,
|
||||
LTC_ASN1_PC_PRIMITIVE,
|
||||
/* 10 */
|
||||
LTC_ASN1_PC_PRIMITIVE,
|
||||
LTC_ASN1_PC_PRIMITIVE,
|
||||
LTC_ASN1_PC_PRIMITIVE,
|
||||
LTC_ASN1_PC_PRIMITIVE,
|
||||
LTC_ASN1_PC_PRIMITIVE,
|
||||
/* 15 */
|
||||
255,
|
||||
LTC_ASN1_PC_CONSTRUCTED,
|
||||
LTC_ASN1_PC_CONSTRUCTED,
|
||||
LTC_ASN1_PC_PRIMITIVE,
|
||||
LTC_ASN1_PC_PRIMITIVE,
|
||||
/* 20 */
|
||||
LTC_ASN1_PC_PRIMITIVE,
|
||||
LTC_ASN1_PC_PRIMITIVE,
|
||||
LTC_ASN1_PC_PRIMITIVE,
|
||||
LTC_ASN1_PC_PRIMITIVE,
|
||||
LTC_ASN1_PC_PRIMITIVE,
|
||||
/* 25 */
|
||||
LTC_ASN1_PC_PRIMITIVE,
|
||||
LTC_ASN1_PC_PRIMITIVE,
|
||||
LTC_ASN1_PC_PRIMITIVE,
|
||||
LTC_ASN1_PC_PRIMITIVE,
|
||||
LTC_ASN1_PC_PRIMITIVE,
|
||||
/* 30 */
|
||||
LTC_ASN1_PC_PRIMITIVE,
|
||||
};
|
||||
static const unsigned long tag_constructed_map_sz = sizeof(tag_constructed_map)/sizeof(tag_constructed_map[0]);
|
||||
|
||||
/**
|
||||
Decode the ASN.1 Identifier
|
||||
@param id Where to store the decoded Identifier
|
||||
@param in Where to read the Identifier from
|
||||
@param inlen [in/out] The size of in available/read
|
||||
@return CRYPT_OK if successful
|
||||
*/
|
||||
int der_decode_asn1_identifier(const unsigned char *in, unsigned long *inlen, ltc_asn1_list *id)
|
||||
{
|
||||
ulong64 tmp;
|
||||
unsigned long tag_len;
|
||||
int err;
|
||||
|
||||
LTC_ARGCHK(id != NULL);
|
||||
LTC_ARGCHK(in != NULL);
|
||||
LTC_ARGCHK(inlen != NULL);
|
||||
|
||||
if (*inlen == 0) {
|
||||
return CRYPT_BUFFER_OVERFLOW;
|
||||
}
|
||||
|
||||
tag_len = 1;
|
||||
id->class = (in[0] >> 6) & 0x3;
|
||||
id->pc = (in[0] >> 5) & 0x1;
|
||||
id->tag = in[0] & 0x1f;
|
||||
|
||||
err = CRYPT_OK;
|
||||
if (id->tag == 0x1f) {
|
||||
id->tag = 0;
|
||||
do {
|
||||
if (*inlen < tag_len) {
|
||||
/* break the loop and trigger the BOF error-code */
|
||||
tmp = 0xff;
|
||||
break;
|
||||
}
|
||||
id->tag <<= 7;
|
||||
id->tag |= in[tag_len] & 0x7f;
|
||||
tmp = in[tag_len] & 0x80;
|
||||
tag_len++;
|
||||
} while ((tmp != 0) && (tag_len < 10));
|
||||
|
||||
if (tmp != 0) {
|
||||
err = CRYPT_BUFFER_OVERFLOW;
|
||||
} else if (id->tag < 0x1f) {
|
||||
err = CRYPT_PK_ASN1_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
if (err != CRYPT_OK) {
|
||||
id->pc = 0;
|
||||
id->class = 0;
|
||||
id->tag = 0;
|
||||
} else {
|
||||
*inlen = tag_len;
|
||||
if ((id->class == LTC_ASN1_CL_UNIVERSAL) &&
|
||||
(id->tag < der_asn1_tag_to_type_map_sz) &&
|
||||
(id->tag < tag_constructed_map_sz) &&
|
||||
(id->pc == tag_constructed_map[id->tag])) {
|
||||
id->type = der_asn1_tag_to_type_map[id->tag];
|
||||
} else {
|
||||
if ((id->class == LTC_ASN1_CL_UNIVERSAL) && (id->tag == 0)) {
|
||||
id->type = LTC_ASN1_EOL;
|
||||
} else {
|
||||
id->type = LTC_ASN1_CUSTOM_TYPE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return CRYPT_OK;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* ref: $Format:%D$ */
|
||||
/* git commit: $Format:%H$ */
|
||||
/* commit time: $Format:%ai$ */
|
97
src/pk/asn1/der/general/der_encode_asn1_identifier.c
Normal file
97
src/pk/asn1/der/general/der_encode_asn1_identifier.c
Normal file
@ -0,0 +1,97 @@
|
||||
/* 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_asn1_identifier.c
|
||||
ASN.1 DER, encode the ASN.1 Identifier, Steffen Jaeckel
|
||||
*/
|
||||
|
||||
#ifdef LTC_DER
|
||||
/**
|
||||
Encode the ASN.1 Identifier
|
||||
@param id The ASN.1 Identifer to encode
|
||||
@param out Where to write the identifier to
|
||||
@param outlen [in/out] The size of out available/written
|
||||
@return CRYPT_OK if successful
|
||||
*/
|
||||
int der_encode_asn1_identifier(const ltc_asn1_list *id, unsigned char *out, unsigned long *outlen)
|
||||
{
|
||||
ulong64 tmp;
|
||||
unsigned long tag_len;
|
||||
|
||||
LTC_ARGCHK(id != NULL);
|
||||
LTC_ARGCHK(outlen != NULL);
|
||||
|
||||
if (id->type != LTC_ASN1_CUSTOM_TYPE) {
|
||||
if (id->type >= der_asn1_type_to_identifier_map_sz) {
|
||||
return CRYPT_INVALID_ARG;
|
||||
}
|
||||
if (der_asn1_type_to_identifier_map[id->type] == -1) {
|
||||
return CRYPT_INVALID_ARG;
|
||||
}
|
||||
if (out != NULL) {
|
||||
*out = der_asn1_type_to_identifier_map[id->type];
|
||||
}
|
||||
*outlen = 1;
|
||||
return CRYPT_OK;
|
||||
} else {
|
||||
if (id->class < LTC_ASN1_CL_UNIVERSAL || id->class > LTC_ASN1_CL_PRIVATE) {
|
||||
return CRYPT_INVALID_ARG;
|
||||
}
|
||||
if (id->pc < LTC_ASN1_PC_PRIMITIVE || id->pc > LTC_ASN1_PC_CONSTRUCTED) {
|
||||
return CRYPT_INVALID_ARG;
|
||||
}
|
||||
if (id->tag > (ULONG_MAX >> (8 + 7))) {
|
||||
return CRYPT_INVALID_ARG;
|
||||
}
|
||||
}
|
||||
|
||||
if (out != NULL) {
|
||||
if (*outlen < 1) {
|
||||
return CRYPT_BUFFER_OVERFLOW;
|
||||
}
|
||||
|
||||
out[0] = id->class << 6 | id->pc << 5;
|
||||
}
|
||||
|
||||
if (id->tag < 0x1f) {
|
||||
if (out != NULL) {
|
||||
out[0] |= id->tag & 0x1f;
|
||||
}
|
||||
*outlen = 1;
|
||||
} else {
|
||||
tag_len = 0;
|
||||
tmp = id->tag;
|
||||
do {
|
||||
tag_len++;
|
||||
tmp >>= 7;
|
||||
} while (tmp);
|
||||
|
||||
if (out != NULL) {
|
||||
if (*outlen < tag_len + 1) {
|
||||
return CRYPT_BUFFER_OVERFLOW;
|
||||
}
|
||||
out[0] |= 0x1f;
|
||||
for (tmp = 1; tmp <= tag_len; ++tmp) {
|
||||
out[tmp] = ((id->tag >> (7 * (tag_len - tmp))) & 0x7f) | 0x80;
|
||||
}
|
||||
out[tag_len] &= ~0x80;
|
||||
}
|
||||
*outlen = tag_len + 1;
|
||||
}
|
||||
|
||||
return CRYPT_OK;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* ref: $Format:%D$ */
|
||||
/* git commit: $Format:%H$ */
|
||||
/* commit time: $Format:%ai$ */
|
33
src/pk/asn1/der/general/der_length_asn1_identifier.c
Normal file
33
src/pk/asn1/der/general/der_length_asn1_identifier.c
Normal file
@ -0,0 +1,33 @@
|
||||
/* 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_asn1_identifier.c
|
||||
ASN.1 DER, determine the length when encoding the ASN.1 Identifier, Steffen Jaeckel
|
||||
*/
|
||||
|
||||
#ifdef LTC_DER
|
||||
/**
|
||||
Determine the length required when encoding the ASN.1 Identifier
|
||||
@param id The ASN.1 identifier to encode
|
||||
@param idlen [out] The required length to encode list
|
||||
@return CRYPT_OK if successful
|
||||
*/
|
||||
|
||||
int der_length_asn1_identifier(const ltc_asn1_list *id, unsigned long *idlen)
|
||||
{
|
||||
return der_encode_asn1_identifier(id, NULL, idlen);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* ref: $Format:%D$ */
|
||||
/* git commit: $Format:%H$ */
|
||||
/* commit time: $Format:%ai$ */
|
Loading…
Reference in New Issue
Block a user