Merge branch 'fix/asn1' into develop

This closes #49

[skip ci]
This commit is contained in:
Steffen Jaeckel 2014-08-31 18:02:52 +02:00
commit c342cb5a21
12 changed files with 150 additions and 90 deletions

View File

@ -435,7 +435,7 @@ int dsa_shared_secret(void *private_key, void *base,
#ifdef LTC_DER
/* DER handling */
enum {
typedef enum ltc_asn1_type_ {
LTC_ASN1_EOL,
LTC_ASN1_BOOLEAN,
LTC_ASN1_INTEGER,
@ -455,12 +455,12 @@ enum {
LTC_ASN1_RAW_BIT_STRING,
LTC_ASN1_TELETEX_STRING,
LTC_ASN1_CONSTRUCTED,
};
} ltc_asn1_type;
/** A LTC ASN.1 list type */
typedef struct ltc_asn1_list_ {
/** The LTC ASN.1 enumerated type identifier */
int type;
ltc_asn1_type type;
/** The data to encode or place for decoding */
void *data;
/** The size of the input or resulting output */

View File

@ -51,6 +51,16 @@ int der_decode_choice(const unsigned char *in, unsigned long *inlen,
data = list[x].data;
switch (list[x].type) {
case LTC_ASN1_BOOLEAN:
if (der_decode_boolean(in, *inlen, data) == CRYPT_OK) {
if (der_length_boolean(&z) == CRYPT_OK) {
list[x].used = 1;
*inlen = z;
return CRYPT_OK;
}
}
break;
case LTC_ASN1_INTEGER:
if (der_decode_integer(in, *inlen, data) == CRYPT_OK) {
if (der_length_integer(data, &z) == CRYPT_OK) {
@ -82,6 +92,17 @@ int der_decode_choice(const unsigned char *in, unsigned long *inlen,
}
break;
case LTC_ASN1_RAW_BIT_STRING:
if (der_decode_raw_bit_string(in, *inlen, data, &size) == CRYPT_OK) {
if (der_length_bit_string(size, &z) == CRYPT_OK) {
list[x].used = 1;
list[x].size = size;
*inlen = z;
return CRYPT_OK;
}
}
break;
case LTC_ASN1_OCTET_STRING:
if (der_decode_octet_string(in, *inlen, data, &size) == CRYPT_OK) {
if (der_length_octet_string(size, &z) == CRYPT_OK) {
@ -112,6 +133,17 @@ int der_decode_choice(const unsigned char *in, unsigned long *inlen,
}
break;
case LTC_ASN1_TELETEX_STRING:
if (der_decode_teletex_string(in, *inlen, data, &size) == CRYPT_OK) {
if (der_length_teletex_string(data, size, &z) == CRYPT_OK) {
list[x].used = 1;
list[x].size = size;
*inlen = z;
return CRYPT_OK;
}
}
break;
case LTC_ASN1_IA5_STRING:
if (der_decode_ia5_string(in, *inlen, data, &size) == CRYPT_OK) {
if (der_length_ia5_string(data, size, &z) == CRYPT_OK) {
@ -166,7 +198,9 @@ int der_decode_choice(const unsigned char *in, unsigned long *inlen,
}
break;
default:
case LTC_ASN1_CHOICE:
case LTC_ASN1_CONSTRUCTED:
case LTC_ASN1_EOL:
return CRYPT_INVALID_ARG;
}
}

View File

@ -31,7 +31,8 @@
int der_decode_sequence_ex(const unsigned char *in, unsigned long inlen,
ltc_asn1_list *list, unsigned long outlen, int ordered)
{
int err, type, i;
int err, i;
ltc_asn1_type type;
unsigned long size, x, y, z, blksize;
void *data;
@ -187,6 +188,18 @@ int der_decode_sequence_ex(const unsigned char *in, unsigned long inlen,
}
break;
case LTC_ASN1_TELETEX_STRING:
z = inlen;
if ((err = der_decode_teletex_string(in + x, z, data, &size)) != CRYPT_OK) {
if (!ordered) { continue; }
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) {
@ -270,7 +283,8 @@ int der_decode_sequence_ex(const unsigned char *in, unsigned long inlen,
}
break;
default:
case LTC_ASN1_CONSTRUCTED:
case LTC_ASN1_EOL:
err = CRYPT_INVALID_ARG;
goto LBL_ERR;
}

View File

@ -65,7 +65,7 @@ int der_decode_sequence_flexi(const unsigned char *in, unsigned long *inlen, ltc
ltc_asn1_list *l;
unsigned long err, type, len, totlen, x, y;
void *realloc_tmp;
int isConstructed;
int is_constructed;
LTC_ARGCHK(in != NULL);
LTC_ARGCHK(inlen != NULL);
@ -103,12 +103,16 @@ int der_decode_sequence_flexi(const unsigned char *in, unsigned long *inlen, ltc
l = l->next;
}
if ((isConstructed = ((type & 0xE0) == 0xA0 ? 1 : 0))) {
if ((type & 0x20) && (type != 0x30) && (type != 0x31)) {
is_constructed = 1;
/* constructed, use the 'used' field to store the original tag number */
l->used = (type & 0x1F);
/* treat constructed elements like SETs */
type = 0x31;
}
else {
is_constructed = 0;
}
/* now switch on type */
switch (type) {
@ -332,7 +336,15 @@ int der_decode_sequence_flexi(const unsigned char *in, unsigned long *inlen, ltc
case 0x31: /* SET */
/* init field */
l->type = (isConstructed ? LTC_ASN1_CONSTRUCTED : ((type == 0x30) ? LTC_ASN1_SEQUENCE : LTC_ASN1_SET));
if (is_constructed) {
l->type = LTC_ASN1_CONSTRUCTED;
}
else if (type == 0x30) {
l->type = LTC_ASN1_SEQUENCE;
}
else {
l->type = LTC_ASN1_SET;
}
/* we have to decode the SEQUENCE header and get it's length */

View File

@ -28,7 +28,8 @@
*/
int der_decode_sequence_multi(const unsigned char *in, unsigned long inlen, ...)
{
int err, type;
int err;
ltc_asn1_type type;
unsigned long size, x;
void *data;
va_list args;
@ -40,7 +41,7 @@ int der_decode_sequence_multi(const unsigned char *in, unsigned long inlen, ...)
va_start(args, inlen);
x = 0;
for (;;) {
type = va_arg(args, int);
type = va_arg(args, ltc_asn1_type);
size = va_arg(args, unsigned long);
data = va_arg(args, void*);
@ -64,10 +65,13 @@ int der_decode_sequence_multi(const unsigned char *in, unsigned long inlen, ...)
case LTC_ASN1_SETOF:
case LTC_ASN1_SEQUENCE:
case LTC_ASN1_CHOICE:
case LTC_ASN1_RAW_BIT_STRING:
case LTC_ASN1_TELETEX_STRING:
++x;
break;
default:
case LTC_ASN1_EOL:
case LTC_ASN1_CONSTRUCTED:
va_end(args);
return CRYPT_INVALID_ARG;
}
@ -88,7 +92,7 @@ int der_decode_sequence_multi(const unsigned char *in, unsigned long inlen, ...)
va_start(args, inlen);
x = 0;
for (;;) {
type = va_arg(args, int);
type = va_arg(args, ltc_asn1_type);
size = va_arg(args, unsigned long);
data = va_arg(args, void*);
@ -112,21 +116,18 @@ int der_decode_sequence_multi(const unsigned char *in, unsigned long inlen, ...)
case LTC_ASN1_SET:
case LTC_ASN1_SETOF:
case LTC_ASN1_CHOICE:
list[x].type = type;
list[x].size = size;
list[x++].data = data;
case LTC_ASN1_RAW_BIT_STRING:
case LTC_ASN1_TELETEX_STRING:
LTC_SET_ASN1(list, x++, type, data, size);
break;
case LTC_ASN1_EOL:
case LTC_ASN1_CONSTRUCTED:
break;
default:
va_end(args);
err = CRYPT_INVALID_ARG;
goto LBL_ERR;
}
}
va_end(args);
err = der_decode_sequence(in, inlen, list, x);
LBL_ERR:
XFREE(list);
return err;
}

View File

@ -46,6 +46,7 @@ int der_decode_subject_public_key_info(const unsigned char *in, unsigned long in
LTC_ARGCHK(in != NULL);
LTC_ARGCHK(inlen != 0);
LTC_ARGCHK(public_key_len != NULL);
err = pk_get_oid(algorithm, &oid);
if (err != CRYPT_OK) {
@ -63,8 +64,8 @@ int der_decode_subject_public_key_info(const unsigned char *in, unsigned long in
LTC_SET_ASN1(alg_id, 0, LTC_ASN1_OBJECT_IDENTIFIER, tmpoid, sizeof(tmpoid)/sizeof(tmpoid[0]));
LTC_SET_ASN1(alg_id, 1, parameters_type, parameters, parameters_len);
/* the actual format of the SSL DER key is odd, it stores a RSAPublicKey in a **BIT** string ... so we have to extract it
then proceed to convert bit to octet
/* the actual format of the SSL DER key is odd, it stores a RSAPublicKey
* in a **BIT** string ... so we have to extract it then proceed to convert bit to octet
*/
LTC_SET_ASN1(subject_pubkey, 0, LTC_ASN1_SEQUENCE, alg_id, 2);
LTC_SET_ASN1(subject_pubkey, 1, LTC_ASN1_RAW_BIT_STRING, tmpbuf, MAX_RSA_SIZE*8);
@ -74,6 +75,13 @@ int der_decode_subject_public_key_info(const unsigned char *in, unsigned long in
goto LBL_ERR;
}
if ((alg_id[0].size != oid.OIDlen) ||
memcmp(oid.OID, alg_id[0].data, oid.OIDlen * sizeof(oid.OID[0]))) {
/* OID mismatch */
err = CRYPT_PK_INVALID_TYPE;
goto LBL_ERR;
}
len = subject_pubkey[1].size/8;
if (*public_key_len > len) {
memcpy(public_key, subject_pubkey[1].data, len);

View File

@ -31,7 +31,8 @@
int der_encode_sequence_ex(ltc_asn1_list *list, unsigned long inlen,
unsigned char *out, unsigned long *outlen, int type_of)
{
int err, type;
int err;
ltc_asn1_type type;
unsigned long size, x, y, z, i;
void *data;
@ -135,7 +136,10 @@ int der_encode_sequence_ex(ltc_asn1_list *list, unsigned long inlen,
y += x;
break;
default:
case LTC_ASN1_CHOICE:
case LTC_ASN1_CONSTRUCTED:
case LTC_ASN1_EOL:
case LTC_ASN1_TELETEX_STRING:
err = CRYPT_INVALID_ARG;
goto LBL_ERR;
}
@ -330,7 +334,10 @@ int der_encode_sequence_ex(ltc_asn1_list *list, unsigned long inlen,
*outlen -= z;
break;
default:
case LTC_ASN1_CHOICE:
case LTC_ASN1_CONSTRUCTED:
case LTC_ASN1_EOL:
case LTC_ASN1_TELETEX_STRING:
err = CRYPT_INVALID_ARG;
goto LBL_ERR;
}

View File

@ -28,7 +28,8 @@
*/
int der_encode_sequence_multi(unsigned char *out, unsigned long *outlen, ...)
{
int err, type;
int err;
ltc_asn1_type type;
unsigned long size, x;
void *data;
va_list args;
@ -41,7 +42,7 @@ int der_encode_sequence_multi(unsigned char *out, unsigned long *outlen, ...)
va_start(args, outlen);
x = 0;
for (;;) {
type = va_arg(args, int);
type = va_arg(args, ltc_asn1_type);
size = va_arg(args, unsigned long);
data = va_arg(args, void*);
@ -68,7 +69,10 @@ int der_encode_sequence_multi(unsigned char *out, unsigned long *outlen, ...)
++x;
break;
default:
case LTC_ASN1_CHOICE:
case LTC_ASN1_CONSTRUCTED:
case LTC_ASN1_EOL:
case LTC_ASN1_TELETEX_STRING:
va_end(args);
return CRYPT_INVALID_ARG;
}
@ -89,7 +93,7 @@ int der_encode_sequence_multi(unsigned char *out, unsigned long *outlen, ...)
va_start(args, outlen);
x = 0;
for (;;) {
type = va_arg(args, int);
type = va_arg(args, ltc_asn1_type);
size = va_arg(args, unsigned long);
data = va_arg(args, void*);
@ -113,12 +117,13 @@ int der_encode_sequence_multi(unsigned char *out, unsigned long *outlen, ...)
case LTC_ASN1_SET:
case LTC_ASN1_SETOF:
case LTC_ASN1_RAW_BIT_STRING:
list[x].type = type;
list[x].size = size;
list[x++].data = data;
LTC_SET_ASN1(list, x++, type, data, size);
break;
default:
case LTC_ASN1_CHOICE:
case LTC_ASN1_CONSTRUCTED:
case LTC_ASN1_EOL:
case LTC_ASN1_TELETEX_STRING:
va_end(args);
err = CRYPT_INVALID_ARG;
goto LBL_ERR;

View File

@ -49,13 +49,8 @@ int der_encode_subject_public_key_info(unsigned char *out, unsigned long *outlen
return err;
}
alg_id[0].data = oid.OID;
alg_id[0].size = oid.OIDlen;
alg_id[0].type = LTC_ASN1_OBJECT_IDENTIFIER;
alg_id[1].data = parameters;
alg_id[1].size = parameters_len;
alg_id[1].type = parameters_type;
LTC_SET_ASN1(alg_id, 0, LTC_ASN1_OBJECT_IDENTIFIER, oid.OID, oid.OIDlen);
LTC_SET_ASN1(alg_id, 1, parameters_type, parameters, parameters_len);
return der_encode_sequence_multi(out, outlen,
LTC_ASN1_SEQUENCE, (unsigned long)sizeof(alg_id)/sizeof(alg_id[0]), alg_id,

View File

@ -18,35 +18,40 @@
#ifdef LTC_DER
/* LTC define to ASN.1 TAG */
static int ltc_to_asn1(int v)
static int ltc_to_asn1(ltc_asn1_type v)
{
switch (v) {
case LTC_ASN1_BOOLEAN: return 0x01;
case LTC_ASN1_INTEGER:
case LTC_ASN1_SHORT_INTEGER: return 0x02;
case LTC_ASN1_RAW_BIT_STRING:
case LTC_ASN1_BIT_STRING: return 0x03;
case LTC_ASN1_OCTET_STRING: return 0x04;
case LTC_ASN1_NULL: return 0x05;
case LTC_ASN1_OBJECT_IDENTIFIER: return 0x06;
case LTC_ASN1_UTF8_STRING: return 0x0C;
case LTC_ASN1_PRINTABLE_STRING: return 0x13;
case LTC_ASN1_TELETEX_STRING: return 0x14;
case LTC_ASN1_IA5_STRING: return 0x16;
case LTC_ASN1_UTCTIME: return 0x17;
case LTC_ASN1_SEQUENCE: return 0x30;
case LTC_ASN1_SET:
case LTC_ASN1_SETOF: return 0x31;
default: return -1;
case LTC_ASN1_CHOICE:
case LTC_ASN1_CONSTRUCTED:
case LTC_ASN1_EOL: return -1;
}
}
return -1;
}
static int qsort_helper(const void *a, const void *b)
{
ltc_asn1_list *A = (ltc_asn1_list *)a, *B = (ltc_asn1_list *)b;
int r;
r = ltc_to_asn1(A->type) - ltc_to_asn1(B->type);
/* for QSORT the order is UNDEFINED if they are "equal" which means it is NOT DETERMINISTIC. So we force it to be :-) */
if (r == 0) {
/* their order in the original list now determines the position */
@ -54,13 +59,13 @@ static int qsort_helper(const void *a, const void *b)
} else {
return r;
}
}
}
/*
Encode a SET type
@param list The list of items to encode
@param inlen The number of items in the list
@param out [out] The destination
@param out [out] The destination
@param outlen [in/out] The size of the output
@return CRYPT_OK on success
*/
@ -70,30 +75,30 @@ int der_encode_set(ltc_asn1_list *list, unsigned long inlen,
ltc_asn1_list *copy;
unsigned long x;
int err;
/* make copy of list */
copy = XCALLOC(inlen, sizeof(*copy));
if (copy == NULL) {
return CRYPT_MEM;
}
}
/* fill in used member with index so we can fully sort it */
for (x = 0; x < inlen; x++) {
copy[x] = list[x];
copy[x].used = x;
}
}
/* sort it by the "type" field */
XQSORT(copy, inlen, sizeof(*copy), &qsort_helper);
XQSORT(copy, inlen, sizeof(*copy), &qsort_helper);
/* call der_encode_sequence_ex() */
err = der_encode_sequence_ex(copy, inlen, out, outlen, LTC_ASN1_SET);
err = der_encode_sequence_ex(copy, inlen, out, outlen, LTC_ASN1_SET);
/* free list */
XFREE(copy);
return err;
}
}
#endif

View File

@ -40,7 +40,7 @@ int der_decode_teletex_string(const unsigned char *in, unsigned long inlen,
return CRYPT_INVALID_PACKET;
}
/* check for 0x13 */
/* check for 0x14 */
if ((in[0] & 0x1F) != 0x14) {
return CRYPT_INVALID_PACKET;
}
@ -87,7 +87,7 @@ int der_decode_teletex_string(const unsigned char *in, unsigned long inlen,
return CRYPT_OK;
}
#endif
/* $Source$ */

View File

@ -22,7 +22,6 @@ static void der_set_test(void)
unsigned char strs[10][10], outbuf[128];
unsigned long x, val, outlen;
int err;
/* make structure and encode it */
LTC_SET_ASN1(list, 0, LTC_ASN1_OCTET_STRING, oct_str, sizeof(oct_str));
@ -31,21 +30,14 @@ static void der_set_test(void)
/* encode it */
outlen = sizeof(outbuf);
if ((err = der_encode_set(list, 3, outbuf, &outlen)) != CRYPT_OK) {
fprintf(stderr, "error encoding set: %s\n", error_to_string(err));
exit(EXIT_FAILURE);
}
DO(der_encode_set(list, 3, outbuf, &outlen));
/* first let's test the set_decoder out of order to see what happens, we should get all the fields we expect even though they're in a diff order */
LTC_SET_ASN1(list, 0, LTC_ASN1_BIT_STRING, strs[1], sizeof(strs[1]));
LTC_SET_ASN1(list, 1, LTC_ASN1_SHORT_INTEGER, &val, 1);
LTC_SET_ASN1(list, 2, LTC_ASN1_OCTET_STRING, strs[0], sizeof(strs[0]));
if ((err = der_decode_set(outbuf, outlen, list, 3)) != CRYPT_OK) {
fprintf(stderr, "error decoding set using der_decode_set: %s\n", error_to_string(err));
exit(EXIT_FAILURE);
}
DO(der_decode_set(outbuf, outlen, list, 3));
/* now compare the items */
if (memcmp(strs[0], oct_str, sizeof(oct_str))) {
@ -79,20 +71,14 @@ static void der_set_test(void)
}
outlen = sizeof(outbuf);
if ((err = der_encode_setof(list, 10, outbuf, &outlen)) != CRYPT_OK) {
fprintf(stderr, "error encoding SET OF: %s\n", error_to_string(err));
exit(EXIT_FAILURE);
}
DO(der_encode_setof(list, 10, outbuf, &outlen));
for (x = 0; x < 10; x++) {
LTC_SET_ASN1(list, x, LTC_ASN1_PRINTABLE_STRING, strs[x], sizeof(strs[x]) - 1);
}
XMEMSET(strs, 0, sizeof(strs));
if ((err = der_decode_set(outbuf, outlen, list, 10)) != CRYPT_OK) {
fprintf(stderr, "error decoding SET OF: %s\n", error_to_string(err));
exit(EXIT_FAILURE);
}
DO(der_decode_set(outbuf, outlen, list, 10));
/* now compare */
for (x = 1; x < 10; x++) {
@ -143,7 +129,6 @@ static void der_flexi_test(void)
unsigned char encode_buf[192];
unsigned long encode_buf_len, decode_len;
int err;
ltc_asn1_list static_list[5][3], *decoded_list, *l;
@ -169,10 +154,7 @@ static void der_flexi_test(void)
/* encode it */
encode_buf_len = sizeof(encode_buf);
if ((err = der_encode_sequence(&static_list[0][0], 3, encode_buf, &encode_buf_len)) != CRYPT_OK) {
fprintf(stderr, "Encoding static_list: %s\n", error_to_string(err));
exit(EXIT_FAILURE);
}
DO(der_encode_sequence(&static_list[0][0], 3, encode_buf, &encode_buf_len));
#if 0
{
@ -185,10 +167,7 @@ static void der_flexi_test(void)
/* decode with flexi */
decode_len = encode_buf_len;
if ((err = der_decode_sequence_flexi(encode_buf, &decode_len, &decoded_list)) != CRYPT_OK) {
fprintf(stderr, "decoding static_list: %s\n", error_to_string(err));
exit(EXIT_FAILURE);
}
DO(der_decode_sequence_flexi(encode_buf, &decode_len, &decoded_list));
if (decode_len != encode_buf_len) {
fprintf(stderr, "Decode len of %lu does not match encode len of %lu \n", decode_len, encode_buf_len);