From 2cb8c441131585ca67a2133dce264f777d9e1f9d Mon Sep 17 00:00:00 2001 From: Christopher Brown Date: Thu, 24 Jan 2013 11:14:05 -0800 Subject: [PATCH] der fixes and additions --- libtomcrypt_VS2005.vcproj | 158 +++++++++++++ libtomcrypt_VS2008.vcproj | 34 ++- src/headers/tomcrypt_pk.h | 12 +- src/misc/pk_get_oid.c | 8 +- src/pk/asn1/der/boolean/der_decode_boolean.c | 2 +- .../der/sequence/der_decode_sequence_flexi.c | 40 +++- .../der_decode_subject_public_key_info.c | 3 +- src/pk/asn1/der/sequence/der_sequence_free.c | 2 + .../der_decode_teletex_string.c | 95 ++++++++ .../der_length_teletex_string.c | 210 ++++++++++++++++++ 10 files changed, 551 insertions(+), 13 deletions(-) create mode 100644 src/pk/asn1/der/teletex_string/der_decode_teletex_string.c create mode 100644 src/pk/asn1/der/teletex_string/der_length_teletex_string.c diff --git a/libtomcrypt_VS2005.vcproj b/libtomcrypt_VS2005.vcproj index 4af31c6..6a93fa2 100644 --- a/libtomcrypt_VS2005.vcproj +++ b/libtomcrypt_VS2005.vcproj @@ -2910,6 +2910,28 @@ /> + + + + + + + + @@ -4731,6 +4753,28 @@ /> + + + + + + + + @@ -4753,6 +4797,28 @@ /> + + + + + + + + @@ -5290,6 +5356,28 @@ PreprocessorDefinitions="" /> + + + + + + + + + + + + + + + + @@ -5498,6 +5608,54 @@ + + + + + + + + + + + + + + + + + + diff --git a/libtomcrypt_VS2008.vcproj b/libtomcrypt_VS2008.vcproj index b51b634..a854068 100644 --- a/libtomcrypt_VS2008.vcproj +++ b/libtomcrypt_VS2008.vcproj @@ -1,7 +1,7 @@ + + @@ -4741,6 +4745,10 @@ /> + + @@ -4763,6 +4771,10 @@ /> + + @@ -5301,6 +5313,10 @@ /> + + @@ -5345,6 +5361,10 @@ /> + + @@ -5648,6 +5668,18 @@ + + + + + + next; } - /* now switch on type */ + if ((isConstructed = ((type & 0xE0) == 0xA0 ? 1 : 0))) { + /* constructed, use the 'used' field to store the original tag number */ + l->used = (type & 0x1F); + /* treat constructed elements like SETs */ + type = 0x31; + } + + /* now switch on type */ switch (type) { case 0x01: /* BOOLEAN */ l->type = LTC_ASN1_BOOLEAN; @@ -259,6 +267,26 @@ int der_decode_sequence_flexi(const unsigned char *in, unsigned long *inlen, ltc } break; + case 0x14: /* TELETEXT */ + + /* init field */ + l->type = LTC_ASN1_TELETEX_STRING; + 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 */ /* init field */ @@ -304,7 +332,7 @@ int der_decode_sequence_flexi(const unsigned char *in, unsigned long *inlen, ltc case 0x31: /* SET */ /* init field */ - l->type = (type == 0x30) ? LTC_ASN1_SEQUENCE : LTC_ASN1_SET; + l->type = (isConstructed ? LTC_ASN1_CONSTRUCTED : ((type == 0x30) ? LTC_ASN1_SEQUENCE : LTC_ASN1_SET)); /* we have to decode the SEQUENCE header and get it's length */ @@ -343,9 +371,11 @@ int der_decode_sequence_flexi(const unsigned char *in, unsigned long *inlen, ltc default: /* invalid byte ... this is a soft error */ /* remove link */ - l = l->prev; - XFREE(l->next); - l->next = NULL; + if (l->prev) { + l = l->prev; + XFREE(l->next); + l->next = NULL; + } goto outside; } 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 16c9897..74522f7 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 @@ -36,7 +36,8 @@ int der_decode_subject_public_key_info(const unsigned char *in, unsigned long in unsigned int algorithm, void* public_key, unsigned long* public_key_len, unsigned long parameters_type, ltc_asn1_list* parameters, unsigned long parameters_len) { - int err, len; + int err; + unsigned long len; oid_st oid; unsigned char *tmpbuf; unsigned long tmpoid[16]; diff --git a/src/pk/asn1/der/sequence/der_sequence_free.c b/src/pk/asn1/der/sequence/der_sequence_free.c index 56ecce7..77e263a 100644 --- a/src/pk/asn1/der/sequence/der_sequence_free.c +++ b/src/pk/asn1/der/sequence/der_sequence_free.c @@ -24,6 +24,8 @@ 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) { 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 new file mode 100644 index 0000000..2dfc5c7 --- /dev/null +++ b/src/pk/asn1/der/teletex_string/der_decode_teletex_string.c @@ -0,0 +1,95 @@ +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file der_decode_teletex_string.c + ASN.1 DER, encode a teletex STRING +*/ + +#ifdef LTC_DER + +/** + Store a teletex STRING + @param in The DER encoded teletex STRING + @param inlen The size of the DER teletex STRING + @param out [out] The array of octets stored (one per char) + @param outlen [in/out] The number of octets stored + @return CRYPT_OK if successful +*/ +int der_decode_teletex_string(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen) +{ + unsigned long x, y, len; + int t; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + + /* must have header at least */ + if (inlen < 2) { + return CRYPT_INVALID_PACKET; + } + + /* check for 0x13 */ + if ((in[0] & 0x1F) != 0x14) { + return CRYPT_INVALID_PACKET; + } + x = 1; + + /* decode the length */ + if (in[x] & 0x80) { + /* valid # of bytes in length are 1,2,3 */ + y = in[x] & 0x7F; + if ((y == 0) || (y > 3) || ((x + y) > inlen)) { + return CRYPT_INVALID_PACKET; + } + + /* read the length in */ + len = 0; + ++x; + while (y--) { + len = (len << 8) | in[x++]; + } + } else { + len = in[x++] & 0x7F; + } + + /* is it too long? */ + if (len > *outlen) { + *outlen = len; + return CRYPT_BUFFER_OVERFLOW; + } + + if (len + x > inlen) { + return CRYPT_INVALID_PACKET; + } + + /* read the data */ + for (y = 0; y < len; y++) { + t = der_teletex_value_decode(in[x++]); + if (t == -1) { + return CRYPT_INVALID_ARG; + } + out[y] = t; + } + + *outlen = y; + + return CRYPT_OK; +} + +#endif + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/pk/asn1/der/teletex_string/der_length_teletex_string.c b/src/pk/asn1/der/teletex_string/der_length_teletex_string.c new file mode 100644 index 0000000..85cd1a4 --- /dev/null +++ b/src/pk/asn1/der/teletex_string/der_length_teletex_string.c @@ -0,0 +1,210 @@ +/* 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. + * + * Tom St Denis, tomstdenis@gmail.com, http://libtom.org + */ +#include "tomcrypt.h" + +/** + @file der_length_teletex_string.c + ASN.1 DER, get length of teletex STRING +*/ + +#ifdef LTC_DER + +static const struct { + int code, value; +} teletex_table[] = { +{ '\0', 0 }, +{ '\a', 7 }, +{ '\b', 8 }, +{ '\t', 9 }, +{ '\n', 10 }, +{ '\v', 11 }, +{ '\f', 12 }, +{ '\r', 13 }, +{ ' ', 32 }, +{ '!', 33 }, +{ '"', 34 }, +{ '%', 37 }, +{ '&', 38 }, +{ '\'', 39 }, +{ '(', 40 }, +{ ')', 41 }, +{ '+', 43 }, +{ ',', 44 }, +{ '-', 45 }, +{ '.', 46 }, +{ '/', 47 }, +{ '0', 48 }, +{ '1', 49 }, +{ '2', 50 }, +{ '3', 51 }, +{ '4', 52 }, +{ '5', 53 }, +{ '6', 54 }, +{ '7', 55 }, +{ '8', 56 }, +{ '9', 57 }, +{ ':', 58 }, +{ ';', 59 }, +{ '<', 60 }, +{ '=', 61 }, +{ '>', 62 }, +{ '?', 63 }, +{ '@', 64 }, +{ 'A', 65 }, +{ 'B', 66 }, +{ 'C', 67 }, +{ 'D', 68 }, +{ 'E', 69 }, +{ 'F', 70 }, +{ 'G', 71 }, +{ 'H', 72 }, +{ 'I', 73 }, +{ 'J', 74 }, +{ 'K', 75 }, +{ 'L', 76 }, +{ 'M', 77 }, +{ 'N', 78 }, +{ 'O', 79 }, +{ 'P', 80 }, +{ 'Q', 81 }, +{ 'R', 82 }, +{ 'S', 83 }, +{ 'T', 84 }, +{ 'U', 85 }, +{ 'V', 86 }, +{ 'W', 87 }, +{ 'X', 88 }, +{ 'Y', 89 }, +{ 'Z', 90 }, +{ '[', 91 }, +{ ']', 93 }, +{ '_', 95 }, +{ 'a', 97 }, +{ 'b', 98 }, +{ 'c', 99 }, +{ 'd', 100 }, +{ 'e', 101 }, +{ 'f', 102 }, +{ 'g', 103 }, +{ 'h', 104 }, +{ 'i', 105 }, +{ 'j', 106 }, +{ 'k', 107 }, +{ 'l', 108 }, +{ 'm', 109 }, +{ 'n', 110 }, +{ 'o', 111 }, +{ 'p', 112 }, +{ 'q', 113 }, +{ 'r', 114 }, +{ 's', 115 }, +{ 't', 116 }, +{ 'u', 117 }, +{ 'v', 118 }, +{ 'w', 119 }, +{ 'x', 120 }, +{ 'y', 121 }, +{ 'z', 122 }, +{ '|', 124 }, +{ ' ', 160 }, +{ 0xa1, 161 }, +{ 0xa2, 162 }, +{ 0xa3, 163 }, +{ '$', 164 }, +{ 0xa5, 165 }, +{ '#', 166 }, +{ 0xa7, 167 }, +{ 0xa4, 168 }, +{ 0xab, 171 }, +{ 0xb0, 176 }, +{ 0xb1, 177 }, +{ 0xb2, 178 }, +{ 0xb3, 179 }, +{ 0xd7, 180 }, +{ 0xb5, 181 }, +{ 0xb6, 182 }, +{ 0xb7, 183 }, +{ 0xf7, 184 }, +{ 0xbb, 187 }, +{ 0xbc, 188 }, +{ 0xbd, 189 }, +{ 0xbe, 190 }, +{ 0xbf, 191 }, +}; + +int der_teletex_char_encode(int c) +{ + int x; + for (x = 0; x < (int)(sizeof(teletex_table)/sizeof(teletex_table[0])); x++) { + if (teletex_table[x].code == c) { + return teletex_table[x].value; + } + } + return -1; +} + +int der_teletex_value_decode(int v) +{ + int x; + for (x = 0; x < (int)(sizeof(teletex_table)/sizeof(teletex_table[0])); x++) { + if (teletex_table[x].value == v) { + return teletex_table[x].code; + } + } + return -1; +} + +/** + Gets length of DER encoding of teletex STRING + @param octets The values you want to encode + @param noctets The number of octets in the string to encode + @param outlen [out] The length of the DER encoding for the given string + @return CRYPT_OK if successful +*/ +int der_length_teletex_string(const unsigned char *octets, unsigned long noctets, unsigned long *outlen) +{ + unsigned long x; + + LTC_ARGCHK(outlen != NULL); + LTC_ARGCHK(octets != NULL); + + /* scan string for validity */ + for (x = 0; x < noctets; x++) { + if (der_teletex_char_encode(octets[x]) == -1) { + return CRYPT_INVALID_ARG; + } + } + + if (noctets < 128) { + /* 16 LL DD DD DD ... */ + *outlen = 2 + noctets; + } else if (noctets < 256) { + /* 16 81 LL DD DD DD ... */ + *outlen = 3 + noctets; + } else if (noctets < 65536UL) { + /* 16 82 LL LL DD DD DD ... */ + *outlen = 4 + noctets; + } else if (noctets < 16777216UL) { + /* 16 83 LL LL LL DD DD DD ... */ + *outlen = 5 + noctets; + } else { + return CRYPT_INVALID_ARG; + } + + return CRYPT_OK; +} + +#endif + + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */