Merge pull request #309 from libtom/pr/ecc-asn1-part-minimal

ECC-step1: ASN.1 changes required for future ECC enhancements
This commit is contained in:
Steffen Jaeckel 2018-02-25 23:34:09 +01:00 committed by GitHub
commit 64298c1819
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
85 changed files with 2926 additions and 1056 deletions

View File

@ -5563,6 +5563,10 @@ typedef struct {
void *data;
unsigned long size;
int used;
int optional;
ltc_asn1_class class;
ltc_asn1_pc pc;
ulong64 tag;
struct ltc_asn1_list_ *prev, *next,
*child, *parent;
} ltc_asn1_list;
@ -5625,9 +5629,8 @@ LTC_SET_ASN1(sequence, x++, LTC_ASN1_NULL, NULL, 0);
\hline LTC\_ASN1\_SETOF & SET OF \\
\hline LTC\_ASN1\_RAW\_BIT\_STRING & BIT STRING (one octet per char) \\
\hline LTC\_ASN1\_TELETEX\_STRING & TELETEX STRING (one octet per char) \\
\hline LTC\_ASN1\_CONSTRUCTED & A constructed type that is not SEQUENCE or SET \\
\hline LTC\_ASN1\_CONTEXT\_SPECIFIC & A context-specific type \\
\hline LTC\_ASN1\_GENERALIZEDTIME & GeneralizedTime (see ltc\_generalizedtime structure) \\
\hline LTC\_ASN1\_CUSTOM\_TYPE & A custom type (see LTC\_SET\_ASN1\_CUSTOM\_XXX macros) \\
\hline
\end{tabular}
\caption{List of ASN.1 Supported Types}
@ -5636,6 +5639,36 @@ LTC_SET_ASN1(sequence, x++, LTC_ASN1_NULL, NULL, 0);
\end{center}
\end{figure}
\index{LTC\_ASN1\_CUSTOM\_TYPE}
\index{LTC\_SET\_ASN1\_CUSTOM\_CONSTRUCTED macro}
\index{LTC\_SET\_ASN1\_CUSTOM\_PRIMITIVE macro}
To be able to encode and decode all other valid ASN.1 Identifiers, such as Context-Specific types the macros
\textit{LTC\_SET\_ASN1\_CUSTOM\_CONSTRUCTED(list, index, Class, Tag, Data)} resp.
\textit{LTC\_SET\_ASN1\_CUSTOM\_PRIMITIVE(list, index, Class, Tag, Type, Data, Size)} have been provided.
They will assign to the \textit{index}th position in the \textit{list} the Identifier-triplet (Class, CONSTRUCTED resp. PRIMITIVE, Tag).
An example usage would be:
\begin{small}
\begin{verbatim}
...
ltc_asn1_list sequence[4], custom[1];
unsigned long three=3;
unsigned char buf[128];
LTC_SET_ASN1(sequence, 0, LTC_ASN1_IA5_STRING, "hello", 5);
LTC_SET_ASN1(sequence, 1, LTC_ASN1_SHORT_INTEGER, &three, 1);
LTC_SET_ASN1(sequence, 2, LTC_ASN1_NULL, NULL, 0);
LTC_SET_ASN1_CUSTOM_PRIMITIVE(sequence, 3, LTC_ASN1_CL_CONTEXT_SPECIFIC, 23, \
LTC_ASN1_OCTET_STRING, buf, sizeof(buf));
LTC_SET_ASN1_CUSTOM_CONSTRUCTED(custom, 0, LTC_ASN1_CL_CONTEXT_SPECIFIC, 0, sequence);
\end{verbatim}
\end{small}
This would allow (un)pack'ing the given \textit{sequence} from/in the context-specific tag \textit{[0]}.
\subsection{SEQUENCE Type}
The SEQUENCE data type is a collection of other ASN.1 data types encapsulated with a small header which is a useful way of sending multiple data types in one packet.
@ -5660,6 +5693,7 @@ the \textit{data} pointer is simply a pointer to another \textbf{ltc\_asn1\_list
\subsubsection{SEQUENCE Decoding}
\index{der\_decode\_sequence()}
\index{der\_decode\_sequence\_strict()}
Decoding a SEQUENCE is similar to encoding. You set up an array of \textbf{ltc\_asn1\_list} where in this case the \textit{size} member is the maximum size
(in certain cases). For types such as IA5 STRING, BIT STRING, OCTET STRING (etc) the \textit{size} field is updated after successful decoding to reflect how many
@ -5670,18 +5704,27 @@ int der_decode_sequence(const unsigned char *in,
unsigned long inlen,
ltc_asn1_list *list,
unsigned long outlen);
int der_decode_sequence_strict(const unsigned char *in,
unsigned long inlen,
ltc_asn1_list *list,
unsigned long outlen);
\end{verbatim}
This will decode upto \textit{outlen} items from the input buffer \textit{in} of length \textit{inlen} octets. The function will stop (gracefully) when it runs out of items to decode.
It will fail (for among other reasons) when it runs out of input bytes to read, a data type is invalid or a heap failure occurred.
The regular variant will return \textbf{CRYPT\_INPUT\_TOO\_LONG} in cases where there was more data to be decoded given through \textit{inlen} than the ASN.1 length-tag specified.
The strict variant \textit{der\_decode\_sequence\_strict()} returns an error in this case.
For the following types the \textit{size} field will be updated to reflect the number of units read of the given type.
\begin{enumerate}
\item BIT STRING
\item (RAW) BIT STRING
\item OCTET STRING
\item OBJECT IDENTIFIER
\item IA5 STRING
\item PRINTABLE STRING
\item TELETEX STRING
\item UTF8 STRING
\end{enumerate}
\subsubsection{SEQUENCE Length}
@ -6139,32 +6182,53 @@ This will decode the input in the \textit{in} field of length \textit{inlen}. I
\textit{outlen} elements. The \textit{inlen} field will be updated with the length of the decoded data type, as well as the respective entry in the \textit{list} field
will have the \textit{used} flag set to non--zero to reflect it was the data type decoded.
\subsection{ASN.1 Custom Types}
To be able to represent all other valid types besides the primitive types having their own decoder, the \textit{custom\_type} de- and encoders are provided.
\index{der\_encode\_custom\_type()} \index{der\_decode\_custom\_type()} \index{der\_length\_custom\_type()} \index{LTC\_ASN1\_CUSTOM\_TYPE}
\begin{verbatim}
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);
\end{verbatim}
The usage of this de- and encoder is a bit different than the others since the type to be encoded has to be passed to the function.
Therefore the \textit{root} parameter identifies the type that should be encoded which has been set by the \textit{LTC\_SET\_ASN1}
and \textit{LTC\_SET\_ASN1\_IDENTIFIER}, resp. \textit{LTC\_SET\_ASN1\_CUSTOM} macros.
The value to de-/encode has to be linked through the \textit{data} argument of the \textit{LTC\_SET\_ASN1} macro, as done for sequences.
The value that should be de-/encoded can either be a primitive or a constructed type.
\subsection{ASN.1 Flexi Decoder}
The ASN.1 \textit{flexi} decoder allows the developer to decode arbitrary ASN.1 DER packets (provided they use data types LibTomCrypt supports) without first knowing
the structure of the data. Where der\_decode\_sequence() requires the developer to specify the data types to decode in advance the flexi decoder is entirely
free form.
The ASN.1 \textit{flexi} decoder allows the developer to decode arbitrary ASN.1 DER packets without first knowing the structure of the data.
Where der\_decode\_sequence() requires the developer to specify the data types to decode in advance the flexi decoder is entirely free form.
The flexi decoder uses the same \textit{ltc\_asn1\_list} but instead of being stored in an array it uses the linked list pointers \textit{prev}, \textit{next}, \textit{parent}
and \textit{child}. The list works as a \textit{doubly-linked list} structure where decoded items at the same level are siblings (using next and prev) and items
encoded in a SEQUENCE are stored as a child element.
and \textit{child}. The list works as a \textit{doubly-linked list} structure where decoded items at the same level are siblings (using \textit{next} and \textit{prev}) and items
encoded in a SEQUENCE are stored as a \textit{child} element.
When a SEQUENCE or SET has been encountered a SEQUENCE (or SET resp.) item will be added as a sibling (e.g. list.type == LTC\_ASN1\_SEQUENCE) and the child
When a SEQUENCE or SET has been encountered a SEQUENCE (or SET resp.) item will be added as a sibling (e.g. list.type == LTC\_ASN1\_SEQUENCE) and the \textit{child}
pointer points to a new list of items contained within the object.
\index{der\_decode\_sequence\_flexi()}
\index{LTC\_ASN1\_CONSTRUCTED}
\index{LTC\_ASN1\_CONTEXT\_SPECIFIC}
\begin{verbatim}
int der_decode_sequence_flexi(const unsigned char *in,
unsigned long *inlen,
ltc_asn1_list **out);
ltc_asn1_list **out);
\end{verbatim}
This will decode items in the \textit{in} buffer of max input length \textit{inlen} and store the newly created pointer to the list in \textit{out}. This function allocates
all required memory for the decoding. It stores the number of octets read back into \textit{inlen}.
The function will terminate when either it hits an invalid ASN.1 tag, or it reads \textit{inlen} octets. An early termination is a soft error, and returns
normally. The decoded list \textit{out} will point to the very first element of the list (e.g. both parent and prev pointers will be \textbf{NULL}).
normally. The decoded list \textit{out} will point to the very first element of the list (i.e. both parent and prev pointers will be \textbf{NULL}).
An invalid decoding will terminate the process, and free the allocated memory automatically.
@ -6175,18 +6239,12 @@ However the parent processing will continue with a "soft-error".
This can be detected by checking for \textit{child} elements with
type \textbf{LTC\_ASN1\_EOL} after decoding.
As of v1.18.0 the flexi decoder will also decode arbitrary constructed types
other than SEQUENCE and SET. The \textit{type} field will be set to
\textbf{LTC\_ASN1\_CONSTRUCTED} and the plain identifier that was indicated in the ASN.1
encoding is stored in the \textit{used} field. Further decoding is done in the
same way as if it were a SEQUENCE or SET.
The v1.18.0 of the library had support for decoding two new types, \textbf{LTC\_ASN1\_CONSTRUCTED} and \textbf{LTC\_ASN1\_CONTEXT\_SPECIFIC},
which has been replaced in FIXME-version-next by a more complete approach.
As of FIXME-version-next all ASN.1 Identifiers which don't have a decoder implemented (and thereby their own type) will be marked as
\textbf{LTC\_ASN1\_CUSTOM\_TYPE}.
Also as of v1.18.0 the flexi decoder is capable to handle
\textit{context-specific} encodings. The \textit{type} field will be set to
\textbf{LTC\_ASN1\_CONTEXT\_SPECIFIC} and the plain identifier that was indicated
in the ASN.1 encoding is stored in the \textit{used} field. Encapsulated data
in the \textit{context-specific} encoding is copied to newly allocated memory
and is accessible through the \textit{data} field.
\textbf{Note:} the list decoded by this function is \textbf{NOT} in the correct form for der\_encode\_sequence() to use directly. You will first
have to convert the list by first storing all of the siblings in an array then storing all the children as sub-lists of a sequence using the \textit{.data}

View File

@ -1849,6 +1849,54 @@
>
</File>
</Filter>
<Filter
Name="custom_type"
>
<File
RelativePath="src\pk\asn1\der\custom_type\der_decode_custom_type.c"
>
</File>
<File
RelativePath="src\pk\asn1\der\custom_type\der_encode_custom_type.c"
>
</File>
<File
RelativePath="src\pk\asn1\der\custom_type\der_length_custom_type.c"
>
</File>
</Filter>
<Filter
Name="general"
>
<File
RelativePath="src\pk\asn1\der\general\der_asn1_maps.c"
>
</File>
<File
RelativePath="src\pk\asn1\der\general\der_decode_asn1_identifier.c"
>
</File>
<File
RelativePath="src\pk\asn1\der\general\der_decode_asn1_length.c"
>
</File>
<File
RelativePath="src\pk\asn1\der\general\der_encode_asn1_identifier.c"
>
</File>
<File
RelativePath="src\pk\asn1\der\general\der_encode_asn1_length.c"
>
</File>
<File
RelativePath="src\pk\asn1\der\general\der_length_asn1_identifier.c"
>
</File>
<File
RelativePath="src\pk\asn1\der\general\der_length_asn1_length.c"
>
</File>
</Filter>
<Filter
Name="generalizedtime"
>
@ -1960,10 +2008,6 @@
RelativePath="src\pk\asn1\der\sequence\der_decode_sequence_multi.c"
>
</File>
<File
RelativePath="src\pk\asn1\der\sequence\der_decode_subject_public_key_info.c"
>
</File>
<File
RelativePath="src\pk\asn1\der\sequence\der_encode_sequence_ex.c"
>
@ -1972,10 +2016,6 @@
RelativePath="src\pk\asn1\der\sequence\der_encode_sequence_multi.c"
>
</File>
<File
RelativePath="src\pk\asn1\der\sequence\der_encode_subject_public_key_info.c"
>
</File>
<File
RelativePath="src\pk\asn1\der\sequence\der_length_sequence.c"
>
@ -2062,6 +2102,18 @@
</File>
</Filter>
</Filter>
<Filter
Name="x509"
>
<File
RelativePath="src\pk\asn1\x509\x509_decode_subject_public_key_info.c"
>
</File>
<File
RelativePath="src\pk\asn1\x509\x509_encode_subject_public_key_info.c"
>
</File>
</Filter>
</Filter>
<Filter
Name="dh"

View File

@ -130,6 +130,12 @@ src/pk/asn1/der/bit/der_decode_raw_bit_string.o src/pk/asn1/der/bit/der_encode_b
src/pk/asn1/der/bit/der_encode_raw_bit_string.o src/pk/asn1/der/bit/der_length_bit_string.o \
src/pk/asn1/der/boolean/der_decode_boolean.o src/pk/asn1/der/boolean/der_encode_boolean.o \
src/pk/asn1/der/boolean/der_length_boolean.o src/pk/asn1/der/choice/der_decode_choice.o \
src/pk/asn1/der/custom_type/der_decode_custom_type.o \
src/pk/asn1/der/custom_type/der_encode_custom_type.o \
src/pk/asn1/der/custom_type/der_length_custom_type.o src/pk/asn1/der/general/der_asn1_maps.o \
src/pk/asn1/der/general/der_decode_asn1_identifier.o src/pk/asn1/der/general/der_decode_asn1_length.o \
src/pk/asn1/der/general/der_encode_asn1_identifier.o src/pk/asn1/der/general/der_encode_asn1_length.o \
src/pk/asn1/der/general/der_length_asn1_identifier.o src/pk/asn1/der/general/der_length_asn1_length.o \
src/pk/asn1/der/generalizedtime/der_decode_generalizedtime.o \
src/pk/asn1/der/generalizedtime/der_encode_generalizedtime.o \
src/pk/asn1/der/generalizedtime/der_length_generalizedtime.o \
@ -147,13 +153,11 @@ src/pk/asn1/der/printable_string/der_length_printable_string.o \
src/pk/asn1/der/sequence/der_decode_sequence_ex.o \
src/pk/asn1/der/sequence/der_decode_sequence_flexi.o \
src/pk/asn1/der/sequence/der_decode_sequence_multi.o \
src/pk/asn1/der/sequence/der_decode_subject_public_key_info.o \
src/pk/asn1/der/sequence/der_encode_sequence_ex.o \
src/pk/asn1/der/sequence/der_encode_sequence_multi.o \
src/pk/asn1/der/sequence/der_encode_subject_public_key_info.o \
src/pk/asn1/der/sequence/der_length_sequence.o src/pk/asn1/der/sequence/der_sequence_free.o \
src/pk/asn1/der/sequence/der_sequence_shrink.o src/pk/asn1/der/set/der_encode_set.o \
src/pk/asn1/der/set/der_encode_setof.o src/pk/asn1/der/short_integer/der_decode_short_integer.o \
src/pk/asn1/der/sequence/der_encode_sequence_multi.o src/pk/asn1/der/sequence/der_length_sequence.o \
src/pk/asn1/der/sequence/der_sequence_free.o src/pk/asn1/der/sequence/der_sequence_shrink.o \
src/pk/asn1/der/set/der_encode_set.o src/pk/asn1/der/set/der_encode_setof.o \
src/pk/asn1/der/short_integer/der_decode_short_integer.o \
src/pk/asn1/der/short_integer/der_encode_short_integer.o \
src/pk/asn1/der/short_integer/der_length_short_integer.o \
src/pk/asn1/der/teletex_string/der_decode_teletex_string.o \
@ -161,10 +165,11 @@ src/pk/asn1/der/teletex_string/der_length_teletex_string.o \
src/pk/asn1/der/utctime/der_decode_utctime.o src/pk/asn1/der/utctime/der_encode_utctime.o \
src/pk/asn1/der/utctime/der_length_utctime.o src/pk/asn1/der/utf8/der_decode_utf8_string.o \
src/pk/asn1/der/utf8/der_encode_utf8_string.o src/pk/asn1/der/utf8/der_length_utf8_string.o \
src/pk/dh/dh.o src/pk/dh/dh_check_pubkey.o src/pk/dh/dh_export.o src/pk/dh/dh_export_key.o \
src/pk/dh/dh_free.o src/pk/dh/dh_generate_key.o src/pk/dh/dh_import.o src/pk/dh/dh_set.o \
src/pk/dh/dh_set_pg_dhparam.o src/pk/dh/dh_shared_secret.o src/pk/dsa/dsa_decrypt_key.o \
src/pk/dsa/dsa_encrypt_key.o src/pk/dsa/dsa_export.o src/pk/dsa/dsa_free.o \
src/pk/asn1/x509/x509_decode_subject_public_key_info.o \
src/pk/asn1/x509/x509_encode_subject_public_key_info.o src/pk/dh/dh.o src/pk/dh/dh_check_pubkey.o \
src/pk/dh/dh_export.o src/pk/dh/dh_export_key.o src/pk/dh/dh_free.o src/pk/dh/dh_generate_key.o \
src/pk/dh/dh_import.o src/pk/dh/dh_set.o src/pk/dh/dh_set_pg_dhparam.o src/pk/dh/dh_shared_secret.o \
src/pk/dsa/dsa_decrypt_key.o src/pk/dsa/dsa_encrypt_key.o src/pk/dsa/dsa_export.o src/pk/dsa/dsa_free.o \
src/pk/dsa/dsa_generate_key.o src/pk/dsa/dsa_generate_pqg.o src/pk/dsa/dsa_import.o \
src/pk/dsa/dsa_make_key.o src/pk/dsa/dsa_set.o src/pk/dsa/dsa_set_pqg_dsaparam.o \
src/pk/dsa/dsa_shared_secret.o src/pk/dsa/dsa_sign_hash.o src/pk/dsa/dsa_verify_hash.o \

View File

