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:
commit
64298c1819
106
doc/crypt.tex
106
doc/crypt.tex
@ -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}
|
||||
|
@ -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"
|
||||
|
@ -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 \
|
||||
|
@ -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 \
|
||||
|
@ -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 \
|
||||
|
@ -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 \
|
||||
|
@ -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. */
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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.",
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
420
src/pk/asn1/der/custom_type/der_decode_custom_type.c
Normal file
420
src/pk/asn1/der/custom_type/der_decode_custom_type.c
Normal 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$ */
|
238
src/pk/asn1/der/custom_type/der_encode_custom_type.c
Normal file
238
src/pk/asn1/der/custom_type/der_encode_custom_type.c
Normal 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$ */
|
213
src/pk/asn1/der/custom_type/der_length_custom_type.c
Normal file
213
src/pk/asn1/der/custom_type/der_length_custom_type.c
Normal 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$ */
|
167
src/pk/asn1/der/general/der_asn1_maps.c
Normal file
167
src/pk/asn1/der/general/der_asn1_maps.c
Normal 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$ */
|
133
src/pk/asn1/der/general/der_decode_asn1_identifier.c
Normal file
133
src/pk/asn1/der/general/der_decode_asn1_identifier.c
Normal 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$ */
|
67
src/pk/asn1/der/general/der_decode_asn1_length.c
Normal file
67
src/pk/asn1/der/general/der_decode_asn1_length.c
Normal 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$ */
|
97
src/pk/asn1/der/general/der_encode_asn1_identifier.c
Normal file
97
src/pk/asn1/der/general/der_encode_asn1_identifier.c
Normal file
@ -0,0 +1,97 @@
|
||||
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
|
||||
*
|
||||
* LibTomCrypt is a library that provides various cryptographic
|
||||
* algorithms in a highly modular and flexible manner.
|
||||
*
|
||||
* The library is free for all purposes without any express
|
||||
* guarantee it works.
|
||||
*/
|
||||
#include "tomcrypt.h"
|
||||
|
||||
/**
|
||||
@file der_encode_asn1_identifier.c
|
||||
ASN.1 DER, encode the ASN.1 Identifier, Steffen Jaeckel
|
||||
*/
|
||||
|
||||
#ifdef LTC_DER
|
||||
/**
|
||||
Encode the ASN.1 Identifier
|
||||
@param id The ASN.1 Identifer to encode
|
||||
@param out Where to write the identifier to
|
||||
@param outlen [in/out] The size of out available/written
|
||||
@return CRYPT_OK if successful
|
||||
*/
|
||||
int der_encode_asn1_identifier(const ltc_asn1_list *id, unsigned char *out, unsigned long *outlen)
|
||||
{
|
||||
ulong64 tmp;
|
||||
unsigned long tag_len;
|
||||
|
||||
LTC_ARGCHK(id != NULL);
|
||||
LTC_ARGCHK(outlen != NULL);
|
||||
|
||||
if (id->type != LTC_ASN1_CUSTOM_TYPE) {
|
||||
if (id->type >= der_asn1_type_to_identifier_map_sz) {
|
||||
return CRYPT_INVALID_ARG;
|
||||
}
|
||||
if (der_asn1_type_to_identifier_map[id->type] == -1) {
|
||||
return CRYPT_INVALID_ARG;
|
||||
}
|
||||
if (out != NULL) {
|
||||
*out = der_asn1_type_to_identifier_map[id->type];
|
||||
}
|
||||
*outlen = 1;
|
||||
return CRYPT_OK;
|
||||
} else {
|
||||
if (id->class < LTC_ASN1_CL_UNIVERSAL || id->class > LTC_ASN1_CL_PRIVATE) {
|
||||
return CRYPT_INVALID_ARG;
|
||||
}
|
||||
if (id->pc < LTC_ASN1_PC_PRIMITIVE || id->pc > LTC_ASN1_PC_CONSTRUCTED) {
|
||||
return CRYPT_INVALID_ARG;
|
||||
}
|
||||
if (id->tag > (ULONG_MAX >> (8 + 7))) {
|
||||
return CRYPT_INVALID_ARG;
|
||||
}
|
||||
}
|
||||
|
||||
if (out != NULL) {
|
||||
if (*outlen < 1) {
|
||||
return CRYPT_BUFFER_OVERFLOW;
|
||||
}
|
||||
|
||||
out[0] = id->class << 6 | id->pc << 5;
|
||||
}
|
||||
|
||||
if (id->tag < 0x1f) {
|
||||
if (out != NULL) {
|
||||
out[0] |= id->tag & 0x1f;
|
||||
}
|
||||
*outlen = 1;
|
||||
} else {
|
||||
tag_len = 0;
|
||||
tmp = id->tag;
|
||||
do {
|
||||
tag_len++;
|
||||
tmp >>= 7;
|
||||
} while (tmp);
|
||||
|
||||
if (out != NULL) {
|
||||
if (*outlen < tag_len + 1) {
|
||||
return CRYPT_BUFFER_OVERFLOW;
|
||||
}
|
||||
out[0] |= 0x1f;
|
||||
for (tmp = 1; tmp <= tag_len; ++tmp) {
|
||||
out[tmp] = ((id->tag >> (7 * (tag_len - tmp))) & 0x7f) | 0x80;
|
||||
}
|
||||
out[tag_len] &= ~0x80;
|
||||
}
|
||||
*outlen = tag_len + 1;
|
||||
}
|
||||
|
||||
return CRYPT_OK;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* ref: $Format:%D$ */
|
||||
/* git commit: $Format:%H$ */
|
||||
/* commit time: $Format:%ai$ */
|
121
src/pk/asn1/der/general/der_encode_asn1_length.c
Normal file
121
src/pk/asn1/der/general/der_encode_asn1_length.c
Normal 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$ */
|
33
src/pk/asn1/der/general/der_length_asn1_identifier.c
Normal file
33
src/pk/asn1/der/general/der_length_asn1_identifier.c
Normal file
@ -0,0 +1,33 @@
|
||||
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
|
||||
*
|
||||
* LibTomCrypt is a library that provides various cryptographic
|
||||
* algorithms in a highly modular and flexible manner.
|
||||
*
|
||||
* The library is free for all purposes without any express
|
||||
* guarantee it works.
|
||||
*/
|
||||
#include "tomcrypt.h"
|
||||
|
||||
/**
|
||||
@file der_length_asn1_identifier.c
|
||||
ASN.1 DER, determine the length when encoding the ASN.1 Identifier, Steffen Jaeckel
|
||||
*/
|
||||
|
||||
#ifdef LTC_DER
|
||||
/**
|
||||
Determine the length required when encoding the ASN.1 Identifier
|
||||
@param id The ASN.1 identifier to encode
|
||||
@param idlen [out] The required length to encode list
|
||||
@return CRYPT_OK if successful
|
||||
*/
|
||||
|
||||
int der_length_asn1_identifier(const ltc_asn1_list *id, unsigned long *idlen)
|
||||
{
|
||||
return der_encode_asn1_identifier(id, NULL, idlen);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* ref: $Format:%D$ */
|
||||
/* git commit: $Format:%H$ */
|
||||
/* commit time: $Format:%ai$ */
|
32
src/pk/asn1/der/general/der_length_asn1_length.c
Normal file
32
src/pk/asn1/der/general/der_length_asn1_length.c
Normal 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$ */
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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++) {
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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 */
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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];
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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++) {
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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++) {
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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:
|
||||
|
@ -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;
|
||||
|
@ -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];
|
||||
}
|
||||
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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 */
|
@ -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)
|
||||
{
|
@ -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]));
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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; }
|
||||
|
@ -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:
|
||||
|
@ -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 */
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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
BIN
tests/asn1/0x00.crt
Normal file
Binary file not shown.
BIN
tests/asn1/0x80.crt
Normal file
BIN
tests/asn1/0x80.crt
Normal file
Binary file not shown.
BIN
tests/asn1/0xff.crt
Normal file
BIN
tests/asn1/0xff.crt
Normal file
Binary file not shown.
BIN
tests/asn1/illegal_padding1.crt
Normal file
BIN
tests/asn1/illegal_padding1.crt
Normal file
Binary file not shown.
BIN
tests/asn1/illegal_padding2.crt
Normal file
BIN
tests/asn1/illegal_padding2.crt
Normal file
Binary file not shown.
BIN
tests/asn1/illegal_padding3.crt
Normal file
BIN
tests/asn1/illegal_padding3.crt
Normal file
Binary file not shown.
BIN
tests/asn1/oid_overflow_test.der
Normal file
BIN
tests/asn1/oid_overflow_test.der
Normal file
Binary file not shown.
BIN
tests/asn1/oid_size_test.der
Normal file
BIN
tests/asn1/oid_size_test.der
Normal file
Binary file not shown.
BIN
tests/asn1/private.der
Normal file
BIN
tests/asn1/private.der
Normal file
Binary file not shown.
BIN
tests/asn1/root-ca.der
Normal file
BIN
tests/asn1/root-ca.der
Normal file
Binary file not shown.
BIN
tests/asn1/type0x08.crt
Normal file
BIN
tests/asn1/type0x08.crt
Normal file
Binary file not shown.
623
tests/der_test.c
623
tests/der_test.c
@ -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, >ime, 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, >ime, 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
|
||||
|
@ -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");
|
||||
|
BIN
tests/rsa/rsa_size_1024_bits.der
Normal file
BIN
tests/rsa/rsa_size_1024_bits.der
Normal file
Binary file not shown.
BIN
tests/rsa/rsa_size_16384_bits.der
Normal file
BIN
tests/rsa/rsa_size_16384_bits.der
Normal file
Binary file not shown.
BIN
tests/rsa/rsa_size_1999_bits.der
Normal file
BIN
tests/rsa/rsa_size_1999_bits.der
Normal file
Binary file not shown.
BIN
tests/rsa/rsa_size_2048_bits.der
Normal file
BIN
tests/rsa/rsa_size_2048_bits.der
Normal file
Binary file not shown.
BIN
tests/rsa/rsa_size_4096_bits.der
Normal file
BIN
tests/rsa/rsa_size_4096_bits.der
Normal file
Binary file not shown.
BIN
tests/rsa/rsa_size_512_bits.der
Normal file
BIN
tests/rsa/rsa_size_512_bits.der
Normal file
Binary file not shown.
BIN
tests/rsa/rsa_size_8192_bits.der
Normal file
BIN
tests/rsa/rsa_size_8192_bits.der
Normal file
Binary file not shown.
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user