diff --git a/src/headers/tomcrypt_pk.h b/src/headers/tomcrypt_pk.h index ef0a5f9..3621140 100644 --- a/src/headers/tomcrypt_pk.h +++ b/src/headers/tomcrypt_pk.h @@ -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 */ diff --git a/src/pk/asn1/der/choice/der_decode_choice.c b/src/pk/asn1/der/choice/der_decode_choice.c index ebadc5f..17aa105 100644 --- a/src/pk/asn1/der/choice/der_decode_choice.c +++ b/src/pk/asn1/der/choice/der_decode_choice.c @@ -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; } } diff --git a/src/pk/asn1/der/sequence/der_decode_sequence_ex.c b/src/pk/asn1/der/sequence/der_decode_sequence_ex.c index 27d6614..b233641 100644 --- a/src/pk/asn1/der/sequence/der_decode_sequence_ex.c +++ b/src/pk/asn1/der/sequence/der_decode_sequence_ex.c @@ -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; } diff --git a/src/pk/asn1/der/sequence/der_decode_sequence_flexi.c b/src/pk/asn1/der/sequence/der_decode_sequence_flexi.c index 057370a..8bd3b5d 100644 --- a/src/pk/asn1/der/sequence/der_decode_sequence_flexi.c +++ b/src/pk/asn1/der/sequence/der_decode_sequence_flexi.c @@ -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 */ diff --git a/src/pk/asn1/der/sequence/der_decode_sequence_multi.c b/src/pk/asn1/der/sequence/der_decode_sequence_multi.c index da25827..2169938 100644 --- a/src/pk/asn1/der/sequence/der_decode_sequence_multi.c +++ b/src/pk/asn1/der/sequence/der_decode_sequence_multi.c @@ -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; } diff --git a/src/pk/asn1/der/sequence/der_decode_subject_public_key_info.c b/src/pk/asn1/der/sequence/der_decode_subject_public_key_info.c index 74522f7..b0f2f94 100644 --- a/src/pk/asn1/der/sequence/der_decode_subject_public_key_info.c +++ b/src/pk/asn1/der/sequence/der_decode_subject_public_key_info.c @@ -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); diff --git a/src/pk/asn1/der/sequence/der_encode_sequence_ex.c b/src/pk/asn1/der/sequence/der_encode_sequence_ex.c index e054840..10f4dbe 100644 --- a/src/pk/asn1/der/sequence/der_encode_sequence_ex.c +++ b/src/pk/asn1/der/sequence/der_encode_sequence_ex.c @@ -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; } diff --git a/src/pk/asn1/der/sequence/der_encode_sequence_multi.c b/src/pk/asn1/der/sequence/der_encode_sequence_multi.c index abd0457..da5d371 100644 --- a/src/pk/asn1/der/sequence/der_encode_sequence_multi.c +++ b/src/pk/asn1/der/sequence/der_encode_sequence_multi.c @@ -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; diff --git a/src/pk/asn1/der/sequence/der_encode_subject_public_key_info.c b/src/pk/asn1/der/sequence/der_encode_subject_public_key_info.c index 6c1442f..681a53f 100644 --- a/src/pk/asn1/der/sequence/der_encode_subject_public_key_info.c +++ b/src/pk/asn1/der/sequence/der_encode_subject_public_key_info.c @@ -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, diff --git a/src/pk/asn1/der/set/der_encode_set.c b/src/pk/asn1/der/set/der_encode_set.c index a2d0128..fdf55f8 100644 --- a/src/pk/asn1/der/set/der_encode_set.c +++ b/src/pk/asn1/der/set/der_encode_set.c @@ -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 diff --git a/src/pk/asn1/der/teletex_string/der_decode_teletex_string.c b/src/pk/asn1/der/teletex_string/der_decode_teletex_string.c index 2dfc5c7..b935745 100644 --- a/src/pk/asn1/der/teletex_string/der_decode_teletex_string.c +++ b/src/pk/asn1/der/teletex_string/der_decode_teletex_string.c @@ -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$ */ diff --git a/testprof/der_tests.c b/testprof/der_tests.c index a99f7c0..c75e3d3 100644 --- a/testprof/der_tests.c +++ b/testprof/der_tests.c @@ -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);