@ -123,6 +123,12 @@ src/pk/asn1/der/bit/der_decode_raw_bit_string.obj src/pk/asn1/der/bit/der_encode
src/pk/asn1/der/bit/der_encode_raw_bit_string.obj src/pk/asn1/der/bit/der_length_bit_string.obj \
src/pk/asn1/der/boolean/der_decode_boolean.obj src/pk/asn1/der/boolean/der_encode_boolean.obj \
src/pk/asn1/der/boolean/der_length_boolean.obj src/pk/asn1/der/choice/der_decode_choice.obj \
src/pk/asn1/der/custom_type/der_decode_custom_type.obj \
src/pk/asn1/der/custom_type/der_encode_custom_type.obj \
src/pk/asn1/der/custom_type/der_length_custom_type.obj src/pk/asn1/der/general/der_asn1_maps.obj \
src/pk/asn1/der/general/der_decode_asn1_identifier.obj src/pk/asn1/der/general/der_decode_asn1_length.obj \
src/pk/asn1/der/general/der_encode_asn1_identifier.obj src/pk/asn1/der/general/der_encode_asn1_length.obj \
src/pk/asn1/der/general/der_length_asn1_identifier.obj src/pk/asn1/der/general/der_length_asn1_length.obj \
src/pk/asn1/der/generalizedtime/der_decode_generalizedtime.obj \
src/pk/asn1/der/generalizedtime/der_encode_generalizedtime.obj \
src/pk/asn1/der/generalizedtime/der_length_generalizedtime.obj \
@ -140,13 +146,11 @@ src/pk/asn1/der/printable_string/der_length_printable_string.obj \
src/pk/asn1/der/sequence/der_decode_sequence_ex.obj \
src/pk/asn1/der/sequence/der_decode_sequence_flexi.obj \
src/pk/asn1/der/sequence/der_decode_sequence_multi.obj \
src/pk/asn1/der/sequence/der_decode_subject_public_key_info.obj \
src/pk/asn1/der/sequence/der_encode_sequence_ex.obj \
src/pk/asn1/der/sequence/der_encode_sequence_multi.obj \
src/pk/asn1/der/sequence/der_encode_subject_public_key_info.obj \
src/pk/asn1/der/sequence/der_length_sequence.obj src/pk/asn1/der/sequence/der_sequence_free.obj \
src/pk/asn1/der/sequence/der_sequence_shrink.obj src/pk/asn1/der/set/der_encode_set.obj \
src/pk/asn1/der/set/der_encode_setof.obj src/pk/asn1/der/short_integer/der_decode_short_integer.obj \
src/pk/asn1/der/sequence/der_encode_sequence_multi.obj src/pk/asn1/der/sequence/der_length_sequence.obj \
src/pk/asn1/der/sequence/der_sequence_free.obj src/pk/asn1/der/sequence/der_sequence_shrink.obj \
src/pk/asn1/der/set/der_encode_set.obj src/pk/asn1/der/set/der_encode_setof.obj \
src/pk/asn1/der/short_integer/der_decode_short_integer.obj \
src/pk/asn1/der/short_integer/der_encode_short_integer.obj \
src/pk/asn1/der/short_integer/der_length_short_integer.obj \
src/pk/asn1/der/teletex_string/der_decode_teletex_string.obj \
@ -154,10 +158,11 @@ src/pk/asn1/der/teletex_string/der_length_teletex_string.obj \
src/pk/asn1/der/utctime/der_decode_utctime.obj src/pk/asn1/der/utctime/der_encode_utctime.obj \
src/pk/asn1/der/utctime/der_length_utctime.obj src/pk/asn1/der/utf8/der_decode_utf8_string.obj \
src/pk/asn1/der/utf8/der_encode_utf8_string.obj src/pk/asn1/der/utf8/der_length_utf8_string.obj \
src/pk/dh/dh.obj src/pk/dh/dh_check_pubkey.obj src/pk/dh/dh_export.obj src/pk/dh/dh_export_key.obj \
src/pk/dh/dh_free.obj src/pk/dh/dh_generate_key.obj src/pk/dh/dh_import.obj src/pk/dh/dh_set.obj \
src/pk/dh/dh_set_pg_dhparam.obj src/pk/dh/dh_shared_secret.obj src/pk/dsa/dsa_decrypt_key.obj \
src/pk/dsa/dsa_encrypt_key.obj src/pk/dsa/dsa_export.obj src/pk/dsa/dsa_free.obj \
src/pk/asn1/x509/x509_decode_subject_public_key_info.obj \
src/pk/asn1/x509/x509_encode_subject_public_key_info.obj src/pk/dh/dh.obj src/pk/dh/dh_check_pubkey.obj \
src/pk/dh/dh_export.obj src/pk/dh/dh_export_key.obj src/pk/dh/dh_free.obj src/pk/dh/dh_generate_key.obj \
src/pk/dh/dh_import.obj src/pk/dh/dh_set.obj src/pk/dh/dh_set_pg_dhparam.obj src/pk/dh/dh_shared_secret.obj \
src/pk/dsa/dsa_decrypt_key.obj src/pk/dsa/dsa_encrypt_key.obj src/pk/dsa/dsa_export.obj src/pk/dsa/dsa_free.obj \
src/pk/dsa/dsa_generate_key.obj src/pk/dsa/dsa_generate_pqg.obj src/pk/dsa/dsa_import.obj \
src/pk/dsa/dsa_make_key.obj src/pk/dsa/dsa_set.obj src/pk/dsa/dsa_set_pqg_dsaparam.obj \
src/pk/dsa/dsa_shared_secret.obj src/pk/dsa/dsa_sign_hash.obj src/pk/dsa/dsa_verify_hash.obj \

View File

@ -140,6 +140,12 @@ src/pk/asn1/der/bit/der_decode_raw_bit_string.o src/pk/asn1/der/bit/der_encode_b
src/pk/asn1/der/bit/der_encode_raw_bit_string.o src/pk/asn1/der/bit/der_length_bit_string.o \
src/pk/asn1/der/boolean/der_decode_boolean.o src/pk/asn1/der/boolean/der_encode_boolean.o \
src/pk/asn1/der/boolean/der_length_boolean.o src/pk/asn1/der/choice/der_decode_choice.o \
src/pk/asn1/der/custom_type/der_decode_custom_type.o \
src/pk/asn1/der/custom_type/der_encode_custom_type.o \
src/pk/asn1/der/custom_type/der_length_custom_type.o src/pk/asn1/der/general/der_asn1_maps.o \
src/pk/asn1/der/general/der_decode_asn1_identifier.o src/pk/asn1/der/general/der_decode_asn1_length.o \
src/pk/asn1/der/general/der_encode_asn1_identifier.o src/pk/asn1/der/general/der_encode_asn1_length.o \
src/pk/asn1/der/general/der_length_asn1_identifier.o src/pk/asn1/der/general/der_length_asn1_length.o \
src/pk/asn1/der/generalizedtime/der_decode_generalizedtime.o \
src/pk/asn1/der/generalizedtime/der_encode_generalizedtime.o \
src/pk/asn1/der/generalizedtime/der_length_generalizedtime.o \
@ -157,13 +163,11 @@ src/pk/asn1/der/printable_string/der_length_printable_string.o \
src/pk/asn1/der/sequence/der_decode_sequence_ex.o \
src/pk/asn1/der/sequence/der_decode_sequence_flexi.o \
src/pk/asn1/der/sequence/der_decode_sequence_multi.o \
src/pk/asn1/der/sequence/der_decode_subject_public_key_info.o \
src/pk/asn1/der/sequence/der_encode_sequence_ex.o \
src/pk/asn1/der/sequence/der_encode_sequence_multi.o \
src/pk/asn1/der/sequence/der_encode_subject_public_key_info.o \
src/pk/asn1/der/sequence/der_length_sequence.o src/pk/asn1/der/sequence/der_sequence_free.o \
src/pk/asn1/der/sequence/der_sequence_shrink.o src/pk/asn1/der/set/der_encode_set.o \
src/pk/asn1/der/set/der_encode_setof.o src/pk/asn1/der/short_integer/der_decode_short_integer.o \
src/pk/asn1/der/sequence/der_encode_sequence_multi.o src/pk/asn1/der/sequence/der_length_sequence.o \
src/pk/asn1/der/sequence/der_sequence_free.o src/pk/asn1/der/sequence/der_sequence_shrink.o \
src/pk/asn1/der/set/der_encode_set.o src/pk/asn1/der/set/der_encode_setof.o \
src/pk/asn1/der/short_integer/der_decode_short_integer.o \
src/pk/asn1/der/short_integer/der_encode_short_integer.o \
src/pk/asn1/der/short_integer/der_length_short_integer.o \
src/pk/asn1/der/teletex_string/der_decode_teletex_string.o \
@ -171,10 +175,11 @@ src/pk/asn1/der/teletex_string/der_length_teletex_string.o \
src/pk/asn1/der/utctime/der_decode_utctime.o src/pk/asn1/der/utctime/der_encode_utctime.o \
src/pk/asn1/der/utctime/der_length_utctime.o src/pk/asn1/der/utf8/der_decode_utf8_string.o \
src/pk/asn1/der/utf8/der_encode_utf8_string.o src/pk/asn1/der/utf8/der_length_utf8_string.o \
src/pk/dh/dh.o src/pk/dh/dh_check_pubkey.o src/pk/dh/dh_export.o src/pk/dh/dh_export_key.o \
src/pk/dh/dh_free.o src/pk/dh/dh_generate_key.o src/pk/dh/dh_import.o src/pk/dh/dh_set.o \
src/pk/dh/dh_set_pg_dhparam.o src/pk/dh/dh_shared_secret.o src/pk/dsa/dsa_decrypt_key.o \
src/pk/dsa/dsa_encrypt_key.o src/pk/dsa/dsa_export.o src/pk/dsa/dsa_free.o \
src/pk/asn1/x509/x509_decode_subject_public_key_info.o \
src/pk/asn1/x509/x509_encode_subject_public_key_info.o src/pk/dh/dh.o src/pk/dh/dh_check_pubkey.o \
src/pk/dh/dh_export.o src/pk/dh/dh_export_key.o src/pk/dh/dh_free.o src/pk/dh/dh_generate_key.o \
src/pk/dh/dh_import.o src/pk/dh/dh_set.o src/pk/dh/dh_set_pg_dhparam.o src/pk/dh/dh_shared_secret.o \
src/pk/dsa/dsa_decrypt_key.o src/pk/dsa/dsa_encrypt_key.o src/pk/dsa/dsa_export.o src/pk/dsa/dsa_free.o \
src/pk/dsa/dsa_generate_key.o src/pk/dsa/dsa_generate_pqg.o src/pk/dsa/dsa_import.o \
src/pk/dsa/dsa_make_key.o src/pk/dsa/dsa_set.o src/pk/dsa/dsa_set_pqg_dsaparam.o \
src/pk/dsa/dsa_shared_secret.o src/pk/dsa/dsa_sign_hash.o src/pk/dsa/dsa_verify_hash.o \

View File

@ -280,6 +280,12 @@ src/pk/asn1/der/bit/der_decode_raw_bit_string.o src/pk/asn1/der/bit/der_encode_b
src/pk/asn1/der/bit/der_encode_raw_bit_string.o src/pk/asn1/der/bit/der_length_bit_string.o \
src/pk/asn1/der/boolean/der_decode_boolean.o src/pk/asn1/der/boolean/der_encode_boolean.o \
src/pk/asn1/der/boolean/der_length_boolean.o src/pk/asn1/der/choice/der_decode_choice.o \
src/pk/asn1/der/custom_type/der_decode_custom_type.o \
src/pk/asn1/der/custom_type/der_encode_custom_type.o \
src/pk/asn1/der/custom_type/der_length_custom_type.o src/pk/asn1/der/general/der_asn1_maps.o \
src/pk/asn1/der/general/der_decode_asn1_identifier.o src/pk/asn1/der/general/der_decode_asn1_length.o \
src/pk/asn1/der/general/der_encode_asn1_identifier.o src/pk/asn1/der/general/der_encode_asn1_length.o \
src/pk/asn1/der/general/der_length_asn1_identifier.o src/pk/asn1/der/general/der_length_asn1_length.o \
src/pk/asn1/der/generalizedtime/der_decode_generalizedtime.o \
src/pk/asn1/der/generalizedtime/der_encode_generalizedtime.o \
src/pk/asn1/der/generalizedtime/der_length_generalizedtime.o \
@ -297,13 +303,11 @@ src/pk/asn1/der/printable_string/der_length_printable_string.o \
src/pk/asn1/der/sequence/der_decode_sequence_ex.o \
src/pk/asn1/der/sequence/der_decode_sequence_flexi.o \
src/pk/asn1/der/sequence/der_decode_sequence_multi.o \
src/pk/asn1/der/sequence/der_decode_subject_public_key_info.o \
src/pk/asn1/der/sequence/der_encode_sequence_ex.o \
src/pk/asn1/der/sequence/der_encode_sequence_multi.o \
src/pk/asn1/der/sequence/der_encode_subject_public_key_info.o \
src/pk/asn1/der/sequence/der_length_sequence.o src/pk/asn1/der/sequence/der_sequence_free.o \
src/pk/asn1/der/sequence/der_sequence_shrink.o src/pk/asn1/der/set/der_encode_set.o \
src/pk/asn1/der/set/der_encode_setof.o src/pk/asn1/der/short_integer/der_decode_short_integer.o \
src/pk/asn1/der/sequence/der_encode_sequence_multi.o src/pk/asn1/der/sequence/der_length_sequence.o \
src/pk/asn1/der/sequence/der_sequence_free.o src/pk/asn1/der/sequence/der_sequence_shrink.o \
src/pk/asn1/der/set/der_encode_set.o src/pk/asn1/der/set/der_encode_setof.o \
src/pk/asn1/der/short_integer/der_decode_short_integer.o \
src/pk/asn1/der/short_integer/der_encode_short_integer.o \
src/pk/asn1/der/short_integer/der_length_short_integer.o \
src/pk/asn1/der/teletex_string/der_decode_teletex_string.o \
@ -311,10 +315,11 @@ src/pk/asn1/der/teletex_string/der_length_teletex_string.o \
src/pk/asn1/der/utctime/der_decode_utctime.o src/pk/asn1/der/utctime/der_encode_utctime.o \
src/pk/asn1/der/utctime/der_length_utctime.o src/pk/asn1/der/utf8/der_decode_utf8_string.o \
src/pk/asn1/der/utf8/der_encode_utf8_string.o src/pk/asn1/der/utf8/der_length_utf8_string.o \
src/pk/dh/dh.o src/pk/dh/dh_check_pubkey.o src/pk/dh/dh_export.o src/pk/dh/dh_export_key.o \
src/pk/dh/dh_free.o src/pk/dh/dh_generate_key.o src/pk/dh/dh_import.o src/pk/dh/dh_set.o \
src/pk/dh/dh_set_pg_dhparam.o src/pk/dh/dh_shared_secret.o src/pk/dsa/dsa_decrypt_key.o \
src/pk/dsa/dsa_encrypt_key.o src/pk/dsa/dsa_export.o src/pk/dsa/dsa_free.o \
src/pk/asn1/x509/x509_decode_subject_public_key_info.o \
src/pk/asn1/x509/x509_encode_subject_public_key_info.o src/pk/dh/dh.o src/pk/dh/dh_check_pubkey.o \
src/pk/dh/dh_export.o src/pk/dh/dh_export_key.o src/pk/dh/dh_free.o src/pk/dh/dh_generate_key.o \
src/pk/dh/dh_import.o src/pk/dh/dh_set.o src/pk/dh/dh_set_pg_dhparam.o src/pk/dh/dh_shared_secret.o \
src/pk/dsa/dsa_decrypt_key.o src/pk/dsa/dsa_encrypt_key.o src/pk/dsa/dsa_export.o src/pk/dsa/dsa_free.o \
src/pk/dsa/dsa_generate_key.o src/pk/dsa/dsa_generate_pqg.o src/pk/dsa/dsa_import.o \
src/pk/dsa/dsa_make_key.o src/pk/dsa/dsa_set.o src/pk/dsa/dsa_set_pqg_dsaparam.o \
src/pk/dsa/dsa_shared_secret.o src/pk/dsa/dsa_sign_hash.o src/pk/dsa/dsa_verify_hash.o \

View File

@ -67,7 +67,7 @@ enum {
CRYPT_OVERFLOW, /* An overflow of a value was detected/prevented */
CRYPT_UNUSED1, /* UNUSED1 */
CRYPT_PK_ASN1_ERROR, /* An error occurred while en- or decoding ASN.1 data */
CRYPT_INPUT_TOO_LONG, /* The input was longer than expected. */

View File

@ -513,12 +513,22 @@ typedef enum ltc_asn1_type_ {
LTC_ASN1_SETOF,
LTC_ASN1_RAW_BIT_STRING,
LTC_ASN1_TELETEX_STRING,
LTC_ASN1_CONSTRUCTED,
LTC_ASN1_CONTEXT_SPECIFIC,
/* 20 */
LTC_ASN1_GENERALIZEDTIME,
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 */
@ -527,8 +537,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;
/** 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;
@ -541,39 +560,120 @@ 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].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)
#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;
extern const char* der_asn1_pc_to_string_map[];
extern const unsigned long der_asn1_pc_to_string_map_sz;
extern const char* der_asn1_tag_to_string_map[];
extern const unsigned long der_asn1_tag_to_string_map_sz;
/* SEQUENCE */
int der_encode_sequence_ex(ltc_asn1_list *list, unsigned long inlen,
unsigned char *out, unsigned long *outlen, int type_of);
#define der_encode_sequence(list, inlen, out, outlen) der_encode_sequence_ex(list, inlen, out, outlen, LTC_ASN1_SEQUENCE)
int der_decode_sequence_ex(const unsigned char *in, unsigned long inlen,
ltc_asn1_list *list, unsigned long outlen, int ordered);
/** The supported bitmap for all the
* decoders with a `flags` argument.
*/
enum ltc_der_seq {
LTC_DER_SEQ_ZERO = 0x0u,
#define der_decode_sequence(in, inlen, list, outlen) der_decode_sequence_ex(in, inlen, list, outlen, 1)
/** Bit0 - [0]=Unordered (SET or SETOF)
* [1]=Ordered (SEQUENCE) */
LTC_DER_SEQ_UNORDERED = LTC_DER_SEQ_ZERO,
LTC_DER_SEQ_ORDERED = 0x1u,
/** Bit1 - [0]=Relaxed
* [1]=Strict */
LTC_DER_SEQ_RELAXED = LTC_DER_SEQ_ZERO,
LTC_DER_SEQ_STRICT = 0x2u,
/** Alternative naming */
LTC_DER_SEQ_SET = LTC_DER_SEQ_UNORDERED,
LTC_DER_SEQ_SEQUENCE = LTC_DER_SEQ_ORDERED,
};
int der_decode_sequence_ex(const unsigned char *in, unsigned long inlen,
ltc_asn1_list *list, unsigned long outlen, unsigned int flags);
#define der_decode_sequence(in, inlen, list, outlen) der_decode_sequence_ex(in, inlen, list, outlen, LTC_DER_SEQ_SEQUENCE | LTC_DER_SEQ_RELAXED)
#define der_decode_sequence_strict(in, inlen, list, outlen) der_decode_sequence_ex(in, inlen, list, outlen, LTC_DER_SEQ_SEQUENCE | LTC_DER_SEQ_STRICT)
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_decode_custom_type_ex(const unsigned char *in, unsigned long inlen,
ltc_asn1_list *root,
ltc_asn1_list *list, unsigned long outlen, unsigned int flags);
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);
/* SUBJECT PUBLIC KEY INFO */
int der_encode_subject_public_key_info(unsigned char *out, unsigned long *outlen,
unsigned int algorithm, void* public_key, unsigned long public_key_len,
unsigned long parameters_type, void* parameters, unsigned long parameters_len);
int der_decode_subject_public_key_info(const unsigned char *in, unsigned long inlen,
unsigned int algorithm, void* public_key, unsigned long* public_key_len,
unsigned long parameters_type, ltc_asn1_list* parameters, unsigned long parameters_len);
extern const ltc_asn1_type der_asn1_tag_to_type_map[];
extern const unsigned long der_asn1_tag_to_type_map_sz;
extern const int der_asn1_type_to_identifier_map[];
extern const unsigned long der_asn1_type_to_identifier_map_sz;
#endif /* LTC_SOURCE */
/* SET */
#define der_decode_set(in, inlen, list, outlen) der_decode_sequence_ex(in, inlen, list, outlen, 0)
#define der_decode_set(in, inlen, list, outlen) der_decode_sequence_ex(in, inlen, list, outlen, LTC_DER_SEQ_SET)
#define der_length_set der_length_sequence
int der_encode_set(ltc_asn1_list *list, unsigned long inlen,
unsigned char *out, unsigned long *outlen);
@ -584,6 +684,10 @@ int der_encode_setof(ltc_asn1_list *list, unsigned long inlen,
/* VA list handy helpers with triplets of <type, size, data> */
int der_encode_sequence_multi(unsigned char *out, unsigned long *outlen, ...);
int der_decode_sequence_multi(const unsigned char *in, unsigned long inlen, ...);
#ifdef LTC_SOURCE
/* internal helper functions */
int der_decode_sequence_multi_ex(const unsigned char *in, unsigned long inlen, unsigned int flags, ...);
#endif /* LTC_SOURCE */
/* FLEXI DECODER handle unknown list decoder */
int der_decode_sequence_flexi(const unsigned char *in, unsigned long *inlen, ltc_asn1_list **out);
@ -739,6 +843,17 @@ int der_decode_generalizedtime(const unsigned char *in, unsigned long *inlen,
int der_length_generalizedtime(ltc_generalizedtime *gtime, unsigned long *outlen);
#ifdef LTC_SOURCE
/* internal helper functions */
/* SUBJECT PUBLIC KEY INFO */
int x509_encode_subject_public_key_info(unsigned char *out, unsigned long *outlen,
unsigned int algorithm, void* public_key, unsigned long public_key_len,
unsigned long parameters_type, void* parameters, unsigned long parameters_len);
int x509_decode_subject_public_key_info(const unsigned char *in, unsigned long inlen,
unsigned int algorithm, void* public_key, unsigned long* public_key_len,
unsigned long parameters_type, void* parameters, unsigned long *parameters_len);
#endif /* LTC_SOURCE */
#endif

View File

@ -47,7 +47,7 @@ static const crypt_constant _crypt_constants[] = {
_C_STRINGIFY(CRYPT_FILE_NOTFOUND),
_C_STRINGIFY(CRYPT_PK_INVALID_TYPE),
_C_STRINGIFY(CRYPT_OVERFLOW),
_C_STRINGIFY(CRYPT_UNUSED1),
_C_STRINGIFY(CRYPT_PK_ASN1_ERROR),
_C_STRINGIFY(CRYPT_INPUT_TOO_LONG),
_C_STRINGIFY(CRYPT_PK_INVALID_SIZE),
_C_STRINGIFY(CRYPT_INVALID_PRIME_SIZE),
@ -129,9 +129,8 @@ static const crypt_constant _crypt_constants[] = {
_C_STRINGIFY(LTC_ASN1_SETOF),
_C_STRINGIFY(LTC_ASN1_RAW_BIT_STRING),
_C_STRINGIFY(LTC_ASN1_TELETEX_STRING),
_C_STRINGIFY(LTC_ASN1_CONSTRUCTED),
_C_STRINGIFY(LTC_ASN1_CONTEXT_SPECIFIC),
_C_STRINGIFY(LTC_ASN1_GENERALIZEDTIME),
_C_STRINGIFY(LTC_ASN1_CUSTOM_TYPE),
#endif
#ifdef LTC_CTR_MODE

View File

@ -46,7 +46,7 @@ static const char * const err_2_str[] =
"An overflow of a value was detected/prevented.",
"UNUSED1.",
"An ASN.1 decoding error occurred.",
"The input was longer than expected.",

View File

@ -28,6 +28,7 @@ int der_decode_bit_string(const unsigned char *in, unsigned long inlen,
unsigned char *out, unsigned long *outlen)
{
unsigned long dlen, blen, x, y;
int err;
LTC_ARGCHK(in != NULL);
LTC_ARGCHK(out != NULL);
@ -47,27 +48,13 @@ int der_decode_bit_string(const unsigned char *in, unsigned long inlen,
x = 1;
/* get the length of the data */
if (in[x] & 0x80) {
/* long format get number of length bytes */
y = in[x++] & 0x7F;
/* invalid if 0 or > 2 */
if (y == 0 || y > 2) {
return CRYPT_INVALID_PACKET;
}
/* read the data len */
dlen = 0;
while (y--) {
dlen = (dlen << 8) | (unsigned long)in[x++];
}
} else {
/* short format */
dlen = in[x++] & 0x7F;
y = inlen - 1;
if ((err = der_decode_asn1_length(in + x, &y, &dlen)) != CRYPT_OK) {
return err;
}
x += y;
/* is the data len too long or too short? */
if ((dlen == 0) || (dlen + x > inlen)) {
if ((dlen == 0) || (dlen > (inlen - x))) {
return CRYPT_INVALID_PACKET;
}

View File

@ -31,6 +31,7 @@ int der_decode_raw_bit_string(const unsigned char *in, unsigned long inlen,
unsigned char *out, unsigned long *outlen)
{
unsigned long dlen, blen, x, y;
int err;
LTC_ARGCHK(in != NULL);
LTC_ARGCHK(out != NULL);
@ -50,27 +51,13 @@ int der_decode_raw_bit_string(const unsigned char *in, unsigned long inlen,
x = 1;
/* get the length of the data */
if (in[x] & 0x80) {
/* long format get number of length bytes */
y = in[x++] & 0x7F;
/* invalid if 0 or > 2 */
if (y == 0 || y > 2) {
return CRYPT_INVALID_PACKET;
}
/* read the data len */
dlen = 0;
while (y--) {
dlen = (dlen << 8) | (unsigned long)in[x++];
}
} else {
/* short format */
dlen = in[x++] & 0x7F;
y = inlen - 1;
if ((err = der_decode_asn1_length(in + x, &y, &dlen)) != CRYPT_OK) {
return err;
}
x += y;
/* is the data len too long or too short? */
if ((dlen == 0) || (dlen + x > inlen)) {
if ((dlen == 0) || (dlen > (inlen - x))) {
return CRYPT_INVALID_PACKET;
}

View File

@ -50,16 +50,11 @@ int der_encode_bit_string(const unsigned char *in, unsigned long inlen,
y = ((inlen + 7) >> 3) + 1;
out[x++] = 0x03;
if (y < 128) {
out[x++] = (unsigned char)y;
} else if (y < 256) {
out[x++] = 0x81;
out[x++] = (unsigned char)y;
} else if (y < 65536) {
out[x++] = 0x82;
out[x++] = (unsigned char)((y>>8)&255);
out[x++] = (unsigned char)(y&255);
len = *outlen - x;
if ((err = der_encode_asn1_length(y, out + x, &len)) != CRYPT_OK) {
return err;
}
x += len;
/* store number of zero padding bits */
out[x++] = (unsigned char)((8 - inlen) & 7);

View File

@ -52,16 +52,11 @@ int der_encode_raw_bit_string(const unsigned char *in, unsigned long inlen,
y = ((inlen + 7) >> 3) + 1;
out[x++] = 0x03;
if (y < 128) {
out[x++] = (unsigned char)y;
} else if (y < 256) {
out[x++] = 0x81;
out[x++] = (unsigned char)y;
} else if (y < 65536) {
out[x++] = 0x82;
out[x++] = (unsigned char)((y>>8)&255);
out[x++] = (unsigned char)(y&255);
len = *outlen - x;
if ((err = der_encode_asn1_length(y, out + x, &len)) != CRYPT_OK) {
return err;
}
x += len;
/* store number of zero padding bits */
out[x++] = (unsigned char)((8 - inlen) & 7);

View File

@ -22,24 +22,18 @@
*/
int der_length_bit_string(unsigned long nbits, unsigned long *outlen)
{
unsigned long nbytes;
unsigned long nbytes, x;
int err;
LTC_ARGCHK(outlen != NULL);
/* get the number of the bytes */
nbytes = (nbits >> 3) + ((nbits & 7) ? 1 : 0) + 1;
if (nbytes < 128) {
/* 03 LL PP DD DD DD ... */
*outlen = 2 + nbytes;
} else if (nbytes < 256) {
/* 03 81 LL PP DD DD DD ... */
*outlen = 3 + nbytes;
} else if (nbytes < 65536) {
/* 03 82 LL LL PP DD DD DD ... */
*outlen = 4 + nbytes;
} else {
return CRYPT_INVALID_ARG;
if ((err = der_length_asn1_length(nbytes, &x)) != CRYPT_OK) {
return err;
}
*outlen = 1 + x + nbytes;
return CRYPT_OK;
}

View File

@ -205,9 +205,17 @@ int der_decode_choice(const unsigned char *in, unsigned long *inlen,
}
break;
case LTC_ASN1_CUSTOM_TYPE:
if (der_decode_custom_type(in, *inlen, &list[x]) == CRYPT_OK) {
if (der_length_custom_type(&list[x], &z, NULL) == CRYPT_OK) {
list[x].used = 1;
*inlen = z;
return CRYPT_OK;
}
}
break;
case LTC_ASN1_CHOICE:
case LTC_ASN1_CONSTRUCTED:
case LTC_ASN1_CONTEXT_SPECIFIC:
case LTC_ASN1_EOL:
return CRYPT_INVALID_ARG;
}

View File

@ -0,0 +1,420 @@
/* 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)
{
LTC_ARGCHK(root != NULL);
return der_decode_custom_type_ex(in, inlen, root, NULL, 0, LTC_DER_SEQ_ORDERED | LTC_DER_SEQ_RELAXED);
}
/**
Extended-decode a Custom type
This function is used to decode custom types and sequences/sets
For custom types root is used
For sequences/sets list and outlen are used
@param in The DER encoded input
@param inlen The size of the input
@param root The item that defines the custom type to decode
@param list The list of items to decode
@param outlen The number of items in the list
@param flags c.f. enum ltc_der_seq
@return CRYPT_OK on success
*/
int der_decode_custom_type_ex(const unsigned char *in, unsigned long inlen,
ltc_asn1_list *root,
ltc_asn1_list *list, unsigned long outlen,
unsigned int flags)
{
int err, seq_err, i, ordered;
ltc_asn1_type type;
ltc_asn1_list ident;
unsigned long size, x, y, z, blksize;
unsigned char* in_new = NULL;
void *data;
LTC_ARGCHK(in != NULL);
/* get blk size */
if (inlen < 2) {
return CRYPT_INVALID_PACKET;
}
x = 0;
if (root == NULL) {
LTC_ARGCHK(list != NULL);
/* sequence type? We allow 0x30 SEQUENCE and 0x31 SET since fundamentally they're the same structure */
if (in[x] != 0x30 && in[x] != 0x31) {
return CRYPT_INVALID_PACKET;
}
++x;
} else {
if (root->type != LTC_ASN1_CUSTOM_TYPE) {
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;
}
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 != NULL && root->pc == LTC_ASN1_PC_PRIMITIVE) {
if (((unsigned long)root->used >= der_asn1_type_to_identifier_map_sz) ||
(der_asn1_type_to_identifier_map[root->used] == -1)) {
err = CRYPT_INVALID_PACKET;
goto LBL_ERR;
}
root->type = (ltc_asn1_type)root->used;
list = root;
outlen = 1;
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 (blksize > (inlen - x)) {
err = CRYPT_INVALID_PACKET;
goto LBL_ERR;
}
/* mark all as unused */
for (i = 0; i < (int)outlen; i++) {
list[i].used = 0;
}
ordered = flags & LTC_DER_SEQ_ORDERED;
/* ok read data */
seq_err = CRYPT_OK;
blksize += x;
inlen -= x;
for (i = 0; i < (int)outlen; i++) {
z = 0;
type = list[i].type;
size = list[i].size;
data = list[i].data;
if (!ordered && list[i].used == 1) { continue; }
if (type == LTC_ASN1_EOL) {
break;
}
if (root != NULL && 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) {
if (!ordered || list[i].optional) { continue; }
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) {
if (!ordered || list[i].optional) { continue; }
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) {
if (!ordered || list[i].optional) { continue; }
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) {
if (!ordered || list[i].optional) { continue; }
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) {
if (!ordered || list[i].optional) { continue; }
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) {
if (!ordered || list[i].optional) { continue; }
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) {
if (!ordered || list[i].optional) { continue; }
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) {
if (!ordered || list[i].optional) { continue; }
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) {
if (!ordered || list[i].optional) { 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) {
if (!ordered || list[i].optional) { continue; }
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) {
if (!ordered || list[i].optional) { continue; }
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) {
if (!ordered || list[i].optional) { continue; }
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) {
if (!ordered || list[i].optional) { continue; }
goto LBL_ERR;
}
break;
case LTC_ASN1_GENERALIZEDTIME:
z = inlen;
if ((err = der_decode_generalizedtime(in + x, &z, data)) != CRYPT_OK) {
if (!ordered || list[i].optional) { continue; }
goto LBL_ERR;
}
break;
case LTC_ASN1_SET:
z = inlen;
if ((err = der_decode_set(in + x, z, data, size)) != CRYPT_OK) {
if (!ordered || list[i].optional) { continue; }
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;
err = der_decode_sequence_ex(in + x, z, data, size, flags);
if (err == CRYPT_INPUT_TOO_LONG) {
seq_err = CRYPT_INPUT_TOO_LONG;
err = CRYPT_OK;
}
if (err != CRYPT_OK) {
if (!ordered || list[i].optional) { continue; }
goto LBL_ERR;
}
if ((err = der_length_sequence(data, size, &z)) != CRYPT_OK) {
goto LBL_ERR;
}
break;
case LTC_ASN1_CUSTOM_TYPE:
z = inlen;
err = der_decode_custom_type(in + x, z, &list[i]);
if (err == CRYPT_INPUT_TOO_LONG) {
seq_err = CRYPT_INPUT_TOO_LONG;
err = CRYPT_OK;
}
if (err != CRYPT_OK) {
if (!ordered || list[i].optional) { continue; }
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) {
if (!ordered || list[i].optional) { continue; }
goto LBL_ERR;
}
break;
case LTC_ASN1_EOL:
err = CRYPT_INVALID_ARG;
goto LBL_ERR;
}
x += z;
inlen -= z;
list[i].used = 1;
if (!ordered) {
/* restart the decoder */
i = -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 (blksize == x && seq_err == CRYPT_OK && inlen == 0) {
/* everything decoded and no errors in nested sequences */
err = CRYPT_OK;
} else if (blksize == x && seq_err == CRYPT_INPUT_TOO_LONG && inlen == 0) {
/* a sequence reported too-long input, but now we've decoded everything */
err = CRYPT_OK;
} else if (blksize != x && ((flags & LTC_DER_SEQ_STRICT) == LTC_DER_SEQ_STRICT)) {
err = CRYPT_INVALID_PACKET;
} 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$ */

View File

@ -0,0 +1,238 @@
/* 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;
const 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) {
list = root;
inlen = 1;
/* 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 {
list = root->data;
inlen = root->size;
/* 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;
}
/* store data */
*outlen -= x;
for (i = 0; i < inlen; i++) {
if (root->pc == LTC_ASN1_PC_PRIMITIVE) {
type = (ltc_asn1_type)list[i].used;
} else {
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_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$ */

View 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;
const 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);
/* get size of output that will be required */
if ((err = der_length_asn1_identifier(root, &id_len)) != CRYPT_OK) {
return err;
}
y = id_len;
if (root->pc == LTC_ASN1_PC_PRIMITIVE) {
list = root;
inlen = 1;
} else {
list = root->data;
inlen = root->size;
}
for (i = 0; i < inlen; i++) {
if (root->pc == LTC_ASN1_PC_PRIMITIVE) {
type = (ltc_asn1_type)list[i].used;
} else {
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_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$ */

View File

@ -0,0 +1,167 @@
/* 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_asn1_maps.c
ASN.1 DER, a collection of maps to convert between different representations, Steffen Jaeckel
*/
#ifdef LTC_DER
/**
A Map from ltc_asn1_type to the regularly used ASN.1 identifier
*/
const int der_asn1_type_to_identifier_map[] =
{
/* 0 */
-1, /* LTC_ASN1_EOL, */
1, /* LTC_ASN1_BOOLEAN, */
2, /* LTC_ASN1_INTEGER, */
2, /* LTC_ASN1_SHORT_INTEGER, */
3, /* LTC_ASN1_BIT_STRING, */
/* 5 */
4, /* LTC_ASN1_OCTET_STRING, */
5, /* LTC_ASN1_NULL, */
6, /* LTC_ASN1_OBJECT_IDENTIFIER, */
22, /* LTC_ASN1_IA5_STRING, */
19, /* LTC_ASN1_PRINTABLE_STRING, */
/* 10 */
12, /* LTC_ASN1_UTF8_STRING, */
23, /* LTC_ASN1_UTCTIME, */
-1, /* LTC_ASN1_CHOICE, */
48, /* LTC_ASN1_SEQUENCE, */
49, /* LTC_ASN1_SET, */
/* 15 */
49, /* LTC_ASN1_SETOF, */
3, /* LTC_ASN1_RAW_BIT_STRING, */
20, /* LTC_ASN1_TELETEX_STRING, */
24, /* LTC_ASN1_GENERALIZEDTIME, */
-1, /* LTC_ASN1_CUSTOM_TYPE, */
};
const unsigned long der_asn1_type_to_identifier_map_sz = sizeof(der_asn1_type_to_identifier_map)/sizeof(der_asn1_type_to_identifier_map[0]);
/**
A Map from the ASN.1 Class to its string
*/
const char* der_asn1_class_to_string_map[] =
{
"UNIVERSAL",
"APPLICATION",
"CONTEXT-SPECIFIC",
"PRIVATE",
};
const unsigned long der_asn1_class_to_string_map_sz = sizeof(der_asn1_class_to_string_map)/sizeof(der_asn1_class_to_string_map[0]);
/**
A Map from the ASN.1 P/C-bit to its string
*/
const char* der_asn1_pc_to_string_map[] =
{
"PRIMITIVE",
"CONSTRUCTED",
};
const unsigned long der_asn1_pc_to_string_map_sz = sizeof(der_asn1_pc_to_string_map)/sizeof(der_asn1_pc_to_string_map[0]);
/**
A Map from the ASN.1 tag to its string
*/
const char* der_asn1_tag_to_string_map[] =
{
"Reserved for use by the encoding rules",
"Boolean type",
"Integer type",
"Bitstring type",
"Octetstring type",
"Null type",
"Object identifier type",
"Object descriptor type",
"External type and Instance-of type",
"Real type",
"Enumerated type",
"Embedded-pdv type",
"UTF8String type",
"Relative object identifier type",
"The time type",
"Reserved for future editions of this Recommendation | International Standard",
"Sequence and Sequence-of types",
"Set and Set-of types",
"NumericString type",
"PrintableString type",
"TeletexString (T61String) type",
"VideotexString type",
"IA5String type",
"UTCTime type",
"GeneralizedTime type",
"GraphicString type",
"VisibleString (ISO646String) type",
"GeneralString type",
"UniversalString type",
"UnrestrictedCharacterString type",
"BMPString type",
"Date type",
"TimeOfDay type",
"DateTime type",
"Duration type",
"OID internationalized resource identifier type",
"Relative OID internationalized resource identifier type",
};
const unsigned long der_asn1_tag_to_string_map_sz = sizeof(der_asn1_tag_to_string_map)/sizeof(der_asn1_tag_to_string_map[0]);
/**
A Map from ASN.1 Tags to ltc_asn1_type
*/
const ltc_asn1_type der_asn1_tag_to_type_map[] =
{
/* 0 */
LTC_ASN1_EOL, /* Reserved for use by the encoding rules */
LTC_ASN1_BOOLEAN, /* Boolean type */
LTC_ASN1_INTEGER, /* Integer type */
LTC_ASN1_BIT_STRING, /* Bitstring type */
LTC_ASN1_OCTET_STRING, /* Octetstring type */
/* 5 */
LTC_ASN1_NULL, /* Null type */
LTC_ASN1_OBJECT_IDENTIFIER, /* Object identifier type */
LTC_ASN1_CUSTOM_TYPE, /* Object descriptor type */
LTC_ASN1_CUSTOM_TYPE, /* External type and Instance-of type */
LTC_ASN1_CUSTOM_TYPE, /* Real type */
/* 10 */
LTC_ASN1_CUSTOM_TYPE, /* Enumerated type */
LTC_ASN1_CUSTOM_TYPE, /* Embedded-pdv type */
LTC_ASN1_UTF8_STRING, /* UTF8String type */
LTC_ASN1_CUSTOM_TYPE, /* Relative object identifier type */
LTC_ASN1_CUSTOM_TYPE, /* The time type */
/* 15 */
LTC_ASN1_EOL, /* Reserved for future editions of this Recommendation | International Standard */
LTC_ASN1_SEQUENCE, /* Sequence and Sequence-of types */
LTC_ASN1_SET, /* Set and Set-of types */
LTC_ASN1_CUSTOM_TYPE, /* NumericString types */
LTC_ASN1_PRINTABLE_STRING, /* PrintableString types */
/* 20 */
LTC_ASN1_TELETEX_STRING, /* TeletexString (T61String) types */
LTC_ASN1_CUSTOM_TYPE, /* VideotexString types */
LTC_ASN1_IA5_STRING, /* IA5String types */
LTC_ASN1_UTCTIME, /* UTCTime types */
LTC_ASN1_GENERALIZEDTIME, /* GeneralizedTime types */
/* 25 */
LTC_ASN1_CUSTOM_TYPE, /* GraphicString types */
LTC_ASN1_CUSTOM_TYPE, /* VisibleString (ISO646String) types */
LTC_ASN1_CUSTOM_TYPE, /* GeneralString types */
LTC_ASN1_CUSTOM_TYPE, /* UniversalString types */
LTC_ASN1_CUSTOM_TYPE, /* UnrestrictedCharacterString types */
/* 30 */
LTC_ASN1_CUSTOM_TYPE, /* BMPString types */
};
const unsigned long der_asn1_tag_to_type_map_sz = sizeof(der_asn1_tag_to_type_map)/sizeof(der_asn1_tag_to_type_map[0]);
#endif
/* ref: $Format:%D$ */
/* git commit: $Format:%H$ */
/* commit time: $Format:%ai$ */

View File

@ -0,0 +1,133 @@
/* 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,
};
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$ */

View File

@ -0,0 +1,67 @@
/* 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_length.c
ASN.1 DER, decode the ASN.1 Length field, Steffen Jaeckel
*/
#ifdef LTC_DER
/**
Decode the ASN.1 Length field
@param in Where to read the length field from
@param inlen [in/out] The size of in available/read
@param outlen [out] The decoded ASN.1 length
@return CRYPT_OK if successful
*/
int der_decode_asn1_length(const unsigned char *in, unsigned long *inlen, unsigned long *outlen)
{
unsigned long real_len, decoded_len, offset, i;
LTC_ARGCHK(in != NULL);
LTC_ARGCHK(inlen != NULL);
if (*inlen < 1) {
return CRYPT_BUFFER_OVERFLOW;
}
real_len = in[0];
if (real_len < 128) {
decoded_len = real_len;
offset = 1;
} else {
real_len &= 0x7F;
if (real_len == 0) {
return CRYPT_PK_ASN1_ERROR;
} else if (real_len > sizeof(decoded_len)) {
return CRYPT_OVERFLOW;
} else if (real_len > (*inlen - 1)) {
return CRYPT_BUFFER_OVERFLOW;
}
decoded_len = 0;
offset = 1 + real_len;
for (i = 0; i < real_len; i++) {
decoded_len = (decoded_len << 8) | in[1 + i];
}
}
if (outlen != NULL) *outlen = decoded_len;
if (decoded_len > (*inlen - offset)) return CRYPT_OVERFLOW;
*inlen = offset;
return CRYPT_OK;
}
#endif
/* ref: $Format:%D$ */
/* git commit: $Format:%H$ */
/* commit time: $Format:%ai$ */

View 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$ */

View File

@ -0,0 +1,121 @@
/* 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_length.c
ASN.1 DER, encode the ASN.1 length field, Steffen Jaeckel
*/
#ifdef LTC_DER
/**
Encode the ASN.1 length field
@param len The length to encode
@param out Where to write the length field to
@param outlen [in/out] The size of out available/written
@return CRYPT_OK if successful
*/
int der_encode_asn1_length(unsigned long len, unsigned char *out, unsigned long *outlen)
{
unsigned long x, y;
LTC_ARGCHK(outlen != NULL);
x = len;
y = 0;
while(x != 0) {
y++;
x >>= 8;
}
if (y == 0) {
return CRYPT_PK_ASN1_ERROR;
}
if (out == NULL) {
if (len < 128) {
x = y;
} else {
x = y + 1;
}
} else {
if (*outlen < y) {
return CRYPT_BUFFER_OVERFLOW;
}
x = 0;
if (len < 128) {
out[x++] = (unsigned char)len;
} else if (len <= 0xffUL) {
out[x++] = 0x81;
out[x++] = (unsigned char)len;
} else if (len <= 0xffffUL) {
out[x++] = 0x82;
out[x++] = (unsigned char)((len>>8UL)&255);
out[x++] = (unsigned char)(len&255);
} else if (len <= 0xffffffUL) {
out[x++] = 0x83;
out[x++] = (unsigned char)((len>>16UL)&255);
out[x++] = (unsigned char)((len>>8UL)&255);
out[x++] = (unsigned char)(len&255);
} else if (len <= 0xffffffffUL) {
out[x++] = 0x84;
out[x++] = (unsigned char)((len>>24UL)&255);
out[x++] = (unsigned char)((len>>16UL)&255);
out[x++] = (unsigned char)((len>>8UL)&255);
out[x++] = (unsigned char)(len&255);
#if ULONG_MAX == ULLONG_MAX
} else if (len <= 0xffffffffffULL) {
out[x++] = 0x85;
out[x++] = (unsigned char)((len>>32ULL)&255);
out[x++] = (unsigned char)((len>>24ULL)&255);
out[x++] = (unsigned char)((len>>16ULL)&255);
out[x++] = (unsigned char)((len>>8ULL)&255);
out[x++] = (unsigned char)(len&255);
} else if (len <= 0xffffffffffffULL) {
out[x++] = 0x86;
out[x++] = (unsigned char)((len>>40ULL)&255);
out[x++] = (unsigned char)((len>>32ULL)&255);
out[x++] = (unsigned char)((len>>24ULL)&255);
out[x++] = (unsigned char)((len>>16ULL)&255);
out[x++] = (unsigned char)((len>>8ULL)&255);
out[x++] = (unsigned char)(len&255);
} else if (len <= 0xffffffffffffffULL) {
out[x++] = 0x87;
out[x++] = (unsigned char)((len>>48ULL)&255);
out[x++] = (unsigned char)((len>>40ULL)&255);
out[x++] = (unsigned char)((len>>32ULL)&255);
out[x++] = (unsigned char)((len>>24ULL)&255);
out[x++] = (unsigned char)((len>>16ULL)&255);
out[x++] = (unsigned char)((len>>8ULL)&255);
out[x++] = (unsigned char)(len&255);
} else if (len <= 0xffffffffffffffffULL) {
out[x++] = 0x88;
out[x++] = (unsigned char)((len>>56ULL)&255);
out[x++] = (unsigned char)((len>>48ULL)&255);
out[x++] = (unsigned char)((len>>40ULL)&255);
out[x++] = (unsigned char)((len>>32ULL)&255);
out[x++] = (unsigned char)((len>>24ULL)&255);
out[x++] = (unsigned char)((len>>16ULL)&255);
out[x++] = (unsigned char)((len>>8ULL)&255);
out[x++] = (unsigned char)(len&255);
#endif
} else {
return CRYPT_INPUT_TOO_LONG;
}
}
*outlen = x;
return CRYPT_OK;
}
#endif
/* ref: $Format:%D$ */
/* git commit: $Format:%H$ */
/* commit time: $Format:%ai$ */

View 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$ */

View File

@ -0,0 +1,32 @@
/* 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_length.c
ASN.1 DER, determine the length of the ASN.1 length field, Steffen Jaeckel
*/
#ifdef LTC_DER
/**
Determine the length required to encode len in the ASN.1 length field
@param len The length to encode
@param outlen [out] The length that's required to store len
@return CRYPT_OK if successful
*/
int der_length_asn1_length(unsigned long len, unsigned long *outlen)
{
return der_encode_asn1_length(len, NULL, outlen);
}
#endif
/* ref: $Format:%D$ */
/* git commit: $Format:%H$ */
/* commit time: $Format:%ai$ */

View File

@ -28,7 +28,7 @@ int der_decode_ia5_string(const unsigned char *in, unsigned long inlen,
unsigned char *out, unsigned long *outlen)
{
unsigned long x, y, len;
int t;
int t, err;
LTC_ARGCHK(in != NULL);
LTC_ARGCHK(out != NULL);
@ -45,23 +45,12 @@ int der_decode_ia5_string(const unsigned char *in, unsigned long inlen,
}
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;
/* get the length of the data */
y = inlen - x;
if ((err = der_decode_asn1_length(in + x, &y, &len)) != CRYPT_OK) {
return err;
}
x += y;
/* is it too long? */
if (len > *outlen) {
@ -69,7 +58,7 @@ int der_decode_ia5_string(const unsigned char *in, unsigned long inlen,
return CRYPT_BUFFER_OVERFLOW;
}
if (len + x > inlen) {
if (len > (inlen - x)) {
return CRYPT_INVALID_PACKET;
}

View File

@ -47,23 +47,11 @@ int der_encode_ia5_string(const unsigned char *in, unsigned long inlen,
/* encode the header+len */
x = 0;
out[x++] = 0x16;
if (inlen < 128) {
out[x++] = (unsigned char)inlen;
} else if (inlen < 256) {
out[x++] = 0x81;
out[x++] = (unsigned char)inlen;
} else if (inlen < 65536UL) {
out[x++] = 0x82;
out[x++] = (unsigned char)((inlen>>8)&255);
out[x++] = (unsigned char)(inlen&255);
} else if (inlen < 16777216UL) {
out[x++] = 0x83;
out[x++] = (unsigned char)((inlen>>16)&255);
out[x++] = (unsigned char)((inlen>>8)&255);
out[x++] = (unsigned char)(inlen&255);
} else {
return CRYPT_INVALID_ARG;
len = *outlen - x;
if ((err = der_encode_asn1_length(inlen, out + x, &len)) != CRYPT_OK) {
return err;
}
x += len;
/* store octets */
for (y = 0; y < inlen; y++) {

View File

@ -154,6 +154,7 @@ int der_ia5_value_decode(int v)
int der_length_ia5_string(const unsigned char *octets, unsigned long noctets, unsigned long *outlen)
{
unsigned long x;
int err;
LTC_ARGCHK(outlen != NULL);
LTC_ARGCHK(octets != NULL);
@ -165,21 +166,10 @@ int der_length_ia5_string(const unsigned char *octets, unsigned long noctets, un
}
}
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;
if ((err = der_length_asn1_length(noctets, &x)) != CRYPT_OK) {
return err;
}
*outlen = 1 + x + noctets;
return CRYPT_OK;
}

View File

@ -25,7 +25,7 @@
*/
int der_decode_integer(const unsigned char *in, unsigned long inlen, void *num)
{
unsigned long x, y, z;
unsigned long x, y;
int err;
LTC_ARGCHK(num != NULL);
@ -42,45 +42,15 @@ int der_decode_integer(const unsigned char *in, unsigned long inlen, void *num)
return CRYPT_INVALID_PACKET;
}
/* now decode the len stuff */
z = in[x++];
/* get the length of the data */
inlen -= x;
if ((err = der_decode_asn1_length(in + x, &inlen, &y)) != CRYPT_OK) {
return err;
}
x += inlen;
if ((z & 0x80) == 0x00) {
/* short form */
/* will it overflow? */
if (x + z > inlen) {
return CRYPT_INVALID_PACKET;
}
/* no so read it */
if ((err = mp_read_unsigned_bin(num, (unsigned char *)in + x, z)) != CRYPT_OK) {
return err;
}
} else {
/* long form */
z &= 0x7F;
/* will number of length bytes overflow? (or > 4) */
if (((x + z) > inlen) || (z > 4) || (z == 0)) {
return CRYPT_INVALID_PACKET;
}
/* now read it in */
y = 0;
while (z--) {
y = ((unsigned long)(in[x++])) | (y << 8);
}
/* now will reading y bytes overrun? */
if ((x + y) > inlen) {
return CRYPT_INVALID_PACKET;
}
/* no so read it */
if ((err = mp_read_unsigned_bin(num, (unsigned char *)in + x, y)) != CRYPT_OK) {
return err;
}
if ((err = mp_read_unsigned_bin(num, (unsigned char *)in + x, y)) != CRYPT_OK) {
return err;
}
/* see if it's negative */

View File

@ -26,7 +26,7 @@
*/
int der_encode_integer(void *num, unsigned char *out, unsigned long *outlen)
{
unsigned long tmplen, y;
unsigned long tmplen, y, len;
int err, leading_zero;
LTC_ARGCHK(num != NULL);
@ -63,24 +63,11 @@ int der_encode_integer(void *num, unsigned char *out, unsigned long *outlen)
/* now store initial data */
*out++ = 0x02;
if (y < 128) {
/* short form */
*out++ = (unsigned char)y;
} else if (y < 256) {
*out++ = 0x81;
*out++ = (unsigned char)y;
} else if (y < 65536UL) {
*out++ = 0x82;
*out++ = (unsigned char)((y>>8)&255);
*out++ = (unsigned char)y;
} else if (y < 16777216UL) {
*out++ = 0x83;
*out++ = (unsigned char)((y>>16)&255);
*out++ = (unsigned char)((y>>8)&255);
*out++ = (unsigned char)y;
} else {
return CRYPT_INVALID_ARG;
len = *outlen - 1;
if ((err = der_encode_asn1_length(y, out, &len)) != CRYPT_OK) {
return err;
}
out += len;
/* now store msbyte of zero if num is non-zero */
if (leading_zero) {

View File

@ -24,7 +24,7 @@
int der_length_integer(void *num, unsigned long *outlen)
{
unsigned long z, len;
int leading_zero;
int leading_zero, err;
LTC_ARGCHK(num != NULL);
LTC_ARGCHK(outlen != NULL);
@ -40,35 +40,21 @@ int der_length_integer(void *num, unsigned long *outlen)
}
/* size for bignum */
z = len = leading_zero + mp_unsigned_bin_size(num);
len = leading_zero + mp_unsigned_bin_size(num);
} else {
/* it's negative */
/* find power of 2 that is a multiple of eight and greater than count bits */
z = mp_count_bits(num);
z = z + (8 - (z & 7));
if (((mp_cnt_lsb(num)+1)==mp_count_bits(num)) && ((mp_count_bits(num)&7)==0)) --z;
len = z = z >> 3;
len = z >> 3;
}
/* now we need a length */
if (z < 128) {
/* short form */
++len;
} else {
/* long form (relies on z != 0), assumes length bytes < 128 */
++len;
while (z) {
++len;
z >>= 8;
}
if ((err = der_length_asn1_length(len, &z)) != CRYPT_OK) {
return err;
}
*outlen = 1 + z + len;
/* we need a 0x02 to indicate it's INTEGER */
++len;
/* return length */
*outlen = len;
return CRYPT_OK;
}

View File

@ -49,21 +49,14 @@ int der_decode_object_identifier(const unsigned char *in, unsigned long inle
return CRYPT_INVALID_PACKET;
}
/* get the length */
if (in[x] < 128) {
len = in[x++];
} else {
if (in[x] < 0x81 || in[x] > 0x82) {
return CRYPT_INVALID_PACKET;
}
y = in[x++] & 0x7F;
len = 0;
while (y--) {
len = (len << 8) | (unsigned long)in[x++];
}
/* get the length of the data */
y = inlen - x;
if ((err = der_decode_asn1_length(in + x, &y, &len)) != CRYPT_OK) {
return err;
}
x += y;
if (len < 1 || (len + x) > inlen) {
if ((len == 0) || (len > (inlen - x))) {
return CRYPT_INVALID_PACKET;
}

View File

@ -55,18 +55,11 @@ int der_encode_object_identifier(unsigned long *words, unsigned long nwords,
/* store header + length */
x = 0;
out[x++] = 0x06;
if (z < 128) {
out[x++] = (unsigned char)z;
} else if (z < 256) {
out[x++] = 0x81;
out[x++] = (unsigned char)z;
} else if (z < 65536UL) {
out[x++] = 0x82;
out[x++] = (unsigned char)((z>>8)&255);
out[x++] = (unsigned char)(z&255);
} else {
return CRYPT_INVALID_ARG;
y = *outlen - x;
if ((err = der_encode_asn1_length(z, out + x, &y)) != CRYPT_OK) {
return err;
}
x += y;
/* store first byte */
wordbuf = words[0] * 40 + words[1];

View File

@ -28,6 +28,7 @@ int der_decode_octet_string(const unsigned char *in, unsigned long inlen,
unsigned char *out, unsigned long *outlen)
{
unsigned long x, y, len;
int err;
LTC_ARGCHK(in != NULL);
LTC_ARGCHK(out != NULL);
@ -44,23 +45,12 @@ int der_decode_octet_string(const unsigned char *in, unsigned long inlen,
}
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;
/* get the length of the data */
y = inlen - x;
if ((err = der_decode_asn1_length(in + x, &y, &len)) != CRYPT_OK) {
return err;
}
x += y;
/* is it too long? */
if (len > *outlen) {
@ -68,7 +58,7 @@ int der_decode_octet_string(const unsigned char *in, unsigned long inlen,
return CRYPT_BUFFER_OVERFLOW;
}
if (len + x > inlen) {
if (len > (inlen - x)) {
return CRYPT_INVALID_PACKET;
}

View File

@ -48,23 +48,11 @@ int der_encode_octet_string(const unsigned char *in, unsigned long inlen,
/* encode the header+len */
x = 0;
out[x++] = 0x04;
if (inlen < 128) {
out[x++] = (unsigned char)inlen;
} else if (inlen < 256) {
out[x++] = 0x81;
out[x++] = (unsigned char)inlen;
} else if (inlen < 65536UL) {
out[x++] = 0x82;
out[x++] = (unsigned char)((inlen>>8)&255);
out[x++] = (unsigned char)(inlen&255);
} else if (inlen < 16777216UL) {
out[x++] = 0x83;
out[x++] = (unsigned char)((inlen>>16)&255);
out[x++] = (unsigned char)((inlen>>8)&255);
out[x++] = (unsigned char)(inlen&255);
} else {
return CRYPT_INVALID_ARG;
len = *outlen - x;
if ((err = der_encode_asn1_length(inlen, out + x, &len)) != CRYPT_OK) {
return err;
}
x += len;
/* store octets */
for (y = 0; y < inlen; y++) {

View File

@ -22,23 +22,15 @@
*/
int der_length_octet_string(unsigned long noctets, unsigned long *outlen)
{
unsigned long x;
int err;
LTC_ARGCHK(outlen != NULL);
if (noctets < 128) {
/* 04 LL DD DD DD ... */
*outlen = 2 + noctets;
} else if (noctets < 256) {
/* 04 81 LL DD DD DD ... */
*outlen = 3 + noctets;
} else if (noctets < 65536UL) {
/* 04 82 LL LL DD DD DD ... */
*outlen = 4 + noctets;
} else if (noctets < 16777216UL) {
/* 04 83 LL LL LL DD DD DD ... */
*outlen = 5 + noctets;
} else {
return CRYPT_INVALID_ARG;
if ((err = der_length_asn1_length(noctets, &x)) != CRYPT_OK) {
return err;
}
*outlen = 1 + x + noctets;
return CRYPT_OK;
}

View File

@ -28,7 +28,7 @@ int der_decode_printable_string(const unsigned char *in, unsigned long inlen,
unsigned char *out, unsigned long *outlen)
{
unsigned long x, y, len;
int t;
int t, err;
LTC_ARGCHK(in != NULL);
LTC_ARGCHK(out != NULL);
@ -45,23 +45,12 @@ int der_decode_printable_string(const unsigned char *in, unsigned long inlen,
}
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;
/* get the length of the data */
y = inlen - x;
if ((err = der_decode_asn1_length(in + x, &y, &len)) != CRYPT_OK) {
return err;
}
x += y;
/* is it too long? */
if (len > *outlen) {
@ -69,7 +58,7 @@ int der_decode_printable_string(const unsigned char *in, unsigned long inlen,
return CRYPT_BUFFER_OVERFLOW;
}
if (len + x > inlen) {
if (len > (inlen - x)) {
return CRYPT_INVALID_PACKET;
}

View File

@ -47,23 +47,11 @@ int der_encode_printable_string(const unsigned char *in, unsigned long inlen,
/* encode the header+len */
x = 0;
out[x++] = 0x13;
if (inlen < 128) {
out[x++] = (unsigned char)inlen;
} else if (inlen < 256) {
out[x++] = 0x81;
out[x++] = (unsigned char)inlen;
} else if (inlen < 65536UL) {
out[x++] = 0x82;
out[x++] = (unsigned char)((inlen>>8)&255);
out[x++] = (unsigned char)(inlen&255);
} else if (inlen < 16777216UL) {
out[x++] = 0x83;
out[x++] = (unsigned char)((inlen>>16)&255);
out[x++] = (unsigned char)((inlen>>8)&255);
out[x++] = (unsigned char)(inlen&255);
} else {
return CRYPT_INVALID_ARG;
len = *outlen - x;
if ((err = der_encode_asn1_length(inlen, out + x, &len)) != CRYPT_OK) {
return err;
}
x += len;
/* store octets */
for (y = 0; y < inlen; y++) {

View File

@ -126,6 +126,7 @@ int der_printable_value_decode(int v)
int der_length_printable_string(const unsigned char *octets, unsigned long noctets, unsigned long *outlen)
{
unsigned long x;
int err;
LTC_ARGCHK(outlen != NULL);
LTC_ARGCHK(octets != NULL);
@ -137,21 +138,10 @@ int der_length_printable_string(const unsigned char *octets, unsigned long nocte
}
}
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;
if ((err = der_length_asn1_length(noctets, &x)) != CRYPT_OK) {
return err;
}
*outlen = 1 + x + noctets;
return CRYPT_OK;
}

View File

@ -22,303 +22,13 @@
@param inlen The size of the input
@param list The list of items to decode
@param outlen The number of items in the list
@param ordered Search an unordeded or ordered list
@param flags c.f. enum ltc_der_seq
@return CRYPT_OK on success
*/
int der_decode_sequence_ex(const unsigned char *in, unsigned long inlen,
ltc_asn1_list *list, unsigned long outlen, int ordered)
ltc_asn1_list *list, unsigned long outlen, unsigned int flags)
{
int err, i;
ltc_asn1_type type;
unsigned long size, x, y, z, blksize;
void *data;
LTC_ARGCHK(in != NULL);
LTC_ARGCHK(list != NULL);
/* get blk size */
if (inlen < 2) {
return CRYPT_INVALID_PACKET;
}
/* sequence type? We allow 0x30 SEQUENCE and 0x31 SET since fundamentally they're the same structure */
x = 0;
if (in[x] != 0x30 && in[x] != 0x31) {
return CRYPT_INVALID_PACKET;
}
++x;
/* check if the msb is set, which signals that the
* 7 lsb bits represent the number of bytes of the length
*/
if (in[x] < 128) {
blksize = in[x++];
} else {
if (in[x] < 0x81 || in[x] > 0x83) {
return CRYPT_INVALID_PACKET;
}
y = in[x++] & 0x7F;
/* would reading the len bytes overrun? */
if (x + y > inlen) {
return CRYPT_INVALID_PACKET;
}
/* read len */
blksize = 0;
while (y--) {
blksize = (blksize << 8) | (unsigned long)in[x++];
}
}
/* would this blksize overflow? */
if (x + blksize > inlen) {
return CRYPT_INVALID_PACKET;
}
/* 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 (!ordered && list[i].used == 1) { continue; }
if (type == LTC_ASN1_EOL) {
break;
}
switch (type) {
case LTC_ASN1_BOOLEAN:
z = inlen;
if ((err = der_decode_boolean(in + x, z, ((int *)data))) != CRYPT_OK) {
if (!ordered) { continue; }
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) {
if (!ordered) { continue; }
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) {
if (!ordered) { continue; }
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) {
if (!ordered) { continue; }
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) {
if (!ordered) { continue; }
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) {
if (!ordered) { continue; }
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) {
if (!ordered) { continue; }
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) {
if (!ordered) { continue; }
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) {
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) {
if (!ordered) { continue; }
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) {
if (!ordered) { continue; }
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) {
if (!ordered) { continue; }
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) {
if (!ordered) { continue; }
goto LBL_ERR;
}
break;
case LTC_ASN1_GENERALIZEDTIME:
z = inlen;
if ((err = der_decode_generalizedtime(in + x, &z, data)) != CRYPT_OK) {
if (!ordered) { continue; }
goto LBL_ERR;
}
break;
case LTC_ASN1_SET:
z = inlen;
if ((err = der_decode_set(in + x, z, data, size)) != CRYPT_OK) {
if (!ordered) { continue; }
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) {
if (!ordered) { continue; }
goto LBL_ERR;
}
if ((err = der_length_sequence(data, size, &z)) != CRYPT_OK) {
goto LBL_ERR;
}
break;
case LTC_ASN1_CHOICE:
z = inlen;
if ((err = der_decode_choice(in + x, &z, data, size)) != CRYPT_OK) {
if (!ordered) { continue; }
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;
if (!ordered) {
/* restart the decoder */
i = -1;
}
}
for (i = 0; i < (int)outlen; i++) {
if (list[i].used == 0) {
err = CRYPT_INVALID_PACKET;
goto LBL_ERR;
}
}
if (inlen == 0) {
err = CRYPT_OK;
} else {
err = CRYPT_INPUT_TOO_LONG;
}
LBL_ERR:
return err;
return der_decode_custom_type_ex(in, inlen, NULL, list, outlen, flags);
}
#endif

View File

@ -15,42 +15,6 @@
#ifdef LTC_DER
static unsigned long _fetch_length(const unsigned char *in, unsigned long inlen, unsigned long *data_offset)
{
unsigned long x, z;
*data_offset = 0;
/* skip type and read len */
if (inlen < 2) {
return 0xFFFFFFFF;
}
++in; ++(*data_offset);
/* read len */
x = *in++; ++(*data_offset);
/* <128 means literal */
if (x < 128) {
return x+*data_offset;
}
x &= 0x7F; /* the lower 7 bits are the length of the length */
inlen -= 2;
/* len means len of len! */
if (x == 0 || x > 4 || x > inlen) {
return 0xFFFFFFFF;
}
*data_offset += x;
z = 0;
while (x--) {
z = (z<<8) | ((unsigned long)*in);
++in;
}
return z+*data_offset;
}
static int _new_element(ltc_asn1_list **l)
{
/* alloc new link */
@ -80,7 +44,7 @@ static int _new_element(ltc_asn1_list **l)
int der_decode_sequence_flexi(const unsigned char *in, unsigned long *inlen, ltc_asn1_list **out)
{
ltc_asn1_list *l;
unsigned long err, type, len, totlen, data_offset;
unsigned long err, identifier, len, totlen, data_offset, id_len, len_len;
void *realloc_tmp;
LTC_ARGCHK(in != NULL);
@ -99,38 +63,76 @@ int der_decode_sequence_flexi(const unsigned char *in, unsigned long *inlen, ltc
/* scan the input and and get lengths and what not */
while (*inlen) {
/* read the type byte */
type = *in;
/* fetch length */
len = _fetch_length(in, *inlen, &data_offset);
if (len > *inlen) {
err = CRYPT_INVALID_PACKET;
goto error;
}
/* alloc new link */
if ((err = _new_element(&l)) != CRYPT_OK) {
goto error;
}
if ((type & 0x20) && (type != 0x30) && (type != 0x31)) {
/* constructed, use the 'used' field to store the original identifier */
l->used = type;
/* treat constructed elements like SETs */
type = 0x20;
id_len = *inlen;
if ((err = der_decode_asn1_identifier(in, &id_len, l)) != CRYPT_OK) {
goto error;
}
else if ((type & 0xC0) == 0x80) {
/* context-specific, use the 'used' field to store the original identifier */
l->used = type;
/* context-specific elements are treated as opaque data */
type = 0x80;
/* read the type byte */
identifier = *in;
if (l->type != LTC_ASN1_EOL) {
/* fetch length */
len_len = *inlen - id_len;
#if defined(LTC_TEST_DBG)
data_offset = 666;
len = 0;
#endif
if ((err = der_decode_asn1_length(&in[id_len], &len_len, &len)) != CRYPT_OK) {
#if defined(LTC_TEST_DBG)
fprintf(stderr, "E1 %02lx: hl=%4lu l=%4lu - %s (%s)\n", identifier, data_offset, len, der_asn1_tag_to_string_map[l->tag], error_to_string(err));
#endif
goto error;
} else if (len > (*inlen - id_len - len_len)) {
err = CRYPT_INVALID_PACKET;
#if defined(LTC_TEST_DBG)
fprintf(stderr, "E2 %02lx: hl=%4lu l=%4lu - %s (%s)\n", identifier, data_offset, len, der_asn1_tag_to_string_map[l->tag], error_to_string(err));
#endif
goto error;
}
data_offset = id_len + len_len;
#if defined(LTC_TEST_DBG) && LTC_TEST_DBG > 1
if (l->type == LTC_ASN1_CUSTOM_TYPE && l->class == LTC_ASN1_CL_CONTEXT_SPECIFIC) {
fprintf(stderr, "OK %02lx: hl=%4lu l=%4lu - Context Specific[%s %llu]\n", identifier, data_offset, len, der_asn1_pc_to_string_map[l->pc], l->tag);
} else {
fprintf(stderr, "OK %02lx: hl=%4lu l=%4lu - %s\n", identifier, data_offset, len, der_asn1_tag_to_string_map[l->tag]);
}
#endif
len += data_offset;
if (l->type == LTC_ASN1_CUSTOM_TYPE) {
/* Custom type, use the 'used' field to store the original identifier */
l->used = identifier;
if (l->pc == LTC_ASN1_PC_CONSTRUCTED) {
/* treat constructed elements like SEQUENCEs */
identifier = 0x20;
} else {
/* primitive elements are treated as opaque data */
identifier = 0x80;
}
}
} else {
/* Init this so gcc won't complain,
* as this case will only be hit when we
* can't decode the identifier so the
* switch-case should go to default anyway...
*/
data_offset = 0;
}
/* now switch on type */
switch (type) {
switch (identifier) {
case 0x01: /* BOOLEAN */
l->type = LTC_ASN1_BOOLEAN;
if (l->type != LTC_ASN1_BOOLEAN) {
err = CRYPT_PK_ASN1_ERROR;
goto error;
}
/* init field */
l->size = 1;
l->data = XCALLOC(1, sizeof(int));
@ -144,8 +146,12 @@ int der_decode_sequence_flexi(const unsigned char *in, unsigned long *inlen, ltc
break;
case 0x02: /* INTEGER */
if (l->type != LTC_ASN1_INTEGER) {
err = CRYPT_PK_ASN1_ERROR;
goto error;
}
/* init field */
l->type = LTC_ASN1_INTEGER;
l->size = 1;
if ((err = mp_init(&l->data)) != CRYPT_OK) {
goto error;
@ -163,8 +169,12 @@ int der_decode_sequence_flexi(const unsigned char *in, unsigned long *inlen, ltc
break;
case 0x03: /* BIT */
if (l->type != LTC_ASN1_BIT_STRING) {
err = CRYPT_PK_ASN1_ERROR;
goto error;
}
/* init field */
l->type = LTC_ASN1_BIT_STRING;
l->size = len * 8; /* *8 because we store decoded bits one per char and they are encoded 8 per char. */
if ((l->data = XCALLOC(1, l->size)) == NULL) {
@ -182,9 +192,12 @@ int der_decode_sequence_flexi(const unsigned char *in, unsigned long *inlen, ltc
break;
case 0x04: /* OCTET */
if (l->type != LTC_ASN1_OCTET_STRING) {
err = CRYPT_PK_ASN1_ERROR;
goto error;
}
/* init field */
l->type = LTC_ASN1_OCTET_STRING;
l->size = len;
if ((l->data = XCALLOC(1, l->size)) == NULL) {
@ -202,6 +215,10 @@ int der_decode_sequence_flexi(const unsigned char *in, unsigned long *inlen, ltc
break;
case 0x05: /* NULL */
if (l->type != LTC_ASN1_NULL) {
err = CRYPT_PK_ASN1_ERROR;
goto error;
}
/* valid NULL is 0x05 0x00 */
if (in[0] != 0x05 || in[1] != 0x00) {
@ -210,7 +227,6 @@ int der_decode_sequence_flexi(const unsigned char *in, unsigned long *inlen, ltc
}
/* simple to store ;-) */
l->type = LTC_ASN1_NULL;
l->data = NULL;
l->size = 0;
len = 2;
@ -218,9 +234,12 @@ int der_decode_sequence_flexi(const unsigned char *in, unsigned long *inlen, ltc
break;
case 0x06: /* OID */
if (l->type != LTC_ASN1_OBJECT_IDENTIFIER) {
err = CRYPT_PK_ASN1_ERROR;
goto error;
}
/* init field */
l->type = LTC_ASN1_OBJECT_IDENTIFIER;
l->size = len;
if ((l->data = XCALLOC(len, sizeof(unsigned long))) == NULL) {
@ -247,7 +266,10 @@ int der_decode_sequence_flexi(const unsigned char *in, unsigned long *inlen, ltc
case 0x0C: /* UTF8 */
/* init field */
l->type = LTC_ASN1_UTF8_STRING;
if (l->type != LTC_ASN1_UTF8_STRING) {
err = CRYPT_PK_ASN1_ERROR;
goto error;
}
l->size = len;
if ((l->data = XCALLOC(sizeof(wchar_t), l->size)) == NULL) {
@ -265,9 +287,12 @@ int der_decode_sequence_flexi(const unsigned char *in, unsigned long *inlen, ltc
break;
case 0x13: /* PRINTABLE */
if (l->type != LTC_ASN1_PRINTABLE_STRING) {
err = CRYPT_PK_ASN1_ERROR;
goto error;
}
/* init field */
l->type = LTC_ASN1_PRINTABLE_STRING;
l->size = len;
if ((l->data = XCALLOC(1, l->size)) == NULL) {
@ -285,9 +310,12 @@ int der_decode_sequence_flexi(const unsigned char *in, unsigned long *inlen, ltc
break;
case 0x14: /* TELETEXT */
if (l->type != LTC_ASN1_TELETEX_STRING) {
err = CRYPT_PK_ASN1_ERROR;
goto error;
}
/* init field */
l->type = LTC_ASN1_TELETEX_STRING;
l->size = len;
if ((l->data = XCALLOC(1, l->size)) == NULL) {
@ -305,9 +333,12 @@ int der_decode_sequence_flexi(const unsigned char *in, unsigned long *inlen, ltc
break;
case 0x16: /* IA5 */
if (l->type != LTC_ASN1_IA5_STRING) {
err = CRYPT_PK_ASN1_ERROR;
goto error;
}
/* init field */
l->type = LTC_ASN1_IA5_STRING;
l->size = len;
if ((l->data = XCALLOC(1, l->size)) == NULL) {
@ -325,9 +356,12 @@ int der_decode_sequence_flexi(const unsigned char *in, unsigned long *inlen, ltc
break;
case 0x17: /* UTC TIME */
if (l->type != LTC_ASN1_UTCTIME) {
err = CRYPT_PK_ASN1_ERROR;
goto error;
}
/* init field */
l->type = LTC_ASN1_UTCTIME;
l->size = 1;
if ((l->data = XCALLOC(1, sizeof(ltc_utctime))) == NULL) {
@ -346,7 +380,12 @@ int der_decode_sequence_flexi(const unsigned char *in, unsigned long *inlen, ltc
break;
case 0x18:
l->type = LTC_ASN1_GENERALIZEDTIME;
if (l->type != LTC_ASN1_GENERALIZEDTIME) {
err = CRYPT_PK_ASN1_ERROR;
goto error;
}
/* init field */
l->size = len;
if ((l->data = XCALLOC(1, sizeof(ltc_generalizedtime))) == NULL) {
@ -369,14 +408,23 @@ int der_decode_sequence_flexi(const unsigned char *in, unsigned long *inlen, ltc
case 0x31: /* SET */
/* init field */
if (type == 0x20) {
l->type = LTC_ASN1_CONSTRUCTED;
if (identifier == 0x20) {
if (l->type != LTC_ASN1_CUSTOM_TYPE) {
err = CRYPT_PK_ASN1_ERROR;
goto error;
}
}
else if (type == 0x30) {
l->type = LTC_ASN1_SEQUENCE;
else if (identifier == 0x30) {
if (l->type != LTC_ASN1_SEQUENCE) {
err = CRYPT_PK_ASN1_ERROR;
goto error;
}
}
else {
l->type = LTC_ASN1_SET;
if (l->type != LTC_ASN1_SET) {
err = CRYPT_PK_ASN1_ERROR;
goto error;
}
}
if ((l->data = XMALLOC(len)) == NULL) {
@ -391,12 +439,19 @@ int der_decode_sequence_flexi(const unsigned char *in, unsigned long *inlen, ltc
/* jump to the start of the data */
in += data_offset;
*inlen -= data_offset;
len = len - data_offset;
len -= data_offset;
/* save the decoded ASN.1 len */
len_len = len;
/* Sequence elements go as child */
if ((err = der_decode_sequence_flexi(in, &len, &(l->child))) != CRYPT_OK) {
goto error;
}
if (len_len != len) {
err = CRYPT_PK_ASN1_ERROR;
goto error;
}
/* len update */
totlen += data_offset;
@ -410,7 +465,10 @@ int der_decode_sequence_flexi(const unsigned char *in, unsigned long *inlen, ltc
break;
case 0x80: /* Context-specific */
l->type = LTC_ASN1_CONTEXT_SPECIFIC;
if (l->type != LTC_ASN1_CUSTOM_TYPE) {
err = CRYPT_PK_ASN1_ERROR;
goto error;
}
if ((l->data = XCALLOC(1, len - data_offset)) == NULL) {
err = CRYPT_MEM;

View File

@ -21,27 +21,27 @@
Decode a SEQUENCE type using a VA list
@param in Input buffer
@param inlen Length of input in octets
@remark <...> is of the form <type, size, data> (int, unsigned long, void*)
@param a1 Initialized argument list #1
@param a2 Initialized argument list #2 (copy of #1)
@param flags c.f. enum ltc_der_seq
@return CRYPT_OK on success
*/
int der_decode_sequence_multi(const unsigned char *in, unsigned long inlen, ...)
static int _der_decode_sequence_va(const unsigned char *in, unsigned long inlen, va_list a1, va_list a2, unsigned int flags)
{
int err;
ltc_asn1_type type;
unsigned long size, x;
void *data;
va_list args;
ltc_asn1_list *list;
LTC_ARGCHK(in != NULL);
/* get size of output that will be required */
va_start(args, inlen);
x = 0;
for (;;) {
type = (ltc_asn1_type)va_arg(args, int);
size = va_arg(args, unsigned long);
data = va_arg(args, void*);
type = (ltc_asn1_type)va_arg(a1, int);
size = va_arg(a1, unsigned long);
data = va_arg(a1, void*);
LTC_UNUSED_PARAM(size);
LTC_UNUSED_PARAM(data);
@ -72,13 +72,10 @@ int der_decode_sequence_multi(const unsigned char *in, unsigned long inlen, ...)
break;
case LTC_ASN1_EOL:
case LTC_ASN1_CONSTRUCTED:
case LTC_ASN1_CONTEXT_SPECIFIC:
va_end(args);
case LTC_ASN1_CUSTOM_TYPE:
return CRYPT_INVALID_ARG;
}
}
va_end(args);
/* allocate structure for x elements */
if (x == 0) {
@ -91,12 +88,11 @@ int der_decode_sequence_multi(const unsigned char *in, unsigned long inlen, ...)
}
/* fill in the structure */
va_start(args, inlen);
x = 0;
for (;;) {
type = (ltc_asn1_type)va_arg(args, int);
size = va_arg(args, unsigned long);
data = va_arg(args, void*);
type = (ltc_asn1_type)va_arg(a2, int);
size = va_arg(a2, unsigned long);
data = va_arg(a2, void*);
if (type == LTC_ASN1_EOL) {
break;
@ -125,18 +121,67 @@ int der_decode_sequence_multi(const unsigned char *in, unsigned long inlen, ...)
break;
/* coverity[dead_error_line] */
case LTC_ASN1_EOL:
case LTC_ASN1_CONSTRUCTED:
case LTC_ASN1_CONTEXT_SPECIFIC:
case LTC_ASN1_CUSTOM_TYPE:
break;
}
}
va_end(args);
err = der_decode_sequence(in, inlen, list, x);
err = der_decode_sequence_ex(in, inlen, list, x, flags);
XFREE(list);
return err;
}
/**
Decode a SEQUENCE type using a VA list
@param in Input buffer
@param inlen Length of input in octets
@remark <...> is of the form <type, size, data> (int, unsigned long, void*)
@return CRYPT_OK on success
*/
int der_decode_sequence_multi(const unsigned char *in, unsigned long inlen, ...)
{
va_list a1, a2;
int err;
LTC_ARGCHK(in != NULL);
va_start(a1, inlen);
va_start(a2, inlen);
err = _der_decode_sequence_va(in, inlen, a1, a2, LTC_DER_SEQ_SEQUENCE | LTC_DER_SEQ_RELAXED);
va_end(a2);
va_end(a1);
return err;
}
/**
Decode a SEQUENCE type using a VA list
@param in Input buffer
@param inlen Length of input in octets
@param flags c.f. enum ltc_der_seq
@remark <...> is of the form <type, size, data> (int, unsigned long, void*)
@return CRYPT_OK on success
*/
int der_decode_sequence_multi_ex(const unsigned char *in, unsigned long inlen, unsigned int flags, ...)
{
va_list a1, a2;
int err;
LTC_ARGCHK(in != NULL);
va_start(a1, flags);
va_start(a2, flags);
err = _der_decode_sequence_va(in, inlen, a1, a2, flags);
va_end(a2);
va_end(a1);
return err;
}
#endif

View File

@ -52,21 +52,11 @@ int der_encode_sequence_ex(ltc_asn1_list *list, unsigned long inlen,
x = 0;
out[x++] = (type_of == LTC_ASN1_SEQUENCE) ? 0x30 : 0x31;
if (z < 128) {
out[x++] = (unsigned char)z;
} else if (z < 256) {
out[x++] = 0x81;
out[x++] = (unsigned char)z;
} else if (z < 65536UL) {
out[x++] = 0x82;
out[x++] = (unsigned char)((z>>8UL)&255);
out[x++] = (unsigned char)(z&255);
} else if (z < 16777216UL) {
out[x++] = 0x83;
out[x++] = (unsigned char)((z>>16UL)&255);
out[x++] = (unsigned char)((z>>8UL)&255);
out[x++] = (unsigned char)(z&255);
y = *outlen - x;
if ((err = der_encode_asn1_length(z, &out[x], &y)) != CRYPT_OK) {
goto LBL_ERR;
}
x += y;
/* store data */
*outlen -= x;
@ -191,9 +181,14 @@ int der_encode_sequence_ex(ltc_asn1_list *list, unsigned long inlen,
}
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;

View File

@ -71,8 +71,7 @@ int der_encode_sequence_multi(unsigned char *out, unsigned long *outlen, ...)
break;
case LTC_ASN1_CHOICE:
case LTC_ASN1_CONSTRUCTED:
case LTC_ASN1_CONTEXT_SPECIFIC:
case LTC_ASN1_CUSTOM_TYPE:
case LTC_ASN1_EOL:
case LTC_ASN1_TELETEX_STRING:
va_end(args);
@ -124,8 +123,7 @@ int der_encode_sequence_multi(unsigned char *out, unsigned long *outlen, ...)
break;
case LTC_ASN1_CHOICE:
case LTC_ASN1_CONSTRUCTED:
case LTC_ASN1_CONTEXT_SPECIFIC:
case LTC_ASN1_CUSTOM_TYPE:
case LTC_ASN1_EOL:
case LTC_ASN1_TELETEX_STRING:
va_end(args);

View File

@ -33,7 +33,7 @@ int der_length_sequence_ex(ltc_asn1_list *list, unsigned long inlen,
{
int err;
ltc_asn1_type type;
unsigned long size, x, y, i, z;
unsigned long size, x, y, i;
void *data;
LTC_ARGCHK(list != NULL);
@ -50,6 +50,9 @@ int der_length_sequence_ex(ltc_asn1_list *list, unsigned long inlen,
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) {
@ -140,6 +143,13 @@ int der_length_sequence_ex(ltc_asn1_list *list, unsigned long inlen,
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:
@ -149,37 +159,23 @@ int der_length_sequence_ex(ltc_asn1_list *list, unsigned long inlen,
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;
}
}
/* calc header size */
z = y;
if (y < 128) {
y += 2;
} else if (y < 256) {
/* 0x30 0x81 LL */
y += 3;
} else if (y < 65536UL) {
/* 0x30 0x82 LL LL */
y += 4;
} else if (y < 16777216UL) {
/* 0x30 0x83 LL LL LL */
y += 5;
} else {
err = CRYPT_INVALID_ARG;
if ((err = der_length_asn1_length(y, &x)) != CRYPT_OK) {
goto LBL_ERR;
}
if (payloadlen != NULL) {
*payloadlen = y;
}
/* store size */
if (payloadlen) *payloadlen = z;
*outlen = y;
*outlen = y + x + 1;
err = CRYPT_OK;
LBL_ERR:

View File

@ -32,7 +32,7 @@ void der_sequence_shrink(ltc_asn1_list *in)
}
switch (in->type) {
case LTC_ASN1_CONSTRUCTED:
case LTC_ASN1_CUSTOM_TYPE:
case LTC_ASN1_SET:
case LTC_ASN1_SEQUENCE : if (in->data != NULL) { XFREE(in->data); in->data = NULL; } break;
default: break;

View File

@ -18,30 +18,7 @@
/* LTC define to ASN.1 TAG */
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_GENERALIZEDTIME: return 0x18;
case LTC_ASN1_SEQUENCE: return 0x30;
case LTC_ASN1_SET:
case LTC_ASN1_SETOF: return 0x31;
case LTC_ASN1_CHOICE:
case LTC_ASN1_CONSTRUCTED:
case LTC_ASN1_CONTEXT_SPECIFIC:
case LTC_ASN1_EOL: return -1;
}
return -1;
return der_asn1_type_to_identifier_map[v];
}

View File

@ -23,7 +23,8 @@
*/
int der_length_short_integer(unsigned long num, unsigned long *outlen)
{
unsigned long z, y, len;
unsigned long z, y;
int err;
LTC_ARGCHK(outlen != NULL);
@ -41,22 +42,15 @@ int der_length_short_integer(unsigned long num, unsigned long *outlen)
/* handle zero */
if (z == 0) {
z = 1;
} else if ((num&(1UL<<((z<<3) - 1))) != 0) {
/* in case msb is set */
++z;
}
/* we need a 0x02 to indicate it's INTEGER */
len = 1;
/* length byte */
++len;
/* bytes in value */
len += z;
/* see if msb is set */
len += (num&(1UL<<((z<<3) - 1))) ? 1 : 0;
/* return length */
*outlen = len;
if ((err = der_length_asn1_length(z, &y)) != CRYPT_OK) {
return err;
}
*outlen = 1 + y + z;
return CRYPT_OK;
}

View File

@ -27,7 +27,7 @@ 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;
int t, err;
LTC_ARGCHK(in != NULL);
LTC_ARGCHK(out != NULL);
@ -44,23 +44,12 @@ int der_decode_teletex_string(const unsigned char *in, unsigned long inlen,
}
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;
/* get the length of the data */
y = inlen - x;
if ((err = der_decode_asn1_length(in + x, &y, &len)) != CRYPT_OK) {
return err;
}
x += y;
/* is it too long? */
if (len > *outlen) {
@ -68,7 +57,7 @@ int der_decode_teletex_string(const unsigned char *in, unsigned long inlen,
return CRYPT_BUFFER_OVERFLOW;
}
if (len + x > inlen) {
if (len > (inlen - x)) {
return CRYPT_INVALID_PACKET;
}

View File

@ -170,6 +170,7 @@ int der_teletex_value_decode(int v)
int der_length_teletex_string(const unsigned char *octets, unsigned long noctets, unsigned long *outlen)
{
unsigned long x;
int err;
LTC_ARGCHK(outlen != NULL);
LTC_ARGCHK(octets != NULL);
@ -181,21 +182,10 @@ int der_length_teletex_string(const unsigned char *octets, unsigned long noctets
}
}
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;
if ((err = der_length_asn1_length(noctets, &x)) != CRYPT_OK) {
return err;
}
*outlen = 1 + x + noctets;
return CRYPT_OK;
}

View File

@ -46,25 +46,14 @@ int der_decode_utf8_string(const unsigned char *in, unsigned long inlen,
}
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;
/* get the length of the data */
y = inlen - x;
if ((err = der_decode_asn1_length(in + x, &y, &len)) != CRYPT_OK) {
return err;
}
x += y;
if (len + x > inlen) {
if (len > (inlen - x)) {
return CRYPT_INVALID_PACKET;
}

View File

@ -28,6 +28,7 @@ int der_encode_utf8_string(const wchar_t *in, unsigned long inlen,
unsigned char *out, unsigned long *outlen)
{
unsigned long x, y, len;
int err;
LTC_ARGCHK(in != NULL);
LTC_ARGCHK(out != NULL);
@ -38,46 +39,26 @@ int der_encode_utf8_string(const wchar_t *in, unsigned long inlen,
if (!der_utf8_valid_char(in[x])) return CRYPT_INVALID_ARG;
len += der_utf8_charsize(in[x]);
}
if (len < 128) {
y = 2 + len;
} else if (len < 256) {
y = 3 + len;
} else if (len < 65536UL) {
y = 4 + len;
} else if (len < 16777216UL) {
y = 5 + len;
} else {
return CRYPT_INVALID_ARG;
if ((err = der_length_asn1_length(len, &x)) != CRYPT_OK) {
return err;
}
x += len + 1;
/* too big? */
if (y > *outlen) {
*outlen = y;
if (x > *outlen) {
*outlen = x;
return CRYPT_BUFFER_OVERFLOW;
}
/* encode the header+len */
x = 0;
out[x++] = 0x0C;
if (len < 128) {
out[x++] = (unsigned char)len;
} else if (len < 256) {
out[x++] = 0x81;
out[x++] = (unsigned char)len;
} else if (len < 65536UL) {
out[x++] = 0x82;
out[x++] = (unsigned char)((len>>8)&255);
out[x++] = (unsigned char)(len&255);
} else if (len < 16777216UL) {
out[x++] = 0x83;
out[x++] = (unsigned char)((len>>16)&255);
out[x++] = (unsigned char)((len>>8)&255);
out[x++] = (unsigned char)(len&255);
} else {
/* coverity[dead_error_line] */
return CRYPT_INVALID_ARG;
y = *outlen - x;
if ((err = der_encode_asn1_length(len, out + x, &y)) != CRYPT_OK) {
return err;
}
x += y;
/* store UTF8 */
for (y = 0; y < inlen; y++) {
@ -91,7 +72,7 @@ int der_encode_utf8_string(const wchar_t *in, unsigned long inlen,
}
}
/* retun length */
/* return length */
*outlen = x;
return CRYPT_OK;

View File

@ -65,6 +65,7 @@ int der_utf8_valid_char(const wchar_t c)
int der_length_utf8_string(const wchar_t *in, unsigned long noctets, unsigned long *outlen)
{
unsigned long x, len;
int err;
LTC_ARGCHK(in != NULL);
LTC_ARGCHK(outlen != NULL);
@ -75,21 +76,10 @@ int der_length_utf8_string(const wchar_t *in, unsigned long noctets, unsigned lo
len += der_utf8_charsize(in[x]);
}
if (len < 128) {
/* 0C LL DD DD DD ... */
*outlen = 2 + len;
} else if (len < 256) {
/* 0C 81 LL DD DD DD ... */
*outlen = 3 + len;
} else if (len < 65536UL) {
/* 0C 82 LL LL DD DD DD ... */
*outlen = 4 + len;
} else if (len < 16777216UL) {
/* 0C 83 LL LL LL DD DD DD ... */
*outlen = 5 + len;
} else {
return CRYPT_INVALID_ARG;
if ((err = der_length_asn1_length(len, &x)) != CRYPT_OK) {
return err;
}
*outlen = 1 + x + len;
return CRYPT_OK;
}

View File

@ -7,9 +7,10 @@
* guarantee it works.
*/
#include "tomcrypt.h"
/**
@file der_decode_subject_public_key_info.c
ASN.1 DER, encode a Subject Public Key structure --nmav
@file x509_decode_subject_public_key_info.c
ASN.1 DER/X.509, encode a SubjectPublicKeyInfo structure --nmav
*/
#ifdef LTC_DER
@ -25,7 +26,7 @@
* }
*/
/**
Decode a subject public key info
Decode a SubjectPublicKeyInfo
@param in The input buffer
@param inlen The length of the input buffer
@param algorithm One out of the enum #public_key_algorithms
@ -33,12 +34,12 @@
@param public_key_len [in/out] The length of the public key buffer and the written length
@param parameters_type The parameters' type out of the enum ltc_asn1_type
@param parameters The parameters to include
@param parameters_len The number of parameters to include
@param parameters_len [in/out]The number of parameters to include
@return CRYPT_OK on success
*/
int der_decode_subject_public_key_info(const unsigned char *in, unsigned long inlen,
int x509_decode_subject_public_key_info(const unsigned char *in, unsigned long inlen,
unsigned int algorithm, void* public_key, unsigned long* public_key_len,
unsigned long parameters_type, ltc_asn1_list* parameters, unsigned long parameters_len)
unsigned long parameters_type, void* parameters, unsigned long *parameters_len)
{
int err;
unsigned long len;
@ -51,6 +52,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);
LTC_ARGCHK(parameters_len != NULL);
err = pk_get_oid(algorithm, &oid);
if (err != CRYPT_OK) {
@ -66,7 +68,7 @@ int der_decode_subject_public_key_info(const unsigned char *in, unsigned long in
/* this includes the internal hash ID and optional params (NULL in this case) */
LTC_SET_ASN1(alg_id, 0, LTC_ASN1_OBJECT_IDENTIFIER, tmpoid, sizeof(tmpoid)/sizeof(tmpoid[0]));
LTC_SET_ASN1(alg_id, 1, (ltc_asn1_type)parameters_type, parameters, parameters_len);
LTC_SET_ASN1(alg_id, 1, (ltc_asn1_type)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
@ -79,6 +81,8 @@ int der_decode_subject_public_key_info(const unsigned char *in, unsigned long in
goto LBL_ERR;
}
*parameters_len = alg_id[1].size;
if ((alg_id[0].size != oid.OIDlen) ||
XMEMCMP(oid.OID, alg_id[0].data, oid.OIDlen * sizeof(oid.OID[0]))) {
/* OID mismatch */

View File

@ -9,8 +9,8 @@
#include "tomcrypt.h"
/**
@file der_encode_subject_public_key_info.c
ASN.1 DER, encode a Subject Public Key structure --nmav
@file x509_encode_subject_public_key_info.c
ASN.1 DER/X.509, encode a SubjectPublicKeyInfo structure --nmav
*/
#ifdef LTC_DER
@ -26,7 +26,7 @@
* }
*/
/**
Encode a subject public key info
Encode a SubjectPublicKeyInfo
@param out The output buffer
@param outlen [in/out] Length of buffer and resulting length of output
@param algorithm One out of the enum #public_key_algorithms
@ -37,7 +37,7 @@
@param parameters_len The number of parameters to include
@return CRYPT_OK on success
*/
int der_encode_subject_public_key_info(unsigned char *out, unsigned long *outlen,
int x509_encode_subject_public_key_info(unsigned char *out, unsigned long *outlen,
unsigned int algorithm, void* public_key, unsigned long public_key_len,
unsigned long parameters_type, void* parameters, unsigned long parameters_len)
{

View File

@ -86,7 +86,7 @@ int dsa_export(unsigned char *out, unsigned long *outlen, int type, dsa_key *key
LTC_SET_ASN1(int_list, 1, LTC_ASN1_INTEGER, key->q, 1UL);
LTC_SET_ASN1(int_list, 2, LTC_ASN1_INTEGER, key->g, 1UL);
err = der_encode_subject_public_key_info(out, outlen, PKA_DSA, tmp,
err = x509_encode_subject_public_key_info(out, outlen, PKA_DSA, tmp,
tmplen, LTC_ASN1_SEQUENCE, int_list,
sizeof(int_list) / sizeof(int_list[0]));

View File

@ -25,7 +25,7 @@
int dsa_import(const unsigned char *in, unsigned long inlen, dsa_key *key)
{
int err, stat;
unsigned long zero = 0;
unsigned long zero = 0, len;
unsigned char* tmpbuf = NULL;
unsigned char flags[1];
@ -102,9 +102,10 @@ int dsa_import(const unsigned char *in, unsigned long inlen, dsa_key *key)
goto LBL_ERR;
}
err = der_decode_subject_public_key_info(in, inlen, PKA_DSA,
len = 3;
err = x509_decode_subject_public_key_info(in, inlen, PKA_DSA,
tmpbuf, &tmpbuf_len,
LTC_ASN1_SEQUENCE, params, 3);
LTC_ASN1_SEQUENCE, params, &len);
if (err != CRYPT_OK) {
XFREE(tmpbuf);
goto LBL_ERR;

View File

@ -111,7 +111,7 @@ int dsa_verify_hash(const unsigned char *sig, unsigned long siglen,
LTC_SET_ASN1(sig_seq, 0, LTC_ASN1_INTEGER, r, 1UL);
LTC_SET_ASN1(sig_seq, 1, LTC_ASN1_INTEGER, s, 1UL);
err = der_decode_sequence(sig, siglen, sig_seq, 2);
err = der_decode_sequence_strict(sig, siglen, sig_seq, 2);
if (err != CRYPT_OK) {
goto LBL_ERR;
}

View File

@ -66,7 +66,7 @@ static int _ecc_verify_hash(const unsigned char *sig, unsigned long siglen,
}
else {
/* ASN.1 format */
if ((err = der_decode_sequence_multi(sig, siglen,
if ((err = der_decode_sequence_multi_ex(sig, siglen, LTC_DER_SEQ_SEQUENCE | LTC_DER_SEQ_STRICT,
LTC_ASN1_INTEGER, 1UL, r,
LTC_ASN1_INTEGER, 1UL, s,
LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) { goto error; }

View File

@ -79,7 +79,7 @@ int rsa_export(unsigned char *out, unsigned long *outlen, int type, rsa_key *key
goto finish;
}
err = der_encode_subject_public_key_info(out, outlen,
err = x509_encode_subject_public_key_info(out, outlen,
PKA_RSA, tmp, tmplen, LTC_ASN1_NULL, NULL, 0);
finish:

View File

@ -27,7 +27,7 @@ int rsa_import(const unsigned char *in, unsigned long inlen, rsa_key *key)
int err;
void *zero;
unsigned char *tmpbuf=NULL;
unsigned long tmpbuf_len;
unsigned long tmpbuf_len, len;
LTC_ARGCHK(in != NULL);
LTC_ARGCHK(key != NULL);
@ -47,9 +47,10 @@ int rsa_import(const unsigned char *in, unsigned long inlen, rsa_key *key)
goto LBL_ERR;
}
err = der_decode_subject_public_key_info(in, inlen,
len = 0;
err = x509_decode_subject_public_key_info(in, inlen,
PKA_RSA, tmpbuf, &tmpbuf_len,
LTC_ASN1_NULL, NULL, 0);
LTC_ASN1_NULL, NULL, &len);
if (err == CRYPT_OK) { /* SubjectPublicKeyInfo format */

View File

@ -26,7 +26,7 @@ int rsa_import_x509(const unsigned char *in, unsigned long inlen, rsa_key *key)
{
int err;
unsigned char *tmpbuf;
unsigned long tmpbuf_len, tmp_inlen;
unsigned long tmpbuf_len, tmp_inlen, len;
ltc_asn1_list *decoded_list = NULL, *l;
LTC_ARGCHK(in != NULL);
@ -77,9 +77,10 @@ int rsa_import_x509(const unsigned char *in, unsigned long inlen, rsa_key *key)
l->child->type == LTC_ASN1_SEQUENCE && l->child->child &&
l->child->child->type == LTC_ASN1_OBJECT_IDENTIFIER && l->child->next &&
l->child->next->type == LTC_ASN1_BIT_STRING) {
err = der_decode_subject_public_key_info(l->data, l->size,
len = 0;
err = x509_decode_subject_public_key_info(l->data, l->size,
PKA_RSA, tmpbuf, &tmpbuf_len,
LTC_ASN1_NULL, NULL, 0);
LTC_ASN1_NULL, NULL, &len);
if (err == CRYPT_OK) {
/* now it should be SEQUENCE { INTEGER, INTEGER } */
if ((err = der_decode_sequence_multi(tmpbuf, tmpbuf_len,

View File

@ -142,10 +142,10 @@ int rsa_verify_hash_ex(const unsigned char *sig, unsigned long siglen,
LTC_SET_ASN1(siginfo, 0, LTC_ASN1_SEQUENCE, digestinfo, 2);
LTC_SET_ASN1(siginfo, 1, LTC_ASN1_OCTET_STRING, tmpbuf, siglen);
if ((err = der_decode_sequence(out, outlen, siginfo, 2)) != CRYPT_OK) {
if ((err = der_decode_sequence_strict(out, outlen, siginfo, 2)) != CRYPT_OK) {
/* fallback to Legacy:missing NULL */
LTC_SET_ASN1(siginfo, 0, LTC_ASN1_SEQUENCE, digestinfo, 1);
if ((err = der_decode_sequence(out, outlen, siginfo, 2)) != CRYPT_OK) {
if ((err = der_decode_sequence_strict(out, outlen, siginfo, 2)) != CRYPT_OK) {
XFREE(out);
goto bail_2;
}

BIN
tests/asn1/0x00.crt Normal file

Binary file not shown.

BIN
tests/asn1/0x80.crt Normal file

Binary file not shown.

BIN
tests/asn1/0xff.crt Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
tests/asn1/private.der Normal file

Binary file not shown.

BIN
tests/asn1/root-ca.der Normal file

Binary file not shown.

BIN
tests/asn1/type0x08.crt Normal file

Binary file not shown.

View File

@ -17,6 +17,10 @@ int der_test(void)
#else
#include <sys/stat.h>
#include <sys/types.h>
#include <dirent.h>
static const unsigned char _der_tests_stinky_root_cert[] =
"MIIFETCCA/mgAwIBAgIQbv53JNmv518t5lkCHE272jANBgkqhkiG9w0BAQUFADCB"
"lTELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2Ug"
@ -259,6 +263,8 @@ static void _der_tests_print_flexi(ltc_asn1_list* l, unsigned int level)
break;
case LTC_ASN1_INTEGER:
name = "INTEGER";
mp_toradix(l->data, buf, 10);
text = buf;
break;
case LTC_ASN1_SHORT_INTEGER:
name = "SHORT INTEGER";
@ -374,37 +380,22 @@ static void _der_tests_print_flexi(ltc_asn1_list* l, unsigned int level)
name = "TELETEX STRING";
text = l->data;
break;
case LTC_ASN1_CONSTRUCTED:
if (l->used & 0x80)
name = "CONTEXT SPECIFIC";
else
name = "CONSTRUCTED";
snprintf(buf, sizeof(buf), "[%d]", l->used & 0x1f);
text = buf;
break;
case LTC_ASN1_CONTEXT_SPECIFIC:
name = "CONTEXT SPECIFIC";
case LTC_ASN1_CUSTOM_TYPE:
name = "NON STANDARD";
{
int r;
char* s = buf;
int sz = sizeof(buf);
r = snprintf(s, sz, "[%d] ", l->used & 0x1f);
if (r < 0 || r >= sz) {
printf("Context Specific boom");
exit(EXIT_FAILURE);
}
s += r;
sz -= r;
for (n = 0; n < l->size; ++n) {
r = snprintf(s, sz, "%02X", ((unsigned char*)l->data)[n]);
if (r < 0 || r >= sz) {
printf("Context Specific boom");
exit(EXIT_FAILURE);
}
s += r;
sz -= r;
}
text = buf;
int r;
char* s = buf;
int sz = sizeof(buf);
r = snprintf(s, sz, "[%s %s %llu]", der_asn1_class_to_string_map[l->class], der_asn1_pc_to_string_map[l->pc], l->tag);
if (r < 0 || r >= sz) {
fprintf(stderr, "%s boom\n", name);
exit(EXIT_FAILURE);
}
s += r;
sz -= r;
text = buf;
}
break;
}
@ -488,7 +479,7 @@ SEQUENCE(3 elem)
INTEGER 2
*/
CHECK_ASN1_TYPE(l1, LTC_ASN1_CONSTRUCTED);
CHECK_ASN1_TYPE(l1, LTC_ASN1_CUSTOM_TYPE);
CHECK_ASN1_HAS_CHILD(l1);
CHECK_ASN1_HAS_NEXT(l1);
@ -1028,11 +1019,13 @@ static void der_flexi_test(void)
}
static int der_choice_test(void)
static int der_choice_n_custom_test(void)
{
ltc_asn1_list types[7], host[1];
unsigned char bitbuf[10], octetbuf[10], ia5buf[10], printbuf[10], outbuf[256], x, y;
unsigned long integer, oidbuf[10], outlen, inlen;
ltc_asn1_list types[10], host[1], custom[1], root[1], child[1];
int boolean[1];
unsigned char bitbuf[10], octetbuf[10], ia5buf[10], printbuf[10], outbuf[256], custbuf[256], x, y;
wchar_t utf8buf[10];
unsigned long integer, oidbuf[10], outlen, custlen, inlen, n;
void *mpinteger;
ltc_utctime utctime = { 91, 5, 6, 16, 45, 40, 1, 7, 0 };
ltc_generalizedtime gtime = { 2038, 01, 19, 3, 14, 8, 0, 0, 0, 0 };
@ -1042,54 +1035,543 @@ static int der_choice_test(void)
for (x = 0; x < sizeof(octetbuf); x++) { octetbuf[x] = x; }
for (x = 0; x < sizeof(ia5buf); x++) { ia5buf[x] = 'a'; }
for (x = 0; x < sizeof(printbuf); x++) { printbuf[x] = 'a'; }
for (x = 0; x < sizeof(utf8buf)/sizeof(utf8buf[0]); x++) { utf8buf[x] = L'a'; }
integer = 1;
boolean[0] = 1;
for (x = 0; x < sizeof(oidbuf)/sizeof(oidbuf[0]); x++) { oidbuf[x] = x + 1; }
DO(mp_init(&mpinteger));
for (x = 0; x < 14; x++) {
n = sizeof(types)/sizeof(types[0]);
for (x = 0; x < n * 2; x++) {
/* setup list */
LTC_SET_ASN1(types, 0, LTC_ASN1_PRINTABLE_STRING, printbuf, sizeof(printbuf));
LTC_SET_ASN1(types, 1, LTC_ASN1_BIT_STRING, bitbuf, sizeof(bitbuf));
LTC_SET_ASN1(types, 2, LTC_ASN1_OCTET_STRING, octetbuf, sizeof(octetbuf));
LTC_SET_ASN1(types, 3, LTC_ASN1_IA5_STRING, ia5buf, sizeof(ia5buf));
if (x > 7) {
LTC_SET_ASN1(types, 4, LTC_ASN1_SHORT_INTEGER, &integer, 1);
y = 0;
LTC_SET_ASN1(types, y++, LTC_ASN1_PRINTABLE_STRING, printbuf, sizeof(printbuf));
if (x > n) {
LTC_SET_ASN1(types, y++, LTC_ASN1_BIT_STRING, bitbuf, sizeof(bitbuf));
} else {
LTC_SET_ASN1(types, 4, LTC_ASN1_INTEGER, mpinteger, 1);
LTC_SET_ASN1(types, y++, LTC_ASN1_RAW_BIT_STRING, bitbuf, sizeof(bitbuf));
}
LTC_SET_ASN1(types, 5, LTC_ASN1_OBJECT_IDENTIFIER, oidbuf, sizeof(oidbuf)/sizeof(oidbuf[0]));
if (x > 7) {
LTC_SET_ASN1(types, 6, LTC_ASN1_UTCTIME, &utctime, 1);
LTC_SET_ASN1(types, y++, LTC_ASN1_OCTET_STRING, octetbuf, sizeof(octetbuf));
LTC_SET_ASN1(types, y++, LTC_ASN1_IA5_STRING, ia5buf, sizeof(ia5buf));
LTC_SET_ASN1(types, y++, LTC_ASN1_BOOLEAN, boolean, sizeof(boolean)/sizeof(boolean[0]));
if (x > n) {
LTC_SET_ASN1(types, y++, LTC_ASN1_SHORT_INTEGER, &integer, 1);
} else {
LTC_SET_ASN1(types, 6, LTC_ASN1_GENERALIZEDTIME, &gtime, 1);
LTC_SET_ASN1(types, y++, LTC_ASN1_INTEGER, mpinteger, 1);
}
LTC_SET_ASN1(types, y++, LTC_ASN1_OBJECT_IDENTIFIER, oidbuf, sizeof(oidbuf)/sizeof(oidbuf[0]));
if (x > n) {
LTC_SET_ASN1(types, y++, LTC_ASN1_UTCTIME, &utctime, 1);
} else {
LTC_SET_ASN1(types, y++, LTC_ASN1_GENERALIZEDTIME, &gtime, 1);
}
LTC_SET_ASN1(host, 0, LTC_ASN1_CHOICE, types, 7);
LTC_SET_ASN1(custom, 0, LTC_ASN1_NULL, NULL, 0);
LTC_SET_ASN1_CUSTOM_CONSTRUCTED(types, y++, LTC_ASN1_CL_CONTEXT_SPECIFIC, 0, custom);
LTC_SET_ASN1(types, y++, LTC_ASN1_UTF8_STRING, utf8buf, sizeof(utf8buf)/sizeof(utf8buf[0]));
LTC_SET_ASN1(host, 0, LTC_ASN1_CHOICE, types, n);
/* encode */
outlen = sizeof(outbuf);
DO(der_encode_sequence(&types[x>6?x-7:x], 1, outbuf, &outlen));
DO(der_encode_sequence(&types[x % n], 1, outbuf, &outlen));
/* custom encode */
child[0] = types[x % n];
if (x < n) {
LTC_SET_ASN1_CUSTOM_CONSTRUCTED(root, 0, LTC_ASN1_CL_CONTEXT_SPECIFIC, 1U << (x % n), child);
} else {
LTC_SET_ASN1_CUSTOM_PRIMITIVE(root, 0, LTC_ASN1_CL_CONTEXT_SPECIFIC, 1U << (x % n), child->type, child->data, child->size);
}
custlen = sizeof(custbuf);
/* don't try to custom-encode a primitive custom-type */
if (child[0].type != LTC_ASN1_CUSTOM_TYPE || root->pc != LTC_ASN1_PC_PRIMITIVE) {
DO(der_encode_custom_type(root, custbuf, &custlen));
}
/* decode it */
inlen = outlen;
DO(der_decode_sequence(outbuf, inlen, &host[0], 1));
DO(der_decode_sequence(outbuf, inlen, host, 1));
for (y = 0; y < 7; y++) {
if (types[y].used && y != (x>6?x-7:x)) {
for (y = 0; y < n; y++) {
if (types[y].used && y != (x % n)) {
fprintf(stderr, "CHOICE, flag %u in trial %u was incorrectly set to one\n", y, x);
return 1;
}
if (!types[y].used && y == (x>6?x-7:x)) {
if (!types[y].used && y == (x % n)) {
fprintf(stderr, "CHOICE, flag %u in trial %u was incorrectly set to zero\n", y, x);
return 1;
}
}
/* custom decode */
if (child[0].type != LTC_ASN1_CUSTOM_TYPE || root->pc != LTC_ASN1_PC_PRIMITIVE) {
DO(der_decode_custom_type(custbuf, custlen, root));
}
}
mp_clear(mpinteger);
return 0;
}
static void _der_decode_print(const void* p, unsigned long* plen)
{
ltc_asn1_list *list;
DO(der_decode_sequence_flexi(p, plen, &list));
#ifdef LTC_DER_TESTS_PRINT_FLEXI
fprintf(stderr, "\n\n");
_der_tests_print_flexi(list, 0);
fprintf(stderr, "\n\n");
#endif
der_sequence_free(list);
}
static const unsigned char eckey_privc_der[] = {
0x30, 0x81, 0xf0, 0x02, 0x01, 0x01, 0x04, 0x18, 0x96, 0x9d, 0x28, 0xf2, 0x40, 0x48, 0x19, 0x11,
0x79, 0xb0, 0x47, 0x8e, 0x8c, 0x6b, 0x3d, 0x9b, 0xf2, 0x31, 0x16, 0x10, 0x08, 0x72, 0xb1, 0x86,
0xa0, 0x81, 0xb2, 0x30, 0x81, 0xaf, 0x02, 0x01, 0x01, 0x30, 0x24, 0x06, 0x07, 0x2a, 0x86, 0x48,
0xce, 0x3d, 0x01, 0x01, 0x02, 0x19, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x30,
0x4b, 0x04, 0x18, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x04, 0x18, 0x22, 0x12, 0x3d,
0xc2, 0x39, 0x5a, 0x05, 0xca, 0xa7, 0x42, 0x3d, 0xae, 0xcc, 0xc9, 0x47, 0x60, 0xa7, 0xd4, 0x62,
0x25, 0x6b, 0xd5, 0x69, 0x16, 0x03, 0x15, 0x00, 0xc4, 0x69, 0x68, 0x44, 0x35, 0xde, 0xb3, 0x78,
0xc4, 0xb6, 0x5c, 0xa9, 0x59, 0x1e, 0x2a, 0x57, 0x63, 0x05, 0x9a, 0x2e, 0x04, 0x19, 0x02, 0x7d,
0x29, 0x77, 0x81, 0x00, 0xc6, 0x5a, 0x1d, 0xa1, 0x78, 0x37, 0x16, 0x58, 0x8d, 0xce, 0x2b, 0x8b,
0x4a, 0xee, 0x8e, 0x22, 0x8f, 0x18, 0x96, 0x02, 0x19, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7a, 0x62, 0xd0, 0x31, 0xc8, 0x3f, 0x42, 0x94, 0xf6, 0x40,
0xec, 0x13, 0x02, 0x01, 0x01, 0xa1, 0x1c, 0x03, 0x1a, 0x00, 0x02, 0x55, 0x2c, 0xb8, 0x73, 0x5c,
0x9d, 0x98, 0xe4, 0x57, 0xfe, 0xd5, 0x96, 0x0a, 0x73, 0x8d, 0x82, 0xd7, 0xce, 0x05, 0xa9, 0x79,
0x91, 0x5c, 0xf9
};
static const unsigned char eckey_privs_der[] = {
0x30, 0x50, 0x02, 0x01, 0x01, 0x04, 0x14, 0x82, 0xef, 0x42, 0x0b, 0xc7, 0xe2, 0x9f, 0x3a, 0x84,
0xe5, 0x74, 0xec, 0x9c, 0xc5, 0x10, 0x26, 0x63, 0x8d, 0xb5, 0x46, 0xa0, 0x07, 0x06, 0x05, 0x2b,
0x81, 0x04, 0x00, 0x09, 0xa1, 0x2c, 0x03, 0x2a, 0x00, 0x04, 0xb5, 0xb1, 0x5a, 0xb0, 0x2a, 0x10,
0xd1, 0xf5, 0x4d, 0x6a, 0x41, 0xde, 0xcd, 0x69, 0x09, 0xb3, 0x5f, 0x26, 0xb0, 0xa2, 0xaf, 0xd3,
0x02, 0x89, 0x5e, 0xd4, 0x96, 0x5c, 0xbc, 0x2a, 0x7e, 0x75, 0x85, 0x86, 0x29, 0xb3, 0x29, 0x13,
0x77, 0xc3
};
static void der_custom_test(void)
{
ltc_asn1_list bool_ean[1], seq1[1], custom[1];
int boolean;
unsigned long len;
unsigned char buf[1024];
unsigned char buf1[] = { 0xbf, 0xa0, 0x00, 0x04, 0x30, 0x02, 0x05, 0x00 };
unsigned char buf2[] = { 0x30, 0x08, 0xbf, 0xa0, 0x00, 0x04, 0x30, 0x02, 0x05, 0x00 };
boolean = 0x1;
LTC_SET_ASN1(bool_ean, 0, LTC_ASN1_BOOLEAN, &boolean, 1);
LTC_SET_ASN1(seq1, 0, LTC_ASN1_SEQUENCE, bool_ean, 1);
LTC_SET_ASN1_CUSTOM_CONSTRUCTED(custom, 0, LTC_ASN1_CL_CONTEXT_SPECIFIC, 0x1000, seq1);
DO(der_length_custom_type(custom, &len, NULL));
len = sizeof(buf);
DO(der_encode_custom_type(custom, buf, &len));
_der_decode_print(buf, &len);
boolean = 0x0;
DO(der_decode_custom_type(buf, len, custom));
DO(der_length_sequence(custom, 1, &len));
len = sizeof(buf);
DO(der_encode_sequence(custom, 1, buf, &len));
_der_decode_print(buf, &len);
boolean = 0x0;
DO(der_decode_sequence(buf, len, custom, 1));
LTC_SET_ASN1_CUSTOM_PRIMITIVE(bool_ean, 0, LTC_ASN1_CL_CONTEXT_SPECIFIC, 0x8000, LTC_ASN1_BOOLEAN, &boolean, 1);
DO(der_length_custom_type(bool_ean, &len, NULL));
len = sizeof(buf);
DO(der_encode_custom_type(bool_ean, buf, &len));
_der_decode_print(buf, &len);
LTC_SET_ASN1_CUSTOM_PRIMITIVE(bool_ean, 0, LTC_ASN1_CL_CONTEXT_SPECIFIC, 0x8000, LTC_ASN1_BOOLEAN, &boolean, 1);
DO(der_decode_custom_type(buf, len, bool_ean));
len = sizeof(buf1);
_der_decode_print(buf1, &len);
len = sizeof(buf2);
_der_decode_print(buf2, &len);
len = sizeof(eckey_privc_der);
_der_decode_print(eckey_privc_der, &len);
len = sizeof(eckey_privs_der);
_der_decode_print(eckey_privs_der, &len);
}
typedef int (*_der_Xcode)(const void*, unsigned long, void*, unsigned long*);
typedef struct {
_der_Xcode encode;
_der_Xcode decode;
const void* in;
size_t in_sz;
size_t factor;
size_t type_sz;
const char* what;
} der_Xcode_t;
static void der_Xcode_run(const der_Xcode_t* x)
{
unsigned long l1, l2, sz;
void *d1, *d2;
int err;
l1 = 1;
d1 = XMALLOC(l1 * x->type_sz);
sz = (x->in_sz * x->factor)/x->type_sz;
if ((err = x->encode(x->in, sz, d1, &l1)) == CRYPT_BUFFER_OVERFLOW) {
d1 = XREALLOC(d1, l1 * x->type_sz);
}
DO(x->encode(x->in, sz, d1, &l1));
l2 = 1;
d2 = XMALLOC(l2 * x->type_sz);
while ((err = x->decode(d1, l1, d2, &l2)) == CRYPT_BUFFER_OVERFLOW) {
d2 = XREALLOC(d2, l2 * x->type_sz);
}
DO(x->decode(d1, l1, d2, &l2));
DO(compare_testvector(d2, (l2/x->factor) * x->type_sz, x->in, x->in_sz, x->what, __LINE__) == 0 ? CRYPT_OK : CRYPT_FAIL_TESTVECTOR);
XFREE(d2);
XFREE(d1);
}
#define DER_XCODE_X(n, b, x) { \
(_der_Xcode)der_encode_ ## n, \
(_der_Xcode)der_decode_ ## n, \
b, \
sizeof(b), \
x, \
sizeof(typeof(b[0])),\
#n \
}
#define DER_XCODE(n, b) DER_XCODE_X(n, b, 1)
static void der_Xcode_test(void)
{
unsigned long i;
ltc_asn1_list *list;
ltc_asn1_list ttex_neg_int[2];
unsigned char buf[128];
void* mpinteger;
const unsigned long oid[3] = { 1, 23, 42 };
const unsigned char bit_string[] = { 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1 };
const unsigned char multi_buf[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
const char multi_string[] = {'l','i','b','t','o','m','c','r','y','p','t'};
const wchar_t wchar_string[] = L"libtomcrypt";
const unsigned char teletex_neg_int[] = { 0x30, 0x11, 0x14, 0x0b, 0x6c, 0x69, 0x62, 0x74,
0x6f, 0x6d, 0x63, 0x72, 0x79, 0x70, 0x74, 0x02,
0x02, 0xfc, 0x19 };
const der_Xcode_t xcode_tests[] =
{
DER_XCODE(bit_string, bit_string),
DER_XCODE_X(raw_bit_string, multi_buf, 8),
DER_XCODE(octet_string, multi_buf),
DER_XCODE(object_identifier, oid),
DER_XCODE(ia5_string, multi_string),
DER_XCODE(printable_string, multi_string),
DER_XCODE(utf8_string, wchar_string),
};
for (i = 0; i < sizeof(xcode_tests)/sizeof(xcode_tests[0]); ++i) {
der_Xcode_run(&xcode_tests[i]);
}
i = sizeof(teletex_neg_int);
DO(der_decode_sequence_flexi(teletex_neg_int, &i, &list));
#ifdef LTC_DER_TESTS_PRINT_FLEXI
fprintf(stderr, "\n\n");
_der_tests_print_flexi(list, 0);
fprintf(stderr, "\n\n");
#endif
if (list->child == NULL || list->child->next == NULL)
exit(EXIT_FAILURE);
ttex_neg_int[0] = *list->child->next;
i = sizeof(buf);
DO(der_encode_sequence(ttex_neg_int, 1, buf, &i));
der_sequence_free(list);
DO(mp_init(&mpinteger));
LTC_SET_ASN1(ttex_neg_int, 0, LTC_ASN1_TELETEX_STRING, buf, sizeof(buf));
LTC_SET_ASN1(ttex_neg_int, 1, LTC_ASN1_INTEGER, mpinteger, 1);
DO(der_decode_sequence(teletex_neg_int, sizeof(teletex_neg_int), ttex_neg_int, 2));
mp_clear(mpinteger);
}
static off_t fsize(const char *filename)
{
struct stat st;
if (stat(filename, &st) == 0) return st.st_size;
return -1;
}
static void der_asn1_test(void)
{
DIR *d = opendir("tests/asn1");
struct dirent *de;
char fname[PATH_MAX];
void* buf = NULL;
FILE *f = NULL;
off_t fsz;
unsigned long sz;
ltc_asn1_list *list;
int err;
if (d == NULL)
return;
while((de = readdir(d)) != NULL) {
fname[0] = '\0';
if (strcmp(de->d_name, ".") == 0 || strcmp(de->d_name, "..") == 0)
continue;
strcat(fname, "tests/asn1/");
strcat(fname, de->d_name);
fsz = fsize(fname);
if (fsz == -1)
break;
#if defined(LTC_TEST_DBG) && LTC_TEST_DBG > 1
fprintf(stderr, "Try to decode %s\n", fname);
#endif
f = fopen(fname, "rb");
sz = fsz;
buf = XMALLOC(fsz);
if (fread(buf, 1, sz, f) != sz)
break;
if ((err = der_decode_sequence_flexi(buf, &sz, &list)) == CRYPT_OK) {
#ifdef LTC_DER_TESTS_PRINT_FLEXI
fprintf(stderr, "\n\n");
_der_tests_print_flexi(list, 0);
fprintf(stderr, "\n\n");
#endif
der_sequence_free(list);
} else {
#if defined(LTC_TEST_DBG)
fprintf(stderr, "Could not decode %s: %s\n\n", fname, error_to_string(err));
#endif
}
XFREE(buf);
buf = NULL;
fclose(f);
f = NULL;
}
if (buf != NULL) XFREE(buf);
if (f != NULL) fclose(f);
closedir(d);
}
static void _der_regression_test(void)
{
static const unsigned char _broken_sequence[] = {
0x30,0x41,0x02,0x84,0x7f,0xff,0xff,0xff,0x1e,0x41,0xb4,0x79,0xad,0x57,0x69,
0x05,0xb9,0x60,0xfe,0x14,0xea,0xdb,0x91,0xb0,0xcc,0xf3,0x48,0x43,0xda,0xb9,
0x16,0x17,0x3b,0xb8,0xc9,0xcd,0x02,0x1d,0x00,0xad,0xe6,0x59,0x88,0xd2,0x37,
0xd3,0x0f,0x9e,0xf4,0x1d,0xd4,0x24,0xa4,0xe1,0xc8,0xf1,0x69,0x67,0xcf,0x33,
0x65,0x81,0x3f,0xe8,0x78,0x62,0x36
};
static const unsigned char _addtl_bytes[] = {
0x30,0x45,0x02,0x21,0x00,0xb7,0xba,0xba,0xe9,0x33,0x2b,0x54,0xb8,0xa3,0xa0,0x5b,0x70,0x04,0x57,
0x98,0x21,0xa8,0x87,0xa1,0xb2,0x14,0x65,0xf7,0xdb,0x8a,0x3d,0x49,0x1b,0x39,0xfd,0x2c,0x3f,0x02,
0x20,0x74,0x72,0x91,0xdd,0x2f,0x3f,0x44,0xaf,0x7a,0xce,0x68,0xea,0x33,0x43,0x1d,0x6f,0x94,0xe4,
0x18,0xc1,0x06,0xa6,0xe7,0x62,0x85,0xcd,0x59,0xf4,0x32,0x60,0xec,0xce,0x00,0x00
};
unsigned long len;
void *x, *y;
ltc_asn1_list seq[2];
mp_init_multi(&x, &y, NULL);
LTC_SET_ASN1(seq, 0, LTC_ASN1_INTEGER, x, 1UL);
LTC_SET_ASN1(seq, 1, LTC_ASN1_INTEGER, y, 1UL);
DO(der_decode_sequence(_broken_sequence, sizeof(_broken_sequence), seq, 2) != CRYPT_OK ? CRYPT_OK : CRYPT_FAIL_TESTVECTOR);
mp_cleanup_multi(&y, &x, NULL);
len = sizeof(_broken_sequence);
mp_init_multi(&x, &y, NULL);
LTC_SET_ASN1(seq, 0, LTC_ASN1_INTEGER, x, 1UL);
LTC_SET_ASN1(seq, 1, LTC_ASN1_INTEGER, y, 1UL);
DO(der_decode_sequence(_addtl_bytes, sizeof(_addtl_bytes), seq, 2) == CRYPT_INPUT_TOO_LONG ? CRYPT_OK : CRYPT_FAIL_TESTVECTOR);
mp_cleanup_multi(&y, &x, NULL);
len = sizeof(_addtl_bytes);
_der_decode_print(_addtl_bytes, &len);
}
static void der_toolong_test(void)
{
int n, err, failed = 0;
ltc_asn1_list *list;
unsigned long len, oid[16];
unsigned char buf5[5], buf12[12], buf32[32];
static const unsigned char invalid1[] = {
0x30,0x19, /* SEQUENCE len=25 bytes */
0x30,0x0a, /* SEQUENCE len=10 bytes (which is wrong, should be 9) */
0x04,0x05, /* OCTET STRING len=5 */ 0x2b,0x0e,0x03,0x02,0x1a,
0x05,0x00, /* NULL */
0x04,0x0c, /* OCTET STRING len=12 */ 0xf7,0xff,0x9e,0x8b,0x7b,0xb2,0xe0,0x9b,0x70,0x93,0x5a,0x5d,
};
static const unsigned char invalid2[] = {
0x30,0x0d, /* SEQUENCE len=13 bytes*/
0x02,0x05, /* INTEGER len=5 */ 0x00,0xb7,0xba,0xba,0xe9,
0x02,0x04, /* INTEGER len=4 */ 0x74,0x72,0x91,0xdd,
0x00,0x00 /* garbage after the sequence, der_decode_sequence_flexi should ignore this */
};
static const unsigned char invalid3[] = {
0x30,0x0f, /* SEQUENCE len=15 bytes*/
0x02,0x05, /* INTEGER len=5 */ 0x00,0xb7,0xba,0xba,0xe9,
0x02,0x04, /* INTEGER len=4 */ 0x74,0x72,0x91,0xdd,
0x00,0x00 /* garbage inside the sequence */
};
static const unsigned char invalid4[] = {
0x30, 0x30,
0x30, 0x0d,
0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01,
0x05, 0x00,
0x04, 0x20, 0x53, 0x2e, 0xaa, 0xbd, 0x95, 0x74, 0x88, 0x0d, 0xbf, 0x76, 0xb9, 0xb8, 0xcc, 0x00, 0x83, 0x2c,
0x20, 0xa6, 0xec, 0x11, 0x3d, 0x68, 0x22, 0x99, 0x55, 0x0d, 0x7a, 0x6e, 0x0f, 0x34, 0x5e, 0x25
};
static const unsigned char invalid5[] = {
0x30, 0x31,
0x30, 0x0e,
0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01,
0x05, 0x00,
0x04, 0x20, 0x53, 0x2e, 0xaa, 0xbd, 0x95,0x74, 0x88, 0x0d, 0xbf, 0x76, 0xb9, 0xb8, 0xcc,0x00, 0x83, 0x2c,
0x20, 0xa6, 0xec, 0x11, 0x3d,0x68, 0x22, 0x99, 0x55, 0x0d, 0x7a, 0x6e, 0x0f,0x34, 0x5e, 0x25
};
static const unsigned char invalid6[] = {
0x30, 0x31,
0x30, 0x0c,
0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01,
0x05, 0x00,
0x04, 0x20, 0x53, 0x2e, 0xaa, 0xbd, 0x95,0x74, 0x88, 0x0d, 0xbf, 0x76, 0xb9, 0xb8, 0xcc,0x00, 0x83, 0x2c,
0x20, 0xa6, 0xec, 0x11, 0x3d,0x68, 0x22, 0x99, 0x55, 0x0d, 0x7a, 0x6e, 0x0f,0x34, 0x5e, 0x25
};
ltc_asn1_list seqsub[2], seqoid[2], seqmain[2], seqint[2];
void *int1, *int2;
LTC_SET_ASN1(seqsub, 0, LTC_ASN1_OCTET_STRING, buf5, 5);
LTC_SET_ASN1(seqsub, 1, LTC_ASN1_NULL, NULL, 0);
LTC_SET_ASN1(seqmain, 0, LTC_ASN1_SEQUENCE, seqsub, 2);
LTC_SET_ASN1(seqmain, 1, LTC_ASN1_OCTET_STRING, buf12, 12);
n = 1;
len = sizeof(invalid1);
err = der_decode_sequence_strict(invalid1, len, seqmain, 2);
if (err == CRYPT_OK) {
fprintf(stderr,"Sequence invalid%d accepted by der_decode_sequence\n", n);
failed = 1;
}
len = sizeof(invalid1);
err = der_decode_sequence_flexi(invalid1, &len, &list);
if (err == CRYPT_OK) {
fprintf(stderr,"Sequence invalid%d accepted by der_decode_sequence_flexi\n", n);
failed = 1;
der_sequence_free(list);
}
mp_init_multi(&int1, &int2, NULL);
LTC_SET_ASN1(seqint, 0, LTC_ASN1_INTEGER, int1, 1);
LTC_SET_ASN1(seqint, 1, LTC_ASN1_INTEGER, int2, 1);
n++;
len = sizeof(invalid2);
err = der_decode_sequence_strict(invalid2, len, seqint, 2);
if (err == CRYPT_OK) {
fprintf(stderr,"Sequence invalid%d accepted by der_decode_sequence\n", n);
failed = 1;
}
len = sizeof(invalid2);
err = der_decode_sequence_flexi(invalid2, &len, &list);
/* flexi parser should decode this; however returning "len" shorter than "sizeof(invalid2)" */
if (err != CRYPT_OK || len != 15) {
fprintf(stderr,"der_decode_sequence_flexi failed, err=%d (expected 0) len=%lu (expected 15)\n", err, len);
failed = 1;
}
if (err == CRYPT_OK)
der_sequence_free(list);
n++;
len = sizeof(invalid3);
err = der_decode_sequence_strict(invalid3, len, seqint, 2);
if (err == CRYPT_OK) {
fprintf(stderr,"Sequence invalid%d accepted by der_decode_sequence\n", n);
failed = 1;
}
len = sizeof(invalid3);
err = der_decode_sequence_flexi(invalid3, &len, &list);
if (err == CRYPT_OK) {
fprintf(stderr,"Sequence invalid%d accepted by der_decode_sequence_flexi\n", n);
failed = 1;
der_sequence_free(list);
}
mp_clear_multi(int1, int2, NULL);
LTC_SET_ASN1(seqoid, 0, LTC_ASN1_OBJECT_IDENTIFIER, oid, sizeof(oid)/sizeof(oid[0]));
LTC_SET_ASN1(seqoid, 1, LTC_ASN1_NULL, NULL, 0);
LTC_SET_ASN1(seqmain, 0, LTC_ASN1_SEQUENCE, seqoid, 2);
LTC_SET_ASN1(seqmain, 1, LTC_ASN1_OCTET_STRING, buf32, 32);
n++;
len = sizeof(invalid4);
err = der_decode_sequence_strict(invalid4, len, seqmain, 2);
if (err == CRYPT_OK) {
fprintf(stderr,"Sequence invalid%d accepted by der_decode_sequence\n", n);
failed = 1;
}
len = sizeof(invalid4);
err = der_decode_sequence_flexi(invalid4, &len, &list);
if (err == CRYPT_OK) {
fprintf(stderr,"Sequence invalid%d accepted by der_decode_sequence_flexi\n", n);
failed = 1;
der_sequence_free(list);
}
n++;
len = sizeof(invalid5);
err = der_decode_sequence_strict(invalid5, len, seqmain, 2);
if (err == CRYPT_OK) {
fprintf(stderr,"Sequence invalid%d accepted by der_decode_sequence\n", n);
failed = 1;
}
len = sizeof(invalid5);
err = der_decode_sequence_flexi(invalid5, &len, &list);
if (err == CRYPT_OK) {
fprintf(stderr,"Sequence invalid%d accepted by der_decode_sequence_flexi\n", n);
failed = 1;
der_sequence_free(list);
}
n++;
len = sizeof(invalid6);
err = der_decode_sequence_strict(invalid6, len, seqmain, 2);
if (err == CRYPT_OK) {
fprintf(stderr,"Sequence invalid%d accepted by der_decode_sequence\n", n);
failed = 1;
}
len = sizeof(invalid6);
err = der_decode_sequence_flexi(invalid6, &len, &list);
if (err == CRYPT_OK) {
fprintf(stderr,"Sequence invalid%d accepted by der_decode_sequence_flexi\n", n);
failed = 1;
der_sequence_free(list);
}
if (failed) exit(EXIT_FAILURE);
}
int der_test(void)
{
@ -1125,8 +1607,39 @@ int der_test(void)
if (ltc_mp.name == NULL) return CRYPT_NOP;
der_Xcode_test();
der_asn1_test();
der_custom_test();
_der_regression_test();
der_toolong_test();
der_cacert_test();
y = 0xffffff00;
#if ULONG_MAX == ULLONG_MAX
y <<= 32;
#endif
while (y != 0) {
/* we have to modify x to be larger than the encoded
* length as der_decode_asn1_length() checks also if
* the encoded length is reasonable in regards to the
* available buffer size.
*/
x = sizeof(buf[0]);
DO(der_encode_asn1_length(y, buf[0], &x));
x = y + x;
DO(der_decode_asn1_length(buf[0], &x, &z));
if (y != z) {
fprintf(stderr, "Failed to en- or decode length correctly! %lu != %lu\n", y, z);
return 1;
}
y >>= 3;
}
DO(mp_init_multi(&a, &b, &c, &d, &e, &f, &g, NULL));
for (zz = 0; zz < 16; zz++) {
#ifdef USE_TFM
@ -1143,7 +1656,7 @@ int der_test(void)
x = sizeof(buf[0]);
DO(der_encode_integer(a, buf[0], &x));
DO(der_length_integer(a, &y));
if (y != x) { fprintf(stderr, "DER INTEGER size mismatch\n"); return 1; }
if (y != x) { fprintf(stderr, "DER INTEGER size mismatch %lu != %lu\n", y, x); return 1; }
mp_set_int(b, 0);
DO(der_decode_integer(buf[0], y, b));
if (y != x || mp_cmp(a, b) != LTC_MP_EQ) {
@ -1440,7 +1953,7 @@ tmp_time.off_hh);
der_set_test();
der_flexi_test();
return der_choice_test();
return der_choice_n_custom_test();
}
#endif

View File

@ -306,7 +306,8 @@ static int _dsa_wycheproof_test(void)
}
stat = 666; /* intentionally not one, not zero */
DO(dsa_verify_hash(sig, sizeof(sig), hash, hashlen, &stat, &key));
DOX(dsa_verify_hash(sig, sizeof(sig), hash, hashlen, &stat, &key)
== CRYPT_INPUT_TOO_LONG ? CRYPT_OK:CRYPT_INVALID_PACKET, "should be too long");
/* this should be invalid */
if (stat != 0) {
fprintf(stderr, "dsa_verify_hash did not reject invalid signature\n");

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -10,6 +10,10 @@
#if defined(LTC_MRSA)
#include <sys/stat.h>
#include <sys/types.h>
#include <dirent.h>
#define RSA_MSGSIZE 78
/* These are test keys [see file test.key] that I use to test my import/export against */
@ -343,6 +347,76 @@ static int _rsa_issue_301(int prng_idx)
return CRYPT_OK;
}
static off_t fsize(const char *filename)
{
struct stat st;
if (stat(filename, &st) == 0) return st.st_size;
return -1;
}
static int _rsa_size_test(void)
{
DIR *d = opendir("tests/rsa");
struct dirent *de;
char fname[PATH_MAX];
void* buf = NULL;
FILE *f = NULL;
off_t fsz;
unsigned long sz;
int err = CRYPT_FILE_NOTFOUND;
rsa_key k;
if (d == NULL)
return CRYPT_FILE_NOTFOUND;
while((de = readdir(d)) != NULL) {
fname[0] = '\0';
if (strcmp(de->d_name, ".") == 0 || strcmp(de->d_name, "..") == 0)
continue;
strcat(fname, "tests/rsa/");
strcat(fname, de->d_name);
fsz = fsize(fname);
if (fsz == -1)
break;
/* here we use the filesize as indicator for the rsa size
* that would fail to import for tfm because it's fixed-size
*/
if ((strcmp(ltc_mp.name, "TomsFastMath") == 0) && (fsz > 2048)) {
#if defined(LTC_TEST_DBG) && LTC_TEST_DBG > 1
fprintf(stderr, "TomsFastMath skip: %s\n", fname);
#endif
continue;
}
#if defined(LTC_TEST_DBG) && LTC_TEST_DBG > 1
fprintf(stderr, "Try to import %s\n", fname);
#endif
f = fopen(fname, "rb");
sz = fsz;
buf = XMALLOC(fsz);
if (fread(buf, 1, sz, f) != sz) {
err = CRYPT_ERROR;
break;
}
if ((err = rsa_import_x509(buf, sz, &k)) == CRYPT_OK) {
rsa_free(&k);
} else {
#if defined(LTC_TEST_DBG)
fprintf(stderr, "Could not import RSA key of %s: %s\n\n", fname, error_to_string(err));
#endif
break;
}
XFREE(buf);
buf = NULL;
fclose(f);
f = NULL;
}
if (buf != NULL) XFREE(buf);
if (f != NULL) fclose(f);
closedir(d);
return err;
}
int rsa_test(void)
{
unsigned char in[1024], out[1024], tmp[3072];
@ -368,6 +442,8 @@ int rsa_test(void)
return 1;
}
DO(_rsa_size_test());
DO(_rsa_issue_301(prng_idx));
/* make 10 random key */
@ -657,11 +733,8 @@ print_hex("q", tmp, len);
len3 = sizeof(tmp);
/* (6) */
if (i < 8)
DOX(rsa_verify_hash_ex(p2, len2, p, 20, LTC_PKCS_1_V1_5, hash_idx, -1, &stat, &pubKey)
DOX(rsa_verify_hash_ex(p2, len2, p, 20, LTC_PKCS_1_V1_5, hash_idx, -1, &stat, &pubKey)
== CRYPT_INVALID_PACKET ? CRYPT_OK:CRYPT_INVALID_PACKET, "should fail");
else
DOX(rsa_verify_hash_ex(p2, len2, p, 20, LTC_PKCS_1_V1_5, hash_idx, -1, &stat, &pubKey), "should succeed");
DOX(stat == 0?CRYPT_OK:CRYPT_FAIL_TESTVECTOR, "should fail");
}
rsa_free(&key);